Loading android/app/src/com/android/bluetooth/gatt/GattService.java +8 −1 Original line number Diff line number Diff line Loading @@ -284,7 +284,7 @@ public class GattService extends ProfileService { /** * Set of restricted (which require a BLUETOOTH_PRIVILEGED permission) handles per connectionId. */ private final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>(); @VisibleForTesting final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>(); /** * HashMap used to synchronize writeCharacteristic calls mapping remote device address to Loading Loading @@ -397,6 +397,9 @@ public class GattService extends ProfileService { mScannerMap.clear(); mAdvertiserMap.clear(); mClientMap.clear(); if (Flags.gattCleanupRestrictedHandles()) { mRestrictedHandles.clear(); } mServerMap.clear(); mHandleMap.clear(); mReliableQueue.clear(); Loading Loading @@ -2281,6 +2284,10 @@ public class GattService extends ProfileService { mClientMap.removeConnection(clientIf, connId); ClientMap.App app = mClientMap.getById(clientIf); if (Flags.gattCleanupRestrictedHandles()) { mRestrictedHandles.remove(connId); } // Remove AtomicBoolean representing permit if no other connections rely on this remote device. if (!mClientMap.getConnectedDevices().contains(address)) { synchronized (mPermits) { Loading android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ import android.os.RemoteException; import android.os.WorkSource; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.rule.ServiceTestRule; Loading Loading @@ -107,6 +109,9 @@ public class GattServiceTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private BluetoothDevice mDevice; private BluetoothAdapter mAdapter; private AttributionSource mAttributionSource; Loading Loading @@ -885,4 +890,46 @@ public class GattServiceTest { BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED); } @RequiresFlagsEnabled(Flags.FLAG_GATT_CLEANUP_RESTRICTED_HANDLES) @Test public void restrictedHandles() throws Exception { int clientIf = 1; int connId = 1; ArrayList<GattDbElement> db = new ArrayList<>(); GattService.ClientMap.App app = mock(GattService.ClientMap.App.class); IBluetoothGattCallback callback = mock(IBluetoothGattCallback.class); doReturn(app).when(mClientMap).getByConnId(connId); app.callback = callback; GattDbElement hidService = GattDbElement.createPrimaryService( UUID.fromString("00001812-0000-1000-8000-00805F9B34FB")); hidService.id = 1; GattDbElement hidInfoChar = GattDbElement.createCharacteristic( UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"), 0, 0); hidInfoChar.id = 2; GattDbElement randomChar = GattDbElement.createCharacteristic( UUID.fromString("0000FFFF-0000-1000-8000-00805F9B34FB"), 0, 0); randomChar.id = 3; db.add(hidService); db.add(hidInfoChar); db.add(randomChar); mService.onGetGattDb(connId, db); // HID characteristics should be restricted assertThat(mService.mRestrictedHandles.get(connId)).contains(hidInfoChar.id); assertThat(mService.mRestrictedHandles.get(connId)).doesNotContain(randomChar.id); mService.onDisconnected( clientIf, connId, BluetoothGatt.GATT_SUCCESS, REMOTE_DEVICE_ADDRESS); assertThat(mService.mRestrictedHandles).doesNotContainKey(connId); } } Loading
android/app/src/com/android/bluetooth/gatt/GattService.java +8 −1 Original line number Diff line number Diff line Loading @@ -284,7 +284,7 @@ public class GattService extends ProfileService { /** * Set of restricted (which require a BLUETOOTH_PRIVILEGED permission) handles per connectionId. */ private final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>(); @VisibleForTesting final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>(); /** * HashMap used to synchronize writeCharacteristic calls mapping remote device address to Loading Loading @@ -397,6 +397,9 @@ public class GattService extends ProfileService { mScannerMap.clear(); mAdvertiserMap.clear(); mClientMap.clear(); if (Flags.gattCleanupRestrictedHandles()) { mRestrictedHandles.clear(); } mServerMap.clear(); mHandleMap.clear(); mReliableQueue.clear(); Loading Loading @@ -2281,6 +2284,10 @@ public class GattService extends ProfileService { mClientMap.removeConnection(clientIf, connId); ClientMap.App app = mClientMap.getById(clientIf); if (Flags.gattCleanupRestrictedHandles()) { mRestrictedHandles.remove(connId); } // Remove AtomicBoolean representing permit if no other connections rely on this remote device. if (!mClientMap.getConnectedDevices().contains(address)) { synchronized (mPermits) { Loading
android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,8 @@ import android.os.RemoteException; import android.os.WorkSource; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.rule.ServiceTestRule; Loading Loading @@ -107,6 +109,9 @@ public class GattServiceTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private BluetoothDevice mDevice; private BluetoothAdapter mAdapter; private AttributionSource mAttributionSource; Loading Loading @@ -885,4 +890,46 @@ public class GattServiceTest { BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTED); } @RequiresFlagsEnabled(Flags.FLAG_GATT_CLEANUP_RESTRICTED_HANDLES) @Test public void restrictedHandles() throws Exception { int clientIf = 1; int connId = 1; ArrayList<GattDbElement> db = new ArrayList<>(); GattService.ClientMap.App app = mock(GattService.ClientMap.App.class); IBluetoothGattCallback callback = mock(IBluetoothGattCallback.class); doReturn(app).when(mClientMap).getByConnId(connId); app.callback = callback; GattDbElement hidService = GattDbElement.createPrimaryService( UUID.fromString("00001812-0000-1000-8000-00805F9B34FB")); hidService.id = 1; GattDbElement hidInfoChar = GattDbElement.createCharacteristic( UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"), 0, 0); hidInfoChar.id = 2; GattDbElement randomChar = GattDbElement.createCharacteristic( UUID.fromString("0000FFFF-0000-1000-8000-00805F9B34FB"), 0, 0); randomChar.id = 3; db.add(hidService); db.add(hidInfoChar); db.add(randomChar); mService.onGetGattDb(connId, db); // HID characteristics should be restricted assertThat(mService.mRestrictedHandles.get(connId)).contains(hidInfoChar.id); assertThat(mService.mRestrictedHandles.get(connId)).doesNotContain(randomChar.id); mService.onDisconnected( clientIf, connId, BluetoothGatt.GATT_SUCCESS, REMOTE_DEVICE_ADDRESS); assertThat(mService.mRestrictedHandles).doesNotContainKey(connId); } }