question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

BluetoothLeScannerImplOreo startScan PendingIntent causes leak that eventually fails all future scans

See original GitHub issue

This problem might manifest itself with can't Register GATT client, MAX client reached: 32 output in an unfiltered log.

Please also refer to my StackOverflow question and self-answer: https://stackoverflow.com/q/57104535/252308

Basically, BluetoothLeScannerImplOreo startScanInternal has the following code (I added the log line in my fork):

        final PendingIntent pendingIntent = createStartingPendingIntent(nonNullFilters,
                nonNullSettings, context, callbackIntent);
        Log.v(TAG, "#GATT startScanInternal: pendingIntent=" + pendingIntent);
        return scanner.startScan(nativeFilters, nativeSettings, pendingIntent);

stopScanInternal has the following code (log line added in my fork):

        final PendingIntent pendingIntent = createStoppingPendingIntent(context, callbackIntent);
        Log.v(TAG, "#GATT stopScanInternal: pendingIntent=" + pendingIntent);
        scanner.stopScan(pendingIntent);

Here is a log of my app starting and stopping a few scans:

2019-07-19 21:14:51.230 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.startScan(...)
2019-07-19 21:14:58.424 16905-16905/com.testapp V/BleScannerImplOreo: #GATT startScanInternal: pendingIntent=PendingIntent{1dfc67: android.os.BinderProxy@e560a14}
2019-07-19 21:14:58.468 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 3c2e1fd9-d3fd-6897-a113-863aa50df781
2019-07-19 21:14:58.468 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=7
2019-07-19 21:14:58.478 16905-16905/com.testapp V/BleScannerManager: scan: #GATT bleScanner.startScan(...); result=SUCCESS(0)
2019-07-19 21:14:58.479 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.startScan(...)
2019-07-19 21:14:58.481 16905-16905/com.testapp E/BleScannerManager: #GATT bleScannerStartScanCount=1, elapsedMillisSinceBleScannerStartScanFirstTime=0
2019-07-19 21:15:03.521 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614650173
2019-07-19 21:15:08.250 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.stopScan(...)
2019-07-19 21:15:08.255 16905-16905/com.testapp V/BleScannerImplOreo: #GATT stopScanInternal: pendingIntent=PendingIntent{dc4115f: android.os.BinderProxy@84087ac}
2019-07-19 21:15:08.259 1447-1982/? E/BtGatt.ContextMap: Context not found for info com.android.bluetooth.gatt.GattService$PendingIntentInfo@77d2d25
2019-07-19 21:15:08.260 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.stopScan(...)
2019-07-19 21:15:08.556 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614655208
2019-07-19 21:15:08.570 1447-1554/? E/BtGatt.GattService: Exception: android.app.PendingIntent$CanceledException
2019-07-19 21:15:20.556 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.startScan(...)
2019-07-19 21:15:20.570 16905-16905/com.testapp V/BleScannerImplOreo: #GATT startScanInternal: pendingIntent=PendingIntent{2ce86d6: android.os.BinderProxy@84087ac}
2019-07-19 21:15:20.575 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 6b444e39-d61a-1d92-52d6-afd6e901b56b
2019-07-19 21:15:20.575 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=8
2019-07-19 21:15:20.576 16905-16905/com.testapp V/BleScannerManager: scan: #GATT bleScanner.startScan(...); result=SUCCESS(0)
2019-07-19 21:15:20.576 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.startScan(...)
2019-07-19 21:15:20.576 16905-16905/com.testapp E/BleScannerManager: #GATT bleScannerStartScanCount=2, elapsedMillisSinceBleScannerStartScanFirstTime=22097
2019-07-19 21:15:23.264 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.stopScan(...)
2019-07-19 21:15:23.269 16905-16905/com.testapp V/BleScannerImplOreo: #GATT stopScanInternal: pendingIntent=PendingIntent{ebafcb0: android.os.BinderProxy@ebb6729}
2019-07-19 21:15:23.272 1447-1982/? E/BtGatt.ContextMap: Context not found for info com.android.bluetooth.gatt.GattService$PendingIntentInfo@3abaefa
2019-07-19 21:15:23.272 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.stopScan(...)
2019-07-19 21:15:24.968 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.startScan(...)
2019-07-19 21:15:24.980 16905-16905/com.testapp V/BleScannerImplOreo: #GATT startScanInternal: pendingIntent=PendingIntent{8b1626b: android.os.BinderProxy@ebb6729}
2019-07-19 21:15:24.990 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 0bbb0b8f-2c63-dfc2-268d-fbfe39360ddf
2019-07-19 21:15:24.990 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=9
2019-07-19 21:15:24.990 16905-16905/com.testapp V/BleScannerManager: scan: #GATT bleScanner.startScan(...); result=SUCCESS(0)
2019-07-19 21:15:24.990 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.startScan(...)
2019-07-19 21:15:24.991 16905-16905/com.testapp E/BleScannerManager: #GATT bleScannerStartScanCount=3, elapsedMillisSinceBleScannerStartScanFirstTime=26511
2019-07-19 21:15:25.019 1447-1554/? E/BtGatt.GattService: Exception: android.app.PendingIntent$CanceledException
2019-07-19 21:15:25.795 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register 32a50296-06f2-ed4d-f83c-25da059a4a19
2019-07-19 21:15:25.795 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=10
2019-07-19 21:15:26.046 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614672699
2019-07-19 21:15:27.000 16905-16905/com.testapp V/BleScannerManager: scan: #GATT +bleScanner.stopScan(...)
2019-07-19 21:15:27.005 16905-16905/com.testapp V/BleScannerImplOreo: #GATT stopScanInternal: pendingIntent=PendingIntent{40e339d: android.os.BinderProxy@6340012}
2019-07-19 21:15:27.008 1447-1982/? E/BtGatt.ContextMap: Context not found for info com.android.bluetooth.gatt.GattService$PendingIntentInfo@96b43b4
2019-07-19 21:15:27.009 16905-16905/com.testapp V/BleScannerManager: scan: #GATT -bleScanner.stopScan(...)
2019-07-19 21:15:28.679 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(948)] GATT_Register f119757a-00ff-29b4-72e0-952c5e0db695
2019-07-19 21:15:28.679 1447-1941/? I/bt_stack: [INFO:gatt_api.cc(968)] allocated gatt_if=10
2019-07-19 21:15:28.810 1447-1447/? D/BtGatt.ScanManager: awakened up at time 614675462
2019-07-19 21:15:28.822 1447-1554/? E/BtGatt.GattService: Exception: android.app.PendingIntent$CanceledException

