Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +100 −37 Original line number Diff line number Diff line Loading @@ -531,7 +531,8 @@ public class AdapterService extends Service { mRunningProfiles.add(profile); // TODO(b/228875190): GATT is assumed supported. GATT starting triggers hardware // initialization. Configuring a device without GATT causes start up failures. if (GattService.class.getSimpleName().equals(profile.getName())) { if (GattService.class.getSimpleName().equals(profile.getName()) && !Flags.scanManagerRefactor()) { mNativeInterface.enable(); } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length && mRegisteredProfiles.size() == mRunningProfiles.size()) { Loading @@ -556,8 +557,14 @@ public class AdapterService extends Service { return; } mRunningProfiles.remove(profile); // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the only // profile available in the "BLE ON" state. If only GATT is left, send if (Flags.scanManagerRefactor()) { if (mRunningProfiles.size() == 0) { mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } } else { // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the // only profile available in the "BLE ON" state. If only GATT is left, send // BREDR_STOPPED. If GATT is stopped, deinitialize the hardware. if ((mRunningProfiles.size() == 1 && (GattService.class Loading @@ -567,6 +574,7 @@ public class AdapterService extends Service { } else if (mRunningProfiles.size() == 0) { mNativeInterface.disable(); } } break; default: Log.e(TAG, "Unhandled profile state: " + state); Loading Loading @@ -1027,12 +1035,20 @@ public class AdapterService extends Service { TAG, "GATT is configured off but the stack assumes it to be enabled. Start anyway."); } if (Flags.scanManagerRefactor()) { startScanController(); } else { startGattProfileService(); } } void bringDownBle() { if (Flags.scanManagerRefactor()) { stopScanController(); } else { stopGattProfileService(); } } void stateChangeCallback(int status) { if (status == AbstractionLayer.BT_STATE_OFF) { Loading @@ -1048,9 +1064,20 @@ public class AdapterService extends Service { void startProfileServices() { Log.d(TAG, "startCoreServices()"); int[] supportedProfileServices = Config.getSupportedProfiles(); // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then just // move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause adapter // initialization failures if (Flags.scanManagerRefactor()) { // Scanning is always supported, started separately, and is not a profile service. // This will check other profile services. if (supportedProfileServices.length == 0) { mAdapterProperties.onBluetoothReady(); updateUuids(); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); } } else { // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then // just move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause // adapter initialization failures if (supportedProfileServices.length == 1 && supportedProfileServices[0] == BluetoothProfile.GATT) { mAdapterProperties.onBluetoothReady(); Loading @@ -1060,6 +1087,7 @@ public class AdapterService extends Service { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); } } } void stopProfileServices() { // Make sure to stop classic background tasks now Loading @@ -1067,19 +1095,31 @@ public class AdapterService extends Service { mAdapterProperties.setScanMode(BluetoothAdapter.SCAN_MODE_NONE); int[] supportedProfileServices = Config.getSupportedProfiles(); // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just move on // to BREDR_STOPPED if (Flags.scanManagerRefactor()) { // Scanning is always supported, started separately, and is not a profile service. // This will check other profile services. if (supportedProfileServices.length == 0) { mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); } } else { // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just // move on to BREDR_STOPPED if (supportedProfileServices.length == 1 && (mRunningProfiles.size() == 1 && GattService.class .getSimpleName() .equals(mRunningProfiles.get(0).getName()))) { Log.d(TAG, "stopProfileServices() - No profiles services to stop or already stopped."); Log.d( TAG, "stopProfileServices() - No profiles services to stop or already stopped."); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); } } } private void startGattProfileService() { mGattService = new GattService(this); Loading @@ -1091,6 +1131,11 @@ public class AdapterService extends Service { onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_ON); } private void startScanController() { mScanController = new ScanController(this); mNativeInterface.enable(); } private void stopGattProfileService() { mAdapterProperties.onBleDisable(); if (mRunningProfiles.size() == 0) { Loading @@ -1110,6 +1155,18 @@ public class AdapterService extends Service { } } private void stopScanController() { mAdapterProperties.onBleDisable(); if (mScanController == null) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } else { mScanController.stop(); mScanController = null; mNativeInterface.disable(); } } private void invalidateBluetoothGetStateCache() { BluetoothAdapter.invalidateBluetoothGetStateCache(); } Loading Loading @@ -1529,11 +1586,13 @@ public class AdapterService extends Service { private void setAllProfileServiceStates(int[] profileIds, int state) { for (int profileId : profileIds) { // TODO(b/228875190): GATT is assumed supported and treated differently as part of the // "BLE ON" state, despite GATT not being BLE specific. if (!Flags.scanManagerRefactor()) { // TODO(b/228875190): GATT is assumed supported and treated differently as part of // the "BLE ON" state, despite GATT not being BLE specific. if (profileId == BluetoothProfile.GATT) { continue; } } setProfileServiceState(profileId, state); } } Loading Loading @@ -5951,8 +6010,12 @@ public class AdapterService extends Service { Log.w(TAG, "GATT Service is not running!"); return; } if (Flags.scanManagerRefactor()) { mScanController.notifyProfileConnectionStateChange(profile, fromState, toState); } else { mGattService.notifyProfileConnectionStateChange(profile, fromState, toState); } } /** * Handle Bluetooth app state when connection state changes for a given {@code profile}. Loading android/app/src/com/android/bluetooth/le_scan/ScanController.java +23 −16 Original line number Diff line number Diff line Loading @@ -40,16 +40,12 @@ public class ScanController { private final BluetoothScanBinder mBinder; private boolean isAvailable = false; private boolean mIsAvailable; public ScanController(Context ctx) { mTransitionalScanHelper = new TransitionalScanHelper(ctx, () -> false); mBinder = new BluetoothScanBinder(this); } public void start() { Log.d(TAG, "start()"); isAvailable = true; mIsAvailable = true; HandlerThread thread = new HandlerThread("BluetoothScanManager"); thread.start(); mTransitionalScanHelper.start(thread.getLooper()); Loading @@ -57,11 +53,17 @@ public class ScanController { public void stop() { Log.d(TAG, "stop()"); isAvailable = false; mIsAvailable = false; mBinder.clearScanController(); mTransitionalScanHelper.stop(); mTransitionalScanHelper.cleanup(); } /** Notify Scan manager of bluetooth profile connection state changes */ public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { mTransitionalScanHelper.notifyProfileConnectionStateChange(profile, fromState, toState); } TransitionalScanHelper getTransitionalScanHelper() { return mTransitionalScanHelper; } Loading @@ -71,20 +73,12 @@ public class ScanController { } static class BluetoothScanBinder extends IBluetoothScan.Stub { private final ScanController mScanController; private ScanController mScanController; BluetoothScanBinder(ScanController scanController) { mScanController = scanController; } private ScanController getScanController() { if (mScanController.isAvailable) { return mScanController; } Log.e(TAG, "getScanController() - ScanController requested, but not available!"); return null; } @Override public void registerScanner( IScannerCallback callback, Loading Loading @@ -236,5 +230,18 @@ public class ScanController { .getTransitionalScanHelper() .numHwTrackFiltersAvailable(attributionSource); } private void clearScanController() { mScanController = null; } private ScanController getScanController() { ScanController controller = mScanController; if (controller != null && controller.mIsAvailable) { return controller; } Log.e(TAG, "getScanController() - ScanController requested, but not available!"); return null; } } } android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java +134 −2 Original line number Diff line number Diff line Loading @@ -409,9 +409,11 @@ public class AdapterServiceTest { TestUtils.syncHandler(looper, AdapterState.BLE_TURN_ON); verifyStateChange(callback, STATE_OFF, STATE_BLE_TURNING_ON); if (!Flags.scanManagerRefactor()) { TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_REGISTERED); TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } verify(nativeInterface).enable(); adapter.stateChangeCallback(AbstractionLayer.BT_STATE_ON); Loading Loading @@ -675,6 +677,136 @@ public class AdapterServiceTest { assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); } @Test public void startBleOnly_whenScanManagerRefactorFlagIsOff_onlyStartGattProfile() { mSetFlagsRule.disableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); mAdapterService.bringUpBle(); assertThat(mAdapterService.getBluetoothGatt()).isNotNull(); assertThat(mAdapterService.getBluetoothScan()).isNull(); dropNextMessage(MESSAGE_PROFILE_SERVICE_REGISTERED); dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } @Test public void startBleOnly_whenScanManagerRefactorFlagIsOn_onlyStartScanController() { mSetFlagsRule.enableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); mAdapterService.bringUpBle(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); assertThat(mAdapterService.getBluetoothScan()).isNotNull(); } @Test public void startBleOnly_whenScanManagerRefactorFlagIsOn_startAndStopScanController() { mSetFlagsRule.enableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); assertThat(mAdapterService.getBluetoothScan()).isNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); IBluetoothCallback callback = mock(IBluetoothCallback.class); Binder binder = mock(Binder.class); doReturn(binder).when(callback).asBinder(); mAdapterService.registerRemoteCallback(callback); offToBleOn( mLooper, mMockGattService, mAdapterService, mMockContext, mIBluetoothCallback, mNativeInterface); assertThat(mAdapterService.getBluetoothScan()).isNotNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); mAdapterService.stopBle(); TestUtils.syncHandler(mLooper, AdapterState.BLE_TURN_OFF); verifyStateChange(callback, STATE_BLE_ON, STATE_BLE_TURNING_OFF); verify(mNativeInterface).disable(); mAdapterService.stateChangeCallback(AbstractionLayer.BT_STATE_OFF); TestUtils.syncHandler(mLooper, AdapterState.BLE_STOPPED); verifyStateChange(callback, STATE_BLE_TURNING_OFF, STATE_OFF); assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); mAdapterService.unregisterRemoteCallback(callback); assertThat(mAdapterService.getBluetoothScan()).isNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); } @Test public void startBrDr_whenScanManagerRefactorFlagIsOn_startAndStopScanController() { mSetFlagsRule.enableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); assertThat(mAdapterService.getBluetoothScan()).isNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); IBluetoothCallback callback = mock(IBluetoothCallback.class); Binder binder = mock(Binder.class); doReturn(binder).when(callback).asBinder(); mAdapterService.registerRemoteCallback(callback); assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); offToBleOn( mLooper, mMockGattService, mAdapterService, mMockContext, mIBluetoothCallback, mNativeInterface); assertThat(mAdapterService.getBluetoothScan()).isNotNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); mAdapterService.startBrEdr(); TestUtils.syncHandler(mLooper, AdapterState.USER_TURN_ON); verifyStateChange(callback, STATE_BLE_ON, STATE_TURNING_ON); // Start Mock PBAP, PAN, and GATT services assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(3); List<ProfileService> services = List.of(mMockService, mMockService2, mMockGattService); for (ProfileService service : services) { mAdapterService.addProfile(service); TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_REGISTERED); } for (ProfileService service : services) { mAdapterService.onProfileServiceStateChanged(service, STATE_ON); TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } TestUtils.syncHandler(mLooper, AdapterState.BREDR_STARTED); verifyStateChange(callback, STATE_TURNING_ON, STATE_ON); assertThat(mAdapterService.getState()).isEqualTo(STATE_ON); mAdapterService.disable(); TestUtils.syncHandler(mLooper, AdapterState.USER_TURN_OFF); verifyStateChange(callback, STATE_ON, STATE_TURNING_OFF); // Stop PBAP, PAN, and GATT services assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(6); for (ProfileService service : services) { mAdapterService.onProfileServiceStateChanged(service, STATE_OFF); TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } TestUtils.syncHandler(mLooper, AdapterState.BREDR_STOPPED); verifyStateChange(callback, STATE_TURNING_OFF, STATE_BLE_ON); assertThat(mAdapterService.getState()).isEqualTo(STATE_BLE_ON); mAdapterService.unregisterRemoteCallback(callback); } /** * Test: Don't start a classic profile * Check whether the AdapterService quits gracefully Loading Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +100 −37 Original line number Diff line number Diff line Loading @@ -531,7 +531,8 @@ public class AdapterService extends Service { mRunningProfiles.add(profile); // TODO(b/228875190): GATT is assumed supported. GATT starting triggers hardware // initialization. Configuring a device without GATT causes start up failures. if (GattService.class.getSimpleName().equals(profile.getName())) { if (GattService.class.getSimpleName().equals(profile.getName()) && !Flags.scanManagerRefactor()) { mNativeInterface.enable(); } else if (mRegisteredProfiles.size() == Config.getSupportedProfiles().length && mRegisteredProfiles.size() == mRunningProfiles.size()) { Loading @@ -556,8 +557,14 @@ public class AdapterService extends Service { return; } mRunningProfiles.remove(profile); // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the only // profile available in the "BLE ON" state. If only GATT is left, send if (Flags.scanManagerRefactor()) { if (mRunningProfiles.size() == 0) { mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } } else { // TODO(b/228875190): GATT is assumed supported. GATT is expected to be the // only profile available in the "BLE ON" state. If only GATT is left, send // BREDR_STOPPED. If GATT is stopped, deinitialize the hardware. if ((mRunningProfiles.size() == 1 && (GattService.class Loading @@ -567,6 +574,7 @@ public class AdapterService extends Service { } else if (mRunningProfiles.size() == 0) { mNativeInterface.disable(); } } break; default: Log.e(TAG, "Unhandled profile state: " + state); Loading Loading @@ -1027,12 +1035,20 @@ public class AdapterService extends Service { TAG, "GATT is configured off but the stack assumes it to be enabled. Start anyway."); } if (Flags.scanManagerRefactor()) { startScanController(); } else { startGattProfileService(); } } void bringDownBle() { if (Flags.scanManagerRefactor()) { stopScanController(); } else { stopGattProfileService(); } } void stateChangeCallback(int status) { if (status == AbstractionLayer.BT_STATE_OFF) { Loading @@ -1048,9 +1064,20 @@ public class AdapterService extends Service { void startProfileServices() { Log.d(TAG, "startCoreServices()"); int[] supportedProfileServices = Config.getSupportedProfiles(); // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then just // move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause adapter // initialization failures if (Flags.scanManagerRefactor()) { // Scanning is always supported, started separately, and is not a profile service. // This will check other profile services. if (supportedProfileServices.length == 0) { mAdapterProperties.onBluetoothReady(); updateUuids(); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STARTED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); } } else { // TODO(b/228875190): GATT is assumed supported. If we support no other profiles then // just move on to BREDR_STARTED. Note that configuring GATT to NOT supported will cause // adapter initialization failures if (supportedProfileServices.length == 1 && supportedProfileServices[0] == BluetoothProfile.GATT) { mAdapterProperties.onBluetoothReady(); Loading @@ -1060,6 +1087,7 @@ public class AdapterService extends Service { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON); } } } void stopProfileServices() { // Make sure to stop classic background tasks now Loading @@ -1067,19 +1095,31 @@ public class AdapterService extends Service { mAdapterProperties.setScanMode(BluetoothAdapter.SCAN_MODE_NONE); int[] supportedProfileServices = Config.getSupportedProfiles(); // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just move on // to BREDR_STOPPED if (Flags.scanManagerRefactor()) { // Scanning is always supported, started separately, and is not a profile service. // This will check other profile services. if (supportedProfileServices.length == 0) { mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); } } else { // TODO(b/228875190): GATT is assumed supported. If we support no profiles then just // move on to BREDR_STOPPED if (supportedProfileServices.length == 1 && (mRunningProfiles.size() == 1 && GattService.class .getSimpleName() .equals(mRunningProfiles.get(0).getName()))) { Log.d(TAG, "stopProfileServices() - No profiles services to stop or already stopped."); Log.d( TAG, "stopProfileServices() - No profiles services to stop or already stopped."); mAdapterStateMachine.sendMessage(AdapterState.BREDR_STOPPED); } else { setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_OFF); } } } private void startGattProfileService() { mGattService = new GattService(this); Loading @@ -1091,6 +1131,11 @@ public class AdapterService extends Service { onProfileServiceStateChanged(mGattService, BluetoothAdapter.STATE_ON); } private void startScanController() { mScanController = new ScanController(this); mNativeInterface.enable(); } private void stopGattProfileService() { mAdapterProperties.onBleDisable(); if (mRunningProfiles.size() == 0) { Loading @@ -1110,6 +1155,18 @@ public class AdapterService extends Service { } } private void stopScanController() { mAdapterProperties.onBleDisable(); if (mScanController == null) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } else { mScanController.stop(); mScanController = null; mNativeInterface.disable(); } } private void invalidateBluetoothGetStateCache() { BluetoothAdapter.invalidateBluetoothGetStateCache(); } Loading Loading @@ -1529,11 +1586,13 @@ public class AdapterService extends Service { private void setAllProfileServiceStates(int[] profileIds, int state) { for (int profileId : profileIds) { // TODO(b/228875190): GATT is assumed supported and treated differently as part of the // "BLE ON" state, despite GATT not being BLE specific. if (!Flags.scanManagerRefactor()) { // TODO(b/228875190): GATT is assumed supported and treated differently as part of // the "BLE ON" state, despite GATT not being BLE specific. if (profileId == BluetoothProfile.GATT) { continue; } } setProfileServiceState(profileId, state); } } Loading Loading @@ -5951,8 +6010,12 @@ public class AdapterService extends Service { Log.w(TAG, "GATT Service is not running!"); return; } if (Flags.scanManagerRefactor()) { mScanController.notifyProfileConnectionStateChange(profile, fromState, toState); } else { mGattService.notifyProfileConnectionStateChange(profile, fromState, toState); } } /** * Handle Bluetooth app state when connection state changes for a given {@code profile}. Loading
android/app/src/com/android/bluetooth/le_scan/ScanController.java +23 −16 Original line number Diff line number Diff line Loading @@ -40,16 +40,12 @@ public class ScanController { private final BluetoothScanBinder mBinder; private boolean isAvailable = false; private boolean mIsAvailable; public ScanController(Context ctx) { mTransitionalScanHelper = new TransitionalScanHelper(ctx, () -> false); mBinder = new BluetoothScanBinder(this); } public void start() { Log.d(TAG, "start()"); isAvailable = true; mIsAvailable = true; HandlerThread thread = new HandlerThread("BluetoothScanManager"); thread.start(); mTransitionalScanHelper.start(thread.getLooper()); Loading @@ -57,11 +53,17 @@ public class ScanController { public void stop() { Log.d(TAG, "stop()"); isAvailable = false; mIsAvailable = false; mBinder.clearScanController(); mTransitionalScanHelper.stop(); mTransitionalScanHelper.cleanup(); } /** Notify Scan manager of bluetooth profile connection state changes */ public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { mTransitionalScanHelper.notifyProfileConnectionStateChange(profile, fromState, toState); } TransitionalScanHelper getTransitionalScanHelper() { return mTransitionalScanHelper; } Loading @@ -71,20 +73,12 @@ public class ScanController { } static class BluetoothScanBinder extends IBluetoothScan.Stub { private final ScanController mScanController; private ScanController mScanController; BluetoothScanBinder(ScanController scanController) { mScanController = scanController; } private ScanController getScanController() { if (mScanController.isAvailable) { return mScanController; } Log.e(TAG, "getScanController() - ScanController requested, but not available!"); return null; } @Override public void registerScanner( IScannerCallback callback, Loading Loading @@ -236,5 +230,18 @@ public class ScanController { .getTransitionalScanHelper() .numHwTrackFiltersAvailable(attributionSource); } private void clearScanController() { mScanController = null; } private ScanController getScanController() { ScanController controller = mScanController; if (controller != null && controller.mIsAvailable) { return controller; } Log.e(TAG, "getScanController() - ScanController requested, but not available!"); return null; } } }
android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java +134 −2 Original line number Diff line number Diff line Loading @@ -409,9 +409,11 @@ public class AdapterServiceTest { TestUtils.syncHandler(looper, AdapterState.BLE_TURN_ON); verifyStateChange(callback, STATE_OFF, STATE_BLE_TURNING_ON); if (!Flags.scanManagerRefactor()) { TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_REGISTERED); TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } verify(nativeInterface).enable(); adapter.stateChangeCallback(AbstractionLayer.BT_STATE_ON); Loading Loading @@ -675,6 +677,136 @@ public class AdapterServiceTest { assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); } @Test public void startBleOnly_whenScanManagerRefactorFlagIsOff_onlyStartGattProfile() { mSetFlagsRule.disableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); mAdapterService.bringUpBle(); assertThat(mAdapterService.getBluetoothGatt()).isNotNull(); assertThat(mAdapterService.getBluetoothScan()).isNull(); dropNextMessage(MESSAGE_PROFILE_SERVICE_REGISTERED); dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } @Test public void startBleOnly_whenScanManagerRefactorFlagIsOn_onlyStartScanController() { mSetFlagsRule.enableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); mAdapterService.bringUpBle(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); assertThat(mAdapterService.getBluetoothScan()).isNotNull(); } @Test public void startBleOnly_whenScanManagerRefactorFlagIsOn_startAndStopScanController() { mSetFlagsRule.enableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); assertThat(mAdapterService.getBluetoothScan()).isNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); IBluetoothCallback callback = mock(IBluetoothCallback.class); Binder binder = mock(Binder.class); doReturn(binder).when(callback).asBinder(); mAdapterService.registerRemoteCallback(callback); offToBleOn( mLooper, mMockGattService, mAdapterService, mMockContext, mIBluetoothCallback, mNativeInterface); assertThat(mAdapterService.getBluetoothScan()).isNotNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); mAdapterService.stopBle(); TestUtils.syncHandler(mLooper, AdapterState.BLE_TURN_OFF); verifyStateChange(callback, STATE_BLE_ON, STATE_BLE_TURNING_OFF); verify(mNativeInterface).disable(); mAdapterService.stateChangeCallback(AbstractionLayer.BT_STATE_OFF); TestUtils.syncHandler(mLooper, AdapterState.BLE_STOPPED); verifyStateChange(callback, STATE_BLE_TURNING_OFF, STATE_OFF); assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); mAdapterService.unregisterRemoteCallback(callback); assertThat(mAdapterService.getBluetoothScan()).isNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); } @Test public void startBrDr_whenScanManagerRefactorFlagIsOn_startAndStopScanController() { mSetFlagsRule.enableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR); assertThat(mAdapterService.getBluetoothScan()).isNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); IBluetoothCallback callback = mock(IBluetoothCallback.class); Binder binder = mock(Binder.class); doReturn(binder).when(callback).asBinder(); mAdapterService.registerRemoteCallback(callback); assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF); offToBleOn( mLooper, mMockGattService, mAdapterService, mMockContext, mIBluetoothCallback, mNativeInterface); assertThat(mAdapterService.getBluetoothScan()).isNotNull(); assertThat(mAdapterService.getBluetoothGatt()).isNull(); mAdapterService.startBrEdr(); TestUtils.syncHandler(mLooper, AdapterState.USER_TURN_ON); verifyStateChange(callback, STATE_BLE_ON, STATE_TURNING_ON); // Start Mock PBAP, PAN, and GATT services assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(3); List<ProfileService> services = List.of(mMockService, mMockService2, mMockGattService); for (ProfileService service : services) { mAdapterService.addProfile(service); TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_REGISTERED); } for (ProfileService service : services) { mAdapterService.onProfileServiceStateChanged(service, STATE_ON); TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } TestUtils.syncHandler(mLooper, AdapterState.BREDR_STARTED); verifyStateChange(callback, STATE_TURNING_ON, STATE_ON); assertThat(mAdapterService.getState()).isEqualTo(STATE_ON); mAdapterService.disable(); TestUtils.syncHandler(mLooper, AdapterState.USER_TURN_OFF); verifyStateChange(callback, STATE_ON, STATE_TURNING_OFF); // Stop PBAP, PAN, and GATT services assertThat(mAdapterService.mSetProfileServiceStateCounter).isEqualTo(6); for (ProfileService service : services) { mAdapterService.onProfileServiceStateChanged(service, STATE_OFF); TestUtils.syncHandler(mLooper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED); } TestUtils.syncHandler(mLooper, AdapterState.BREDR_STOPPED); verifyStateChange(callback, STATE_TURNING_OFF, STATE_BLE_ON); assertThat(mAdapterService.getState()).isEqualTo(STATE_BLE_ON); mAdapterService.unregisterRemoteCallback(callback); } /** * Test: Don't start a classic profile * Check whether the AdapterService quits gracefully Loading