Loading services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java 0 → 100644 +175 −0 Original line number Diff line number Diff line /* * 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; /* package */ final class AudioPoliciesDeviceRouteController implements DeviceRouteController { private static final String TAG = "APDeviceRoutesController"; 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 */ AudioPoliciesDeviceRouteController(@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 public boolean selectRoute(@Nullable Integer type) { // No-op as the controller does not support selection from the outside of the class. return false; } @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 = R.string.default_audio_route_name_headphones; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) { type = TYPE_WIRED_HEADSET; name = R.string.default_audio_route_name_headphones; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) { type = TYPE_DOCK; name = R.string.default_audio_route_name_dock_speakers; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) { type = TYPE_HDMI; name = R.string.default_audio_route_name_external_device; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) { type = TYPE_USB_DEVICE; name = 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 (AudioPoliciesDeviceRouteController.this) { mDeviceRoute = deviceRoute; } notifyDeviceRouteUpdate(deviceRoute); } } } services/core/java/com/android/server/media/LegacyDeviceRouteController.java +1 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ import java.util.Objects; */ /* package */ final class LegacyDeviceRouteController implements DeviceRouteController { private static final String TAG = "WiredRoutesController"; private static final String TAG = "LDeviceRouteController"; private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE"; Loading Loading
services/core/java/com/android/server/media/AudioPoliciesDeviceRouteController.java 0 → 100644 +175 −0 Original line number Diff line number Diff line /* * 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; /* package */ final class AudioPoliciesDeviceRouteController implements DeviceRouteController { private static final String TAG = "APDeviceRoutesController"; 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 */ AudioPoliciesDeviceRouteController(@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 public boolean selectRoute(@Nullable Integer type) { // No-op as the controller does not support selection from the outside of the class. return false; } @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 = R.string.default_audio_route_name_headphones; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) { type = TYPE_WIRED_HEADSET; name = R.string.default_audio_route_name_headphones; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) { type = TYPE_DOCK; name = R.string.default_audio_route_name_dock_speakers; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) { type = TYPE_HDMI; name = R.string.default_audio_route_name_external_device; } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) { type = TYPE_USB_DEVICE; name = 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 (AudioPoliciesDeviceRouteController.this) { mDeviceRoute = deviceRoute; } notifyDeviceRouteUpdate(deviceRoute); } } }
services/core/java/com/android/server/media/LegacyDeviceRouteController.java +1 −1 Original line number Diff line number Diff line Loading @@ -54,7 +54,7 @@ import java.util.Objects; */ /* package */ final class LegacyDeviceRouteController implements DeviceRouteController { private static final String TAG = "WiredRoutesController"; private static final String TAG = "LDeviceRouteController"; private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE"; Loading