Loading services/core/java/com/android/server/media/MediaSessionRecord.java +23 −116 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ import java.util.List; * This is the system implementation of a Session. Apps will interact with the * MediaSession wrapper class instead. */ public class MediaSessionRecord implements IBinder.DeathRecipient { public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable { private static final String TAG = "MediaSessionRecord"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); Loading Loading @@ -125,7 +125,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo, MediaSessionService service, Looper handlerLooper) { MediaSessionService service, Looper handlerLooper) throws RemoteException { mOwnerPid = ownerPid; mOwnerUid = ownerUid; mUserId = userId; Loading @@ -142,6 +142,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(); // May throw RemoteException if the session app is killed. mSessionCb.mCb.asBinder().linkToDeath(this, 0); } /** Loading @@ -153,15 +156,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mSession; } /** * Get the controller binder for the {@link MediaController}. * * @return The controller binder apps talk to. */ public ISessionController getControllerBinder() { return mController; } /** * Get the session token for creating {@link MediaController}. * Loading @@ -180,15 +174,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mPackageName; } /** * Get the tag for the session. * * @return The session's tag. */ public String getTag() { return mTag; } /** * Get the intent the app set for their media button receiver. * Loading @@ -198,25 +183,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mMediaButtonReceiver; } /** * Get this session's flags. * * @return The flags for this session. */ public long getFlags() { return mFlags; } /** * Check if this session has the specified flag. * * @param flag The flag to check. * @return True if this session has that flag set, false otherwise. */ public boolean hasFlag(int flag) { return (mFlags & flag) != 0; } /** * Get the UID this session was created for. * Loading Loading @@ -267,7 +233,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { public void adjustVolume(String packageName, String opPackageName, int pid, int uid, boolean asSystemService, int direction, int flags, boolean useSuggested) { int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND; if (isPlaybackActive() || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) { if (checkPlaybackActiveState(true) || isSystemPriority()) { flags &= ~AudioManager.FLAG_PLAY_SOUND; } if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) { Loading Loading @@ -360,84 +326,27 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } /** * Get the playback state. * * @return The current playback state. */ public PlaybackState getPlaybackState() { return mPlaybackState; } /** * Check if the session is currently performing playback. * * @return True if the session is performing playback, false otherwise. */ public boolean isPlaybackActive() { int state = mPlaybackState == null ? PlaybackState.STATE_NONE : mPlaybackState.getState(); return MediaSession.isActiveState(state); } /** * Get the type of playback, either local or remote. * * @return The current type of playback. */ public int getPlaybackType() { return mVolumeType; } /** * Get the local audio stream being used. Only valid if playback type is * local. * * @return The audio stream the session is using. */ public AudioAttributes getAudioAttributes() { return mAudioAttrs; } /** * Get the type of volume control. Only valid if playback type is remote. * Check if the session's playback active state matches with the expectation. This always return * {@code false} if the playback state is {@code null}, where we cannot know the actual playback * state associated with the session. * * @return The volume control type being used. * @param expected True if playback is expected to be active. false otherwise. * @return True if the session's playback matches with the expectation. false otherwise. */ public int getVolumeControl() { return mVolumeControlType; public boolean checkPlaybackActiveState(boolean expected) { if (mPlaybackState == null) { return false; } /** * Get the max volume that can be set. Only valid if playback type is * remote. * * @return The max volume that can be set. */ public int getMaxVolume() { return mMaxVolume; return MediaSession.isActiveState(mPlaybackState.getState()) == expected; } /** * Get the current volume for this session. Only valid if playback type is * remote. * Get whether the playback is local. * * @return The current volume of the remote playback. * @return {@code true} if the playback is local. */ public int getCurrentVolume() { return mCurrentVolume; } /** * Get the volume we'd like it to be set to. This is only valid for a short * while after a call to adjust or set volume. * * @return The current optimistic volume or -1. */ public int getOptimisticVolume() { return mOptimisticVolume; } public boolean isTransportControlEnabled() { return hasFlag(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); public boolean isPlaybackLocal() { return mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL; } @Override Loading @@ -449,21 +358,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { * Finish cleaning up this session, including disconnecting if connected and * removing the death observer from the callback binder. */ public void onDestroy() { @Override public void close() { synchronized (mLock) { if (mDestroyed) { return; } mSessionCb.mCb.asBinder().unlinkToDeath(this, 0); mDestroyed = true; mPlaybackState = null; mHandler.post(MessageHandler.MSG_DESTROYED); } } public ISessionCallback getCallback() { return mSessionCb.mCb; } /** * Sends media button. * Loading services/core/java/com/android/server/media/MediaSessionService.java +5 −10 Original line number Diff line number Diff line Loading @@ -205,7 +205,7 @@ public class MediaSessionService extends SystemService implements Monitor { Log.w(TAG, "Unknown session updated. Ignoring."); return; } if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) { if (record.isSystemPriority()) { if (DEBUG_KEY_EVENT) { Log.d(TAG, "Global priority session is updated, active=" + record.isActive()); } Loading Loading @@ -460,12 +460,7 @@ public class MediaSessionService extends SystemService implements Monitor { } } try { session.getCallback().asBinder().unlinkToDeath(session, 0); } catch (Exception e) { // ignore exceptions while destroying a session. } session.onDestroy(); session.close(); mHandler.postSessionsChanged(session.getUserId()); } Loading Loading @@ -570,10 +565,10 @@ public class MediaSessionService extends SystemService implements Monitor { throw new RuntimeException("Session request from invalid user."); } final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId, callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper()); final MediaSessionRecord session; try { cb.asBinder().linkToDeath(session, 0); session = new MediaSessionRecord(callerPid, callerUid, userId, callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper()); } catch (RemoteException e) { throw new RuntimeException("Media Session owner died prematurely.", e); } Loading services/core/java/com/android/server/media/MediaSessionStack.java +6 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.media; import android.media.session.MediaController.PlaybackInfo; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Debug; Loading Loading @@ -144,7 +143,7 @@ class MediaSessionStack { */ public MediaSessionRecord getMediaSessionRecord(MediaSession.Token sessionToken) { for (MediaSessionRecord record : mSessions) { if (Objects.equals(record.getControllerBinder(), sessionToken.getBinder())) { if (Objects.equals(record.getSessionToken(), sessionToken)) { return record; } } Loading Loading @@ -230,8 +229,8 @@ class MediaSessionStack { MediaSessionRecord mediaButtonSession = null; for (MediaSessionRecord session : mSessions) { if (uid == session.getUid()) { if (session.getPlaybackState() != null && session.isPlaybackActive() == mAudioPlayerStateMonitor.isPlaybackActive(session.getUid())) { if (session.checkPlaybackActiveState( mAudioPlayerStateMonitor.isPlaybackActive(session.getUid()))) { // If there's a media session whose PlaybackState matches // the audio playback state, return it immediately. return session; Loading Loading @@ -287,7 +286,7 @@ class MediaSessionStack { int size = records.size(); for (int i = 0; i < size; i++) { MediaSessionRecord record = records.get(i); if (record.isPlaybackActive()) { if (record.checkPlaybackActiveState(true)) { mCachedVolumeDefault = record; return record; } Loading @@ -301,7 +300,7 @@ class MediaSessionStack { int size = records.size(); for (int i = 0; i < size; i++) { MediaSessionRecord record = records.get(i); if (record.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE) { if (!record.isPlaybackLocal()) { return record; } } Loading Loading @@ -359,7 +358,7 @@ class MediaSessionStack { continue; } if (session.isPlaybackActive()) { if (session.checkPlaybackActiveState(true)) { result.add(lastPlaybackActiveIndex++, session); lastActiveIndex++; } else { Loading Loading
services/core/java/com/android/server/media/MediaSessionRecord.java +23 −116 Original line number Diff line number Diff line Loading @@ -62,7 +62,7 @@ import java.util.List; * This is the system implementation of a Session. Apps will interact with the * MediaSession wrapper class instead. */ public class MediaSessionRecord implements IBinder.DeathRecipient { public class MediaSessionRecord implements IBinder.DeathRecipient, AutoCloseable { private static final String TAG = "MediaSessionRecord"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); Loading Loading @@ -125,7 +125,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName, ISessionCallback cb, String tag, Bundle sessionInfo, MediaSessionService service, Looper handlerLooper) { MediaSessionService service, Looper handlerLooper) throws RemoteException { mOwnerPid = ownerPid; mOwnerUid = ownerUid; mUserId = userId; Loading @@ -142,6 +142,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(); // May throw RemoteException if the session app is killed. mSessionCb.mCb.asBinder().linkToDeath(this, 0); } /** Loading @@ -153,15 +156,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mSession; } /** * Get the controller binder for the {@link MediaController}. * * @return The controller binder apps talk to. */ public ISessionController getControllerBinder() { return mController; } /** * Get the session token for creating {@link MediaController}. * Loading @@ -180,15 +174,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mPackageName; } /** * Get the tag for the session. * * @return The session's tag. */ public String getTag() { return mTag; } /** * Get the intent the app set for their media button receiver. * Loading @@ -198,25 +183,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mMediaButtonReceiver; } /** * Get this session's flags. * * @return The flags for this session. */ public long getFlags() { return mFlags; } /** * Check if this session has the specified flag. * * @param flag The flag to check. * @return True if this session has that flag set, false otherwise. */ public boolean hasFlag(int flag) { return (mFlags & flag) != 0; } /** * Get the UID this session was created for. * Loading Loading @@ -267,7 +233,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { public void adjustVolume(String packageName, String opPackageName, int pid, int uid, boolean asSystemService, int direction, int flags, boolean useSuggested) { int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND; if (isPlaybackActive() || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) { if (checkPlaybackActiveState(true) || isSystemPriority()) { flags &= ~AudioManager.FLAG_PLAY_SOUND; } if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) { Loading Loading @@ -360,84 +326,27 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } /** * Get the playback state. * * @return The current playback state. */ public PlaybackState getPlaybackState() { return mPlaybackState; } /** * Check if the session is currently performing playback. * * @return True if the session is performing playback, false otherwise. */ public boolean isPlaybackActive() { int state = mPlaybackState == null ? PlaybackState.STATE_NONE : mPlaybackState.getState(); return MediaSession.isActiveState(state); } /** * Get the type of playback, either local or remote. * * @return The current type of playback. */ public int getPlaybackType() { return mVolumeType; } /** * Get the local audio stream being used. Only valid if playback type is * local. * * @return The audio stream the session is using. */ public AudioAttributes getAudioAttributes() { return mAudioAttrs; } /** * Get the type of volume control. Only valid if playback type is remote. * Check if the session's playback active state matches with the expectation. This always return * {@code false} if the playback state is {@code null}, where we cannot know the actual playback * state associated with the session. * * @return The volume control type being used. * @param expected True if playback is expected to be active. false otherwise. * @return True if the session's playback matches with the expectation. false otherwise. */ public int getVolumeControl() { return mVolumeControlType; public boolean checkPlaybackActiveState(boolean expected) { if (mPlaybackState == null) { return false; } /** * Get the max volume that can be set. Only valid if playback type is * remote. * * @return The max volume that can be set. */ public int getMaxVolume() { return mMaxVolume; return MediaSession.isActiveState(mPlaybackState.getState()) == expected; } /** * Get the current volume for this session. Only valid if playback type is * remote. * Get whether the playback is local. * * @return The current volume of the remote playback. * @return {@code true} if the playback is local. */ public int getCurrentVolume() { return mCurrentVolume; } /** * Get the volume we'd like it to be set to. This is only valid for a short * while after a call to adjust or set volume. * * @return The current optimistic volume or -1. */ public int getOptimisticVolume() { return mOptimisticVolume; } public boolean isTransportControlEnabled() { return hasFlag(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); public boolean isPlaybackLocal() { return mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL; } @Override Loading @@ -449,21 +358,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { * Finish cleaning up this session, including disconnecting if connected and * removing the death observer from the callback binder. */ public void onDestroy() { @Override public void close() { synchronized (mLock) { if (mDestroyed) { return; } mSessionCb.mCb.asBinder().unlinkToDeath(this, 0); mDestroyed = true; mPlaybackState = null; mHandler.post(MessageHandler.MSG_DESTROYED); } } public ISessionCallback getCallback() { return mSessionCb.mCb; } /** * Sends media button. * Loading
services/core/java/com/android/server/media/MediaSessionService.java +5 −10 Original line number Diff line number Diff line Loading @@ -205,7 +205,7 @@ public class MediaSessionService extends SystemService implements Monitor { Log.w(TAG, "Unknown session updated. Ignoring."); return; } if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) { if (record.isSystemPriority()) { if (DEBUG_KEY_EVENT) { Log.d(TAG, "Global priority session is updated, active=" + record.isActive()); } Loading Loading @@ -460,12 +460,7 @@ public class MediaSessionService extends SystemService implements Monitor { } } try { session.getCallback().asBinder().unlinkToDeath(session, 0); } catch (Exception e) { // ignore exceptions while destroying a session. } session.onDestroy(); session.close(); mHandler.postSessionsChanged(session.getUserId()); } Loading Loading @@ -570,10 +565,10 @@ public class MediaSessionService extends SystemService implements Monitor { throw new RuntimeException("Session request from invalid user."); } final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId, callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper()); final MediaSessionRecord session; try { cb.asBinder().linkToDeath(session, 0); session = new MediaSessionRecord(callerPid, callerUid, userId, callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper()); } catch (RemoteException e) { throw new RuntimeException("Media Session owner died prematurely.", e); } Loading
services/core/java/com/android/server/media/MediaSessionStack.java +6 −7 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.media; import android.media.session.MediaController.PlaybackInfo; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Debug; Loading Loading @@ -144,7 +143,7 @@ class MediaSessionStack { */ public MediaSessionRecord getMediaSessionRecord(MediaSession.Token sessionToken) { for (MediaSessionRecord record : mSessions) { if (Objects.equals(record.getControllerBinder(), sessionToken.getBinder())) { if (Objects.equals(record.getSessionToken(), sessionToken)) { return record; } } Loading Loading @@ -230,8 +229,8 @@ class MediaSessionStack { MediaSessionRecord mediaButtonSession = null; for (MediaSessionRecord session : mSessions) { if (uid == session.getUid()) { if (session.getPlaybackState() != null && session.isPlaybackActive() == mAudioPlayerStateMonitor.isPlaybackActive(session.getUid())) { if (session.checkPlaybackActiveState( mAudioPlayerStateMonitor.isPlaybackActive(session.getUid()))) { // If there's a media session whose PlaybackState matches // the audio playback state, return it immediately. return session; Loading Loading @@ -287,7 +286,7 @@ class MediaSessionStack { int size = records.size(); for (int i = 0; i < size; i++) { MediaSessionRecord record = records.get(i); if (record.isPlaybackActive()) { if (record.checkPlaybackActiveState(true)) { mCachedVolumeDefault = record; return record; } Loading @@ -301,7 +300,7 @@ class MediaSessionStack { int size = records.size(); for (int i = 0; i < size; i++) { MediaSessionRecord record = records.get(i); if (record.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE) { if (!record.isPlaybackLocal()) { return record; } } Loading Loading @@ -359,7 +358,7 @@ class MediaSessionStack { continue; } if (session.isPlaybackActive()) { if (session.checkPlaybackActiveState(true)) { result.add(lastPlaybackActiveIndex++, session); lastActiveIndex++; } else { Loading