Loading packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl +5 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.media; import android.app.PendingIntent; import android.os.Bundle; import android.os.ResultReceiver; Loading @@ -33,8 +34,10 @@ oneway interface IMediaSession2Callback { void onPlaylistParamsChanged(in Bundle params); void onPlaybackInfoChanged(in Bundle playbackInfo); void onConnected(IMediaSession2 sessionBinder, in Bundle commandGroup, in Bundle playbackState); // TODO(jaewan): Handle when the playlist becomes too huge. void onConnected(IMediaSession2 sessionBinder, in Bundle commandGroup, in Bundle playbackState, in Bundle playbackInfo, in Bundle params, in List<Bundle> playlist, int ratingType, in PendingIntent sessionActivity); void onDisconnected(); void onCustomLayoutChanged(in List<Bundle> commandButtonlist); Loading packages/MediaComponents/src/com/android/media/MediaController2Impl.java +33 −8 Original line number Diff line number Diff line Loading @@ -77,6 +77,10 @@ public class MediaController2Impl implements MediaController2Provider { @GuardedBy("mLock") private PlaybackInfo mPlaybackInfo; @GuardedBy("mLock") private int mRatingType; @GuardedBy("mLock") private PendingIntent mSessionActivity; @GuardedBy("mLock") private CommandGroup mCommandGroup; // Assignment should be used with the lock hold, but should be used without a lock to prevent Loading Loading @@ -276,14 +280,12 @@ public class MediaController2Impl implements MediaController2Provider { ////////////////////////////////////////////////////////////////////////////////////// @Override public PendingIntent getSessionActivity_impl() { // TODO(jaewan): Implement return null; return mSessionActivity; } @Override public int getRatingType_impl() { // TODO(jaewan): Implement return 0; return mRatingType; } @Override Loading Loading @@ -508,7 +510,9 @@ public class MediaController2Impl implements MediaController2Provider { // Should be used without a lock to prevent potential deadlock. private void onConnectedNotLocked(IMediaSession2 sessionBinder, final CommandGroup commandGroup, final PlaybackState2 state) { final CommandGroup commandGroup, final PlaybackState2 state, final PlaybackInfo info, final PlaylistParams params, final List<MediaItem2> playlist, final int ratingType, final PendingIntent sessionActivity) { if (DEBUG) { Log.d(TAG, "onConnectedNotLocked sessionBinder=" + sessionBinder + ", commands=" + commandGroup); Loading @@ -532,6 +536,11 @@ public class MediaController2Impl implements MediaController2Provider { } mCommandGroup = commandGroup; mPlaybackState = state; mPlaybackInfo = info; mPlaylistParams = params; mPlaylist = playlist; mRatingType = ratingType; mSessionActivity = sessionActivity; mSessionBinder = sessionBinder; try { // Implementation for the local binder is no-op, Loading Loading @@ -645,6 +654,9 @@ public class MediaController2Impl implements MediaController2Provider { @Override public void onPlaybackInfoChanged(Bundle playbackInfo) throws RuntimeException { if (DEBUG) { Log.d(TAG, "onPlaybackInfoChanged"); } final MediaController2Impl controller; try { controller = getController(); Loading @@ -658,7 +670,8 @@ public class MediaController2Impl implements MediaController2Provider { @Override public void onConnected(IMediaSession2 sessionBinder, Bundle commandGroup, Bundle playbackState) { Bundle playbackState, Bundle playbackInfo, Bundle playlistParams, List<Bundle> playlist, int ratingType, PendingIntent sessionActivity) { final MediaController2Impl controller = mController.get(); if (controller == null) { if (DEBUG) { Loading @@ -666,9 +679,20 @@ public class MediaController2Impl implements MediaController2Provider { } return; } final Context context = controller.getContext(); List<MediaItem2> list = new ArrayList<>(); for (int i = 0; i < playlist.size(); i++) { MediaItem2 item = MediaItem2.fromBundle(context, playlist.get(i)); if (item != null) { list.add(item); } } controller.onConnectedNotLocked(sessionBinder, CommandGroup.fromBundle(controller.getContext(), commandGroup), PlaybackState2.fromBundle(controller.getContext(), playbackState)); CommandGroup.fromBundle(context, commandGroup), PlaybackState2.fromBundle(context, playbackState), PlaybackInfoImpl.fromBundle(context, playbackInfo), PlaylistParams.fromBundle(context, playlistParams), list, ratingType, sessionActivity); } @Override Loading Loading @@ -706,6 +730,7 @@ public class MediaController2Impl implements MediaController2Provider { // Illegal call. Ignore return; } // TODO(jaewan): Fix here. It's controller feature so shouldn't use browser final MediaBrowser2Impl browser; try { browser = getBrowser(); Loading packages/MediaComponents/src/com/android/media/MediaSession2Impl.java +33 −10 Original line number Diff line number Diff line Loading @@ -85,6 +85,8 @@ public class MediaSession2Impl implements MediaSession2Provider { private final SessionToken2 mSessionToken; private final AudioManager mAudioManager; private final List<PlaybackListenerHolder> mListeners = new ArrayList<>(); private final int mRatingType; private final PendingIntent mSessionActivity; @GuardedBy("mLock") private MediaPlayerInterface mPlayer; Loading @@ -102,7 +104,6 @@ public class MediaSession2Impl implements MediaSession2Provider { /** * Can be only called by the {@link Builder#build()}. * * @param instance * @param context * @param player * @param id Loading @@ -123,6 +124,8 @@ public class MediaSession2Impl implements MediaSession2Provider { mId = id; mCallback = callback; mCallbackExecutor = callbackExecutor; mRatingType = ratingType; mSessionActivity = sessionActivity; mSessionStub = new MediaSession2Stub(this); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); Loading Loading @@ -195,9 +198,6 @@ public class MediaSession2Impl implements MediaSession2Provider { if (player == null) { throw new IllegalArgumentException("player shouldn't be null"); } if (player == mPlayer) { return; } PlaybackInfo info = createPlaybackInfo(null /* VolumeProvider */, player.getAudioAttributes()); synchronized (mLock) { Loading @@ -218,10 +218,6 @@ public class MediaSession2Impl implements MediaSession2Provider { if (volumeProvider == null) { throw new IllegalArgumentException("volumeProvider shouldn't be null"); } if (player == mPlayer) { return; } PlaybackInfo info = createPlaybackInfo(volumeProvider, player.getAudioAttributes()); synchronized (mLock) { setPlayerLocked(player); Loading @@ -244,12 +240,25 @@ public class MediaSession2Impl implements MediaSession2Provider { private PlaybackInfo createPlaybackInfo(VolumeProvider2 volumeProvider, AudioAttributes attrs) { PlaybackInfo info; if (volumeProvider == null) { int stream = attrs == null ? AudioManager.STREAM_MUSIC : attrs.getVolumeControlStream(); int stream; if (attrs == null) { stream = AudioManager.STREAM_MUSIC; } else { stream = attrs.getVolumeControlStream(); if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) { // It may happen if the AudioAttributes doesn't have usage. // Change it to the STREAM_MUSIC because it's not supported by audio manager // for querying volume level. stream = AudioManager.STREAM_MUSIC; } } info = PlaybackInfoImpl.createPlaybackInfo( mContext, PlaybackInfo.PLAYBACK_TYPE_LOCAL, attrs, VolumeProvider2.VOLUME_CONTROL_ABSOLUTE, mAudioManager.isVolumeFixed() ? VolumeProvider2.VOLUME_CONTROL_FIXED : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE, mAudioManager.getStreamMaxVolume(stream), mAudioManager.getStreamVolume(stream)); } else { Loading Loading @@ -563,6 +572,20 @@ public class MediaSession2Impl implements MediaSession2Provider { return mVolumeProvider; } PlaybackInfo getPlaybackInfo() { synchronized (mLock) { return mPlaybackInfo; } } int getRatingType() { return mRatingType; } PendingIntent getSessionActivity() { return mSessionActivity; } private static class MyPlaybackListener implements MediaPlayerInterface.PlaybackListener { private final WeakReference<MediaSession2Impl> mSession; private final MediaPlayerInterface mPlayer; Loading packages/MediaComponents/src/com/android/media/MediaSession2Stub.java +28 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.media; import android.app.PendingIntent; import android.content.Context; import android.media.MediaController2; import android.media.MediaController2.PlaybackInfo; Loading Loading @@ -133,10 +134,36 @@ public class MediaSession2Stub extends IMediaSession2.Stub { // TODO(jaewan): Should we protect getting playback state? final PlaybackState2 state = session.getInstance().getPlaybackState(); final Bundle playbackStateBundle = (state != null) ? state.toBundle() : null; final Bundle playbackInfoBundle = ((PlaybackInfoImpl) session.getPlaybackInfo().getProvider()).toBundle(); final PlaylistParams params = session.getInstance().getPlaylistParams(); final Bundle paramsBundle = (params != null) ? params.toBundle() : null; final int ratingType = session.getRatingType(); final PendingIntent sessionActivity = session.getSessionActivity(); final List<MediaItem2> playlist = session.getInstance().getPlaylist(); final List<Bundle> playlistBundle = new ArrayList<>(); if (playlist != null) { // TODO(jaewan): Find a way to avoid concurrent modification exception. for (int i = 0; i < playlist.size(); i++) { final MediaItem2 item = playlist.get(i); if (item != null) { final Bundle itemBundle = item.toBundle(); if (itemBundle != null) { playlistBundle.add(itemBundle); } } } } // Double check if session is still there, because close() can be called in another // thread. if (mSession.get() == null) { return; } try { callback.onConnected(MediaSession2Stub.this, allowedCommands.toBundle(), playbackStateBundle); allowedCommands.toBundle(), playbackStateBundle, playbackInfoBundle, paramsBundle, playlistBundle, ratingType, sessionActivity); } catch (RemoteException e) { // Controller may be died prematurely. // TODO(jaewan): Handle here. Loading packages/MediaComponents/test/AndroidManifest.xml +1 −8 Original line number Diff line number Diff line Loading @@ -20,14 +20,7 @@ <application android:label="Media API Test"> <uses-library android:name="android.test.runner" /> <activity android:name="android.widget2.VideoView2TestActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="VideoView2TestActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> </intent-filter> </activity> <activity android:name="android.media.MockActivity" /> <!-- Keep the test services synced together with the TestUtils.java --> <service android:name="android.media.MockMediaSessionService2"> Loading Loading
packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl +5 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.media; import android.app.PendingIntent; import android.os.Bundle; import android.os.ResultReceiver; Loading @@ -33,8 +34,10 @@ oneway interface IMediaSession2Callback { void onPlaylistParamsChanged(in Bundle params); void onPlaybackInfoChanged(in Bundle playbackInfo); void onConnected(IMediaSession2 sessionBinder, in Bundle commandGroup, in Bundle playbackState); // TODO(jaewan): Handle when the playlist becomes too huge. void onConnected(IMediaSession2 sessionBinder, in Bundle commandGroup, in Bundle playbackState, in Bundle playbackInfo, in Bundle params, in List<Bundle> playlist, int ratingType, in PendingIntent sessionActivity); void onDisconnected(); void onCustomLayoutChanged(in List<Bundle> commandButtonlist); Loading
packages/MediaComponents/src/com/android/media/MediaController2Impl.java +33 −8 Original line number Diff line number Diff line Loading @@ -77,6 +77,10 @@ public class MediaController2Impl implements MediaController2Provider { @GuardedBy("mLock") private PlaybackInfo mPlaybackInfo; @GuardedBy("mLock") private int mRatingType; @GuardedBy("mLock") private PendingIntent mSessionActivity; @GuardedBy("mLock") private CommandGroup mCommandGroup; // Assignment should be used with the lock hold, but should be used without a lock to prevent Loading Loading @@ -276,14 +280,12 @@ public class MediaController2Impl implements MediaController2Provider { ////////////////////////////////////////////////////////////////////////////////////// @Override public PendingIntent getSessionActivity_impl() { // TODO(jaewan): Implement return null; return mSessionActivity; } @Override public int getRatingType_impl() { // TODO(jaewan): Implement return 0; return mRatingType; } @Override Loading Loading @@ -508,7 +510,9 @@ public class MediaController2Impl implements MediaController2Provider { // Should be used without a lock to prevent potential deadlock. private void onConnectedNotLocked(IMediaSession2 sessionBinder, final CommandGroup commandGroup, final PlaybackState2 state) { final CommandGroup commandGroup, final PlaybackState2 state, final PlaybackInfo info, final PlaylistParams params, final List<MediaItem2> playlist, final int ratingType, final PendingIntent sessionActivity) { if (DEBUG) { Log.d(TAG, "onConnectedNotLocked sessionBinder=" + sessionBinder + ", commands=" + commandGroup); Loading @@ -532,6 +536,11 @@ public class MediaController2Impl implements MediaController2Provider { } mCommandGroup = commandGroup; mPlaybackState = state; mPlaybackInfo = info; mPlaylistParams = params; mPlaylist = playlist; mRatingType = ratingType; mSessionActivity = sessionActivity; mSessionBinder = sessionBinder; try { // Implementation for the local binder is no-op, Loading Loading @@ -645,6 +654,9 @@ public class MediaController2Impl implements MediaController2Provider { @Override public void onPlaybackInfoChanged(Bundle playbackInfo) throws RuntimeException { if (DEBUG) { Log.d(TAG, "onPlaybackInfoChanged"); } final MediaController2Impl controller; try { controller = getController(); Loading @@ -658,7 +670,8 @@ public class MediaController2Impl implements MediaController2Provider { @Override public void onConnected(IMediaSession2 sessionBinder, Bundle commandGroup, Bundle playbackState) { Bundle playbackState, Bundle playbackInfo, Bundle playlistParams, List<Bundle> playlist, int ratingType, PendingIntent sessionActivity) { final MediaController2Impl controller = mController.get(); if (controller == null) { if (DEBUG) { Loading @@ -666,9 +679,20 @@ public class MediaController2Impl implements MediaController2Provider { } return; } final Context context = controller.getContext(); List<MediaItem2> list = new ArrayList<>(); for (int i = 0; i < playlist.size(); i++) { MediaItem2 item = MediaItem2.fromBundle(context, playlist.get(i)); if (item != null) { list.add(item); } } controller.onConnectedNotLocked(sessionBinder, CommandGroup.fromBundle(controller.getContext(), commandGroup), PlaybackState2.fromBundle(controller.getContext(), playbackState)); CommandGroup.fromBundle(context, commandGroup), PlaybackState2.fromBundle(context, playbackState), PlaybackInfoImpl.fromBundle(context, playbackInfo), PlaylistParams.fromBundle(context, playlistParams), list, ratingType, sessionActivity); } @Override Loading Loading @@ -706,6 +730,7 @@ public class MediaController2Impl implements MediaController2Provider { // Illegal call. Ignore return; } // TODO(jaewan): Fix here. It's controller feature so shouldn't use browser final MediaBrowser2Impl browser; try { browser = getBrowser(); Loading
packages/MediaComponents/src/com/android/media/MediaSession2Impl.java +33 −10 Original line number Diff line number Diff line Loading @@ -85,6 +85,8 @@ public class MediaSession2Impl implements MediaSession2Provider { private final SessionToken2 mSessionToken; private final AudioManager mAudioManager; private final List<PlaybackListenerHolder> mListeners = new ArrayList<>(); private final int mRatingType; private final PendingIntent mSessionActivity; @GuardedBy("mLock") private MediaPlayerInterface mPlayer; Loading @@ -102,7 +104,6 @@ public class MediaSession2Impl implements MediaSession2Provider { /** * Can be only called by the {@link Builder#build()}. * * @param instance * @param context * @param player * @param id Loading @@ -123,6 +124,8 @@ public class MediaSession2Impl implements MediaSession2Provider { mId = id; mCallback = callback; mCallbackExecutor = callbackExecutor; mRatingType = ratingType; mSessionActivity = sessionActivity; mSessionStub = new MediaSession2Stub(this); mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); Loading Loading @@ -195,9 +198,6 @@ public class MediaSession2Impl implements MediaSession2Provider { if (player == null) { throw new IllegalArgumentException("player shouldn't be null"); } if (player == mPlayer) { return; } PlaybackInfo info = createPlaybackInfo(null /* VolumeProvider */, player.getAudioAttributes()); synchronized (mLock) { Loading @@ -218,10 +218,6 @@ public class MediaSession2Impl implements MediaSession2Provider { if (volumeProvider == null) { throw new IllegalArgumentException("volumeProvider shouldn't be null"); } if (player == mPlayer) { return; } PlaybackInfo info = createPlaybackInfo(volumeProvider, player.getAudioAttributes()); synchronized (mLock) { setPlayerLocked(player); Loading @@ -244,12 +240,25 @@ public class MediaSession2Impl implements MediaSession2Provider { private PlaybackInfo createPlaybackInfo(VolumeProvider2 volumeProvider, AudioAttributes attrs) { PlaybackInfo info; if (volumeProvider == null) { int stream = attrs == null ? AudioManager.STREAM_MUSIC : attrs.getVolumeControlStream(); int stream; if (attrs == null) { stream = AudioManager.STREAM_MUSIC; } else { stream = attrs.getVolumeControlStream(); if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) { // It may happen if the AudioAttributes doesn't have usage. // Change it to the STREAM_MUSIC because it's not supported by audio manager // for querying volume level. stream = AudioManager.STREAM_MUSIC; } } info = PlaybackInfoImpl.createPlaybackInfo( mContext, PlaybackInfo.PLAYBACK_TYPE_LOCAL, attrs, VolumeProvider2.VOLUME_CONTROL_ABSOLUTE, mAudioManager.isVolumeFixed() ? VolumeProvider2.VOLUME_CONTROL_FIXED : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE, mAudioManager.getStreamMaxVolume(stream), mAudioManager.getStreamVolume(stream)); } else { Loading Loading @@ -563,6 +572,20 @@ public class MediaSession2Impl implements MediaSession2Provider { return mVolumeProvider; } PlaybackInfo getPlaybackInfo() { synchronized (mLock) { return mPlaybackInfo; } } int getRatingType() { return mRatingType; } PendingIntent getSessionActivity() { return mSessionActivity; } private static class MyPlaybackListener implements MediaPlayerInterface.PlaybackListener { private final WeakReference<MediaSession2Impl> mSession; private final MediaPlayerInterface mPlayer; Loading
packages/MediaComponents/src/com/android/media/MediaSession2Stub.java +28 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.media; import android.app.PendingIntent; import android.content.Context; import android.media.MediaController2; import android.media.MediaController2.PlaybackInfo; Loading Loading @@ -133,10 +134,36 @@ public class MediaSession2Stub extends IMediaSession2.Stub { // TODO(jaewan): Should we protect getting playback state? final PlaybackState2 state = session.getInstance().getPlaybackState(); final Bundle playbackStateBundle = (state != null) ? state.toBundle() : null; final Bundle playbackInfoBundle = ((PlaybackInfoImpl) session.getPlaybackInfo().getProvider()).toBundle(); final PlaylistParams params = session.getInstance().getPlaylistParams(); final Bundle paramsBundle = (params != null) ? params.toBundle() : null; final int ratingType = session.getRatingType(); final PendingIntent sessionActivity = session.getSessionActivity(); final List<MediaItem2> playlist = session.getInstance().getPlaylist(); final List<Bundle> playlistBundle = new ArrayList<>(); if (playlist != null) { // TODO(jaewan): Find a way to avoid concurrent modification exception. for (int i = 0; i < playlist.size(); i++) { final MediaItem2 item = playlist.get(i); if (item != null) { final Bundle itemBundle = item.toBundle(); if (itemBundle != null) { playlistBundle.add(itemBundle); } } } } // Double check if session is still there, because close() can be called in another // thread. if (mSession.get() == null) { return; } try { callback.onConnected(MediaSession2Stub.this, allowedCommands.toBundle(), playbackStateBundle); allowedCommands.toBundle(), playbackStateBundle, playbackInfoBundle, paramsBundle, playlistBundle, ratingType, sessionActivity); } catch (RemoteException e) { // Controller may be died prematurely. // TODO(jaewan): Handle here. Loading
packages/MediaComponents/test/AndroidManifest.xml +1 −8 Original line number Diff line number Diff line Loading @@ -20,14 +20,7 @@ <application android:label="Media API Test"> <uses-library android:name="android.test.runner" /> <activity android:name="android.widget2.VideoView2TestActivity" android:configChanges="keyboardHidden|orientation|screenSize" android:label="VideoView2TestActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> </intent-filter> </activity> <activity android:name="android.media.MockActivity" /> <!-- Keep the test services synced together with the TestUtils.java --> <service android:name="android.media.MockMediaSessionService2"> Loading