Android 4.3: BLE: Filtering behaviour of startLeScan()

mattthebaker picture mattthebaker · Oct 21, 2013 · Viewed 23.9k times · Source

I'm working on a BluetoothLE sensor device, for which I need to form a one-to-many broadcast of data. As per the spec, peripherals may only have a single master, and due to limitations of the chip and stack I'm designing on, a master can only have three slaves. From what I understand, Android cannot become a BLE slave anyway, so having my device as a master is not an option.

Both the BT4 spec and manufacturer documentation talk about another mode of operation, referred to as Broadcast mode. In broadcast mode, a connection is never made, and the application data is transmitted as part of the advertising packet. This will exactly fit my needs, as many Android/iOS phones can simultaneously scan down each packet. An advertising packet is transmitted multiple times in bursts, so I suspect reception of data to be mostly reliable. If a packet is lost here and there, it can be tolerated.

Where this gets interesting, is that I want these packets to carry live sensor data, that updates at a rate of 10-20Hz. From examples I've found on the web, BLE in this mode is mostly being used for "iBeacon" type implementations, where they are broadcasting static data. I cannot find any information on how advertising packets are filtered within the Android stack. It could be that they return one result per Bluetooth hardware address, or it could be the unique combination of address and data. The second option would work for this application. If starting and stopping the scan resets the filter, I can make something work as well.

The Android documentation mentions nothing about how device filtering in the scan method works. I've been able to find one post on the net attempting to solve this same problem, which has an unresolved response: BLE: Multiple discovery of the same peripheral during scan. In iOS, my colleague informs me that there is a parameter that can be passed to the scan function that makes this possible.

I've attempted to trace the code back from the startLeScan() call in the Android source, but the code is quite complex, and the use of abstraction has made it difficult to identify the implementation of the object that contains it. The farthest I've gotten is to an IBluetoothGatt object returned from the BluetoothManagerService class method getBluetoothGatt(). This object receives the request to start scanning. It is being instantiated around line 790 of BluetoothManagerService.java on the current revision live on github. The object is being cast from the result of a message, so I suspect maybe the result is phone/driver specific. It is beyond my expertise to be able to trace it any further.

Another question I would like to resolve is how rapidly the scanning can be switched on and off. Scanning is a power intensive operation, yet the broadcast of data will happen periodically on a fairly precise, real time timer. As a result, it would be a great optimization if the scan can be switched on and off, such that the broadcast and scan are synchronized, with the scanner shut down the other 90%+ of the time. This will likely need to be tested experimentally.

I'm still doing feasibility research to see if this is possible for our accessory for Android. My present phone cannot yet run version 4.3, so I have no way of testing/hacking this experimentally.

Answer

OneWorld picture OneWorld · Nov 25, 2013

With Android 4.3 and 4.4 so far, it appears to be a mess: Some devices call onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) multiple times for one device in one scan, some don't. There is no way to configure the filtering like in iOS (see answer of Arkadiusz Konior). So, I now start a list, because I can't ask my users such a question about their device.

However, restarting scaning is also no problem on "not filtering" devices. So, I restart scaning on every device now.

Not filtering (Continuously calling onLeScan())

  • Samsung Galaxy S4 with 4.2.2 using Samsung BLE sdk (I owned that device)
  • Nexus 5 with 4.4 (added by [vegarwe]. The device will give scan records continuously for nearby devices while scanning)
  • Samsung Galaxy S3 with 4.3 (JSS15J.I9300XXUGMK6, I was testing on that device)
  • Samsung Galaxy S4 with 4.3 and 4.4.2 using Android SDK (added by arnaud.b, no build provided)
  • HTC One with 4.4.2 (added by arnaud.b, no build number provided)

Filtering devices (applies to Standard)

  • Nexus 4 with 4.3, 4.4 (I own that device)
  • Nexus 7 2013 4G with 4.4.2 (KOT49H, I was testing on that device)
  • Samsung Galaxy S4 mini with 4.2.2 (I was testing on this device)
  • Motorola Moto X (added by user1603602, no information about android version provided)
  • Motorola Moto G with 4.3 (falcon_umts, My testing device)
  • Sony Xperia Tablet Z Wifi with Android 4.3 (Build 10.4.B.0.577, Model SGP311, my testing device)
  • OnePlus One with 5.0.1 and 5.1.1 (Cyanogen 12.1)

Unknown filtering behavior (Please help to associate the device to a certain group)

  • Nexus 7 2013 (Different behavior is reported like here. But I have read more reports that it's belonging to first group.)
  • Other SAMSUNG, HTC, Motorola, ..., devices