Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26f07e70 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Scan from ScanController instead of GattService" into main

parents 928363bd 4fbc1a04
Loading
Loading
Loading
Loading
+100 −37
Original line number Diff line number Diff line
@@ -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()) {
@@ -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
@@ -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);
@@ -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) {
@@ -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();
@@ -1060,6 +1087,7 @@ public class AdapterService extends Service {
                setAllProfileServiceStates(supportedProfileServices, BluetoothAdapter.STATE_ON);
            }
        }
    }

    void stopProfileServices() {
        // Make sure to stop classic background tasks now
@@ -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);
@@ -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) {
@@ -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();
    }
@@ -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);
        }
    }
@@ -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}.
+23 −16
Original line number Diff line number Diff line
@@ -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());
@@ -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;
    }
@@ -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,
@@ -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;
        }
    }
}
+134 −2
Original line number Diff line number Diff line
@@ -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);
@@ -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