Skip to content

Commit

Permalink
Catch SecurityExceptions caused by Samsung Knox
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgyoung committed Oct 20, 2016
1 parent 158ac20 commit 846980a
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 94 deletions.
190 changes: 103 additions & 87 deletions src/main/java/org/altbeacon/beacon/service/scanner/CycledLeScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
}
}

Expand Down Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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");
}

}
});
}
Expand All @@ -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;
}

Expand Down

0 comments on commit 846980a

Please sign in to comment.