Loading packages/MediaComponents/src/com/android/media/IMediaSession2.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,9 @@ oneway interface IMediaSession2 { void setPlaylist(IMediaSession2Callback caller, in List<Bundle> playlist, in Bundle metadata); void updatePlaylistMetadata(IMediaSession2Callback caller, in Bundle metadata); void addPlaylistItem(IMediaSession2Callback caller, int index, in Bundle mediaItem); void removePlaylistItem(IMediaSession2Callback caller, in Bundle mediaItem); void replacePlaylistItem(IMediaSession2Callback caller, int index, in Bundle mediaItem); ////////////////////////////////////////////////////////////////////////////////////////////// // library service specific Loading packages/MediaComponents/src/com/android/media/MediaController2Impl.java +30 −3 Original line number Diff line number Diff line Loading @@ -622,32 +622,59 @@ public class MediaController2Impl implements MediaController2Provider { @Override public void addPlaylistItem_impl(int index, MediaItem2 item) { // TODO(jaewan): Implement (b/73149584) if (index < 0) { throw new IllegalArgumentException("index shouldn't be negative"); } if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAYLIST_ADD_ITEM); if (binder != null) { try { binder.addPlaylistItem(mSessionCallbackStub, index, item.toBundle()); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to the service or the session is gone", e); } } else { Log.w(TAG, "Session isn't active", new IllegalStateException()); } } @Override public void removePlaylistItem_impl(MediaItem2 item) { // TODO(jaewan): Implement (b/73149584) if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAYLIST_REMOVE_ITEM); if (binder != null) { try { binder.removePlaylistItem(mSessionCallbackStub, item.toBundle()); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to the service or the session is gone", e); } } else { Log.w(TAG, "Session isn't active", new IllegalStateException()); } } @Override public void replacePlaylistItem_impl(int index, MediaItem2 item) { // TODO: Implement this (b/73149407) if (index < 0) { throw new IllegalArgumentException("index shouldn't be negative"); } if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAYLIST_REPLACE_ITEM); if (binder != null) { try { binder.replacePlaylistItem(mSessionCallbackStub, index, item.toBundle()); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to the service or the session is gone", e); } } else { Log.w(TAG, "Session isn't active", new IllegalStateException()); } } @Override Loading packages/MediaComponents/src/com/android/media/MediaItem2Impl.java +46 −15 Original line number Diff line number Diff line Loading @@ -31,21 +31,31 @@ import android.media.update.MediaItem2Provider; import android.os.Bundle; import android.text.TextUtils; import java.util.UUID; public class MediaItem2Impl implements MediaItem2Provider { private static final String KEY_ID = "android.media.mediaitem2.id"; private static final String KEY_FLAGS = "android.media.mediaitem2.flags"; private static final String KEY_METADATA = "android.media.mediaitem2.metadata"; private static final String KEY_UUID = "android.media.mediaitem2.uuid"; private final Context mContext; private final MediaItem2 mInstance; private final String mId; private final int mFlags; private final UUID mUUID; private MediaMetadata2 mMetadata; private DataSourceDesc mDataSourceDesc; // From the public API public MediaItem2Impl(@NonNull Context context, @NonNull String mediaId, @Nullable DataSourceDesc dsd, @Nullable MediaMetadata2 metadata, @Flags int flags) { this(context, mediaId, dsd, metadata, flags, null); } private MediaItem2Impl(@NonNull Context context, @NonNull String mediaId, @Nullable DataSourceDesc dsd, @Nullable MediaMetadata2 metadata, @Flags int flags, @Nullable UUID uuid) { if (mediaId == null) { throw new IllegalArgumentException("mediaId shouldn't be null"); } Loading @@ -58,24 +68,18 @@ public class MediaItem2Impl implements MediaItem2Provider { mDataSourceDesc = dsd; mMetadata = metadata; mFlags = flags; mUUID = (uuid == null) ? UUID.randomUUID() : uuid; mInstance = new MediaItem2(this); } // Create anonymized version public MediaItem2Impl(Context context, String mediaId, MediaMetadata2 metadata, @Flags int flags) { if (mediaId == null) { throw new IllegalArgumentException("mediaId shouldn't be null"); @Override public boolean equals_impl(Object obj) { if (!(obj instanceof MediaItem2)) { return false; } if (metadata != null && !TextUtils.equals(mediaId, metadata.getMediaId())) { throw new IllegalArgumentException("metadata's id should be matched with the mediaid"); } mContext = context; mId = mediaId; mMetadata = metadata; mFlags = flags; mInstance = new MediaItem2(this); MediaItem2 other = (MediaItem2) obj; return mUUID.equals(((MediaItem2Impl) other.getProvider()).mUUID); } /** Loading @@ -90,10 +94,37 @@ public class MediaItem2Impl implements MediaItem2Provider { if (mMetadata != null) { bundle.putBundle(KEY_METADATA, mMetadata.toBundle()); } bundle.putString(KEY_UUID, mUUID.toString()); return bundle; } public static MediaItem2 fromBundle(Context context, Bundle bundle) { /** * Create a MediaItem2 from the {@link Bundle}. * * @param context A context. * @param bundle The bundle which was published by {@link MediaItem2#toBundle()}. * @return The newly created MediaItem2 */ public static MediaItem2 fromBundle(@NonNull Context context, @NonNull Bundle bundle) { if (bundle == null) { return null; } final String uuidString = bundle.getString(KEY_UUID); return fromBundle(context, bundle, UUID.fromString(uuidString)); } /** * Create a MediaItem2 from the {@link Bundle} with the specified {@link UUID}. * If {@link UUID} * can be null for creating new. * * @param context A context. * @param bundle The bundle which was published by {@link MediaItem2#toBundle()}. * @param uuid A {@link UUID} to override. Can be {@link null} for override. * @return The newly created MediaItem2 */ static MediaItem2 fromBundle(@NonNull Context context, @NonNull Bundle bundle, @Nullable UUID uuid) { if (bundle == null) { return null; } Loading @@ -102,7 +133,7 @@ public class MediaItem2Impl implements MediaItem2Provider { final MediaMetadata2 metadata = metadataBundle != null ? MediaMetadata2.fromBundle(context, metadataBundle) : null; final int flags = bundle.getInt(KEY_FLAGS); return new MediaItem2Impl(context, id, metadata, flags).getInstance(); return new MediaItem2Impl(context, id, null, metadata, flags, uuid).getInstance(); } private MediaItem2 getInstance() { Loading packages/MediaComponents/src/com/android/media/MediaSession2Impl.java +17 −10 Original line number Diff line number Diff line Loading @@ -527,7 +527,12 @@ public class MediaSession2Impl implements MediaSession2Provider { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } // TODO(jaewan): Implement final MediaPlaylistAgent agent = mPlaylistAgent; if (agent != null) { agent.addPlaylistItem(index, item); } else if (DEBUG) { Log.d(TAG, "API calls after the close()", new IllegalStateException()); } } @Override Loading @@ -535,15 +540,12 @@ public class MediaSession2Impl implements MediaSession2Provider { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } // TODO(jaewan): Implement } @Override public void editPlaylistItem_impl(MediaItem2 item) { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); final MediaPlaylistAgent agent = mPlaylistAgent; if (agent != null) { agent.removePlaylistItem(item); } else if (DEBUG) { Log.d(TAG, "API calls after the close()", new IllegalStateException()); } // TODO(jaewan): Implement } @Override Loading @@ -554,7 +556,12 @@ public class MediaSession2Impl implements MediaSession2Provider { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } // TODO(jaewan): Implement final MediaPlaylistAgent agent = mPlaylistAgent; if (agent != null) { agent.replacePlaylistItem(index, item); } else if (DEBUG) { Log.d(TAG, "API calls after the close()", new IllegalStateException()); } } @Override Loading packages/MediaComponents/src/com/android/media/MediaSession2Stub.java +93 −0 Original line number Diff line number Diff line Loading @@ -746,6 +746,99 @@ public class MediaSession2Stub extends IMediaSession2.Stub { }); } @Override public void addPlaylistItem(IMediaSession2Callback caller, int index, Bundle mediaItem) { final MediaSession2Impl session = getSession(); final ControllerInfo controller = getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_ADD_ITEM); if (session == null || controller == null) { return; } session.getCallbackExecutor().execute(() -> { if (getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_ADD_ITEM) == null) { return; } Command command = new Command(session.getContext(), MediaSession2.COMMAND_CODE_PLAYLIST_ADD_ITEM); boolean accepted = session.getCallback().onCommandRequest(session.getInstance(), controller, command); if (!accepted) { // Don't run rejected command. if (DEBUG) { Log.d(TAG, "addPlaylistItem() from " + controller + " was rejected"); } return; } // Resets the UUID from the incoming media id, so controller may reuse a media item // multiple times for addPlaylistItem. session.getInstance().addPlaylistItem(index, MediaItem2Impl.fromBundle(session.getContext(), mediaItem, null)); }); } @Override public void removePlaylistItem(IMediaSession2Callback caller, Bundle mediaItem) { final MediaSession2Impl session = getSession(); final ControllerInfo controller = getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM); if (session == null || controller == null) { return; } session.getCallbackExecutor().execute(() -> { if (getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM) == null) { return; } Command command = new Command(session.getContext(), MediaSession2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM); boolean accepted = session.getCallback().onCommandRequest(session.getInstance(), controller, command); if (!accepted) { // Don't run rejected command. if (DEBUG) { Log.d(TAG, "removePlaylistItem() from " + controller + " was rejected"); } return; } MediaItem2 item = MediaItem2.fromBundle(session.getContext(), mediaItem); List<MediaItem2> list = session.getInstance().getPlaylist(); // Trick to use the same reference for calls from the controller. session.getInstance().removePlaylistItem(list.get(list.indexOf(item))); }); } @Override public void replacePlaylistItem(IMediaSession2Callback caller, int index, Bundle mediaItem) { final MediaSession2Impl session = getSession(); final ControllerInfo controller = getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM); if (session == null || controller == null) { return; } session.getCallbackExecutor().execute(() -> { if (getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM) == null) { return; } Command command = new Command(session.getContext(), MediaSession2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM); boolean accepted = session.getCallback().onCommandRequest(session.getInstance(), controller, command); if (!accepted) { // Don't run rejected command. if (DEBUG) { Log.d(TAG, "replacePlaylistItem() from " + controller + " was rejected"); } return; } // Resets the UUID from the incoming media id, so controller may reuse a media item // multiple times for replacePlaylistItem. session.getInstance().replacePlaylistItem(index, MediaItem2.fromBundle(session.getContext(), mediaItem)); }); } ////////////////////////////////////////////////////////////////////////////////////////////// // AIDL methods for LibrarySession overrides ////////////////////////////////////////////////////////////////////////////////////////////// Loading Loading
packages/MediaComponents/src/com/android/media/IMediaSession2.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,9 @@ oneway interface IMediaSession2 { void setPlaylist(IMediaSession2Callback caller, in List<Bundle> playlist, in Bundle metadata); void updatePlaylistMetadata(IMediaSession2Callback caller, in Bundle metadata); void addPlaylistItem(IMediaSession2Callback caller, int index, in Bundle mediaItem); void removePlaylistItem(IMediaSession2Callback caller, in Bundle mediaItem); void replacePlaylistItem(IMediaSession2Callback caller, int index, in Bundle mediaItem); ////////////////////////////////////////////////////////////////////////////////////////////// // library service specific Loading
packages/MediaComponents/src/com/android/media/MediaController2Impl.java +30 −3 Original line number Diff line number Diff line Loading @@ -622,32 +622,59 @@ public class MediaController2Impl implements MediaController2Provider { @Override public void addPlaylistItem_impl(int index, MediaItem2 item) { // TODO(jaewan): Implement (b/73149584) if (index < 0) { throw new IllegalArgumentException("index shouldn't be negative"); } if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAYLIST_ADD_ITEM); if (binder != null) { try { binder.addPlaylistItem(mSessionCallbackStub, index, item.toBundle()); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to the service or the session is gone", e); } } else { Log.w(TAG, "Session isn't active", new IllegalStateException()); } } @Override public void removePlaylistItem_impl(MediaItem2 item) { // TODO(jaewan): Implement (b/73149584) if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAYLIST_REMOVE_ITEM); if (binder != null) { try { binder.removePlaylistItem(mSessionCallbackStub, item.toBundle()); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to the service or the session is gone", e); } } else { Log.w(TAG, "Session isn't active", new IllegalStateException()); } } @Override public void replacePlaylistItem_impl(int index, MediaItem2 item) { // TODO: Implement this (b/73149407) if (index < 0) { throw new IllegalArgumentException("index shouldn't be negative"); } if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } final IMediaSession2 binder = getSessionBinderIfAble(COMMAND_CODE_PLAYLIST_REPLACE_ITEM); if (binder != null) { try { binder.replacePlaylistItem(mSessionCallbackStub, index, item.toBundle()); } catch (RemoteException e) { Log.w(TAG, "Cannot connect to the service or the session is gone", e); } } else { Log.w(TAG, "Session isn't active", new IllegalStateException()); } } @Override Loading
packages/MediaComponents/src/com/android/media/MediaItem2Impl.java +46 −15 Original line number Diff line number Diff line Loading @@ -31,21 +31,31 @@ import android.media.update.MediaItem2Provider; import android.os.Bundle; import android.text.TextUtils; import java.util.UUID; public class MediaItem2Impl implements MediaItem2Provider { private static final String KEY_ID = "android.media.mediaitem2.id"; private static final String KEY_FLAGS = "android.media.mediaitem2.flags"; private static final String KEY_METADATA = "android.media.mediaitem2.metadata"; private static final String KEY_UUID = "android.media.mediaitem2.uuid"; private final Context mContext; private final MediaItem2 mInstance; private final String mId; private final int mFlags; private final UUID mUUID; private MediaMetadata2 mMetadata; private DataSourceDesc mDataSourceDesc; // From the public API public MediaItem2Impl(@NonNull Context context, @NonNull String mediaId, @Nullable DataSourceDesc dsd, @Nullable MediaMetadata2 metadata, @Flags int flags) { this(context, mediaId, dsd, metadata, flags, null); } private MediaItem2Impl(@NonNull Context context, @NonNull String mediaId, @Nullable DataSourceDesc dsd, @Nullable MediaMetadata2 metadata, @Flags int flags, @Nullable UUID uuid) { if (mediaId == null) { throw new IllegalArgumentException("mediaId shouldn't be null"); } Loading @@ -58,24 +68,18 @@ public class MediaItem2Impl implements MediaItem2Provider { mDataSourceDesc = dsd; mMetadata = metadata; mFlags = flags; mUUID = (uuid == null) ? UUID.randomUUID() : uuid; mInstance = new MediaItem2(this); } // Create anonymized version public MediaItem2Impl(Context context, String mediaId, MediaMetadata2 metadata, @Flags int flags) { if (mediaId == null) { throw new IllegalArgumentException("mediaId shouldn't be null"); @Override public boolean equals_impl(Object obj) { if (!(obj instanceof MediaItem2)) { return false; } if (metadata != null && !TextUtils.equals(mediaId, metadata.getMediaId())) { throw new IllegalArgumentException("metadata's id should be matched with the mediaid"); } mContext = context; mId = mediaId; mMetadata = metadata; mFlags = flags; mInstance = new MediaItem2(this); MediaItem2 other = (MediaItem2) obj; return mUUID.equals(((MediaItem2Impl) other.getProvider()).mUUID); } /** Loading @@ -90,10 +94,37 @@ public class MediaItem2Impl implements MediaItem2Provider { if (mMetadata != null) { bundle.putBundle(KEY_METADATA, mMetadata.toBundle()); } bundle.putString(KEY_UUID, mUUID.toString()); return bundle; } public static MediaItem2 fromBundle(Context context, Bundle bundle) { /** * Create a MediaItem2 from the {@link Bundle}. * * @param context A context. * @param bundle The bundle which was published by {@link MediaItem2#toBundle()}. * @return The newly created MediaItem2 */ public static MediaItem2 fromBundle(@NonNull Context context, @NonNull Bundle bundle) { if (bundle == null) { return null; } final String uuidString = bundle.getString(KEY_UUID); return fromBundle(context, bundle, UUID.fromString(uuidString)); } /** * Create a MediaItem2 from the {@link Bundle} with the specified {@link UUID}. * If {@link UUID} * can be null for creating new. * * @param context A context. * @param bundle The bundle which was published by {@link MediaItem2#toBundle()}. * @param uuid A {@link UUID} to override. Can be {@link null} for override. * @return The newly created MediaItem2 */ static MediaItem2 fromBundle(@NonNull Context context, @NonNull Bundle bundle, @Nullable UUID uuid) { if (bundle == null) { return null; } Loading @@ -102,7 +133,7 @@ public class MediaItem2Impl implements MediaItem2Provider { final MediaMetadata2 metadata = metadataBundle != null ? MediaMetadata2.fromBundle(context, metadataBundle) : null; final int flags = bundle.getInt(KEY_FLAGS); return new MediaItem2Impl(context, id, metadata, flags).getInstance(); return new MediaItem2Impl(context, id, null, metadata, flags, uuid).getInstance(); } private MediaItem2 getInstance() { Loading
packages/MediaComponents/src/com/android/media/MediaSession2Impl.java +17 −10 Original line number Diff line number Diff line Loading @@ -527,7 +527,12 @@ public class MediaSession2Impl implements MediaSession2Provider { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } // TODO(jaewan): Implement final MediaPlaylistAgent agent = mPlaylistAgent; if (agent != null) { agent.addPlaylistItem(index, item); } else if (DEBUG) { Log.d(TAG, "API calls after the close()", new IllegalStateException()); } } @Override Loading @@ -535,15 +540,12 @@ public class MediaSession2Impl implements MediaSession2Provider { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } // TODO(jaewan): Implement } @Override public void editPlaylistItem_impl(MediaItem2 item) { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); final MediaPlaylistAgent agent = mPlaylistAgent; if (agent != null) { agent.removePlaylistItem(item); } else if (DEBUG) { Log.d(TAG, "API calls after the close()", new IllegalStateException()); } // TODO(jaewan): Implement } @Override Loading @@ -554,7 +556,12 @@ public class MediaSession2Impl implements MediaSession2Provider { if (item == null) { throw new IllegalArgumentException("item shouldn't be null"); } // TODO(jaewan): Implement final MediaPlaylistAgent agent = mPlaylistAgent; if (agent != null) { agent.replacePlaylistItem(index, item); } else if (DEBUG) { Log.d(TAG, "API calls after the close()", new IllegalStateException()); } } @Override Loading
packages/MediaComponents/src/com/android/media/MediaSession2Stub.java +93 −0 Original line number Diff line number Diff line Loading @@ -746,6 +746,99 @@ public class MediaSession2Stub extends IMediaSession2.Stub { }); } @Override public void addPlaylistItem(IMediaSession2Callback caller, int index, Bundle mediaItem) { final MediaSession2Impl session = getSession(); final ControllerInfo controller = getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_ADD_ITEM); if (session == null || controller == null) { return; } session.getCallbackExecutor().execute(() -> { if (getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_ADD_ITEM) == null) { return; } Command command = new Command(session.getContext(), MediaSession2.COMMAND_CODE_PLAYLIST_ADD_ITEM); boolean accepted = session.getCallback().onCommandRequest(session.getInstance(), controller, command); if (!accepted) { // Don't run rejected command. if (DEBUG) { Log.d(TAG, "addPlaylistItem() from " + controller + " was rejected"); } return; } // Resets the UUID from the incoming media id, so controller may reuse a media item // multiple times for addPlaylistItem. session.getInstance().addPlaylistItem(index, MediaItem2Impl.fromBundle(session.getContext(), mediaItem, null)); }); } @Override public void removePlaylistItem(IMediaSession2Callback caller, Bundle mediaItem) { final MediaSession2Impl session = getSession(); final ControllerInfo controller = getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM); if (session == null || controller == null) { return; } session.getCallbackExecutor().execute(() -> { if (getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM) == null) { return; } Command command = new Command(session.getContext(), MediaSession2.COMMAND_CODE_PLAYLIST_REMOVE_ITEM); boolean accepted = session.getCallback().onCommandRequest(session.getInstance(), controller, command); if (!accepted) { // Don't run rejected command. if (DEBUG) { Log.d(TAG, "removePlaylistItem() from " + controller + " was rejected"); } return; } MediaItem2 item = MediaItem2.fromBundle(session.getContext(), mediaItem); List<MediaItem2> list = session.getInstance().getPlaylist(); // Trick to use the same reference for calls from the controller. session.getInstance().removePlaylistItem(list.get(list.indexOf(item))); }); } @Override public void replacePlaylistItem(IMediaSession2Callback caller, int index, Bundle mediaItem) { final MediaSession2Impl session = getSession(); final ControllerInfo controller = getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM); if (session == null || controller == null) { return; } session.getCallbackExecutor().execute(() -> { if (getControllerIfAble( caller, MediaSession2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM) == null) { return; } Command command = new Command(session.getContext(), MediaSession2.COMMAND_CODE_PLAYLIST_REPLACE_ITEM); boolean accepted = session.getCallback().onCommandRequest(session.getInstance(), controller, command); if (!accepted) { // Don't run rejected command. if (DEBUG) { Log.d(TAG, "replacePlaylistItem() from " + controller + " was rejected"); } return; } // Resets the UUID from the incoming media id, so controller may reuse a media item // multiple times for replacePlaylistItem. session.getInstance().replacePlaylistItem(index, MediaItem2.fromBundle(session.getContext(), mediaItem)); }); } ////////////////////////////////////////////////////////////////////////////////////////////// // AIDL methods for LibrarySession overrides ////////////////////////////////////////////////////////////////////////////////////////////// Loading