diff options
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); |