From b85523425990b82c791b5265eddc4d4a990791f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Budnik?= Date: Mon, 23 May 2022 12:38:50 +0000 Subject: [PATCH] Fix remote volume adjustment for Android U Bug: 228021646 Test: Manual Change-Id: I5d637103fffe2b83fdbae1730a4c9813410185a8 --- .../android/media/RoutingSessionInfo.java | 42 ++++++++++++++++++- .../RoutingSessionInfoTest.java | 24 ++++++++++- .../settingslib/media/InfoMediaManager.java | 31 ++++---------- .../volume/VolumeDialogControllerImpl.java | 22 ++++------ .../server/media/MediaSessionRecord.java | 26 +----------- 5 files changed, 80 insertions(+), 65 deletions(-) diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java index 3bea73febc24d..913ac6b975fb0 100644 --- a/media/java/android/media/RoutingSessionInfo.java +++ b/media/java/android/media/RoutingSessionInfo.java @@ -18,6 +18,7 @@ package android.media; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.res.Resources; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -48,6 +49,9 @@ public final class RoutingSessionInfo implements Parcelable { private static final String TAG = "RoutingSessionInfo"; + private static final String KEY_GROUP_ROUTE = "androidx.mediarouter.media.KEY_GROUP_ROUTE"; + private static final String KEY_VOLUME_HANDLING = "volumeHandling"; + final String mId; final CharSequence mName; final String mOwnerPackageName; @@ -67,6 +71,7 @@ public final class RoutingSessionInfo implements Parcelable { final Bundle mControlHints; final boolean mIsSystemSession; + RoutingSessionInfo(@NonNull Builder builder) { Objects.requireNonNull(builder, "builder must not be null."); @@ -85,12 +90,17 @@ public final class RoutingSessionInfo implements Parcelable { mTransferableRoutes = Collections.unmodifiableList( convertToUniqueRouteIds(builder.mTransferableRoutes)); - mVolumeHandling = builder.mVolumeHandling; mVolumeMax = builder.mVolumeMax; mVolume = builder.mVolume; - mControlHints = builder.mControlHints; mIsSystemSession = builder.mIsSystemSession; + + boolean volumeAdjustmentForRemoteGroupSessions = Resources.getSystem().getBoolean( + com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions); + mVolumeHandling = defineVolumeHandling(builder.mVolumeHandling, mSelectedRoutes, + volumeAdjustmentForRemoteGroupSessions); + + mControlHints = updateVolumeHandlingInHints(builder.mControlHints, mVolumeHandling); } RoutingSessionInfo(@NonNull Parcel src) { @@ -115,6 +125,34 @@ public final class RoutingSessionInfo implements Parcelable { mIsSystemSession = src.readBoolean(); } + private static Bundle updateVolumeHandlingInHints(Bundle controlHints, int volumeHandling) { + // Workaround to preserve retro-compatibility with androidx. + // See b/228021646 for more details. + if (controlHints != null && controlHints.containsKey(KEY_GROUP_ROUTE)) { + Bundle groupRoute = controlHints.getBundle(KEY_GROUP_ROUTE); + + if (groupRoute != null && groupRoute.containsKey(KEY_VOLUME_HANDLING) + && volumeHandling != groupRoute.getInt(KEY_VOLUME_HANDLING)) { + //Creating copy of controlHints with updated value. + Bundle newGroupRoute = new Bundle(groupRoute); + newGroupRoute.putInt(KEY_VOLUME_HANDLING, volumeHandling); + Bundle newControlHints = new Bundle(controlHints); + newControlHints.putBundle(KEY_GROUP_ROUTE, newGroupRoute); + return newControlHints; + } + } + //Return same Bundle. + return controlHints; + } + + private static int defineVolumeHandling(int volumeHandling, List selectedRoutes, + boolean volumeAdjustmentForRemoteGroupSessions) { + if (!volumeAdjustmentForRemoteGroupSessions && selectedRoutes.size() > 1) { + return MediaRoute2Info.PLAYBACK_VOLUME_FIXED; + } + return volumeHandling; + } + private static String ensureString(String str) { return str != null ? str : ""; } diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/RoutingSessionInfoTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/RoutingSessionInfoTest.java index 77b3160a8016b..3fe0928eaddab 100644 --- a/media/tests/MediaRouter/src/com/android/mediaroutertest/RoutingSessionInfoTest.java +++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/RoutingSessionInfoTest.java @@ -19,10 +19,12 @@ package com.android.mediaroutertest; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import android.content.res.Resources; +import android.media.MediaRoute2Info; import android.media.RoutingSessionInfo; +import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; @@ -94,4 +96,24 @@ public class RoutingSessionInfoTest { assertEquals(sessionInfoWithProviderId2.getTransferableRoutes(), sessionInfoWithProviderId.getTransferableRoutes()); } + + @Test + public void testGetVolumeHandlingGroupSession() { + RoutingSessionInfo sessionInfo = new RoutingSessionInfo.Builder( + TEST_ID, TEST_CLIENT_PACKAGE_NAME) + .setName(TEST_NAME) + .addSelectedRoute(TEST_ROUTE_ID_0) + .addSelectedRoute(TEST_ROUTE_ID_2) + .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE) + .build(); + + boolean volumeAdjustmentForRemoteGroupSessions = Resources.getSystem().getBoolean( + com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions); + + int expectedResult = volumeAdjustmentForRemoteGroupSessions + ? MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE : + MediaRoute2Info.PLAYBACK_VOLUME_FIXED; + + assertEquals(sessionInfo.getVolumeHandling(), expectedResult); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index a72f311e55edb..192872f5f926c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -73,7 +73,6 @@ public class InfoMediaManager extends MediaManager { MediaRouter2Manager mRouterManager; @VisibleForTesting String mPackageName; - private final boolean mVolumeAdjustmentForRemoteGroupSessions; private MediaDevice mCurrentConnectedDevice; private LocalBluetoothManager mBluetoothManager; @@ -87,9 +86,6 @@ public class InfoMediaManager extends MediaManager { if (!TextUtils.isEmpty(packageName)) { mPackageName = packageName; } - - mVolumeAdjustmentForRemoteGroupSessions = context.getResources().getBoolean( - com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions); } @Override @@ -166,28 +162,18 @@ public class InfoMediaManager extends MediaManager { } boolean isRoutingSessionAvailableForVolumeControl() { - if (mVolumeAdjustmentForRemoteGroupSessions) { - return true; - } List sessions = mRouterManager.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 (!session.isSystemSession() + && session.getVolumeHandling() != MediaRoute2Info.PLAYBACK_VOLUME_FIXED) { + return true; } } - if (!foundNonSystemSession) { - Log.d(TAG, "No routing session for " + mPackageName); - return false; - } - return !isGroup; + + Log.d(TAG, "No routing session for " + mPackageName); + return false; } /** @@ -418,8 +404,7 @@ public class InfoMediaManager extends MediaManager { @TargetApi(Build.VERSION_CODES.R) boolean shouldEnableVolumeSeekBar(RoutingSessionInfo sessionInfo) { return sessionInfo.isSystemSession() // System sessions are not remote - || mVolumeAdjustmentForRemoteGroupSessions - || sessionInfo.getSelectedRoutes().size() <= 1; + || sessionInfo.getVolumeHandling() != MediaRoute2Info.PLAYBACK_VOLUME_FIXED; } private void refreshDevices() { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index bf7c4598b5da0..504590ab4bc93 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -35,6 +35,7 @@ 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; @@ -1222,23 +1223,16 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa String packageName = ctr.getPackageName(); List 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; - } + if (!session.isSystemSession() + && session.getVolumeHandling() != MediaRoute2Info.PLAYBACK_VOLUME_FIXED) { + return true; } } - if (!foundNonSystemSession) { - Log.d(TAG, "No routing session for " + packageName); - return false; - } - return !isGroup; + + Log.d(TAG, "No routing session for " + packageName); + return false; } private Token findToken(int stream) { diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 604e8f3949f4e..34cd6a0129250 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -26,9 +26,7 @@ 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; @@ -463,29 +461,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR @Override public boolean canHandleVolumeKey() { - if (isPlaybackTypeLocal() || mVolumeAdjustmentForRemoteGroupSessions) { - return true; - } - MediaRouter2Manager mRouter2Manager = MediaRouter2Manager.getInstance(mContext); - List 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; + return mVolumeControlType != VolumeProvider.VOLUME_CONTROL_FIXED; } @Override