NordicSemiconductor / Android-nRF-Connect

Documentation and issue tracker for nRF Connect for Android.
1.32k stars 312 forks source link

Android 13 cannot scan some broadcasts #177

Closed JiyeHoo closed 2 years ago

JiyeHoo commented 2 years ago

Describe the bug The app scans the broadcast on Android 12 and Android 13 with different results. (And Android 12 phones) Data of response package cannot be obtained on Android 13. Look at the screenshot below. I guess it is due to the new Bluetooth stack (Gabeldorsche) enabled on Android 13. How to solve this problem。 (The device that sends the broadcast is a Nordic chip, Other manufacturers will also)

Expected behavior I think there should be the same result on Android 12 and Android 13.

Screenshots

(At the same time) On the left is the pixel 4XL of Android 13, and on the right is other Android 12 phones

pic

Versions (please complete the following information):

philips77 commented 2 years ago

Try removing this AR with type 0x00. Android may be validating it and discharging invalid packets.

JiyeHoo commented 2 years ago

Delete a lot of “0” and you can scan them on Android 13.

But if you don't modify the broadcast data, what is the way to make Android 13 get the same results as Android 12? Is there any way we can be compatible with this change of Google?

Thank you very much for your answer. Thank you!

JiyeHoo commented 2 years ago

We wrote a demo to directly call the system API, using Scanner.startscan() method can obtain raw with "0000..." in the middle. That is to say, Android 13 does not discard data, except that Android 12 and 13 process non-standard data in different ways (13 is placed in the middle of raw and 12 is placed at the end). We think NRF connect should be able to display the original raw, and the result should be consistent with the returned data of Android 13 StartScan(). I hope I can support this change

philips77 commented 2 years ago

The raw data displayed is what the app gets from ScanRecord. Parsing is done in the app based on the Len/Type/Value. Can you place here bytes you get on both systems from your sample app?

JiyeHoo commented 2 years ago

We called the ScanRecord$getbytes() method, and the obtained data is as follows:

Android 13:

020106030201a20c1601a2003779707664747033 0000000000000000 0309545919ffd0070203000001001b7455e6546ab5212108ef91216fa99600000000

Other older versions:

020106030201a20c1601a2003779707664747033                  0309545919ffd0070203000001001b7455e6546ab5212108ef91216fa99600000000 0000000000000000
JiyeHoo commented 2 years ago

(Supplement) the data just submitted is another device with the same problem, not the device in the photo. However, the difference can be seen from the data returned by different Android versions.

In addition, the 0x07 (that is, the one on the right in the photo) parsed earlier should be a system problem. The data given by our device does not have 0x07. So please ignore the data in the previous picture.

In the last submitted data, the raw data of "NRF connect" will discard a lot of data after 0. This is a problem we should check

philips77 commented 2 years ago

Parsed data:

02 | 01 | 06 - Flags
03 | 02 | 01a2 - Incomplete List of 16-bit Service Class UUIDs (0xA201)
0c | 16 | 01a2003779707664747033 - Service Data 16-bit (UUID: 0xA201, Data: 003779707664747033)
00 | 00 | 000000000000 <- as the LEN field here (the first byte) is 0, the parser assumes that there's no further data. It is not able to predict where any next sequence would start.
03 | 09 | 5459 - Complete Local Name ("TY")
19 | ff | d0070203000001001b7455e6546ab5212108ef91216fa996 - Manufacturer data
00000000 <- no data again

As I understand, the first 0s are at the end of Advertising packet, while the last 0s are at the end of Scan Response data. Androdi usually returns 2x31 bytes in Raw Data, filling 0s at the end. Looks like Android 12 and older were parsing each packet separately and filling 0s at the end, while Android 13 just concatenates Advertising Data and Scan Response, and then fills 0s. Are you advertising those 0s in Advertising Data? They can be removed from the packet, or you could add the correct LEN (like in the image above you have 0x07).

JiyeHoo commented 2 years ago

Yes, we fill the end of the broadcast packet with 0.

We guess that the broadcast packet and the response packet are only connected on Android 13. While earlier versions of Android took out the valid data in the broadcast packet and the response packet for connection, and then filled "0" at the end.

As far as I know, many ble devices on the market now use "0" as padding at the end of broadcast packets. For such data, NRF connect will not display response packets. But the Android 13 system actually gives the response packet data.

In addition, the data with the length of 0x07 is from Xiaomi 6 mobile phone, and the Arrow OS System (Android 13) is not given by our device. We are currently studying why it gives 0x07 this length, but the pixel 4XL, which is also Android 13, does not. This is another issue unrelated to NRF connect.

JiyeHoo commented 2 years ago
pic

The picture above is the result of scanning at the same time.

ArroOS is a third-party system after all. I think we can ignore it.

According to my understanding, filling 0s at the end of the advertising package should not affect the content of the response package (NRF connect behaves like this on other versions of Android).

We suggest that NRF connect should continue to parse the remaining bytes [] (not shown in the parsing table below) when parsing to a length of 0x00, instead of directly "return", because the advertising package and the response package are independent.

Or raw data does not parse the valid content and directly displays the data with "0" returned by the system.

Thank you for your professional answer.

philips77 commented 2 years ago

The root cause are the 0s filling Advertising packet. Any reason why you have them? It consumes battery, takes air time and has no meaning. Are your devices already in the wild?

As far as I know, many ble devices on the market now use "0" as padding at the end of broadcast packets.

I wouldn't say so.

The issue with continuing parsing is that we don't really know where to start again. Adv packet and Scan Response packet are given as a single byte array. Adding this would also allow for arbitrary 0s in the middle of each packet, which is not valid according to the spec. I mean we could add it, but that will still not be parsed by other devices, like 'ScanResult` in Android, iOS, etc. It becomes impl dependent, not spec dependent.

JiyeHoo commented 2 years ago

OK, thank you for your professional explanation.

JiyeHoo commented 2 years ago

We fed back this problem to Google, and their engineers contacted us, that is, non downward compatibility is a problem. On September 14, Android 13 has fixed this problem (deleted 0s from the data). Currently, nrf Connect works normally.

JiyeHoo commented 2 years ago

https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2212339

philips77 commented 2 years ago

The mentioned Vol 3C chapter 11 also says:

Only the significant part of the data should be sent over the air.