diff options
author | Oliver Woodman <olly@google.com> | 2021-11-03 18:24:09 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-12-25 00:32:43 +0000 |
commit | be0b4fe805582d6c48dbf64ab963fb2ea1878d21 (patch) | |
tree | 375d2fa161cfb842cfb967937a50ca1e8942336a | |
parent | adfc2c6f143d61f617fd73c3bb6b0d1549d68dc2 (diff) | |
download | base-be0b4fe805582d6c48dbf64ab963fb2ea1878d21.tar.gz |
Tweak volume adjustment rules
Test: manual
Bug: 197586676
Bug: 202500642
Merged-In: If531a23f5e7b242d3d637966b74b67acfd303199
Change-Id: If531a23f5e7b242d3d637966b74b67acfd303199
(cherry picked from commit 022081595bf4a082f8354b852eae6d5a015be3fe)
Merged-In:If531a23f5e7b242d3d637966b74b67acfd303199
8 files changed, 102 insertions, 17 deletions
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index db43b5b31e7e..89fb933207f7 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1894,8 +1894,9 @@ STREAM_MUSIC as if it's on TV platform. --> <bool name="config_single_volume">false</bool> - <!-- Flag indicating whether the volume panel should show remote sessions. --> - <bool name="config_volumeShowRemoteSessions">true</bool> + <!-- Flag indicating whether platform level volume adjustments are enabled for remote sessions + on grouped devices. --> + <bool name="config_volumeAdjustmentForRemoteGroupSessions">true</bool> <!-- Flag indicating that an outbound call must have a call capable phone account that has declared it can process the call's handle. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index adb046e76c88..85034a8a4be2 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4422,7 +4422,7 @@ <java-symbol type="dimen" name="config_wallpaperDimAmount" /> - <java-symbol type="bool" name="config_volumeShowRemoteSessions" /> + <java-symbol type="bool" name="config_volumeAdjustmentForRemoteGroupSessions" /> <java-symbol type="integer" name="config_customizedMaxCachedProcesses" /> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index e57059894786..cd6a77836304 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -33,7 +33,11 @@ import android.media.AudioManager; import android.media.AudioSystem; import android.media.IAudioService; import android.media.IVolumeController; +import android.media.MediaRoute2Info; +import android.media.MediaRouter2Manager; +import android.media.RoutingSessionInfo; import android.media.VolumePolicy; +import android.media.session.MediaController; import android.media.session.MediaController.PlaybackInfo; import android.media.session.MediaSession.Token; import android.net.Uri; @@ -71,6 +75,7 @@ import com.android.systemui.util.concurrency.ThreadFactory; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -118,6 +123,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa private final Context mContext; private final Looper mWorkerLooper; private final PackageManager mPackageManager; + private final MediaRouter2Manager mRouter2Manager; private final WakefulnessLifecycle mWakefulnessLifecycle; private AudioManager mAudio; private IAudioService mAudioService; @@ -179,6 +185,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa mWorkerLooper = theadFactory.buildLooperOnNewThread( VolumeDialogControllerImpl.class.getSimpleName()); mWorker = new W(mWorkerLooper); + mRouter2Manager = MediaRouter2Manager.getInstance(mContext); mMediaSessionsCallbacksW = new MediaSessionsCallbacks(mContext); mMediaSessions = createMediaSessions(mContext, mWorkerLooper, mMediaSessionsCallbacksW); mAudio = audioManager; @@ -1149,16 +1156,16 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa private final HashMap<Token, Integer> mRemoteStreams = new HashMap<>(); private int mNextStream = DYNAMIC_STREAM_START_INDEX; - private final boolean mShowRemoteSessions; + private final boolean mVolumeAdjustmentForRemoteGroupSessions; public MediaSessionsCallbacks(Context context) { - mShowRemoteSessions = context.getResources().getBoolean( - com.android.internal.R.bool.config_volumeShowRemoteSessions); + mVolumeAdjustmentForRemoteGroupSessions = context.getResources().getBoolean( + com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions); } @Override public void onRemoteUpdate(Token token, String name, PlaybackInfo pi) { - if (mShowRemoteSessions) { + if (showForSession(token)) { addStream(token, "onRemoteUpdate"); int stream = 0; @@ -1190,7 +1197,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa @Override public void onRemoteVolumeChanged(Token token, int flags) { - if (mShowRemoteSessions) { + if (showForSession(token)) { addStream(token, "onRemoteVolumeChanged"); int stream = 0; synchronized (mRemoteStreams) { @@ -1214,7 +1221,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa @Override public void onRemoteRemoved(Token token) { - if (mShowRemoteSessions) { + if (showForSession(token)) { int stream = 0; synchronized (mRemoteStreams) { if (!mRemoteStreams.containsKey(token)) { @@ -1233,14 +1240,41 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } public void setStreamVolume(int stream, int level) { - if (mShowRemoteSessions) { - final Token t = findToken(stream); - if (t == null) { - Log.w(TAG, "setStreamVolume: No token found for stream: " + stream); - return; + final Token token = findToken(stream); + if (token == null) { + Log.w(TAG, "setStreamVolume: No token found for stream: " + stream); + return; + } + if (showForSession(token)) { + mMediaSessions.setVolume(token, level); + } + } + + private boolean showForSession(Token token) { + if (mVolumeAdjustmentForRemoteGroupSessions) { + return true; + } + MediaController ctr = new MediaController(mContext, token); + String packageName = ctr.getPackageName(); + List<RoutingSessionInfo> sessions = + mRouter2Manager.getRoutingSessions(packageName); + boolean foundNonSystemSession = false; + boolean isGroup = false; + for (RoutingSessionInfo session : sessions) { + if (!session.isSystemSession()) { + foundNonSystemSession = true; + int selectedRouteCount = session.getSelectedRoutes().size(); + if (selectedRouteCount > 1) { + isGroup = true; + break; + } } - mMediaSessions.setVolume(t, level); } + if (!foundNonSystemSession) { + Log.d(TAG, "No routing session for " + packageName); + return false; + } + return !isGroup; } private Token findToken(int stream) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java index 5c0efd36fcd1..c9462d651bc0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java @@ -101,6 +101,11 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase { // Initial non-set value when(mRingerModeLiveData.getValue()).thenReturn(-1); when(mRingerModeInternalLiveData.getValue()).thenReturn(-1); + // Enable group volume adjustments + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions, + true); + mCallback = mock(VolumeDialogControllerImpl.C.class); mThreadFactory.setLooper(TestableLooper.get(this).getLooper()); mVolumeController = new TestableVolumeDialogControllerImpl(mContext, diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java index 607218e20ea8..b424c2083bd4 100644 --- a/services/core/java/com/android/server/media/MediaSession2Record.java +++ b/services/core/java/com/android/server/media/MediaSession2Record.java @@ -146,6 +146,12 @@ public class MediaSession2Record implements MediaSessionRecordImpl { } @Override + public boolean canHandleVolumeKey() { + // TODO: Implement when MediaSession2 starts to get key events. + return false; + } + + @Override public int getSessionPolicies() { synchronized (mLock) { return mPolicies; diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 1525cd4da669..e4ed0e5d4186 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -26,7 +26,9 @@ import android.media.AudioAttributes; import android.media.AudioManager; import android.media.AudioSystem; import android.media.MediaMetadata; +import android.media.MediaRouter2Manager; import android.media.Rating; +import android.media.RoutingSessionInfo; import android.media.VolumeProvider; import android.media.session.ISession; import android.media.session.ISessionCallback; @@ -50,6 +52,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; +import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; @@ -121,6 +124,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR private final SessionCb mSessionCb; private final MediaSessionService mService; private final Context mContext; + private final boolean mVolumeAdjustmentForRemoteGroupSessions; private final Object mLock = new Object(); private final CopyOnWriteArrayList<ISessionControllerCallbackHolder> @@ -180,6 +184,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioAttrs = DEFAULT_ATTRIBUTES; mPolicies = policies; + mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions); // May throw RemoteException if the session app is killed. mSessionCb.mCb.asBinder().linkToDeath(this, 0); @@ -449,6 +455,33 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR } @Override + public boolean canHandleVolumeKey() { + if (isPlaybackTypeLocal() || mVolumeAdjustmentForRemoteGroupSessions) { + return true; + } + MediaRouter2Manager mRouter2Manager = MediaRouter2Manager.getInstance(mContext); + List<RoutingSessionInfo> sessions = + mRouter2Manager.getRoutingSessions(mPackageName); + boolean foundNonSystemSession = false; + boolean isGroup = false; + for (RoutingSessionInfo session : sessions) { + if (!session.isSystemSession()) { + foundNonSystemSession = true; + int selectedRouteCount = session.getSelectedRoutes().size(); + if (selectedRouteCount > 1) { + isGroup = true; + break; + } + } + } + if (!foundNonSystemSession) { + Log.d(TAG, "No routing session for " + mPackageName); + return false; + } + return !isGroup; + } + + @Override public int getSessionPolicies() { synchronized (mLock) { return mPolicies; diff --git a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java index 3c50597b8cfc..8f01f02f2ab1 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecordImpl.java +++ b/services/core/java/com/android/server/media/MediaSessionRecordImpl.java @@ -131,6 +131,13 @@ public interface MediaSessionRecordImpl extends AutoCloseable { KeyEvent ke, int sequenceId, ResultReceiver cb); /** + * Returns whether the media session can handle volume key events. + * + * @return True if this media session can handle volume key events, false otherwise. + */ + boolean canHandleVolumeKey(); + + /** * Get session policies from custom policy provider set when MediaSessionRecord is instantiated. * If custom policy does not exist, will return null. */ diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index c4c21df746b3..b75ba75e028b 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -325,8 +325,7 @@ class MediaSessionStack { int size = records.size(); for (int i = 0; i < size; i++) { MediaSessionRecord record = records.get(i); - // Do not send the volume key events to remote sessions. - if (record.checkPlaybackActiveState(true) && record.isPlaybackTypeLocal()) { + if (record.checkPlaybackActiveState(true) && record.canHandleVolumeKey()) { mCachedVolumeDefault = record; return record; } |