package org.altbeacon.beacon.service; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanSettings; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.os.AsyncTask; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.RestrictTo; import androidx.annotation.WorkerThread; import androidx.core.view.MotionEventCompat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import org.altbeacon.beacon.Beacon; import org.altbeacon.beacon.BeaconManager; import org.altbeacon.beacon.BeaconParser; import org.altbeacon.beacon.Region; import org.altbeacon.beacon.logging.LogManager; import org.altbeacon.beacon.service.scanner.CycledLeScanCallback; import org.altbeacon.beacon.service.scanner.CycledLeScanner; import org.altbeacon.beacon.service.scanner.DistinctPacketDetector; import org.altbeacon.beacon.service.scanner.NonBeaconLeScanCallback; import org.altbeacon.beacon.service.scanner.ScanFilterUtils; import org.altbeacon.beacon.startup.StartupBroadcastReceiver; import org.altbeacon.bluetooth.BluetoothCrashResolver; /* access modifiers changed from: package-private */ public class ScanHelper { private static final String TAG = "ScanHelper"; private BeaconManager mBeaconManager; private Set<BeaconParser> mBeaconParsers = new HashSet(); private Context mContext; private final CycledLeScanCallback mCycledLeScanCallback = new CycledLeScanCallback() { /* class org.altbeacon.beacon.service.ScanHelper.AnonymousClass1 */ @Override // org.altbeacon.beacon.service.scanner.CycledLeScanCallback @TargetApi(11) @MainThread public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bArr) { ScanHelper.this.processScanResult(bluetoothDevice, i, bArr); } @Override // org.altbeacon.beacon.service.scanner.CycledLeScanCallback @SuppressLint({"WrongThread"}) @MainThread public void onCycleEnd() { if (BeaconManager.getBeaconSimulator() != null) { LogManager.d(ScanHelper.TAG, "Beacon simulator enabled", new Object[0]); if (BeaconManager.getBeaconSimulator().getBeacons() != null) { ApplicationInfo applicationInfo = ScanHelper.this.mContext.getApplicationInfo(); int i = applicationInfo.flags & 2; applicationInfo.flags = i; if (i != 0) { String str = ScanHelper.TAG; LogManager.d(str, "Beacon simulator returns " + BeaconManager.getBeaconSimulator().getBeacons().size() + " beacons.", new Object[0]); for (Beacon beacon : BeaconManager.getBeaconSimulator().getBeacons()) { ScanHelper.this.processBeaconFromScan(beacon); } } else { LogManager.w(ScanHelper.TAG, "Beacon simulations provided, but ignored because we are not running in debug mode. Please remove beacon simulations for production.", new Object[0]); } } else { LogManager.w(ScanHelper.TAG, "getBeacons is returning null. No simulated beacons to report.", new Object[0]); } } else if (LogManager.isVerboseLoggingEnabled()) { LogManager.d(ScanHelper.TAG, "Beacon simulator not enabled", new Object[0]); } ScanHelper.this.mDistinctPacketDetector.clearDetections(); ScanHelper.this.mMonitoringStatus.updateNewlyOutside(); ScanHelper.this.processRangeData(); } }; @Nullable private CycledLeScanner mCycledScanner; private DistinctPacketDetector mDistinctPacketDetector = new DistinctPacketDetector(); @Nullable private ExecutorService mExecutor; @NonNull private ExtraDataBeaconTracker mExtraDataBeaconTracker = new ExtraDataBeaconTracker(); private MonitoringStatus mMonitoringStatus; private final Map<Region, RangeState> mRangedRegionState = new HashMap(); private List<Beacon> mSimulatedScanData = null; ScanHelper(Context context) { this.mContext = context; this.mBeaconManager = BeaconManager.getInstanceForApplication(context); } private ExecutorService getExecutor() { if (this.mExecutor == null) { this.mExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1); } return this.mExecutor; } /* access modifiers changed from: package-private */ public void terminateThreads() { ExecutorService executorService = this.mExecutor; if (executorService != null) { executorService.shutdown(); try { if (!this.mExecutor.awaitTermination(10, TimeUnit.MILLISECONDS)) { LogManager.e(TAG, "Can't stop beacon parsing thread.", new Object[0]); } } catch (InterruptedException unused) { LogManager.e(TAG, "Interrupted waiting to stop beacon parsing thread.", new Object[0]); } this.mExecutor = null; } } /* access modifiers changed from: protected */ public void finalize() throws Throwable { super.finalize(); terminateThreads(); } /* access modifiers changed from: package-private */ @Nullable public CycledLeScanner getCycledScanner() { return this.mCycledScanner; } /* access modifiers changed from: package-private */ public MonitoringStatus getMonitoringStatus() { return this.mMonitoringStatus; } /* access modifiers changed from: package-private */ public void setMonitoringStatus(MonitoringStatus monitoringStatus) { this.mMonitoringStatus = monitoringStatus; } /* access modifiers changed from: package-private */ public Map<Region, RangeState> getRangedRegionState() { return this.mRangedRegionState; } /* access modifiers changed from: package-private */ public void setRangedRegionState(Map<Region, RangeState> map) { synchronized (this.mRangedRegionState) { this.mRangedRegionState.clear(); this.mRangedRegionState.putAll(map); } } /* access modifiers changed from: package-private */ public void setExtraDataBeaconTracker(@NonNull ExtraDataBeaconTracker extraDataBeaconTracker) { this.mExtraDataBeaconTracker = extraDataBeaconTracker; } /* access modifiers changed from: package-private */ public void setBeaconParsers(Set<BeaconParser> set) { this.mBeaconParsers = set; } /* access modifiers changed from: package-private */ public void setSimulatedScanData(List<Beacon> list) { this.mSimulatedScanData = list; } /* access modifiers changed from: package-private */ public void createCycledLeScanner(boolean z, BluetoothCrashResolver bluetoothCrashResolver) { this.mCycledScanner = CycledLeScanner.createScanner(this.mContext, BeaconManager.DEFAULT_FOREGROUND_SCAN_PERIOD, 0, z, this.mCycledLeScanCallback, bluetoothCrashResolver); } /* access modifiers changed from: package-private */ @TargetApi(11) public void processScanResult(BluetoothDevice bluetoothDevice, int i, byte[] bArr) { try { new ScanProcessor(this.mBeaconManager.getNonBeaconLeScanCallback()).executeOnExecutor(getExecutor(), new ScanData(bluetoothDevice, i, bArr)); } catch (RejectedExecutionException unused) { LogManager.w(TAG, "Ignoring scan result because we cannot keep up.", new Object[0]); } catch (OutOfMemoryError unused2) { LogManager.w(TAG, "Ignoring scan result because we cannot start a thread to keep up.", new Object[0]); } } /* access modifiers changed from: package-private */ public void reloadParsers() { HashSet hashSet = new HashSet(); hashSet.addAll(this.mBeaconManager.getBeaconParsers()); boolean z = true; for (BeaconParser beaconParser : this.mBeaconManager.getBeaconParsers()) { if (beaconParser.getExtraDataParsers().size() > 0) { z = false; hashSet.addAll(beaconParser.getExtraDataParsers()); } } this.mBeaconParsers = hashSet; this.mExtraDataBeaconTracker = new ExtraDataBeaconTracker(z); } /* access modifiers changed from: package-private */ @RequiresApi(api = MotionEventCompat.AXIS_SCROLL) public void startAndroidOBackgroundScan(Set<BeaconParser> set) { ScanSettings build = new ScanSettings.Builder().setScanMode(0).build(); List<ScanFilter> createScanFiltersForBeaconParsers = new ScanFilterUtils().createScanFiltersForBeaconParsers(new ArrayList(set)); try { BluetoothAdapter adapter = ((BluetoothManager) this.mContext.getApplicationContext().getSystemService("bluetooth")).getAdapter(); if (adapter == null) { LogManager.w(TAG, "Failed to construct a BluetoothAdapter", new Object[0]); } else if (!adapter.isEnabled()) { LogManager.w(TAG, "Failed to start background scan on Android O: BluetoothAdapter is not enabled", new Object[0]); } else { BluetoothLeScanner bluetoothLeScanner = adapter.getBluetoothLeScanner(); if (bluetoothLeScanner != null) { int startScan = bluetoothLeScanner.startScan(createScanFiltersForBeaconParsers, build, getScanCallbackIntent()); if (startScan != 0) { String str = TAG; LogManager.e(str, "Failed to start background scan on Android O. Code: " + startScan, new Object[0]); return; } LogManager.d(TAG, "Started passive beacon scan", new Object[0]); return; } LogManager.e(TAG, "Failed to start background scan on Android O: scanner is null", new Object[0]); } } catch (SecurityException unused) { LogManager.e(TAG, "SecurityException making Android O background scanner", new Object[0]); } catch (NullPointerException e) { LogManager.e(TAG, "NullPointerException starting Android O background scanner", e); } catch (RuntimeException e2) { LogManager.e(TAG, "Unexpected runtime exception starting Android O background scanner", e2); } } /* access modifiers changed from: package-private */ @RequiresApi(api = MotionEventCompat.AXIS_SCROLL) public void stopAndroidOBackgroundScan() { try { BluetoothAdapter adapter = ((BluetoothManager) this.mContext.getApplicationContext().getSystemService("bluetooth")).getAdapter(); if (adapter == null) { LogManager.w(TAG, "Failed to construct a BluetoothAdapter", new Object[0]); } else if (!adapter.isEnabled()) { LogManager.w(TAG, "BluetoothAdapter is not enabled", new Object[0]); } else { BluetoothLeScanner bluetoothLeScanner = adapter.getBluetoothLeScanner(); if (bluetoothLeScanner != null) { bluetoothLeScanner.stopScan(getScanCallbackIntent()); } } } catch (SecurityException unused) { LogManager.e(TAG, "SecurityException stopping Android O background scanner", new Object[0]); } catch (NullPointerException e) { LogManager.e(TAG, "NullPointerException stopping Android O background scanner", e); } catch (RuntimeException e2) { LogManager.e(TAG, "Unexpected runtime exception stopping Android O background scanner", e2); } } /* access modifiers changed from: package-private */ public PendingIntent getScanCallbackIntent() { Intent intent = new Intent(this.mContext, StartupBroadcastReceiver.class); intent.putExtra("o-scan", true); return PendingIntent.getBroadcast(this.mContext, 0, intent, 134217728); } /* access modifiers changed from: package-private */ @RestrictTo({RestrictTo.Scope.TESTS}) public CycledLeScanCallback getCycledLeScanCallback() { return this.mCycledLeScanCallback; } /* access modifiers changed from: private */ /* access modifiers changed from: public */ private void processRangeData() { synchronized (this.mRangedRegionState) { for (Region region : this.mRangedRegionState.keySet()) { RangeState rangeState = this.mRangedRegionState.get(region); LogManager.d(TAG, "Calling ranging callback", new Object[0]); rangeState.getCallback().call(this.mContext, "rangingData", new RangingData(rangeState.finalizeBeacons(), region).toBundle()); } } } /* access modifiers changed from: private */ /* access modifiers changed from: public */ @WorkerThread private void processBeaconFromScan(@NonNull Beacon beacon) { if (Stats.getInstance().isEnabled()) { Stats.getInstance().log(beacon); } if (LogManager.isVerboseLoggingEnabled()) { LogManager.d(TAG, "beacon detected : %s", beacon.toString()); } Beacon track = this.mExtraDataBeaconTracker.track(beacon); if (track != null) { this.mMonitoringStatus.updateNewlyInsideInRegionsContaining(track); LogManager.d(TAG, "looking for ranging region matches for this beacon", new Object[0]); synchronized (this.mRangedRegionState) { for (Region region : matchingRegions(track, this.mRangedRegionState.keySet())) { LogManager.d(TAG, "matches ranging region: %s", region); RangeState rangeState = this.mRangedRegionState.get(region); if (rangeState != null) { rangeState.addBeacon(track); } } } } else if (LogManager.isVerboseLoggingEnabled()) { LogManager.d(TAG, "not processing detections for GATT extra data beacon", new Object[0]); } } /* access modifiers changed from: private */ public class ScanData { @NonNull BluetoothDevice device; final int rssi; @NonNull byte[] scanRecord; ScanData(@NonNull BluetoothDevice bluetoothDevice, int i, @NonNull byte[] bArr) { this.device = bluetoothDevice; this.rssi = i; this.scanRecord = bArr; } } /* access modifiers changed from: private */ public class ScanProcessor extends AsyncTask<ScanData, Void, Void> { final DetectionTracker mDetectionTracker = DetectionTracker.getInstance(); private final NonBeaconLeScanCallback mNonBeaconLeScanCallback; /* access modifiers changed from: protected */ public void onPostExecute(Void r1) { } /* access modifiers changed from: protected */ public void onPreExecute() { } /* access modifiers changed from: protected */ public void onProgressUpdate(Void... voidArr) { } ScanProcessor(NonBeaconLeScanCallback nonBeaconLeScanCallback) { this.mNonBeaconLeScanCallback = nonBeaconLeScanCallback; } /* access modifiers changed from: protected */ /* JADX WARNING: Removed duplicated region for block: B:3:0x0015 */ @WorkerThread public Void doInBackground(ScanData... scanDataArr) { ScanData scanData = scanDataArr[0]; Iterator it = ScanHelper.this.mBeaconParsers.iterator(); Beacon beacon = null; while (it.hasNext() && (beacon = ((BeaconParser) it.next()).fromScanData(scanData.scanRecord, scanData.rssi, scanData.device)) == null) { while (it.hasNext()) { while (it.hasNext()) { } } } if (beacon != null) { if (LogManager.isVerboseLoggingEnabled()) { LogManager.d(ScanHelper.TAG, "Beacon packet detected for: " + beacon + " with rssi " + beacon.getRssi(), new Object[0]); } this.mDetectionTracker.recordDetection(); if (ScanHelper.this.mCycledScanner != null && !ScanHelper.this.mCycledScanner.getDistinctPacketsDetectedPerScan() && !ScanHelper.this.mDistinctPacketDetector.isPacketDistinct(scanData.device.getAddress(), scanData.scanRecord)) { LogManager.i(ScanHelper.TAG, "Non-distinct packets detected in a single scan. Restarting scans unecessary.", new Object[0]); ScanHelper.this.mCycledScanner.setDistinctPacketsDetectedPerScan(true); } ScanHelper.this.processBeaconFromScan(beacon); } else { NonBeaconLeScanCallback nonBeaconLeScanCallback = this.mNonBeaconLeScanCallback; if (nonBeaconLeScanCallback != null) { nonBeaconLeScanCallback.onNonBeaconLeScan(scanData.device, scanData.rssi, scanData.scanRecord); } } return null; } } private List<Region> matchingRegions(Beacon beacon, Collection<Region> collection) { ArrayList arrayList = new ArrayList(); for (Region region : collection) { if (region.matchesBeacon(beacon)) { arrayList.add(region); } else { LogManager.d(TAG, "This region (%s) does not match beacon: %s", region, beacon); } } return arrayList; } }