package org.altbeacon.beacon.service.scanner; import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Process; import android.os.SystemClock; import androidx.annotation.AnyThread; import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; import androidx.core.app.NotificationCompat; import androidx.core.view.MotionEventCompat; import com.baidu.speech.utils.analysis.Analysis; import java.util.Date; import org.altbeacon.beacon.BeaconManager; import org.altbeacon.beacon.logging.LogManager; import org.altbeacon.beacon.startup.StartupBroadcastReceiver; import org.altbeacon.bluetooth.BluetoothCrashResolver; @TargetApi(MotionEventCompat.AXIS_RTRIGGER) public abstract class CycledLeScanner { public static final long ANDROID_N_MAX_SCAN_DURATION_MILLIS = 1800000; private static final long ANDROID_N_MIN_SCAN_CYCLE_MILLIS = 6000; private static final String TAG = "CycledLeScanner"; protected boolean mBackgroundFlag = false; protected long mBetweenScanPeriod; private BluetoothAdapter mBluetoothAdapter; protected final BluetoothCrashResolver mBluetoothCrashResolver; protected final Context mContext; private long mCurrentScanStartTime = 0; protected final CycledLeScanCallback mCycledLeScanCallback; private volatile boolean mDistinctPacketsDetectedPerScan = false; @NonNull protected final Handler mHandler = new Handler(Looper.getMainLooper()); private long mLastScanCycleEndTime = 0; private long mLastScanCycleStartTime = 0; private boolean mLongScanForcingEnabled = false; protected long mNextScanCycleStartTime = 0; protected boolean mRestartNeeded = false; private long mScanCycleStopTime = 0; private boolean mScanCyclerStarted = false; @NonNull protected final Handler mScanHandler; private long mScanPeriod; @NonNull private final HandlerThread mScanThread; private boolean mScanning; private boolean mScanningEnabled = false; private boolean mScanningLeftOn = false; protected boolean mScanningPaused; private PendingIntent mWakeUpOperation = null; /* access modifiers changed from: protected */ public abstract boolean deferScanIfNeeded(); /* access modifiers changed from: protected */ public abstract void finishScan(); /* access modifiers changed from: protected */ public abstract void startScan(); /* access modifiers changed from: protected */ public abstract void stopScan(); protected CycledLeScanner(Context context, long j, long j2, boolean z, CycledLeScanCallback cycledLeScanCallback, BluetoothCrashResolver bluetoothCrashResolver) { this.mScanPeriod = j; this.mBetweenScanPeriod = j2; this.mContext = context; this.mCycledLeScanCallback = cycledLeScanCallback; this.mBluetoothCrashResolver = bluetoothCrashResolver; this.mBackgroundFlag = z; this.mScanThread = new HandlerThread("CycledLeScannerThread"); this.mScanThread.start(); this.mScanHandler = new Handler(this.mScanThread.getLooper()); } public static CycledLeScanner createScanner(Context context, long j, long j2, boolean z, CycledLeScanCallback cycledLeScanCallback, BluetoothCrashResolver bluetoothCrashResolver) { boolean z2 = false; if (Build.VERSION.SDK_INT < 18) { LogManager.w(TAG, "Not supported prior to API 18.", new Object[0]); return null; } boolean z3 = true; if (Build.VERSION.SDK_INT < 21) { LogManager.i(TAG, "This is pre Android 5.0. We are using old scanning APIs", new Object[0]); z3 = false; } else if (Build.VERSION.SDK_INT >= 26) { LogManager.i(TAG, "Using Android O scanner", new Object[0]); z2 = true; z3 = false; } else if (BeaconManager.isAndroidLScanningDisabled()) { LogManager.i(TAG, "This is Android 5.0, but L scanning is disabled. We are using old scanning APIs", new Object[0]); z3 = false; } else { LogManager.i(TAG, "This is Android 5.0. We are using new scanning APIs", new Object[0]); } if (z2) { return new CycledLeScannerForAndroidO(context, j, j2, z, cycledLeScanCallback, bluetoothCrashResolver); } if (z3) { return new CycledLeScannerForLollipop(context, j, j2, z, cycledLeScanCallback, bluetoothCrashResolver); } return new CycledLeScannerForJellyBeanMr2(context, j, j2, z, cycledLeScanCallback, bluetoothCrashResolver); } public void setLongScanForcingEnabled(boolean z) { this.mLongScanForcingEnabled = z; } @MainThread public void setScanPeriods(long j, long j2, boolean z) { LogManager.d(TAG, "Set scan periods called with %s, %s Background mode must have changed.", Long.valueOf(j), Long.valueOf(j2)); if (this.mBackgroundFlag != z) { this.mRestartNeeded = true; } this.mBackgroundFlag = z; this.mScanPeriod = j; this.mBetweenScanPeriod = j2; if (this.mBackgroundFlag) { LogManager.d(TAG, "We are in the background. Setting wakeup alarm", new Object[0]); setWakeUpAlarm(); } else { LogManager.d(TAG, "We are not in the background. Cancelling wakeup alarm", new Object[0]); cancelWakeUpAlarm(); } long elapsedRealtime = SystemClock.elapsedRealtime(); long j3 = this.mNextScanCycleStartTime; if (j3 > elapsedRealtime) { long j4 = this.mLastScanCycleEndTime + j2; if (j4 < j3) { this.mNextScanCycleStartTime = j4; LogManager.i(TAG, "Adjusted nextScanStartTime to be %s", new Date((this.mNextScanCycleStartTime - SystemClock.elapsedRealtime()) + System.currentTimeMillis())); } } long j5 = this.mScanCycleStopTime; if (j5 > elapsedRealtime) { long j6 = this.mLastScanCycleStartTime + j; if (j6 < j5) { this.mScanCycleStopTime = j6; LogManager.i(TAG, "Adjusted scanStopTime to be %s", Long.valueOf(this.mScanCycleStopTime)); } } } @MainThread public void start() { LogManager.d(TAG, "start called", new Object[0]); this.mScanningEnabled = true; if (!this.mScanCyclerStarted) { scanLeDevice(true); } else { LogManager.d(TAG, "scanning already started", new Object[0]); } } @MainThread public void stop() { LogManager.d(TAG, "stop called", new Object[0]); this.mScanningEnabled = false; if (this.mScanCyclerStarted) { scanLeDevice(false); if (this.mScanningLeftOn) { LogManager.d(TAG, "Stopping scanning previously left on.", new Object[0]); this.mScanningLeftOn = false; try { LogManager.d(TAG, "stopping bluetooth le scan", new Object[0]); finishScan(); } catch (Exception e) { LogManager.w(e, TAG, "Internal Android exception scanning for beacons", new Object[0]); } } } else { LogManager.d(TAG, "scanning already stopped", new Object[0]); } } @AnyThread public boolean getDistinctPacketsDetectedPerScan() { return this.mDistinctPacketsDetectedPerScan; } @AnyThread public void setDistinctPacketsDetectedPerScan(boolean z) { this.mDistinctPacketsDetectedPerScan = z; } @MainThread public void destroy() { LogManager.d(TAG, "Destroying", new Object[0]); this.mHandler.removeCallbacksAndMessages(null); this.mScanHandler.post(new Runnable() { /* class org.altbeacon.beacon.service.scanner.CycledLeScanner.AnonymousClass1 */ @WorkerThread public void run() { LogManager.d(CycledLeScanner.TAG, "Quitting scan thread", new Object[0]); CycledLeScanner.this.mScanThread.quit(); } }); } /* access modifiers changed from: protected */ @MainThread public void scanLeDevice(Boolean bool) { try { this.mScanCyclerStarted = true; if (getBluetoothAdapter() == null) { LogManager.e(TAG, "No Bluetooth adapter. beaconService cannot scan.", new Object[0]); } if (!this.mScanningEnabled || !bool.booleanValue()) { LogManager.d(TAG, "disabling scan", new Object[0]); this.mScanning = false; this.mScanCyclerStarted = false; stopScan(); this.mCurrentScanStartTime = 0; this.mLastScanCycleEndTime = SystemClock.elapsedRealtime(); this.mHandler.removeCallbacksAndMessages(null); finishScanCycle(); } else if (!deferScanIfNeeded()) { LogManager.d(TAG, "starting a new scan cycle", new Object[0]); if (this.mScanning && !this.mScanningPaused) { if (!this.mRestartNeeded) { LogManager.d(TAG, "We are already scanning and have been for " + (SystemClock.elapsedRealtime() - this.mCurrentScanStartTime) + " millis", new Object[0]); this.mScanCycleStopTime = SystemClock.elapsedRealtime() + this.mScanPeriod; scheduleScanCycleStop(); LogManager.d(TAG, "Scan started", new Object[0]); } } this.mScanning = true; this.mScanningPaused = false; try { if (getBluetoothAdapter() != null) { if (getBluetoothAdapter().isEnabled()) { if (this.mBluetoothCrashResolver != null && this.mBluetoothCrashResolver.isRecoveryInProgress()) { LogManager.w(TAG, "Skipping scan because crash recovery is in progress.", new Object[0]); } else if (this.mScanningEnabled) { if (this.mRestartNeeded) { this.mRestartNeeded = false; LogManager.d(TAG, "restarting a bluetooth le scan", new Object[0]); } else { LogManager.d(TAG, "starting a new bluetooth le scan", new Object[0]); } try { if (Build.VERSION.SDK_INT < 23 || checkLocationPermission()) { this.mCurrentScanStartTime = SystemClock.elapsedRealtime(); startScan(); } } catch (Exception e) { LogManager.e(e, TAG, "Internal Android exception scanning for beacons", new Object[0]); } } else { LogManager.d(TAG, "Scanning unnecessary - no monitoring or ranging active.", new Object[0]); } this.mLastScanCycleStartTime = SystemClock.elapsedRealtime(); } else { LogManager.d(TAG, "Bluetooth is disabled. Cannot scan for beacons.", new Object[0]); } } } catch (Exception e2) { LogManager.e(e2, TAG, "Exception starting Bluetooth scan. Perhaps Bluetooth is disabled or unavailable?", new Object[0]); } this.mScanCycleStopTime = SystemClock.elapsedRealtime() + this.mScanPeriod; scheduleScanCycleStop(); LogManager.d(TAG, "Scan started", new Object[0]); } } catch (SecurityException unused) { LogManager.w(TAG, "SecurityException working accessing bluetooth.", new Object[0]); } } /* access modifiers changed from: protected */ @MainThread public void scheduleScanCycleStop() { long elapsedRealtime = this.mScanCycleStopTime - SystemClock.elapsedRealtime(); if (!this.mScanningEnabled || elapsedRealtime <= 0) { finishScanCycle(); return; } LogManager.d(TAG, "Waiting to stop scan cycle for another %s milliseconds", Long.valueOf(elapsedRealtime)); if (this.mBackgroundFlag) { setWakeUpAlarm(); } Handler handler = this.mHandler; AnonymousClass2 r3 = new Runnable() { /* class org.altbeacon.beacon.service.scanner.CycledLeScanner.AnonymousClass2 */ @MainThread public void run() { CycledLeScanner.this.scheduleScanCycleStop(); } }; if (elapsedRealtime > 1000) { elapsedRealtime = 1000; } handler.postDelayed(r3, elapsedRealtime); } @MainThread private void finishScanCycle() { LogManager.d(TAG, "Done with scan cycle", new Object[0]); try { this.mCycledLeScanCallback.onCycleEnd(); if (this.mScanning) { if (getBluetoothAdapter() != null) { if (getBluetoothAdapter().isEnabled()) { if (this.mDistinctPacketsDetectedPerScan && this.mBetweenScanPeriod == 0) { if (!mustStopScanToPreventAndroidNScanTimeout()) { LogManager.d(TAG, "Not stopping scanning. Device capable of multiple indistinct detections per scan.", new Object[0]); this.mScanningLeftOn = true; this.mLastScanCycleEndTime = SystemClock.elapsedRealtime(); } } long elapsedRealtime = SystemClock.elapsedRealtime(); if (Build.VERSION.SDK_INT < 24 || this.mBetweenScanPeriod + this.mScanPeriod >= ANDROID_N_MIN_SCAN_CYCLE_MILLIS || elapsedRealtime - this.mLastScanCycleStartTime >= ANDROID_N_MIN_SCAN_CYCLE_MILLIS) { try { LogManager.d(TAG, "stopping bluetooth le scan", new Object[0]); finishScan(); this.mScanningLeftOn = false; } catch (Exception e) { LogManager.w(e, TAG, "Internal Android exception scanning for beacons", new Object[0]); } this.mLastScanCycleEndTime = SystemClock.elapsedRealtime(); } else { LogManager.d(TAG, "Not stopping scan because this is Android N and we keep scanning for a minimum of 6 seconds at a time. We will stop in " + (ANDROID_N_MIN_SCAN_CYCLE_MILLIS - (elapsedRealtime - this.mLastScanCycleStartTime)) + " millisconds.", new Object[0]); this.mScanningLeftOn = true; this.mLastScanCycleEndTime = SystemClock.elapsedRealtime(); } } else { LogManager.d(TAG, "Bluetooth is disabled. Cannot scan for beacons.", new Object[0]); this.mRestartNeeded = true; } } this.mNextScanCycleStartTime = getNextScanStartTime(); if (this.mScanningEnabled) { scanLeDevice(true); } } if (!this.mScanningEnabled) { LogManager.d(TAG, "Scanning disabled. ", new Object[0]); this.mScanCyclerStarted = false; cancelWakeUpAlarm(); } } catch (SecurityException unused) { LogManager.w(TAG, "SecurityException working accessing bluetooth.", new Object[0]); } } /* access modifiers changed from: protected */ public BluetoothAdapter getBluetoothAdapter() { try { if (this.mBluetoothAdapter == null) { this.mBluetoothAdapter = ((BluetoothManager) this.mContext.getApplicationContext().getSystemService("bluetooth")).getAdapter(); if (this.mBluetoothAdapter == null) { LogManager.w(TAG, "Failed to construct a BluetoothAdapter", new Object[0]); } } } catch (SecurityException unused) { LogManager.e(TAG, "Cannot consruct bluetooth adapter. Security Exception", new Object[0]); } return this.mBluetoothAdapter; } /* access modifiers changed from: protected */ public void setWakeUpAlarm() { long j = this.mBetweenScanPeriod; if (BeaconManager.DEFAULT_BACKGROUND_BETWEEN_SCAN_PERIOD >= j) { j = 300000; } long j2 = this.mScanPeriod; if (j < j2) { j = j2; } ((AlarmManager) this.mContext.getSystemService(NotificationCompat.CATEGORY_ALARM)).set(2, SystemClock.elapsedRealtime() + j, getWakeUpOperation()); LogManager.d(TAG, "Set a wakeup alarm to go off in %s ms: %s", Long.valueOf(j), getWakeUpOperation()); } /* access modifiers changed from: protected */ public PendingIntent getWakeUpOperation() { if (this.mWakeUpOperation == null) { Intent intent = new Intent(this.mContext, StartupBroadcastReceiver.class); intent.putExtra(Analysis.Item.TYPE_WAKEUP, true); this.mWakeUpOperation = PendingIntent.getBroadcast(this.mContext, 0, intent, 134217728); } return this.mWakeUpOperation; } /* access modifiers changed from: protected */ public void cancelWakeUpAlarm() { LogManager.d(TAG, "cancel wakeup alarm: %s", this.mWakeUpOperation); ((AlarmManager) this.mContext.getSystemService(NotificationCompat.CATEGORY_ALARM)).set(2, Long.MAX_VALUE, getWakeUpOperation()); LogManager.d(TAG, "Set a wakeup alarm to go off in %s ms: %s", Long.valueOf(Long.MAX_VALUE - SystemClock.elapsedRealtime()), getWakeUpOperation()); } private long getNextScanStartTime() { long j = this.mBetweenScanPeriod; if (j == 0) { return SystemClock.elapsedRealtime(); } long elapsedRealtime = j - (SystemClock.elapsedRealtime() % (this.mScanPeriod + j)); LogManager.d(TAG, "Normalizing between scan period from %s to %s", Long.valueOf(this.mBetweenScanPeriod), Long.valueOf(elapsedRealtime)); return SystemClock.elapsedRealtime() + elapsedRealtime; } private boolean checkLocationPermission() { return checkPermission("android.permission.ACCESS_COARSE_LOCATION") || checkPermission("android.permission.ACCESS_FINE_LOCATION"); } private boolean checkPermission(String str) { return this.mContext.checkPermission(str, Process.myPid(), Process.myUid()) == 0; } /* JADX WARNING: Removed duplicated region for block: B:9:0x0027 */ private boolean mustStopScanToPreventAndroidNScanTimeout() { boolean z; long elapsedRealtime = SystemClock.elapsedRealtime() + this.mBetweenScanPeriod + this.mScanPeriod; if (Build.VERSION.SDK_INT >= 24) { long j = this.mCurrentScanStartTime; if (j > 0 && elapsedRealtime - j > ANDROID_N_MAX_SCAN_DURATION_MILLIS) { z = true; if (z) { LogManager.d(TAG, "The next scan cycle would go over the Android N max duration.", new Object[0]); if (this.mLongScanForcingEnabled) { LogManager.d(TAG, "Stopping scan to prevent Android N scan timeout.", new Object[0]); return true; } LogManager.w(TAG, "Allowing a long running scan to be stopped by the OS. To prevent this, set longScanForcingEnabled in the AndroidBeaconLibrary.", new Object[0]); } return false; } } z = false; if (z) { } return false; } }