Loading framework/tests/bumble/src/android/bluetooth/GattClientTest.java +45 −32 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.bluetooth; import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; Loading Loading @@ -118,7 +121,7 @@ public class GattClientTest { BluetoothGattCallback gattCallback2 = mock(BluetoothGattCallback.class); BluetoothGatt gatt2 = device.connectGatt(mContext, false, gattCallback2); verify(gattCallback2, timeout(1000)) .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); disconnectAndWaitDisconnection(gatt2, gattCallback2); // After reconnecting, verify the first callback was not invoked. Loading Loading @@ -147,7 +150,7 @@ public class GattClientTest { BluetoothGatt gatt = device.connectGatt(mContext, false, gattCallback); inOrder.verify(gattCallback, timeout(1000)) .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); gatt.disconnect(); inOrder.verify(gattCallback, timeout(1000)) Loading @@ -155,7 +158,7 @@ public class GattClientTest { gatt.connect(); inOrder.verify(gattCallback, timeout(1000)) .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); // TODO(323889717): Fix callback being called after gatt.close(). This disconnect shouldn't // be necessary. Loading @@ -172,8 +175,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); assertThat(gatt.getServices().stream().map(BluetoothGattService::getUuid)) .contains(GAP_UUID); Loading @@ -190,8 +192,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattService firstService = gatt.getServices().get(0); Loading @@ -216,8 +217,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattCharacteristic characteristic = gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID); Loading @@ -228,8 +228,7 @@ public class GattClientTest { characteristic, newValue, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); verify(gattCallback, timeout(5000)) .onCharacteristicWrite( any(), eq(characteristic), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); Loading @@ -246,8 +245,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattCharacteristic characteristic = gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID); Loading @@ -260,7 +258,7 @@ public class GattClientTest { assertThat(gatt.writeDescriptor(descriptor)).isTrue(); verify(gattCallback, timeout(5000)) .onDescriptorWrite(any(), eq(descriptor), eq(BluetoothGatt.GATT_SUCCESS)); .onDescriptorWrite(any(), eq(descriptor), eq(GATT_SUCCESS)); gatt.setCharacteristicNotification(characteristic, true); Loading Loading @@ -315,10 +313,8 @@ public class GattClientTest { try { gatt.discoverServices(); gatt2.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback2, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); verify(gattCallback2, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattCharacteristic characteristic = gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID); Loading @@ -341,11 +337,9 @@ public class GattClientTest { == BluetoothStatusCodes.SUCCESS); verify(gattCallback, timeout(5000)) .onCharacteristicWrite( any(), eq(characteristic), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic), eq(GATT_SUCCESS)); verify(gattCallback2, never()) .onCharacteristicWrite( any(), eq(characteristic), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic), eq(GATT_SUCCESS)); assertThat( gatt2.writeCharacteristic( Loading @@ -354,14 +348,33 @@ public class GattClientTest { BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)) .isEqualTo(BluetoothStatusCodes.SUCCESS); verify(gattCallback2, timeout(5000)) .onCharacteristicWrite( any(), eq(characteristic2), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic2), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); disconnectAndWaitDisconnection(gatt2, gattCallback2); } } @Test @RequiresFlagsEnabled(Flags.FLAG_GATT_FIX_MULTIPLE_DIRECT_CONNECT) public void connectMultiple_closeOne_shouldSuccess() { BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); BluetoothGattCallback gattCallback2 = mock(BluetoothGattCallback.class); advertiseWithBumble(); BluetoothDevice device = mAdapter.getRemoteLeDevice( Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); BluetoothGatt gatt = device.connectGatt(mContext, false, gattCallback); BluetoothGatt gatt2 = device.connectGatt(mContext, false, gattCallback2); gatt.disconnect(); gatt.close(); verify(gattCallback2, timeout(1000)) .onConnectionStateChange(eq(gatt2), eq(GATT_SUCCESS), eq(STATE_CONNECTED)); } private void registerWritableGattService() { GattCharacteristicParams characteristicParams = GattCharacteristicParams.newBuilder() Loading Loading @@ -439,8 +452,8 @@ public class GattClientTest { } private BluetoothGatt connectGattAndWaitConnection(BluetoothGattCallback callback) { final int status = BluetoothGatt.GATT_SUCCESS; final int state = BluetoothProfile.STATE_CONNECTED; final int status = GATT_SUCCESS; final int state = STATE_CONNECTED; advertiseWithBumble(); Loading Loading @@ -503,7 +516,7 @@ public class GattClientTest { assertThat(gatt.requestMtu(MTU_REQUESTED)).isTrue(); // Check that only the ANDROID_MTU is returned, not the MTU_REQUESTED verify(gattCallback, timeout(5000)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); } Loading @@ -518,11 +531,11 @@ public class GattClientTest { assertThat(gatt.requestMtu(MTU_REQUESTED)).isTrue(); // Check that only the ANDROID_MTU is returned, not the MTU_REQUESTED verify(gattCallback, timeout(5000)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); assertThat(gatt.requestMtu(ANOTHER_MTU_REQUESTED)).isTrue(); verify(gattCallback, timeout(5000).times(2)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); } Loading @@ -536,17 +549,17 @@ public class GattClientTest { try { assertThat(gatt.requestMtu(MTU_REQUESTED)).isTrue(); verify(gattCallback, timeout(5000)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); BluetoothGattCallback gattCallback2 = mock(BluetoothGattCallback.class); BluetoothGatt gatt2 = connectGattAndWaitConnection(gattCallback2); try { // first callback because there is already a connected device verify(gattCallback2, timeout(9000)) .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(GATT_SUCCESS)); assertThat(gatt2.requestMtu(ANOTHER_MTU_REQUESTED)).isTrue(); verify(gattCallback2, timeout(9000).times(2)) .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt2, gattCallback2); } Loading system/stack/gatt/gatt_utils.cc +4 −1 Original line number Diff line number Diff line Loading @@ -1569,7 +1569,10 @@ bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) { } else { if (!connection_manager::direct_connect_remove(gatt_if, bda)) { if (!connection_manager::is_background_connection(bda)) { if (!com::android::bluetooth::flags::gatt_fix_multiple_direct_connect() || p_tcb->app_hold_link.empty()) { BTM_AcceptlistRemove(bda); } log::info( "Gatt connection manager has no background record but removed " "filter acceptlist gatt_if:{} peer:{}", Loading Loading
framework/tests/bumble/src/android/bluetooth/GattClientTest.java +45 −32 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.bluetooth; import static android.bluetooth.BluetoothGatt.GATT_SUCCESS; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; Loading Loading @@ -118,7 +121,7 @@ public class GattClientTest { BluetoothGattCallback gattCallback2 = mock(BluetoothGattCallback.class); BluetoothGatt gatt2 = device.connectGatt(mContext, false, gattCallback2); verify(gattCallback2, timeout(1000)) .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); disconnectAndWaitDisconnection(gatt2, gattCallback2); // After reconnecting, verify the first callback was not invoked. Loading Loading @@ -147,7 +150,7 @@ public class GattClientTest { BluetoothGatt gatt = device.connectGatt(mContext, false, gattCallback); inOrder.verify(gattCallback, timeout(1000)) .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); gatt.disconnect(); inOrder.verify(gattCallback, timeout(1000)) Loading @@ -155,7 +158,7 @@ public class GattClientTest { gatt.connect(); inOrder.verify(gattCallback, timeout(1000)) .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); .onConnectionStateChange(any(), anyInt(), eq(STATE_CONNECTED)); // TODO(323889717): Fix callback being called after gatt.close(). This disconnect shouldn't // be necessary. Loading @@ -172,8 +175,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); assertThat(gatt.getServices().stream().map(BluetoothGattService::getUuid)) .contains(GAP_UUID); Loading @@ -190,8 +192,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattService firstService = gatt.getServices().get(0); Loading @@ -216,8 +217,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattCharacteristic characteristic = gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID); Loading @@ -228,8 +228,7 @@ public class GattClientTest { characteristic, newValue, BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); verify(gattCallback, timeout(5000)) .onCharacteristicWrite( any(), eq(characteristic), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); Loading @@ -246,8 +245,7 @@ public class GattClientTest { try { gatt.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattCharacteristic characteristic = gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID); Loading @@ -260,7 +258,7 @@ public class GattClientTest { assertThat(gatt.writeDescriptor(descriptor)).isTrue(); verify(gattCallback, timeout(5000)) .onDescriptorWrite(any(), eq(descriptor), eq(BluetoothGatt.GATT_SUCCESS)); .onDescriptorWrite(any(), eq(descriptor), eq(GATT_SUCCESS)); gatt.setCharacteristicNotification(characteristic, true); Loading Loading @@ -315,10 +313,8 @@ public class GattClientTest { try { gatt.discoverServices(); gatt2.discoverServices(); verify(gattCallback, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback2, timeout(10000)) .onServicesDiscovered(any(), eq(BluetoothGatt.GATT_SUCCESS)); verify(gattCallback, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); verify(gattCallback2, timeout(10000)).onServicesDiscovered(any(), eq(GATT_SUCCESS)); BluetoothGattCharacteristic characteristic = gatt.getService(TEST_SERVICE_UUID).getCharacteristic(TEST_CHARACTERISTIC_UUID); Loading @@ -341,11 +337,9 @@ public class GattClientTest { == BluetoothStatusCodes.SUCCESS); verify(gattCallback, timeout(5000)) .onCharacteristicWrite( any(), eq(characteristic), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic), eq(GATT_SUCCESS)); verify(gattCallback2, never()) .onCharacteristicWrite( any(), eq(characteristic), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic), eq(GATT_SUCCESS)); assertThat( gatt2.writeCharacteristic( Loading @@ -354,14 +348,33 @@ public class GattClientTest { BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT)) .isEqualTo(BluetoothStatusCodes.SUCCESS); verify(gattCallback2, timeout(5000)) .onCharacteristicWrite( any(), eq(characteristic2), eq(BluetoothGatt.GATT_SUCCESS)); .onCharacteristicWrite(any(), eq(characteristic2), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); disconnectAndWaitDisconnection(gatt2, gattCallback2); } } @Test @RequiresFlagsEnabled(Flags.FLAG_GATT_FIX_MULTIPLE_DIRECT_CONNECT) public void connectMultiple_closeOne_shouldSuccess() { BluetoothGattCallback gattCallback = mock(BluetoothGattCallback.class); BluetoothGattCallback gattCallback2 = mock(BluetoothGattCallback.class); advertiseWithBumble(); BluetoothDevice device = mAdapter.getRemoteLeDevice( Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); BluetoothGatt gatt = device.connectGatt(mContext, false, gattCallback); BluetoothGatt gatt2 = device.connectGatt(mContext, false, gattCallback2); gatt.disconnect(); gatt.close(); verify(gattCallback2, timeout(1000)) .onConnectionStateChange(eq(gatt2), eq(GATT_SUCCESS), eq(STATE_CONNECTED)); } private void registerWritableGattService() { GattCharacteristicParams characteristicParams = GattCharacteristicParams.newBuilder() Loading Loading @@ -439,8 +452,8 @@ public class GattClientTest { } private BluetoothGatt connectGattAndWaitConnection(BluetoothGattCallback callback) { final int status = BluetoothGatt.GATT_SUCCESS; final int state = BluetoothProfile.STATE_CONNECTED; final int status = GATT_SUCCESS; final int state = STATE_CONNECTED; advertiseWithBumble(); Loading Loading @@ -503,7 +516,7 @@ public class GattClientTest { assertThat(gatt.requestMtu(MTU_REQUESTED)).isTrue(); // Check that only the ANDROID_MTU is returned, not the MTU_REQUESTED verify(gattCallback, timeout(5000)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); } Loading @@ -518,11 +531,11 @@ public class GattClientTest { assertThat(gatt.requestMtu(MTU_REQUESTED)).isTrue(); // Check that only the ANDROID_MTU is returned, not the MTU_REQUESTED verify(gattCallback, timeout(5000)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); assertThat(gatt.requestMtu(ANOTHER_MTU_REQUESTED)).isTrue(); verify(gattCallback, timeout(5000).times(2)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt, gattCallback); } Loading @@ -536,17 +549,17 @@ public class GattClientTest { try { assertThat(gatt.requestMtu(MTU_REQUESTED)).isTrue(); verify(gattCallback, timeout(5000)) .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt), eq(ANDROID_MTU), eq(GATT_SUCCESS)); BluetoothGattCallback gattCallback2 = mock(BluetoothGattCallback.class); BluetoothGatt gatt2 = connectGattAndWaitConnection(gattCallback2); try { // first callback because there is already a connected device verify(gattCallback2, timeout(9000)) .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(GATT_SUCCESS)); assertThat(gatt2.requestMtu(ANOTHER_MTU_REQUESTED)).isTrue(); verify(gattCallback2, timeout(9000).times(2)) .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(BluetoothGatt.GATT_SUCCESS)); .onMtuChanged(eq(gatt2), eq(ANDROID_MTU), eq(GATT_SUCCESS)); } finally { disconnectAndWaitDisconnection(gatt2, gattCallback2); } Loading
system/stack/gatt/gatt_utils.cc +4 −1 Original line number Diff line number Diff line Loading @@ -1569,7 +1569,10 @@ bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) { } else { if (!connection_manager::direct_connect_remove(gatt_if, bda)) { if (!connection_manager::is_background_connection(bda)) { if (!com::android::bluetooth::flags::gatt_fix_multiple_direct_connect() || p_tcb->app_hold_link.empty()) { BTM_AcceptlistRemove(bda); } log::info( "Gatt connection manager has no background record but removed " "filter acceptlist gatt_if:{} peer:{}", Loading