AltBeacon/android-beacon-library

stopRanging fails if Bluetooth disabled

davidgyoung opened this issue · 1 comments

Expected behavior

Library ranging stops when commanded, even with Bluetooth OFF

Actual behavior

Ranging continues

Steps to reproduce this behavior

Reproducible with reference app per davidgyoung/android-beacon-library-reference-kotlin#3

  1. Start Ranging
  2. Disable Bluetooth in Quick Settings
  3. Stop Ranging
  4. Observe that logs say ranging continues even though no results are delivered.

Mobile device model and OS version

Pixel 4a and Android 13 and probably earlier OS versions

Android Beacon Library version

2.19.6

Here is the correct log sequence with Bluetooth ON:

2023-07-01 15:03:50.470 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  API stopRangingBeacons id1: null id2: null id3: null
2023-07-01 15:03:50.470 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  stopRangingBeacons
2023-07-01 15:03:50.470 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  API stopRangingBeacons id1: null id2: null id3: null
2023-07-01 15:03:50.470 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  stopRangingBeaconsInRegion
2023-07-01 15:03:50.470 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  callback packageName: org.altbeacon.beaconreference
2023-07-01 15:03:50.470 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  Unbinding
2023-07-01 15:03:50.472 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  Before unbind, consumer count is 1
2023-07-01 15:03:50.472 19833-19833 BeaconManager           org.altbeacon.beaconreference        D  After unbind, consumer count is 0
2023-07-01 15:03:50.473 19833-19833 BeaconService           org.altbeacon.beaconreference        I  stop ranging received
2023-07-01 15:03:50.474 19833-19833 BeaconService           org.altbeacon.beaconreference        D  Currently ranging 0 regions.
2023-07-01 15:03:50.474 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  stop called
2023-07-01 15:03:50.474 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  disabling scan
2023-07-01 15:03:50.474 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  Done with scan cycle
2023-07-01 15:03:50.474 19833-19833 ScanHelper              org.altbeacon.beaconreference        D  Beacon simulator not enabled
2023-07-01 15:03:50.474 19833-19884 CycledLeSc...orLollipop org.altbeacon.beaconreference        D  Stopping LE scan on scan handler
2023-07-01 15:03:50.474 19833-19884 BluetoothAdapter        org.altbeacon.beaconreference        D  isLeEnabled(): ON
2023-07-01 15:03:50.474 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  Scanning disabled. 
2023-07-01 15:03:50.474 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  cancel wakeup alarm: PendingIntent{9f2b857: android.os.BinderProxy@acd2f44}
2023-07-01 15:03:50.475 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  Set a wakeup alarm to go off in 9223372036853901366 ms: PendingIntent{9f2b857: android.os.BinderProxy@acd2f44}
2023-07-01 15:03:50.475 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  Stopping scanning previously left on.
2023-07-01 15:03:50.475 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  stopping bluetooth le scan
2023-07-01 15:03:50.475 19833-19833 CycledLeSc...orLollipop org.altbeacon.beaconreference        D  Stopping scan
2023-07-01 15:03:50.475 19833-19833 CycledLeSc...orLollipop org.altbeacon.beaconreference        D  unregistering SamsungScreenOffReceiver as we stop the cycled scanner
2023-07-01 15:03:50.476 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  Set scan periods called with 1100, 0 Background mode must have changed.
2023-07-01 15:03:50.476 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  We are not in the background.  Cancelling wakeup alarm
2023-07-01 15:03:50.476 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  cancel wakeup alarm: PendingIntent{9f2b857: android.os.BinderProxy@acd2f44}
2023-07-01 15:03:50.476 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  Set a wakeup alarm to go off in 9223372036853901365 ms: PendingIntent{9f2b857: android.os.BinderProxy@acd2f44}
2023-07-01 15:03:50.476 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        I  Adjusted scanStopTime to be 865645
2023-07-01 15:03:50.477 19833-19833 BeaconService           org.altbeacon.beaconreference        I  unbinding so destroying self
2023-07-01 15:03:50.479 19833-19884 CycledLeSc...orLollipop org.altbeacon.beaconreference        D  Stopping LE scan on scan handler
2023-07-01 15:03:50.479 19833-19884 BluetoothAdapter        org.altbeacon.beaconreference        D  isLeEnabled(): ON
2023-07-01 15:03:50.479 19833-19884 BluetoothLeScanner      org.altbeacon.beaconreference        D  could not find callback wrapper
2023-07-01 15:03:50.490 19833-19833 CycledLeSc...orLollipop org.altbeacon.beaconreference        D  got record
2023-07-01 15:03:50.490 19833-19894 ScanHelper              org.altbeacon.beaconreference        D  Processing packet
2023-07-01 15:03:50.490 19833-19833 BeaconService           org.altbeacon.beaconreference        E  onDestroy()
2023-07-01 15:03:50.490 19833-19833 BeaconService           org.altbeacon.beaconreference        I  onDestroy called.  stopping scanning
2023-07-01 15:03:50.490 19833-19894 ScanHelper              org.altbeacon.beaconreference        D  Decoding beacon. First parser layout: m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24
2023-07-01 15:03:50.490 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  stop called
2023-07-01 15:03:50.490 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  scanning already stopped
2023-07-01 15:03:50.490 19833-19833 CycledLeSc...orLollipop org.altbeacon.beaconreference        D  unregistering SamsungScreenOffReceiver as we stop the cycled scanner
2023-07-01 15:03:50.490 19833-19894 BeaconParser            org.altbeacon.beaconreference        D  Ignoring pdu type 01
2023-07-01 15:03:50.490 19833-19833 CycledLeScanner         org.altbeacon.beaconreference        D  Destroying
2023-07-01 15:03:50.490 19833-19894 BeaconParser            org.altbeacon.beaconreference        D  Ignoring pdu type 0A
2023-07-01 15:03:50.490 19833-19894 BeaconParser            org.altbeacon.beaconreference        D  Processing pdu type FF: 02011a020a070cff4c0010077c1fba601ffa0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000 with startIndex: 8, endIndex: 18
2023-07-01 15:03:50.490 19833-19894 BeaconParser            org.altbeacon.beaconreference        D  This is not a matching Beacon advertisement. (Was expecting 02 15.  The bytes I see are: 02011a020a070cff4c0010077c1fba601ffa0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2023-07-01 15:03:50.490 19833-19884 CycledLeScanner         org.altbeacon.beaconreference        D  Quitting scan thread

Here is the failure with Bluetooth OFF:

023-07-01 15:12:55.478 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  API stopRangingBeacons id1: null id2: null id3: null
2023-07-01 15:12:55.478 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  stopRangingBeacons
2023-07-01 15:12:55.478 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  API stopRangingBeacons id1: null id2: null id3: null
2023-07-01 15:12:55.478 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  stopRangingBeaconsInRegion
2023-07-01 15:12:55.479 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  callback packageName: org.altbeacon.beaconreference
2023-07-01 15:12:55.484 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  Unbinding
2023-07-01 15:12:55.484 24559-24648 ScanHelper              org.altbeacon.beaconreference        D  looking for ranging region matches for this beacon
2023-07-01 15:12:55.484 24559-24648 ScanHelper              org.altbeacon.beaconreference        D  matches ranging region: id1: null id2: null id3: null
2023-07-01 15:12:55.484 24559-24648 RangeState              org.altbeacon.beaconreference        D  adding id1: 2f234454-cf6d-4a0f-adf2-f4911ba9ffa6 id2: 1 id3: 1 to existing range for: org.altbeacon.beacon.service.RangedBeacon@5c71f40
2023-07-01 15:12:55.488 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  Before unbind, consumer count is 1
2023-07-01 15:12:55.488 24559-24559 BeaconManager           org.altbeacon.beaconreference        D  After unbind, consumer count is 0
2023-07-01 15:12:55.490 24559-24559 BeaconService           org.altbeacon.beaconreference        I  stop ranging received
2023-07-01 15:12:55.490 24559-24559 BeaconService           org.altbeacon.beaconreference        D  Currently ranging 0 regions.
2023-07-01 15:12:55.490 24559-24559 CycledLeScanner         org.altbeacon.beaconreference        D  stop called
2023-07-01 15:12:55.490 24559-24559 CycledLeScanner         org.altbeacon.beaconreference        D  disabling scan
2023-07-01 15:12:55.490 24559-24559 CycledLeSc...orLollipop org.altbeacon.beaconreference        D  Not stopping scan because bluetooth is off

The fundamental problem here is that Android's BluetoothAdapter#getState() method returns BluetoothAdapter.STATE_OFF even though scans are allowed and continue.

On Android 9+ if you turn off Bluetooth in quick settings, any scans the library already started continue to return results. The library can programmatically stop them, but a programmatic guard on checking if Bluetooth is on before stopping prevents that.

The solution is to ignore this setting on Android 9+ and just start/stop scans anyway. With this change, scans will always be stopped when we stop ranging and monitoring.

Note that this doesn't mean the library can start NEW scans if Bluetooth is off in quick settings. Based on tests with Android 13 and a Pixel 4a, only pre-existing scans continue -- new scans from 3rd party apps are not allowed to start and show a SecurityException in the logs (although this is not bubbled up to the app and does not cause it to crash.)