diff options
| author | 2023-10-11 11:11:27 -0400 | |
|---|---|---|
| committer | 2023-10-11 11:13:59 -0400 | |
| commit | 764a626d297f94df28b1067a5afe791a5eac985c (patch) | |
| tree | f2af6881348ec002a9931773d1cbcbd1b72a2318 | |
| parent | 721668de97aee4ffbaf6ff6aa07cf49b5ed08fe8 (diff) | |
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
3 files changed, 47 insertions, 22 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index 945cc6bc2519..53b343c09329 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -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,30 +291,33 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } private void updateAudioProfile() { - boolean audioProfileConnected = false; - boolean otherProfileConnected = false; - - for (CachedBluetoothDevice device : getDevices()) { - for (LocalBluetoothProfile profile : device.getProfiles()) { - int profileId = profile.getProfileId(); - boolean isConnected = device.isConnectedProfile(profile); - if (profileId == BluetoothProfile.HEADSET - || profileId == BluetoothProfile.A2DP - || profileId == BluetoothProfile.HEARING_AID - || profileId == BluetoothProfile.LE_AUDIO) { - audioProfileConnected |= isConnected; - } else { - otherProfileConnected |= isConnected; + // We want this in the background as calls inside `LocalBluetoothProfile` end up being + // binder calls + mBackgroundExecutor.execute(() -> { + boolean audioProfileConnected = false; + boolean otherProfileConnected = false; + + for (CachedBluetoothDevice device : getDevices()) { + for (LocalBluetoothProfile profile : device.getProfiles()) { + int profileId = profile.getProfileId(); + boolean isConnected = device.isConnectedProfile(profile); + if (profileId == BluetoothProfile.HEADSET + || profileId == BluetoothProfile.A2DP + || profileId == BluetoothProfile.HEARING_AID + || profileId == BluetoothProfile.LE_AUDIO) { + audioProfileConnected |= isConnected; + } else { + otherProfileConnected |= isConnected; + } } } - } - - boolean audioProfileOnly = (audioProfileConnected && !otherProfileConnected); - if (audioProfileOnly != mAudioProfileOnly) { - mAudioProfileOnly = audioProfileOnly; - mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); - } + boolean audioProfileOnly = (audioProfileConnected && !otherProfileConnected); + if (audioProfileOnly != mAudioProfileOnly) { + mAudioProfileOnly = audioProfileOnly; + mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); + } + }); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt index 80f3d76f0897..96717c7542d5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/bluetooth/BluetoothRepository.kt @@ -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>, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java index e76163575738..a1da16737aa4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java @@ -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(); } |