From 846980a037236ceaceb538482fe29db6e9d283d1 Mon Sep 17 00:00:00 2001 From: "David G. Young" Date: Thu, 20 Oct 2016 10:10:08 -0400 Subject: [PATCH] Catch SecurityExceptions caused by Samsung Knox --- .../service/scanner/CycledLeScanner.java | 190 ++++++++++-------- .../scanner/CycledLeScannerForLollipop.java | 28 ++- 2 files changed, 124 insertions(+), 94 deletions(-) diff --git a/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScanner.java b/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScanner.java index 57fc004e2..4d370d55e 100644 --- a/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScanner.java +++ b/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScanner.java @@ -177,63 +177,68 @@ public void destroy() { @SuppressLint("NewApi") protected void scanLeDevice(final Boolean enable) { - mScanCyclerStarted = true; - if (getBluetoothAdapter() == null) { - LogManager.e(TAG, "No Bluetooth adapter. beaconService cannot scan."); - } - if (enable) { - if (deferScanIfNeeded()) { - return; + try { + mScanCyclerStarted = true; + if (getBluetoothAdapter() == null) { + LogManager.e(TAG, "No Bluetooth adapter. beaconService cannot scan."); } - LogManager.d(TAG, "starting a new scan cycle"); - if (!mScanning || mScanningPaused || mRestartNeeded) { - mScanning = true; - mScanningPaused = false; - try { - if (getBluetoothAdapter() != null) { - if (getBluetoothAdapter().isEnabled()) { - if (mBluetoothCrashResolver != null && mBluetoothCrashResolver.isRecoveryInProgress()) { - LogManager.w(TAG, "Skipping scan because crash recovery is in progress."); - } else { - if (mScanningEnabled) { - if (mRestartNeeded) { - mRestartNeeded = false; - LogManager.d(TAG, "restarting a bluetooth le scan"); - } else { - LogManager.d(TAG, "starting a new bluetooth le scan"); - } - try { - if (android.os.Build.VERSION.SDK_INT < 23 || checkLocationPermission()) { - startScan(); + if (enable) { + if (deferScanIfNeeded()) { + return; + } + LogManager.d(TAG, "starting a new scan cycle"); + if (!mScanning || mScanningPaused || mRestartNeeded) { + mScanning = true; + mScanningPaused = false; + try { + if (getBluetoothAdapter() != null) { + if (getBluetoothAdapter().isEnabled()) { + if (mBluetoothCrashResolver != null && mBluetoothCrashResolver.isRecoveryInProgress()) { + LogManager.w(TAG, "Skipping scan because crash recovery is in progress."); + } else { + if (mScanningEnabled) { + if (mRestartNeeded) { + mRestartNeeded = false; + LogManager.d(TAG, "restarting a bluetooth le scan"); + } else { + LogManager.d(TAG, "starting a new bluetooth le scan"); + } + try { + if (android.os.Build.VERSION.SDK_INT < 23 || checkLocationPermission()) { + startScan(); + } + } catch (Exception e) { + LogManager.e(e, TAG, "Internal Android exception scanning for beacons"); } - } catch (Exception e) { - LogManager.e(e, TAG, "Internal Android exception scanning for beacons"); + } else { + LogManager.d(TAG, "Scanning unnecessary - no monitoring or ranging active."); } - } else { - LogManager.d(TAG, "Scanning unnecessary - no monitoring or ranging active."); } + mLastScanCycleStartTime = SystemClock.elapsedRealtime(); + } else { + LogManager.d(TAG, "Bluetooth is disabled. Cannot scan for beacons."); } - mLastScanCycleStartTime = SystemClock.elapsedRealtime(); - } else { - LogManager.d(TAG, "Bluetooth is disabled. Cannot scan for beacons."); } + } catch (Exception e) { + LogManager.e(e, TAG, "Exception starting Bluetooth scan. Perhaps Bluetooth is disabled or unavailable?"); } - } catch (Exception e) { - LogManager.e(e, TAG, "Exception starting Bluetooth scan. Perhaps Bluetooth is disabled or unavailable?"); + } else { + LogManager.d(TAG, "We are already scanning"); } + mScanCycleStopTime = (SystemClock.elapsedRealtime() + mScanPeriod); + scheduleScanCycleStop(); + + LogManager.d(TAG, "Scan started"); } else { - LogManager.d(TAG, "We are already scanning"); + LogManager.d(TAG, "disabling scan"); + mScanning = false; + mScanCyclerStarted = false; + stopScan(); + mLastScanCycleEndTime = SystemClock.elapsedRealtime(); } - mScanCycleStopTime = (SystemClock.elapsedRealtime() + mScanPeriod); - scheduleScanCycleStop(); - - LogManager.d(TAG, "Scan started"); - } else { - LogManager.d(TAG, "disabling scan"); - mScanning = false; - mScanCyclerStarted = false; - stopScan(); - mLastScanCycleEndTime = SystemClock.elapsedRealtime(); + } + catch (SecurityException e) { + LogManager.w(TAG, "SecurityException working accessing bluetooth."); } } @@ -261,59 +266,70 @@ public void run() { private void finishScanCycle() { LogManager.d(TAG, "Done with scan cycle"); - mCycledLeScanCallback.onCycleEnd(); - if (mScanning) { - if (getBluetoothAdapter() != null) { - if (getBluetoothAdapter().isEnabled()) { - long now = System.currentTimeMillis(); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && - mBetweenScanPeriod+mScanPeriod < ANDROID_N_MIN_SCAN_CYCLE_MILLIS && - now-mLastScanStopTime < ANDROID_N_MIN_SCAN_CYCLE_MILLIS) { - // As of Android N, only 5 scans may be started in a 30 second period (6 - // seconds per cycle) otherwise they are blocked. So we check here to see - // if the scan period is 6 seconds or less, and if we last stopped scanning - // fewer than 6 seconds ag and if so, we simply do not stop scanning - 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-(now-mLastScanStopTime))+" millisconds."); - } - else { - try { - LogManager.d(TAG, "stopping bluetooth le scan"); - finishScan(); - mLastScanStopTime = now; - } catch (Exception e) { - LogManager.w(e, TAG, "Internal Android exception scanning for beacons"); + try { + mCycledLeScanCallback.onCycleEnd(); + if (mScanning) { + if (getBluetoothAdapter() != null) { + if (getBluetoothAdapter().isEnabled()) { + long now = System.currentTimeMillis(); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && + mBetweenScanPeriod+mScanPeriod < ANDROID_N_MIN_SCAN_CYCLE_MILLIS && + now-mLastScanStopTime < ANDROID_N_MIN_SCAN_CYCLE_MILLIS) { + // As of Android N, only 5 scans may be started in a 30 second period (6 + // seconds per cycle) otherwise they are blocked. So we check here to see + // if the scan period is 6 seconds or less, and if we last stopped scanning + // fewer than 6 seconds ag and if so, we simply do not stop scanning + 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-(now-mLastScanStopTime))+" millisconds."); + } + else { + try { + LogManager.d(TAG, "stopping bluetooth le scan"); + finishScan(); + mLastScanStopTime = now; + } catch (Exception e) { + LogManager.w(e, TAG, "Internal Android exception scanning for beacons"); + } } - } - mLastScanCycleEndTime = SystemClock.elapsedRealtime(); - } else { - LogManager.d(TAG, "Bluetooth is disabled. Cannot scan for beacons."); + mLastScanCycleEndTime = SystemClock.elapsedRealtime(); + } else { + LogManager.d(TAG, "Bluetooth is disabled. Cannot scan for beacons."); + } + } + mNextScanCycleStartTime = getNextScanStartTime(); + if (mScanningEnabled) { + scanLeDevice(true); } } - mNextScanCycleStartTime = getNextScanStartTime(); - if (mScanningEnabled) { - scanLeDevice(true); + if (!mScanningEnabled) { + LogManager.d(TAG, "Scanning disabled. No ranging or monitoring regions are active."); + mScanCyclerStarted = false; + cancelWakeUpAlarm(); } } - if (!mScanningEnabled) { - LogManager.d(TAG, "Scanning disabled. No ranging or monitoring regions are active."); - mScanCyclerStarted = false; - cancelWakeUpAlarm(); + catch (SecurityException e) { + LogManager.w(TAG, "SecurityException working accessing bluetooth."); } } protected BluetoothAdapter getBluetoothAdapter() { - if (mBluetoothAdapter == null) { - // Initializes Bluetooth adapter. - final BluetoothManager bluetoothManager = - (BluetoothManager) mContext.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE); - mBluetoothAdapter = bluetoothManager.getAdapter(); + try { if (mBluetoothAdapter == null) { - LogManager.w(TAG, "Failed to construct a BluetoothAdapter"); + // Initializes Bluetooth adapter. + final BluetoothManager bluetoothManager = + (BluetoothManager) mContext.getApplicationContext().getSystemService(Context.BLUETOOTH_SERVICE); + mBluetoothAdapter = bluetoothManager.getAdapter(); + if (mBluetoothAdapter == null) { + LogManager.w(TAG, "Failed to construct a BluetoothAdapter"); + } } } + catch (SecurityException e) { + // Thrown by Samsung Knox devices if bluetooth access denied for an app + LogManager.e(TAG, "Cannot consruct bluetooth adapter. Security Exception"); + } return mBluetoothAdapter; } diff --git a/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScannerForLollipop.java b/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScannerForLollipop.java index e5ac14d65..844133d33 100644 --- a/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScannerForLollipop.java +++ b/src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScannerForLollipop.java @@ -16,6 +16,7 @@ import org.altbeacon.beacon.service.DetectionTracker; import org.altbeacon.bluetooth.BluetoothCrashResolver; +import java.security.Security; import java.util.ArrayList; import java.util.List; @@ -194,7 +195,11 @@ public void run() { } catch (NullPointerException npe) { // Necessary because of https://code.google.com/p/android/issues/detail?id=160503 LogManager.e(TAG, "Cannot start scan. Unexpected NPE.", npe); + } catch (SecurityException e) { + // Thrown by Samsung Knox devices if bluetooth access denied for an app + LogManager.e(TAG, "Cannot start scan. Security Exception"); } + } }); } @@ -216,22 +221,31 @@ public void run() { } catch (NullPointerException npe) { // Necessary because of https://code.google.com/p/android/issues/detail?id=160503 LogManager.e(TAG, "Cannot stop scan. Unexpected NPE.", npe); + } catch (SecurityException e) { + // Thrown by Samsung Knox devices if bluetooth access denied for an app + LogManager.e(TAG, "Cannot stop scan. Security Exception"); } + } }); } private BluetoothLeScanner getScanner() { - if (mScanner == null) { - LogManager.d(TAG, "Making new Android L scanner"); - BluetoothAdapter bluetoothAdapter = getBluetoothAdapter(); - if (bluetoothAdapter != null) { - mScanner = getBluetoothAdapter().getBluetoothLeScanner(); - } + try { if (mScanner == null) { - LogManager.w(TAG, "Failed to make new Android L scanner"); + LogManager.d(TAG, "Making new Android L scanner"); + BluetoothAdapter bluetoothAdapter = getBluetoothAdapter(); + if (bluetoothAdapter != null) { + mScanner = getBluetoothAdapter().getBluetoothLeScanner(); + } + if (mScanner == null) { + LogManager.w(TAG, "Failed to make new Android L scanner"); + } } } + catch (SecurityException e) { + LogManager.w(TAG, "SecurityException making new Android L scanner"); + } return mScanner; }