-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BluetoothLeScannerImplOreo startScan PendingIntent causes leak that eventually fails all future scans #58
Comments
Thanks for the report. Although, it's weird, as I remember checking, that Android uses |
@philips77 that may be true, and is what I read and thought myself, but only when using this library, when stopScan(PendingIntent) is called after startScan(PendingIntent), there are symptoms that the scanning is still occurring, the two biggest being:
FYI, my repro project here is: If I tweak the code to not use this library, and use direct calls to the android API, there is no "leak". I will continue to look in to this myself, including if the .equals is supposed to work and isn't for some reason. Thanks for looking in to this. |
Just starting to look back in to this. final PendingIntent pendingIntent = createStartingPendingIntent(nonNullFilters,
nonNullSettings, context, callbackIntent);
Log.v(TAG, "#GATT startScanInternal: pendingIntent=" + pendingIntent);
final PendingIntent tempPendingIntentStop = createStoppingPendingIntent(context, callbackIntent);
Log.v(TAG, "#GATT startScanInternal: tempPendingIntentStop=" + pendingIntent);
boolean pendingIntentsEqual = pendingIntent.equals(tempPendingIntentStop);
Log.v(TAG, "#GATT startScanInternal: pendingIntentsEqual=" + pendingIntentsEqual); The log output is:
This definitely needs an androidTest backing it. :/ |
I might have done that wrong. It is not the PendingIntents that need to equal, it seems to be that it is the underlying Intents themselves, evaluated via https://developer.android.com/reference/android/content/Intent.html#filterEquals(android.content.Intent). |
They do equal:
|
I believe I found the problem. In Oreo's |
Fix released in 1.4.1. |
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". Problem found :
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 :
And yes, the requestCode must be the same for start and stop. |
Thanks @pc-bszabo As a semi-unrelated but semi-related problem, it is also possible to entirely orphan a background PendingIntent scan by having one active and then killing the process (either intentionally or unintentionally, including updating while debugging), then the scan will automatically re-start the process and you will be unable to stop it even with direct calls to the OS API using the same requestCode. The OS API underneath seems to not be able to find any matching PendingIntent to cancel and stopping the PendingIntent just results in a no-op. To detect this state I persist the started scan's process id (PID) to SharedPreferences and clear it when the scan is stopped; on every onReceived the started PID saved to SharedPreferences is checked with the current PID, and if they do not match then I know this onReceived is from a newly started process that will be unable to stop the scan; the app may then choose to notify the user with a pseudo-friendly message/notification of their choice (something along the lines of "Your phone's Bluetooth is unstable; please turn Bluetooth off and back on, or reboot your phone".) |
Hi, I just want to chime in that I encountered this issue several months ago. I haven't caught up on the entirety of this conversation but I found that Since my app has only one background scan, I ended up forking this library and just manually passing "0" as the request code. You can see that commit here: barkinglabs@a923b70 That's the version of the library I'm currently using but I would love to see this issue fixed upstream and be able to kill my fork! |
In the release notes for version 1.4.1 it says that this issue is fixed. However, I've just tried reproducing the issue on the latest version of the library (1.4.3) and I've confirmed that the issue is still there. |
@philips77 The latest version of the SDK still has this problem. I have to restart Bluetooth to solve it. I don't have a better solution at present, will I optimize this library in the future? |
Yes, we will release a patch, but have other priorities at the moment. I think creating a PR would be the quickest way if you want to contribute. |
The time has come, I started looking into this issue now. Just after releasing 1.4.4... :( |
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):stopScanInternal
has the following code (log line added in my fork):Here is a log of my app starting and stopping a few scans:
Notice that the
pendingIntent=
logged during astartScan
andstopScan
do not match.This means that the code never actually stops any PendingIntent started scans.
The
pendingIndent
passed tostopScan
must be the exact same one that was passed tostartScan
.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.
The text was updated successfully, but these errors were encountered: