diff options
author | 2025-02-05 14:55:14 +0000 | |
---|---|---|
committer | 2025-02-07 19:22:53 +0000 | |
commit | 5e2ebbd73f3fab0d14da9d3ae224d2662248074c (patch) | |
tree | b8fa6bfbe077ca3f77dc1dd35c574aa16a6b9f68 | |
parent | 1f01fadbfc9d0e898a532629dc2ca2d72d6c9023 (diff) |
Hide MediaSession details from MediaSessions clients
This will enable us to use MediaSessions for other streams that also
support volume adjustment (e.g. mirroring sessions), and not just media
sessions. We can later consider renaming the MediaSessions class to
something like VolumeSessions.
Bug: b/362507305
Test: Presubmit, build and verifying regular volume adjustment
Test: funcionality while casting.
Test: adb shell dumpsys activity service SystemUI | grep -A 100 "VolumeDialogControllerImpl state:"
Flag: EXEMPT Non-functional change
Change-Id: I51739d930d7cdb5b93c58394c699d4b6c3c8567c
3 files changed, 65 insertions, 39 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.kt b/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.kt index 10156c404ebf..bac564c7d0f4 100644 --- a/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.kt +++ b/packages/SettingsLib/src/com/android/settingslib/volume/MediaSessions.kt @@ -20,6 +20,7 @@ import android.content.Intent import android.content.pm.PackageManager import android.media.MediaMetadata import android.media.session.MediaController +import android.media.session.MediaController.PlaybackInfo import android.media.session.MediaSession import android.media.session.MediaSessionManager import android.media.session.PlaybackState @@ -98,16 +99,22 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { } /** Set volume `level` to remote media `token` */ - fun setVolume(token: MediaSession.Token, level: Int) { + fun setVolume(sessionId: SessionId, volumeLevel: Int) { + when (sessionId) { + is SessionId.Media -> setMediaSessionVolume(sessionId.token, volumeLevel) + } + } + + private fun setMediaSessionVolume(token: MediaSession.Token, volumeLevel: Int) { val record = mRecords[token] if (record == null) { Log.w(TAG, "setVolume: No record found for token $token") return } if (D.BUG) { - Log.d(TAG, "Setting level to $level") + Log.d(TAG, "Setting level to $volumeLevel") } - record.controller.setVolumeTo(level, 0) + record.controller.setVolumeTo(volumeLevel, 0) } private fun onRemoteVolumeChangedH(sessionToken: MediaSession.Token, flags: Int) { @@ -122,7 +129,7 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { ) } val token = controller.sessionToken - mCallbacks.onRemoteVolumeChanged(token, flags) + mCallbacks.onRemoteVolumeChanged(SessionId.from(token), flags) } private fun onUpdateRemoteSessionListH(sessionToken: MediaSession.Token?) { @@ -158,7 +165,7 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { controller.registerCallback(record, mHandler) } val record = mRecords[token] - val remote = isRemote(playbackInfo) + val remote = playbackInfo.isRemote() if (remote) { updateRemoteH(token, record!!.name, playbackInfo) record.sentRemote = true @@ -172,7 +179,7 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { Log.d(TAG, "Removing " + record.name + " sentRemote=" + record.sentRemote) } if (record.sentRemote) { - mCallbacks.onRemoteRemoved(token) + mCallbacks.onRemoteRemoved(SessionId.from(token)) record.sentRemote = false } } @@ -213,8 +220,8 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { private fun updateRemoteH( token: MediaSession.Token, name: String?, - pi: MediaController.PlaybackInfo, - ) = mCallbacks.onRemoteUpdate(token, name, pi) + playbackInfo: PlaybackInfo, + ) = mCallbacks.onRemoteUpdate(SessionId.from(token), name, VolumeInfo.from(playbackInfo)) private inner class MediaControllerRecord(val controller: MediaController) : MediaController.Callback() { @@ -225,7 +232,7 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { return method + " " + controller.packageName + " " } - override fun onAudioInfoChanged(info: MediaController.PlaybackInfo) { + override fun onAudioInfoChanged(info: PlaybackInfo) { if (D.BUG) { Log.d( TAG, @@ -235,9 +242,9 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { sentRemote), ) } - val remote = isRemote(info) + val remote = info.isRemote() if (!remote && sentRemote) { - mCallbacks.onRemoteRemoved(controller.sessionToken) + mCallbacks.onRemoteRemoved(SessionId.from(controller.sessionToken)) sentRemote = false } else if (remote) { updateRemoteH(controller.sessionToken, name, info) @@ -301,20 +308,36 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { } } + /** Opaque id for ongoing sessions that support volume adjustment. */ + sealed interface SessionId { + + companion object { + fun from(token: MediaSession.Token) = Media(token) + } + + data class Media(val token: MediaSession.Token) : SessionId + } + + /** Holds session volume information. */ + data class VolumeInfo(val currentVolume: Int, val maxVolume: Int) { + + companion object { + + fun from(playbackInfo: PlaybackInfo) = + VolumeInfo(playbackInfo.currentVolume, playbackInfo.maxVolume) + } + } + /** Callback for remote media sessions */ interface Callbacks { /** Invoked when remote media session is updated */ - fun onRemoteUpdate( - token: MediaSession.Token?, - name: String?, - pi: MediaController.PlaybackInfo?, - ) + fun onRemoteUpdate(token: SessionId?, name: String?, volumeInfo: VolumeInfo?) /** Invoked when remote media session is removed */ - fun onRemoteRemoved(token: MediaSession.Token?) + fun onRemoteRemoved(token: SessionId?) /** Invoked when remote volume is changed */ - fun onRemoteVolumeChanged(token: MediaSession.Token?, flags: Int) + fun onRemoteVolumeChanged(token: SessionId?, flags: Int) } companion object { @@ -325,12 +348,11 @@ class MediaSessions(context: Context, looper: Looper, callbacks: Callbacks) { const val UPDATE_REMOTE_SESSION_LIST: Int = 3 private const val USE_SERVICE_LABEL = false - - private fun isRemote(pi: MediaController.PlaybackInfo?): Boolean = - pi != null && pi.playbackType == MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE } } +private fun PlaybackInfo?.isRemote() = this?.playbackType == PlaybackInfo.PLAYBACK_TYPE_REMOTE + private fun MediaController.dump(n: Int, writer: PrintWriter) { writer.println(" Controller $n: $packageName") diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java index 75f3386ed695..b8e19248b2de 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/VolumeDialogControllerImplTest.java @@ -47,6 +47,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.keyguard.TestScopeProvider; +import com.android.settingslib.volume.MediaSessions; import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCaseExtKt; import com.android.systemui.broadcast.BroadcastDispatcher; @@ -268,13 +269,15 @@ public class VolumeDialogControllerImplTest extends SysuiTestCase { @Test public void testOnRemoteVolumeChanged_newStream_noNullPointer() { MediaSession.Token token = new MediaSession.Token(Process.myUid(), null); - mVolumeController.mMediaSessionsCallbacksW.onRemoteVolumeChanged(token, 0); + var sessionId = MediaSessions.SessionId.Companion.from(token); + mVolumeController.mMediaSessionsCallbacksW.onRemoteVolumeChanged(sessionId, 0); } @Test public void testOnRemoteRemove_newStream_noNullPointer() { MediaSession.Token token = new MediaSession.Token(Process.myUid(), null); - mVolumeController.mMediaSessionsCallbacksW.onRemoteRemoved(token); + var sessionId = MediaSessions.SessionId.Companion.from(token); + mVolumeController.mMediaSessionsCallbacksW.onRemoteRemoved(sessionId); } @Test diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index 68bffeefb0f0..4d5477052388 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -37,8 +37,6 @@ import android.media.IAudioService; import android.media.IVolumeController; import android.media.MediaRouter2Manager; import android.media.VolumePolicy; -import android.media.session.MediaController.PlaybackInfo; -import android.media.session.MediaSession.Token; import android.net.Uri; import android.os.Handler; import android.os.HandlerExecutor; @@ -61,6 +59,7 @@ import androidx.lifecycle.Observer; import com.android.internal.annotations.GuardedBy; import com.android.settingslib.volume.MediaSessions; +import com.android.settingslib.volume.MediaSessions.SessionId; import com.android.systemui.Dumpable; import com.android.systemui.Flags; import com.android.systemui.broadcast.BroadcastDispatcher; @@ -1402,12 +1401,13 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } protected final class MediaSessionsCallbacks implements MediaSessions.Callbacks { - private final HashMap<Token, Integer> mRemoteStreams = new HashMap<>(); + private final HashMap<SessionId, Integer> mRemoteStreams = new HashMap<>(); private int mNextStream = DYNAMIC_STREAM_REMOTE_START_INDEX; @Override - public void onRemoteUpdate(Token token, String name, PlaybackInfo pi) { + public void onRemoteUpdate( + SessionId token, String name, MediaSessions.VolumeInfo volumeInfo) { addStream(token, "onRemoteUpdate"); int stream = 0; @@ -1415,14 +1415,15 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa stream = mRemoteStreams.get(token); } Slog.d(TAG, - "onRemoteUpdate: stream: " + stream + " volume: " + pi.getCurrentVolume()); + "onRemoteUpdate: stream: " + + stream + " volume: " + volumeInfo.getCurrentVolume()); boolean changed = mState.states.indexOfKey(stream) < 0; final StreamState ss = streamStateW(stream); ss.dynamic = true; ss.levelMin = 0; - ss.levelMax = pi.getMaxVolume(); - if (ss.level != pi.getCurrentVolume()) { - ss.level = pi.getCurrentVolume(); + ss.levelMax = volumeInfo.getMaxVolume(); + if (ss.level != volumeInfo.getCurrentVolume()) { + ss.level = volumeInfo.getCurrentVolume(); changed = true; } if (!Objects.equals(ss.remoteLabel, name)) { @@ -1437,11 +1438,11 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } @Override - public void onRemoteVolumeChanged(Token token, int flags) { - addStream(token, "onRemoteVolumeChanged"); + public void onRemoteVolumeChanged(SessionId sessionId, int flags) { + addStream(sessionId, "onRemoteVolumeChanged"); int stream = 0; synchronized (mRemoteStreams) { - stream = mRemoteStreams.get(token); + stream = mRemoteStreams.get(sessionId); } final boolean showUI = shouldShowUI(flags); Slog.d(TAG, "onRemoteVolumeChanged: stream: " + stream + " showui? " + showUI); @@ -1459,7 +1460,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } @Override - public void onRemoteRemoved(Token token) { + public void onRemoteRemoved(SessionId token) { int stream; synchronized (mRemoteStreams) { if (!mRemoteStreams.containsKey(token)) { @@ -1480,7 +1481,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa } public void setStreamVolume(int stream, int level) { - final Token token = findToken(stream); + final SessionId token = findToken(stream); if (token == null) { Log.w(TAG, "setStreamVolume: No token found for stream: " + stream); return; @@ -1488,9 +1489,9 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa mMediaSessions.setVolume(token, level); } - private Token findToken(int stream) { + private SessionId findToken(int stream) { synchronized (mRemoteStreams) { - for (Map.Entry<Token, Integer> entry : mRemoteStreams.entrySet()) { + for (Map.Entry<SessionId, Integer> entry : mRemoteStreams.entrySet()) { if (entry.getValue().equals(stream)) { return entry.getKey(); } @@ -1499,7 +1500,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa return null; } - private void addStream(Token token, String triggeringMethod) { + private void addStream(SessionId token, String triggeringMethod) { synchronized (mRemoteStreams) { if (!mRemoteStreams.containsKey(token)) { mRemoteStreams.put(token, mNextStream); |