diff options
| author | 2025-01-22 16:34:30 +0000 | |
|---|---|---|
| committer | 2025-01-22 16:34:30 +0000 | |
| commit | 54049933b6684a89864c25758d858ef68445d79b (patch) | |
| tree | b49bd788fb6705dee28b26c22cc3ebecce640e32 | |
| parent | a19c3c30246cf7f069838bbba585146168a441d3 (diff) | |
[2/2] Use static singleton AudioManagerRouteController
This change makes the output audio routing HSUM compatible.
Design doc: go/mr2-hsum-compatible
Change-Id: Ib9c3b72d4b333e9e2e057fa4257d21945fb3ecd8
Bug: b/372868909
Test: locally
Flag: com.android.media.flags.enable_use_of_singleton_audio_manager_route_controller
3 files changed, 59 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/media/AudioManagerRouteController.java b/services/core/java/com/android/server/media/AudioManagerRouteController.java index 280d051be239..14f870bd4e87 100644 --- a/services/core/java/com/android/server/media/AudioManagerRouteController.java +++ b/services/core/java/com/android/server/media/AudioManagerRouteController.java @@ -117,6 +117,35 @@ import java.util.concurrent.CopyOnWriteArrayList; @NonNull private MediaRoute2Info mSelectedRoute; + // A singleton AudioManagerRouteController. + private static AudioManagerRouteController mInstance; + + // A flag indicating if the start function has been called. + private boolean mStarted = false; + + // Get the singleton AudioManagerRouteController. Create a new one if it's not available yet. + public static AudioManagerRouteController getInstance( + @NonNull Context context, + @NonNull AudioManager audioManager, + @NonNull Looper looper, + @NonNull AudioProductStrategy strategyForMedia, + @NonNull BluetoothAdapter btAdapter) { + if (!com.android.media.flags.Flags.enableUseOfSingletonAudioManagerRouteController()) { + return new AudioManagerRouteController( + context, audioManager, looper, strategyForMedia, btAdapter); + } + + synchronized (AudioManagerRouteController.class) { + if (mInstance == null) { + mInstance = + new AudioManagerRouteController( + context, audioManager, looper, strategyForMedia, btAdapter); + } + + return mInstance; + } + } + // TODO: b/305199571 - Support nullable btAdapter and strategyForMedia which, when null, means // no support for transferring to inactive bluetooth routes and transferring to any routes // respectively. @@ -130,13 +159,11 @@ import java.util.concurrent.CopyOnWriteArrayList; @NonNull AudioManager audioManager, @NonNull Looper looper, @NonNull AudioProductStrategy strategyForMedia, - @NonNull BluetoothAdapter btAdapter, - @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) { + @NonNull BluetoothAdapter btAdapter) { mContext = Objects.requireNonNull(context); mAudioManager = Objects.requireNonNull(audioManager); mHandler = new Handler(Objects.requireNonNull(looper)); mStrategyForMedia = Objects.requireNonNull(strategyForMedia); - mOnDeviceRouteChangedListeners.add(Objects.requireNonNull(onDeviceRouteChangedListener)); mBuiltInSpeakerSuitabilityStatus = DeviceRouteController.getBuiltInSpeakerSuitabilityStatus(mContext); @@ -154,6 +181,11 @@ import java.util.concurrent.CopyOnWriteArrayList; mOnDeviceRouteChangedListeners.add(onDeviceRouteChangedListener); } + public void unregisterRouteChangeListener( + @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) { + mOnDeviceRouteChangedListeners.remove(onDeviceRouteChangedListener); + } + @RequiresPermission( anyOf = { Manifest.permission.MODIFY_AUDIO_ROUTING, @@ -161,7 +193,18 @@ import java.util.concurrent.CopyOnWriteArrayList; }) @Override public void start(UserHandle mUser) { - mBluetoothRouteController.start(mUser); + // When AudioManagerRouteController is singleton, only need to call this function once. + if (com.android.media.flags.Flags.enableUseOfSingletonAudioManagerRouteController()) { + if (mStarted) { + return; + } + mStarted = true; + } + + mBluetoothRouteController.start( + com.android.media.flags.Flags.enableUseOfSingletonAudioManagerRouteController() + ? UserHandle.SYSTEM + : mUser); mAudioManager.registerAudioDeviceCallback(mAudioDeviceCallback, mHandler); mAudioManager.addOnDevicesForAttributesChangedListener( AudioRoutingUtils.ATTRIBUTES_MEDIA, @@ -176,6 +219,11 @@ import java.util.concurrent.CopyOnWriteArrayList; }) @Override public void stop() { + // Singleton AudioManagerRouteController doesn't need to call stop function. + if (com.android.media.flags.Flags.enableUseOfSingletonAudioManagerRouteController()) { + return; + } + mAudioManager.removeOnDevicesForAttributesChangedListener( mOnDevicesForAttributesChangedListener); mAudioManager.unregisterAudioDeviceCallback(mAudioDeviceCallback); diff --git a/services/core/java/com/android/server/media/DeviceRouteController.java b/services/core/java/com/android/server/media/DeviceRouteController.java index dff0adfca370..0a4cbcd1ea31 100644 --- a/services/core/java/com/android/server/media/DeviceRouteController.java +++ b/services/core/java/com/android/server/media/DeviceRouteController.java @@ -65,13 +65,11 @@ import java.util.List; if (strategyForMedia != null && btAdapter != null && Flags.enableAudioPoliciesDeviceAndBluetoothController()) { - return new AudioManagerRouteController( - context, - audioManager, - looper, - strategyForMedia, - btAdapter, - onDeviceRouteChangedListener); + AudioManagerRouteController controller = + AudioManagerRouteController.getInstance( + context, audioManager, looper, strategyForMedia, btAdapter); + controller.registerRouteChangeListener(onDeviceRouteChangedListener); + return controller; } else { IAudioService audioService = IAudioService.Stub.asInterface( diff --git a/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java b/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java index 439243e85e75..6e9a28f344e3 100644 --- a/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java +++ b/services/tests/media/mediarouterservicetest/src/com/android/server/media/AudioManagerRouteControllerTest.java @@ -139,8 +139,8 @@ public class AudioManagerRouteControllerTest { mMockAudioManager, Looper.getMainLooper(), mMediaAudioProductStrategy, - btAdapter, - mOnDeviceRouteChangedListener); + btAdapter); + mControllerUnderTest.registerRouteChangeListener(mOnDeviceRouteChangedListener); mControllerUnderTest.start(UserHandle.CURRENT_OR_SELF); ArgumentCaptor<AudioDeviceCallback> deviceCallbackCaptor = |