Notice that the pendingIntent= logged during a startScan and stopScan do not match. This means that the code never actually stops any PendingIntent started scans. The pendingIndent passed to stopScan must be the exact same one that was passed to startScan.

You can usually only start about 28, max of 32, scans before the OS blocks all future scans. This repros on every API >= 26 phone I have tried.

I can look in to a fix and send a PR, but I wanted to open this issue to see if there is anything else to discuss.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:14 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
pc-bszabocommented, Jun 4, 2021

The problem is not resolved, with 1.4.1! The “listent” PendingIntent is not broadcasted anymore, that’s true, but the Bluetooth internal scanning is still not stopped, here is the proof :" BtGatt.ScanManager: awakened up at time". Test device : Pixel2 with Android 10

Problem found : BluetoothLeScannerImplOreo -> createStartingPendingIntent(…) and createStoppingPendingIntent(…) in both methods this line of code breaks the normal flow :

  final int id = callbackIntent.hashCode();

In this way the started pendingIntent hashCode() will be different than the stop pendingIntent hashCode()!! this is bad! it’s a bug, cause the doc clarifies that the two intents must be the same, and in this library case are totally different.

Solution : Add “requestCode” as an extra argument to createStartingPendingIntent(..., @NonNull final int requestCode) and createStoppingPendingIntent(..., @NonNull final int requestCode) methods, and use that for id.

  final int id = requestCode; //callbackIntent.hashCode();

And yes, the requestCode must be the same for start and stop.

0reactions
philips77commented, Jun 4, 2021

The time has come, I started looking into this issue now. Just after releasing 1.4.4… 😦

Read more comments on GitHub >

github_iconTop Results From Across the Web

Android BluetoothLeScanner startScan PendingIntent fails ...
I would like to not have this leak in the first place and be able to indefinitely stop and start the scanning every...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found