summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/media/DeviceRouteController.java173
-rw-r--r--services/core/java/com/android/server/media/LegacyDeviceRouteController.java178
-rw-r--r--services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java)12
3 files changed, 214 insertions, 149 deletions
diff --git a/services/core/java/com/android/server/media/DeviceRouteController.java b/services/core/java/com/android/server/media/DeviceRouteController.java
index 8bd6416a6ddb..3fc930903883 100644
--- a/services/core/java/com/android/server/media/DeviceRouteController.java
+++ b/services/core/java/com/android/server/media/DeviceRouteController.java
@@ -16,32 +16,12 @@
package com.android.server.media;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
-import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
-import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
-import static android.media.MediaRoute2Info.TYPE_DOCK;
-import static android.media.MediaRoute2Info.TYPE_HDMI;
-import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
-
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.Context;
import android.media.AudioManager;
-import android.media.AudioRoutesInfo;
-import android.media.IAudioRoutesObserver;
import android.media.IAudioService;
import android.media.MediaRoute2Info;
-import android.os.RemoteException;
import android.os.ServiceManager;
-import android.util.Slog;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Objects;
/**
* Controls device routes.
@@ -49,145 +29,52 @@ import java.util.Objects;
* <p>A device route is a system wired route, for example, built-in speaker, wired
* headsets and headphones, dock, hdmi, or usb devices.
*
- * <p>Thread safe.
- *
* @see SystemMediaRoute2Provider
*/
-/* package */ final class DeviceRouteController {
-
- private static final String TAG = "WiredRoutesController";
-
- private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
-
- @NonNull
- private final Context mContext;
- @NonNull
- private final AudioManager mAudioManager;
- @NonNull
- private final IAudioService mAudioService;
-
- @NonNull
- private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
- @NonNull
- private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
-
- private int mDeviceVolume;
- private MediaRoute2Info mDeviceRoute;
+/* package */ interface DeviceRouteController {
+ /**
+ * Returns a new instance of {@link DeviceRouteController}.
+ */
/* package */ static DeviceRouteController createInstance(@NonNull Context context,
@NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
AudioManager audioManager = context.getSystemService(AudioManager.class);
IAudioService audioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
- return new DeviceRouteController(context,
+ return new LegacyDeviceRouteController(context,
audioManager,
audioService,
onDeviceRouteChangedListener);
}
- @VisibleForTesting
- /* package */ DeviceRouteController(@NonNull Context context,
- @NonNull AudioManager audioManager,
- @NonNull IAudioService audioService,
- @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
- Objects.requireNonNull(context);
- Objects.requireNonNull(audioManager);
- Objects.requireNonNull(audioService);
- Objects.requireNonNull(onDeviceRouteChangedListener);
-
- mContext = context;
- mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
-
- mAudioManager = audioManager;
- mAudioService = audioService;
-
- AudioRoutesInfo newAudioRoutes = null;
- try {
- newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
- } catch (RemoteException e) {
- Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
- }
-
- mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
- }
-
+ /**
+ * Returns currently selected device (built-in or wired) route.
+ *
+ * @return non-null device route.
+ */
@NonNull
- /* package */ synchronized MediaRoute2Info getDeviceRoute() {
- return mDeviceRoute;
- }
-
- /* package */ synchronized boolean updateVolume(int volume) {
- if (mDeviceVolume == volume) {
- return false;
- }
-
- mDeviceVolume = volume;
- mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
- .setVolume(volume)
- .build();
-
- return true;
- }
-
- private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
- int name = R.string.default_audio_route_name;
- int type = TYPE_BUILTIN_SPEAKER;
-
- if (newRoutes != null) {
- if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
- type = TYPE_WIRED_HEADPHONES;
- name = com.android.internal.R.string.default_audio_route_name_headphones;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
- type = TYPE_WIRED_HEADSET;
- name = com.android.internal.R.string.default_audio_route_name_headphones;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
- type = TYPE_DOCK;
- name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
- type = TYPE_HDMI;
- name = com.android.internal.R.string.default_audio_route_name_external_device;
- } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
- type = TYPE_USB_DEVICE;
- name = com.android.internal.R.string.default_audio_route_name_usb;
- }
- }
-
- synchronized (this) {
- return new MediaRoute2Info.Builder(
- DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
- .setVolumeHandling(mAudioManager.isVolumeFixed()
- ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
- : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
- .setVolume(mDeviceVolume)
- .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
- .setType(type)
- .addFeature(FEATURE_LIVE_AUDIO)
- .addFeature(FEATURE_LIVE_VIDEO)
- .addFeature(FEATURE_LOCAL_PLAYBACK)
- .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
- .build();
- }
- }
-
- private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
- mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
- }
-
- /* package */ interface OnDeviceRouteChangedListener {
+ MediaRoute2Info getDeviceRoute();
+
+ /**
+ * Updates device route volume.
+ *
+ * @param volume specifies a volume for the device route or 0 for unknown.
+ * @return {@code true} if updated successfully and {@code false} otherwise.
+ */
+ boolean updateVolume(int volume);
+
+ /**
+ * Interface for receiving events when device route has changed.
+ */
+ interface OnDeviceRouteChangedListener {
+
+ /**
+ * Called when device route has changed.
+ *
+ * @param deviceRoute non-null device route.
+ */
void onDeviceRouteChanged(@NonNull MediaRoute2Info deviceRoute);
}
- private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
-
- @Override
- public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
- MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
- synchronized (DeviceRouteController.this) {
- mDeviceRoute = deviceRoute;
- }
- notifyDeviceRouteUpdate(deviceRoute);
- }
- }
-
}
diff --git a/services/core/java/com/android/server/media/LegacyDeviceRouteController.java b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
new file mode 100644
index 000000000000..c9b62acb5ceb
--- /dev/null
+++ b/services/core/java/com/android/server/media/LegacyDeviceRouteController.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+/**
+ * Controls device routes.
+ *
+ * <p>A device route is a system wired route, for example, built-in speaker, wired
+ * headsets and headphones, dock, hdmi, or usb devices.
+ *
+ * <p>Thread safe.
+ *
+ * @see SystemMediaRoute2Provider
+ */
+/* package */ final class LegacyDeviceRouteController implements DeviceRouteController {
+
+ private static final String TAG = "WiredRoutesController";
+
+ private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final AudioManager mAudioManager;
+ @NonNull
+ private final IAudioService mAudioService;
+
+ @NonNull
+ private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+ @NonNull
+ private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+ private int mDeviceVolume;
+ private MediaRoute2Info mDeviceRoute;
+
+ @VisibleForTesting
+ /* package */ LegacyDeviceRouteController(@NonNull Context context,
+ @NonNull AudioManager audioManager,
+ @NonNull IAudioService audioService,
+ @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+ Objects.requireNonNull(context);
+ Objects.requireNonNull(audioManager);
+ Objects.requireNonNull(audioService);
+ Objects.requireNonNull(onDeviceRouteChangedListener);
+
+ mContext = context;
+ mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+ mAudioManager = audioManager;
+ mAudioService = audioService;
+
+ AudioRoutesInfo newAudioRoutes = null;
+ try {
+ newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+ }
+
+ mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ }
+
+ @Override
+ @NonNull
+ public synchronized MediaRoute2Info getDeviceRoute() {
+ return mDeviceRoute;
+ }
+
+ @Override
+ public synchronized boolean updateVolume(int volume) {
+ if (mDeviceVolume == volume) {
+ return false;
+ }
+
+ mDeviceVolume = volume;
+ mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+ .setVolume(volume)
+ .build();
+
+ return true;
+ }
+
+ private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+ int name = R.string.default_audio_route_name;
+ int type = TYPE_BUILTIN_SPEAKER;
+
+ if (newRoutes != null) {
+ if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+ type = TYPE_WIRED_HEADPHONES;
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+ type = TYPE_WIRED_HEADSET;
+ name = com.android.internal.R.string.default_audio_route_name_headphones;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+ type = TYPE_DOCK;
+ name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+ type = TYPE_HDMI;
+ name = com.android.internal.R.string.default_audio_route_name_external_device;
+ } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+ type = TYPE_USB_DEVICE;
+ name = com.android.internal.R.string.default_audio_route_name_usb;
+ }
+ }
+
+ synchronized (this) {
+ return new MediaRoute2Info.Builder(
+ DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+ .setVolumeHandling(mAudioManager.isVolumeFixed()
+ ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+ : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+ .setVolume(mDeviceVolume)
+ .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+ .setType(type)
+ .addFeature(FEATURE_LIVE_AUDIO)
+ .addFeature(FEATURE_LIVE_VIDEO)
+ .addFeature(FEATURE_LOCAL_PLAYBACK)
+ .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+ .build();
+ }
+ }
+
+ private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
+ mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+ }
+
+ private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+ @Override
+ public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+ MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+ synchronized (LegacyDeviceRouteController.this) {
+ mDeviceRoute = deviceRoute;
+ }
+ notifyDeviceRouteUpdate(deviceRoute);
+ }
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java
index 24ed42cab63a..24e48517f280 100644
--- a/services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/LegacyDeviceRouteControllerTest.java
@@ -50,7 +50,7 @@ import java.util.Arrays;
import java.util.Collection;
@RunWith(Enclosed.class)
-public class DeviceRouteControllerTest {
+public class LegacyDeviceRouteControllerTest {
private static final String DEFAULT_ROUTE_NAME = "default_route";
private static final String DEFAULT_HEADPHONES_NAME = "headphone";
@@ -97,7 +97,7 @@ public class DeviceRouteControllerTest {
// Default route should be initialized even when AudioService returns null.
when(mAudioService.startWatchingRoutes(any())).thenReturn(null);
- DeviceRouteController deviceRouteController = new DeviceRouteController(
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,
@@ -122,7 +122,7 @@ public class DeviceRouteControllerTest {
AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
when(mAudioService.startWatchingRoutes(any())).thenReturn(fakeBluetoothAudioRoute);
- DeviceRouteController deviceRouteController = new DeviceRouteController(
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,
@@ -236,7 +236,7 @@ public class DeviceRouteControllerTest {
when(mResources.getText(mExpectedRouteNameResource))
.thenReturn(mExpectedRouteNameValue);
- DeviceRouteController deviceRouteController = new DeviceRouteController(
+ LegacyDeviceRouteController deviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,
@@ -269,7 +269,7 @@ public class DeviceRouteControllerTest {
@Captor
private ArgumentCaptor<IAudioRoutesObserver.Stub> mAudioRoutesObserverCaptor;
- private DeviceRouteController mDeviceRouteController;
+ private LegacyDeviceRouteController mDeviceRouteController;
private IAudioRoutesObserver.Stub mAudioRoutesObserver;
@Before
@@ -287,7 +287,7 @@ public class DeviceRouteControllerTest {
when(mAudioService.startWatchingRoutes(mAudioRoutesObserverCaptor.capture()))
.thenReturn(audioRoutesInfo);
- mDeviceRouteController = new DeviceRouteController(
+ mDeviceRouteController = new LegacyDeviceRouteController(
mContext,
mAudioManager,
mAudioService,