Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isMultipleAdvertisementSupported() returns false, when getBluetoothLeAdvertiser returns an object?

I am trying to play with BLE transmission on my device.

Here is the code I use and the output:

// check BLE support
Log.i(TAG, "BLE supported: " + getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)); // true

// check BLE transmission support
final BluetoothManager bluetoothManager =
        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

Log.i(TAG, "isMultipleAdvertisementSupported: " + mBluetoothAdapter.isMultipleAdvertisementSupported()); // false
Log.i(TAG, "isOffloadedFilteringSupported: " + mBluetoothAdapter.isOffloadedFilteringSupported()); // false
Log.i(TAG, "isOffloadedScanBatchingSupported: " + mBluetoothAdapter.isOffloadedScanBatchingSupported()); // false

BluetoothLeAdvertiser mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
Log.i(TAG, mBluetoothLeAdvertiser.toString()); //android.bluetooth.le.BluetoothLeAdvertiser@1c51f789

// check BLE transmission support
// android-beacon-library, https://github.com/AltBeacon/android-beacon-library
int result = BeaconTransmitter.checkTransmissionSupported(getApplicationContext());
Log.i(TAG, "ABL checkTransmissionSupported: " + result); // 0

I can not understand why mBluetoothLeAdvertiser is not null, since mBluetoothLeAdvertiser verifies that it is not false:

package android.bluetooth;
// ...

public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
    if (getState() != STATE_ON) {
        return null;
    }
    if (!isMultipleAdvertisementSupported()) {
        return null;
    }
    synchronized(mLock) {
        if (sBluetoothLeAdvertiser == null) {
            sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
        }
    }
    return sBluetoothLeAdvertiser;
}

// ...

public boolean isMultipleAdvertisementSupported() {
    if (getState() != STATE_ON) return false;
    try {
        return mService.isMultiAdvertisementSupported();
    } catch (RemoteException e) {
        Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
    }
    return false;
}
like image 864
LA_ Avatar asked Dec 09 '22 01:12

LA_


1 Answers

Welcome to the world of Android, which is both open source and closed source at the same time! Your analysis of the open source BluetoothLeAdvertiser code above is correct. If that code is running on your mobile device, you would not see the output that your test in the top code snippet shows. Conclusion: the code shown in the second snippet must not be what is on the device.

Android device OEMs are free to fork the source code and modify it to make it work with their hardware. In this case, I know that Motorola did the same thing in this code for their Moto X and Moto G devices. These devices return a BluetoothLeAdvertiser despite the fact that isMultipleAdvertisementSupported() returns false. A Motorola engineer explained to me that they changed this because they wanted to support Advertising despite using a BLE chip that could support only one Advertisement at a time. Indeed, I have verified that Motorola devices can advertise, but if you try to get two advertisements going simultaneously, it fails.

like image 132
davidgyoung Avatar answered May 16 '23 07:05

davidgyoung