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

Commit 764a626d authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Move updateAudioProfile work to bg

updateAudioProfile makes calls to determine state of
CachedBluetoothDevice. Those calls need to happe in the background. As
this is called from the callback in updateConnected (which ends up being
called in main thread), we need to send this off thread.

Also, add annotations on methods we know should be called from a bg
thread.

Test: atest BluetoothControllerImplTest
Test: perfetto trace (no calls in main thread after continuation)
Fixes: 304103830
Fixes: 289430339
Change-Id: Ie1cdbdf63ea6731c553c827fcdbfb8bef340c400
parent 721668de
Loading
Loading
Loading
Loading
+33 −21
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.UserHandle;
import android.os.UserManager;

import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;

import com.android.internal.annotations.GuardedBy;
import com.android.settingslib.bluetooth.BluetoothCallback;
@@ -36,6 +37,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.systemui.bluetooth.BluetoothLogger;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.settings.UserTracker;
@@ -81,6 +83,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
    private int mState;

    private final BluetoothAdapter mAdapter;

    private final Executor mBackgroundExecutor;
    /**
     */
    @Inject
@@ -90,6 +94,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
            DumpManager dumpManager,
            BluetoothLogger logger,
            BluetoothRepository bluetoothRepository,
            @Background Executor executor,
            @Main Looper mainLooper,
            @Nullable LocalBluetoothManager localBluetoothManager,
            @Nullable BluetoothAdapter bluetoothAdapter) {
@@ -98,6 +103,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
        mBluetoothRepository = bluetoothRepository;
        mLocalBluetoothManager = localBluetoothManager;
        mHandler = new H(mainLooper);
        mBackgroundExecutor = executor;
        if (mLocalBluetoothManager != null) {
            mLocalBluetoothManager.getEventManager().registerCallback(this);
            mLocalBluetoothManager.getProfileManager().addServiceListener(this);
@@ -218,6 +224,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
        return mIsActive;
    }

    @WorkerThread
    @Override
    public void setBluetoothEnabled(boolean enabled) {
        if (mLocalBluetoothManager != null) {
@@ -230,6 +237,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
        return mLocalBluetoothManager != null;
    }

    @WorkerThread
    @Override
    public String getConnectedDeviceName() {
        synchronized (mConnectedDevices) {
@@ -251,6 +259,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
                getDevices(), this::onConnectionStatusFetched);
    }

    // Careful! This may be invoked in the main thread.
    private void onConnectionStatusFetched(ConnectionStatusModel status) {
        List<CachedBluetoothDevice> newList = status.getConnectedDevices();
        int state = status.getMaxConnectionState();
@@ -282,6 +291,9 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
    }

    private void updateAudioProfile() {
        // We want this in the background as calls inside `LocalBluetoothProfile` end up being
        // binder calls
        mBackgroundExecutor.execute(() -> {
            boolean audioProfileConnected = false;
            boolean otherProfileConnected = false;

@@ -305,7 +317,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
                mAudioProfileOnly = audioProfileOnly;
                mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED);
            }

        });
    }

    @Override
+2 −1
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@ interface BluetoothRepository {
    /**
     * Fetches the connection statuses for the given [currentDevices] and invokes [callback] once
     * those statuses have been fetched. The fetching occurs on a background thread because IPCs may
     * be required to fetch the statuses (see b/271058380).
     * be required to fetch the statuses (see b/271058380). However, the callback will be invoked in
     * the main thread.
     */
    fun fetchConnectionStatusInBackground(
        currentDevices: Collection<CachedBluetoothDevice>,
+12 −0
Original line number Diff line number Diff line
@@ -75,6 +75,8 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
    private BluetoothAdapter mMockAdapter;
    private List<CachedBluetoothDevice> mDevices;

    private FakeExecutor mBackgroundExecutor;

    @Before
    public void setup() throws Exception {
        mTestableLooper = TestableLooper.get(this);
@@ -91,6 +93,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
        when(mMockBluetoothManager.getProfileManager())
                .thenReturn(mock(LocalBluetoothProfileManager.class));
        mMockDumpManager = mock(DumpManager.class);
        mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());

        BluetoothRepository bluetoothRepository =
                new FakeBluetoothRepository(mMockBluetoothManager);
@@ -101,6 +104,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
                mMockDumpManager,
                mock(BluetoothLogger.class),
                bluetoothRepository,
                mBackgroundExecutor,
                mTestableLooper.getLooper(),
                mMockBluetoothManager,
                mMockAdapter);
@@ -205,6 +209,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
        mBluetoothControllerImpl.onAclConnectionStateChanged(device,
                BluetoothProfile.STATE_CONNECTED);
        mBluetoothControllerImpl.onActiveDeviceChanged(device, BluetoothProfile.HEADSET);
        mBackgroundExecutor.runAllReady();

        assertTrue(mBluetoothControllerImpl.isBluetoothAudioActive());
        assertTrue(mBluetoothControllerImpl.isBluetoothAudioProfileOnly());
@@ -290,6 +295,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
                BluetoothProfile.LE_AUDIO, /* isConnected= */ true, /* isActive= */ false);

        mBluetoothControllerImpl.onDeviceAdded(device);
        mBackgroundExecutor.runAllReady();

        assertThat(mBluetoothControllerImpl.isBluetoothAudioProfileOnly()).isTrue();
    }
@@ -300,6 +306,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
                BluetoothProfile.HEADSET, /* isConnected= */ true, /* isActive= */ false);

        mBluetoothControllerImpl.onDeviceAdded(device);
        mBackgroundExecutor.runAllReady();

        assertThat(mBluetoothControllerImpl.isBluetoothAudioProfileOnly()).isTrue();
    }
@@ -310,6 +317,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
                BluetoothProfile.A2DP, /* isConnected= */ true, /* isActive= */ false);

        mBluetoothControllerImpl.onDeviceAdded(device);
        mBackgroundExecutor.runAllReady();

        assertThat(mBluetoothControllerImpl.isBluetoothAudioProfileOnly()).isTrue();
    }
@@ -320,6 +328,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
                BluetoothProfile.HEARING_AID, /* isConnected= */ true, /* isActive= */ false);

        mBluetoothControllerImpl.onDeviceAdded(device);
        mBackgroundExecutor.runAllReady();

        assertThat(mBluetoothControllerImpl.isBluetoothAudioProfileOnly()).isTrue();
    }
@@ -337,6 +346,8 @@ public class BluetoothControllerImplTest extends SysuiTestCase {
        mBluetoothControllerImpl.onDeviceAdded(device2);
        mBluetoothControllerImpl.onDeviceAdded(device3);

        mBackgroundExecutor.runAllReady();

        assertThat(mBluetoothControllerImpl.isBluetoothAudioProfileOnly()).isTrue();
    }

@@ -349,6 +360,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase {

        mBluetoothControllerImpl.onDeviceAdded(device1);
        mBluetoothControllerImpl.onDeviceAdded(device2);
        mBackgroundExecutor.runAllReady();

        assertThat(mBluetoothControllerImpl.isBluetoothAudioProfileOnly()).isFalse();
    }