Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why `ACTION_GATT_DISCONNECTED` does take so much time to update status?

I am using Bluetooth Low Energy to connect with my galaxy S4. After connection, the connection status will be updated in the function

private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        String intentAction;
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
            Log.d(TAG,"Connected");                

        } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
            Log.d(TAG,"Disconnected");                
        }
    }
}

In which, the status got from

// Implements callback methods for GATT events that the app cares about.  For example,
    // connection change and services discovered.
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server.");
                // Attempts to discover services after successful connection.
                Log.i(TAG, "Attempting to start service discovery:" +
                        mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }
        }

However, the ACTION_GATT_DISCONNECTED takes 10 seconds to update when the connection between the BLE device and the phone lost. In the case of ACTION_GATT_CONNECTED, it updates so fast about 1 seconds. Is it possible to reduce the disconnection status in BLE? Thank all

like image 869
Jame Avatar asked Oct 25 '16 02:10

Jame


2 Answers

There exists a 'link supervision timeout', this is defined as the amount of time the link must be maintained before giving up. This is why it takes so long when your peripheral device stops communicating.

// Link supervision timeout is measured in N * 10ms
int timeout = 2000; // 20s

You can find relevant code starting at line 1646 in com.android.bluetooth.gatt.GattService

https://android.googlesource.com/platform/packages/apps/Bluetooth/+/2b42a4906be952d3761d8b47134fba5a277a7765/src/com/android/bluetooth/gatt/GattService.java

---- Edit ----

The bigger problem seems to be a known bug with lollipop and kitcat in which bluedroid caches devices during discovery when it's not supposed to, see issue https://code.google.com/p/android/issues/detail?id=81130&q=BLE&sort=-stars&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened

There is no way to edit the timeout unless you can compile your own aosp system rom and flash to device.

There is a possible hack to work around this problem but it is not recommend because it is accessing a hidden internal API which may not exist starting in marshmallow (as bluedroid dropped for bluez).

The hack:

After calling disconnect and close force the discovery cache to refresh via reflectively calling the refresh method.

BluetoothGatt localBluetoothGatt = gatt;
Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]);
if (localMethod != null) {
    localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue();
}
like image 71
Gregory Ray Avatar answered Sep 28 '22 06:09

Gregory Ray


Which BLE device are you using to test the connection?. It could be possible that the device is actually closing the connection after some time. In some cases BLE device will close the connection after some time because it might have to write some characteristics which you have requested. In some cases it actually depends on the device Embedded code to determine when to close the connection.

In my situation my BLE device will close the connection after 5 secs. That 5 secs is like a buffer for the device to send me any pending write, read characteristics that i have requested.

We have configured our BLE device to notify when the end of broadcast broadcast which i used to notify user that the connection has been closed but in the background the BLE device is still open for 5 secs so that it can write some characteristics or user may want to regain the connection.

like image 37
Avinash4551 Avatar answered Sep 28 '22 05:09

Avinash4551