Merge "Merge "Frameworks: Annotate JUnit4 test with @Test" am: 3a12454f9a am: af8f4b192d am: b4654687ef"
diff --git a/api/current.txt b/api/current.txt
index 573e635..fff502a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22842,6 +22842,27 @@
field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
}
+ public class MediaBrowser2 extends android.media.MediaController2 {
+ ctor public MediaBrowser2(android.content.Context, android.media.SessionToken2, java.util.concurrent.Executor, android.media.MediaBrowser2.BrowserCallback);
+ method public void getChildren(java.lang.String, int, int, android.os.Bundle);
+ method public void getItem(java.lang.String);
+ method public void getLibraryRoot(android.os.Bundle);
+ method public void getSearchResult(java.lang.String, int, int, android.os.Bundle);
+ method public void search(java.lang.String, android.os.Bundle);
+ method public void subscribe(java.lang.String, android.os.Bundle);
+ method public void unsubscribe(java.lang.String);
+ }
+
+ public static class MediaBrowser2.BrowserCallback extends android.media.MediaController2.ControllerCallback {
+ ctor public MediaBrowser2.BrowserCallback();
+ method public void onChildrenChanged(java.lang.String, int, android.os.Bundle);
+ method public void onGetChildrenDone(java.lang.String, int, int, java.util.List<android.media.MediaItem2>, android.os.Bundle);
+ method public void onGetItemDone(java.lang.String, android.media.MediaItem2);
+ method public void onGetLibraryRootDone(android.os.Bundle, java.lang.String, android.os.Bundle);
+ method public void onGetSearchResultDone(java.lang.String, int, int, java.util.List<android.media.MediaItem2>, android.os.Bundle);
+ method public void onSearchResultChanged(java.lang.String, int, android.os.Bundle);
+ }
+
public final class MediaCas implements java.lang.AutoCloseable {
ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
method public void close();
@@ -23318,6 +23339,73 @@
field public static final int REGULAR_CODECS = 0; // 0x0
}
+ public class MediaController2 implements java.lang.AutoCloseable {
+ ctor public MediaController2(android.content.Context, android.media.SessionToken2, java.util.concurrent.Executor, android.media.MediaController2.ControllerCallback);
+ method public void addPlaylistItem(int, android.media.MediaItem2);
+ method public void adjustVolume(int, int);
+ method public void close();
+ method public void fastForward();
+ method public long getBufferedPosition();
+ method public android.media.MediaItem2 getCurrentPlaylistItem();
+ method public android.media.MediaController2.PlaybackInfo getPlaybackInfo();
+ method public float getPlaybackSpeed();
+ method public int getPlayerState();
+ method public java.util.List<android.media.MediaItem2> getPlaylist();
+ method public android.media.MediaSession2.PlaylistParams getPlaylistParams();
+ method public long getPosition();
+ method public android.app.PendingIntent getSessionActivity();
+ method public android.media.SessionToken2 getSessionToken();
+ method public boolean isConnected();
+ method public void pause();
+ method public void play();
+ method public void playFromMediaId(java.lang.String, android.os.Bundle);
+ method public void playFromSearch(java.lang.String, android.os.Bundle);
+ method public void playFromUri(android.net.Uri, android.os.Bundle);
+ method public void prepare();
+ method public void prepareFromMediaId(java.lang.String, android.os.Bundle);
+ method public void prepareFromSearch(java.lang.String, android.os.Bundle);
+ method public void prepareFromUri(android.net.Uri, android.os.Bundle);
+ method public void removePlaylistItem(android.media.MediaItem2);
+ method public void rewind();
+ method public void seekTo(long);
+ method public void sendCustomCommand(android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
+ method public void setPlaylistParams(android.media.MediaSession2.PlaylistParams);
+ method public void setRating(java.lang.String, android.media.Rating2);
+ method public void setVolumeTo(int, int);
+ method public void skipToNext();
+ method public void skipToPlaylistItem(android.media.MediaItem2);
+ method public void skipToPrevious();
+ method public void stop();
+ }
+
+ public static abstract class MediaController2.ControllerCallback {
+ ctor public MediaController2.ControllerCallback();
+ method public void onAllowedCommandsChanged(android.media.MediaSession2.CommandGroup);
+ method public void onBufferedPositionChanged(long);
+ method public void onConnected(android.media.MediaSession2.CommandGroup);
+ method public void onCurrentPlaylistItemChanged(android.media.MediaItem2);
+ method public void onCustomCommand(android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
+ method public void onCustomLayoutChanged(java.util.List<android.media.MediaSession2.CommandButton>);
+ method public void onDisconnected();
+ method public void onError(int, int);
+ method public void onPlaybackInfoChanged(android.media.MediaController2.PlaybackInfo);
+ method public void onPlaybackSpeedChanged(float);
+ method public void onPlayerStateChanged(int);
+ method public void onPlaylistChanged(java.util.List<android.media.MediaItem2>);
+ method public void onPlaylistParamsChanged(android.media.MediaSession2.PlaylistParams);
+ method public void onPositionUpdated(long, long);
+ }
+
+ public static final class MediaController2.PlaybackInfo {
+ method public android.media.AudioAttributes getAudioAttributes();
+ method public int getControlType();
+ method public int getCurrentVolume();
+ method public int getMaxVolume();
+ method public int getPlaybackType();
+ field public static final int PLAYBACK_TYPE_LOCAL = 1; // 0x1
+ field public static final int PLAYBACK_TYPE_REMOTE = 2; // 0x2
+ }
+
public final class MediaCrypto {
ctor public MediaCrypto(java.util.UUID, byte[]) throws android.media.MediaCryptoException;
method protected void finalize();
@@ -23713,6 +23801,69 @@
field public static final java.lang.String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
}
+ public class MediaItem2 {
+ method public static android.media.MediaItem2 fromBundle(android.content.Context, android.os.Bundle);
+ method public android.media.DataSourceDesc getDataSourceDesc();
+ method public int getFlags();
+ method public java.lang.String getMediaId();
+ method public android.media.MediaMetadata2 getMetadata();
+ method public boolean isBrowsable();
+ method public boolean isPlayable();
+ method public void setMetadata(android.media.MediaMetadata2);
+ method public android.os.Bundle toBundle();
+ field public static final int FLAG_BROWSABLE = 1; // 0x1
+ field public static final int FLAG_PLAYABLE = 2; // 0x2
+ }
+
+ public static final class MediaItem2.Builder {
+ ctor public MediaItem2.Builder(android.content.Context, int);
+ method public android.media.MediaItem2 build();
+ method public android.media.MediaItem2.Builder setDataSourceDesc(android.media.DataSourceDesc);
+ method public android.media.MediaItem2.Builder setMediaId(java.lang.String);
+ method public android.media.MediaItem2.Builder setMetadata(android.media.MediaMetadata2);
+ }
+
+ public abstract class MediaLibraryService2 extends android.media.MediaSessionService2 {
+ ctor public MediaLibraryService2();
+ method public abstract android.media.MediaLibraryService2.MediaLibrarySession onCreateSession(java.lang.String);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.media.MediaLibraryService2";
+ }
+
+ public static final class MediaLibraryService2.LibraryRoot {
+ ctor public MediaLibraryService2.LibraryRoot(android.content.Context, java.lang.String, android.os.Bundle);
+ method public android.os.Bundle getExtras();
+ method public java.lang.String getRootId();
+ field public static final java.lang.String EXTRA_OFFLINE = "android.media.extra.OFFLINE";
+ field public static final java.lang.String EXTRA_RECENT = "android.media.extra.RECENT";
+ field public static final java.lang.String EXTRA_SUGGESTED = "android.media.extra.SUGGESTED";
+ }
+
+ public static final class MediaLibraryService2.MediaLibrarySession extends android.media.MediaSession2 {
+ method public void notifyChildrenChanged(android.media.MediaSession2.ControllerInfo, java.lang.String, int, android.os.Bundle);
+ method public void notifyChildrenChanged(java.lang.String, int, android.os.Bundle);
+ method public void notifySearchResultChanged(android.media.MediaSession2.ControllerInfo, java.lang.String, int, android.os.Bundle);
+ }
+
+ public static final class MediaLibraryService2.MediaLibrarySession.Builder {
+ ctor public MediaLibraryService2.MediaLibrarySession.Builder(android.media.MediaLibraryService2, android.media.MediaPlayerBase, java.util.concurrent.Executor, android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback);
+ method public android.media.MediaLibraryService2.MediaLibrarySession build();
+ method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setId(java.lang.String);
+ method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setSessionActivity(android.app.PendingIntent);
+ method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setSessionCallback(java.util.concurrent.Executor, android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback);
+ method public android.media.MediaLibraryService2.MediaLibrarySession.Builder setVolumeProvider(android.media.VolumeProvider2);
+ }
+
+ public static class MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback extends android.media.MediaSession2.SessionCallback {
+ ctor public MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback(android.content.Context);
+ method public java.util.List<android.media.MediaItem2> onGetChildren(android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
+ method public android.media.MediaItem2 onGetItem(android.media.MediaSession2.ControllerInfo, java.lang.String);
+ method public android.media.MediaLibraryService2.LibraryRoot onGetLibraryRoot(android.media.MediaSession2.ControllerInfo, android.os.Bundle);
+ method public java.util.List<android.media.MediaItem2> onGetSearchResult(android.media.MediaSession2.ControllerInfo, java.lang.String, int, int, android.os.Bundle);
+ method public void onSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+ method public void onSubscribe(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+ method public void onUnsubscribe(android.media.MediaSession2.ControllerInfo, java.lang.String);
+ }
+
public final class MediaMetadata implements android.os.Parcelable {
method public boolean containsKey(java.lang.String);
method public int describeContents();
@@ -23768,6 +23919,79 @@
method public android.media.MediaMetadata.Builder putText(java.lang.String, java.lang.CharSequence);
}
+ public final class MediaMetadata2 {
+ method public boolean containsKey(java.lang.String);
+ method public static android.media.MediaMetadata2 fromBundle(android.content.Context, android.os.Bundle);
+ method public android.graphics.Bitmap getBitmap(java.lang.String);
+ method public android.os.Bundle getExtras();
+ method public float getFloat(java.lang.String);
+ method public long getLong(java.lang.String);
+ method public java.lang.String getMediaId();
+ method public android.media.Rating2 getRating(java.lang.String);
+ method public java.lang.String getString(java.lang.String);
+ method public java.lang.CharSequence getText(java.lang.String);
+ method public java.util.Set<java.lang.String> keySet();
+ method public int size();
+ method public android.os.Bundle toBundle();
+ field public static final long BT_FOLDER_TYPE_ALBUMS = 2L; // 0x2L
+ field public static final long BT_FOLDER_TYPE_ARTISTS = 3L; // 0x3L
+ field public static final long BT_FOLDER_TYPE_GENRES = 4L; // 0x4L
+ field public static final long BT_FOLDER_TYPE_MIXED = 0L; // 0x0L
+ field public static final long BT_FOLDER_TYPE_PLAYLISTS = 5L; // 0x5L
+ field public static final long BT_FOLDER_TYPE_TITLES = 1L; // 0x1L
+ field public static final long BT_FOLDER_TYPE_YEARS = 6L; // 0x6L
+ field public static final java.lang.String METADATA_KEY_ADVERTISEMENT = "android.media.metadata.ADVERTISEMENT";
+ field public static final java.lang.String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
+ field public static final java.lang.String METADATA_KEY_ALBUM_ART = "android.media.metadata.ALBUM_ART";
+ field public static final java.lang.String METADATA_KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+ field public static final java.lang.String METADATA_KEY_ALBUM_ART_URI = "android.media.metadata.ALBUM_ART_URI";
+ field public static final java.lang.String METADATA_KEY_ART = "android.media.metadata.ART";
+ field public static final java.lang.String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
+ field public static final java.lang.String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
+ field public static final java.lang.String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+ field public static final java.lang.String METADATA_KEY_BT_FOLDER_TYPE = "android.media.metadata.BT_FOLDER_TYPE";
+ field public static final java.lang.String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+ field public static final java.lang.String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
+ field public static final java.lang.String METADATA_KEY_DATE = "android.media.metadata.DATE";
+ field public static final java.lang.String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+ field public static final java.lang.String METADATA_KEY_DISPLAY_DESCRIPTION = "android.media.metadata.DISPLAY_DESCRIPTION";
+ field public static final java.lang.String METADATA_KEY_DISPLAY_ICON = "android.media.metadata.DISPLAY_ICON";
+ field public static final java.lang.String METADATA_KEY_DISPLAY_ICON_URI = "android.media.metadata.DISPLAY_ICON_URI";
+ field public static final java.lang.String METADATA_KEY_DISPLAY_SUBTITLE = "android.media.metadata.DISPLAY_SUBTITLE";
+ field public static final java.lang.String METADATA_KEY_DISPLAY_TITLE = "android.media.metadata.DISPLAY_TITLE";
+ field public static final java.lang.String METADATA_KEY_DOWNLOAD_STATUS = "android.media.metadata.DOWNLOAD_STATUS";
+ field public static final java.lang.String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
+ field public static final java.lang.String METADATA_KEY_EXTRAS = "android.media.metadata.EXTRAS";
+ field public static final java.lang.String METADATA_KEY_GENRE = "android.media.metadata.GENRE";
+ field public static final java.lang.String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
+ field public static final java.lang.String METADATA_KEY_MEDIA_URI = "android.media.metadata.MEDIA_URI";
+ field public static final java.lang.String METADATA_KEY_NUM_TRACKS = "android.media.metadata.NUM_TRACKS";
+ field public static final java.lang.String METADATA_KEY_RADIO_CALLSIGN = "android.media.metadata.RADIO_CALLSIGN";
+ field public static final java.lang.String METADATA_KEY_RADIO_FREQUENCY = "android.media.metadata.RADIO_FREQUENCY";
+ field public static final java.lang.String METADATA_KEY_RATING = "android.media.metadata.RATING";
+ field public static final java.lang.String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
+ field public static final java.lang.String METADATA_KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+ field public static final java.lang.String METADATA_KEY_USER_RATING = "android.media.metadata.USER_RATING";
+ field public static final java.lang.String METADATA_KEY_WRITER = "android.media.metadata.WRITER";
+ field public static final java.lang.String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
+ field public static final long STATUS_DOWNLOADED = 2L; // 0x2L
+ field public static final long STATUS_DOWNLOADING = 1L; // 0x1L
+ field public static final long STATUS_NOT_DOWNLOADED = 0L; // 0x0L
+ }
+
+ public static final class MediaMetadata2.Builder {
+ ctor public MediaMetadata2.Builder(android.content.Context);
+ ctor public MediaMetadata2.Builder(android.content.Context, android.media.MediaMetadata2);
+ method public android.media.MediaMetadata2 build();
+ method public android.media.MediaMetadata2.Builder putBitmap(java.lang.String, android.graphics.Bitmap);
+ method public android.media.MediaMetadata2.Builder putFloat(java.lang.String, float);
+ method public android.media.MediaMetadata2.Builder putLong(java.lang.String, long);
+ method public android.media.MediaMetadata2.Builder putRating(java.lang.String, android.media.Rating2);
+ method public android.media.MediaMetadata2.Builder putString(java.lang.String, java.lang.String);
+ method public android.media.MediaMetadata2.Builder putText(java.lang.String, java.lang.CharSequence);
+ method public android.media.MediaMetadata2.Builder setExtras(android.os.Bundle);
+ }
+
public abstract deprecated class MediaMetadataEditor {
method public synchronized void addEditableKey(int);
method public abstract void apply();
@@ -24239,6 +24463,19 @@
field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
}
+ public abstract class MediaPlayerBase implements java.lang.AutoCloseable {
+ ctor public MediaPlayerBase();
+ method public abstract android.media.AudioAttributes getAudioAttributes();
+ method public abstract int getPlayerState();
+ method public abstract void pause();
+ method public abstract void play();
+ method public abstract void setAudioAttributes(android.media.AudioAttributes);
+ field public static final int STATE_ERROR = 0; // 0x0
+ field public static final int STATE_IDLE = 0; // 0x0
+ field public static final int STATE_PAUSED = 0; // 0x0
+ field public static final int STATE_PLAYING = 0; // 0x0
+ }
+
public class MediaRecorder implements android.media.AudioRouting {
ctor public MediaRecorder();
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
@@ -24515,6 +24752,172 @@
method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
}
+ public class MediaSession2 implements java.lang.AutoCloseable {
+ method public void addPlaylistItem(int, android.media.MediaItem2);
+ method public void close();
+ method public void editPlaylistItem(android.media.MediaItem2);
+ method public void fastForward();
+ method public java.util.List<android.media.MediaSession2.ControllerInfo> getConnectedControllers();
+ method public android.media.MediaItem2 getCurrentPlaylistItem();
+ method public android.media.MediaPlayerBase getPlayer();
+ method public java.util.List<android.media.MediaItem2> getPlaylist();
+ method public android.media.MediaSession2.PlaylistParams getPlaylistParams();
+ method public android.media.SessionToken2 getToken();
+ method public void notifyError(int, int);
+ method public void pause();
+ method public void play();
+ method public void prepare();
+ method public void removePlaylistItem(android.media.MediaItem2);
+ method public void rewind();
+ method public void seekTo(long);
+ method public void sendCustomCommand(android.media.MediaSession2.Command, android.os.Bundle);
+ method public void sendCustomCommand(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
+ method public void setAllowedCommands(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.CommandGroup);
+ method public void setCustomLayout(android.media.MediaSession2.ControllerInfo, java.util.List<android.media.MediaSession2.CommandButton>);
+ method public void setPlayer(android.media.MediaPlayerBase);
+ method public void setPlayer(android.media.MediaPlayerBase, android.media.VolumeProvider2);
+ method public void setPlaylist(java.util.List<android.media.MediaItem2>);
+ method public void setPlaylistParams(android.media.MediaSession2.PlaylistParams);
+ method public void skipToNext();
+ method public void skipToPlaylistItem(android.media.MediaItem2);
+ method public void skipToPrevious();
+ method public void stop();
+ field public static final int COMMAND_CODE_BROWSER = 22; // 0x16
+ field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
+ field public static final int COMMAND_CODE_PLAYBACK_FAST_FORWARD = 7; // 0x7
+ field public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2; // 0x2
+ field public static final int COMMAND_CODE_PLAYBACK_PLAY = 1; // 0x1
+ field public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6; // 0x6
+ field public static final int COMMAND_CODE_PLAYBACK_REWIND = 8; // 0x8
+ field public static final int COMMAND_CODE_PLAYBACK_SEEK_TO = 9; // 0x9
+ field public static final int COMMAND_CODE_PLAYBACK_SET_CURRENT_PLAYLIST_ITEM = 10; // 0xa
+ field public static final int COMMAND_CODE_PLAYBACK_SET_PLAYLIST_PARAMS = 11; // 0xb
+ field public static final int COMMAND_CODE_PLAYBACK_SKIP_NEXT_ITEM = 4; // 0x4
+ field public static final int COMMAND_CODE_PLAYBACK_SKIP_PREV_ITEM = 5; // 0x5
+ field public static final int COMMAND_CODE_PLAYBACK_STOP = 3; // 0x3
+ field public static final int COMMAND_CODE_PLAYLIST_ADD = 12; // 0xc
+ field public static final int COMMAND_CODE_PLAYLIST_GET = 14; // 0xe
+ field public static final int COMMAND_CODE_PLAYLIST_REMOVE = 13; // 0xd
+ field public static final int COMMAND_CODE_PLAY_FROM_MEDIA_ID = 16; // 0x10
+ field public static final int COMMAND_CODE_PLAY_FROM_SEARCH = 18; // 0x12
+ field public static final int COMMAND_CODE_PLAY_FROM_URI = 17; // 0x11
+ field public static final int COMMAND_CODE_PREPARE_FROM_MEDIA_ID = 19; // 0x13
+ field public static final int COMMAND_CODE_PREPARE_FROM_SEARCH = 21; // 0x15
+ field public static final int COMMAND_CODE_PREPARE_FROM_URI = 20; // 0x14
+ field public static final int COMMAND_CODE_SET_VOLUME = 15; // 0xf
+ field public static final int ERROR_CODE_ACTION_ABORTED = 10; // 0xa
+ field public static final int ERROR_CODE_APP_ERROR = 1; // 0x1
+ field public static final int ERROR_CODE_AUTHENTICATION_EXPIRED = 3; // 0x3
+ field public static final int ERROR_CODE_CONCURRENT_STREAM_LIMIT = 5; // 0x5
+ field public static final int ERROR_CODE_CONTENT_ALREADY_PLAYING = 8; // 0x8
+ field public static final int ERROR_CODE_END_OF_QUEUE = 11; // 0xb
+ field public static final int ERROR_CODE_NOT_AVAILABLE_IN_REGION = 7; // 0x7
+ field public static final int ERROR_CODE_NOT_SUPPORTED = 2; // 0x2
+ field public static final int ERROR_CODE_PARENTAL_CONTROL_RESTRICTED = 6; // 0x6
+ field public static final int ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED = 4; // 0x4
+ field public static final int ERROR_CODE_SETUP_REQUIRED = 12; // 0xc
+ field public static final int ERROR_CODE_SKIP_LIMIT_REACHED = 9; // 0x9
+ field public static final int ERROR_CODE_UNKNOWN_ERROR = 0; // 0x0
+ }
+
+ public static final class MediaSession2.Builder {
+ ctor public MediaSession2.Builder(android.content.Context, android.media.MediaPlayerBase);
+ method public android.media.MediaSession2 build();
+ method public android.media.MediaSession2.Builder setId(java.lang.String);
+ method public android.media.MediaSession2.Builder setSessionActivity(android.app.PendingIntent);
+ method public android.media.MediaSession2.Builder setSessionCallback(java.util.concurrent.Executor, android.media.MediaSession2.SessionCallback);
+ method public android.media.MediaSession2.Builder setVolumeProvider(android.media.VolumeProvider2);
+ }
+
+ public static final class MediaSession2.Command {
+ ctor public MediaSession2.Command(android.content.Context, int);
+ ctor public MediaSession2.Command(android.content.Context, java.lang.String, android.os.Bundle);
+ method public int getCommandCode();
+ method public java.lang.String getCustomCommand();
+ method public android.os.Bundle getExtra();
+ }
+
+ public static final class MediaSession2.CommandButton {
+ method public android.media.MediaSession2.Command getCommand();
+ method public java.lang.String getDisplayName();
+ method public android.os.Bundle getExtra();
+ method public int getIconResId();
+ method public boolean isEnabled();
+ }
+
+ public static final class MediaSession2.CommandButton.Builder {
+ ctor public MediaSession2.CommandButton.Builder(android.content.Context);
+ method public android.media.MediaSession2.CommandButton build();
+ method public android.media.MediaSession2.CommandButton.Builder setCommand(android.media.MediaSession2.Command);
+ method public android.media.MediaSession2.CommandButton.Builder setDisplayName(java.lang.String);
+ method public android.media.MediaSession2.CommandButton.Builder setEnabled(boolean);
+ method public android.media.MediaSession2.CommandButton.Builder setExtra(android.os.Bundle);
+ method public android.media.MediaSession2.CommandButton.Builder setIconResId(int);
+ }
+
+ public static final class MediaSession2.CommandGroup {
+ ctor public MediaSession2.CommandGroup(android.content.Context);
+ ctor public MediaSession2.CommandGroup(android.content.Context, android.media.MediaSession2.CommandGroup);
+ method public void addAllPredefinedCommands();
+ method public void addCommand(android.media.MediaSession2.Command);
+ method public boolean hasCommand(android.media.MediaSession2.Command);
+ method public boolean hasCommand(int);
+ method public void removeCommand(android.media.MediaSession2.Command);
+ }
+
+ public static final class MediaSession2.ControllerInfo {
+ method public java.lang.String getPackageName();
+ method public int getUid();
+ method public boolean isTrusted();
+ }
+
+ public static final class MediaSession2.PlaylistParams {
+ ctor public MediaSession2.PlaylistParams(android.content.Context, int, int, android.media.MediaMetadata2);
+ method public static android.media.MediaSession2.PlaylistParams fromBundle(android.content.Context, android.os.Bundle);
+ method public android.media.MediaMetadata2 getPlaylistMetadata();
+ method public int getRepeatMode();
+ method public int getShuffleMode();
+ method public android.os.Bundle toBundle();
+ field public static final int REPEAT_MODE_ALL = 2; // 0x2
+ field public static final int REPEAT_MODE_GROUP = 3; // 0x3
+ field public static final int REPEAT_MODE_NONE = 0; // 0x0
+ field public static final int REPEAT_MODE_ONE = 1; // 0x1
+ field public static final int SHUFFLE_MODE_ALL = 1; // 0x1
+ field public static final int SHUFFLE_MODE_GROUP = 2; // 0x2
+ field public static final int SHUFFLE_MODE_NONE = 0; // 0x0
+ }
+
+ public static abstract class MediaSession2.SessionCallback {
+ ctor public MediaSession2.SessionCallback(android.content.Context);
+ method public boolean onCommandRequest(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command);
+ method public android.media.MediaSession2.CommandGroup onConnect(android.media.MediaSession2.ControllerInfo);
+ method public void onCustomCommand(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
+ method public void onDisconnected(android.media.MediaSession2.ControllerInfo);
+ method public void onPlayFromMediaId(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+ method public void onPlayFromSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+ method public void onPlayFromUri(android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
+ method public void onPrepareFromMediaId(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+ method public void onPrepareFromSearch(android.media.MediaSession2.ControllerInfo, java.lang.String, android.os.Bundle);
+ method public void onPrepareFromUri(android.media.MediaSession2.ControllerInfo, android.net.Uri, android.os.Bundle);
+ method public void onSetRating(android.media.MediaSession2.ControllerInfo, java.lang.String, android.media.Rating2);
+ }
+
+ public abstract class MediaSessionService2 extends android.app.Service {
+ ctor public MediaSessionService2();
+ method public final android.media.MediaSession2 getSession();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract android.media.MediaSession2 onCreateSession(java.lang.String);
+ method public android.media.MediaSessionService2.MediaNotification onUpdateNotification();
+ field public static final java.lang.String SERVICE_INTERFACE = "android.media.MediaSessionService2";
+ field public static final java.lang.String SERVICE_META_DATA = "android.media.session";
+ }
+
+ public static class MediaSessionService2.MediaNotification {
+ ctor public MediaSessionService2.MediaNotification(android.content.Context, int, android.app.Notification);
+ method public android.app.Notification getNotification();
+ method public int getNotificationId();
+ }
+
public final class MediaSync {
ctor public MediaSync();
method public android.view.Surface createInputSurface();
@@ -24645,6 +25048,29 @@
field public static final int RATING_THUMB_UP_DOWN = 2; // 0x2
}
+ public final class Rating2 {
+ method public static android.media.Rating2 fromBundle(android.content.Context, android.os.Bundle);
+ method public float getPercentRating();
+ method public int getRatingStyle();
+ method public float getStarRating();
+ method public boolean hasHeart();
+ method public boolean isRated();
+ method public boolean isThumbUp();
+ method public static android.media.Rating2 newHeartRating(android.content.Context, boolean);
+ method public static android.media.Rating2 newPercentageRating(android.content.Context, float);
+ method public static android.media.Rating2 newStarRating(android.content.Context, int, float);
+ method public static android.media.Rating2 newThumbRating(android.content.Context, boolean);
+ method public static android.media.Rating2 newUnratedRating(android.content.Context, int);
+ method public android.os.Bundle toBundle();
+ field public static final int RATING_3_STARS = 3; // 0x3
+ field public static final int RATING_4_STARS = 4; // 0x4
+ field public static final int RATING_5_STARS = 5; // 0x5
+ field public static final int RATING_HEART = 1; // 0x1
+ field public static final int RATING_NONE = 0; // 0x0
+ field public static final int RATING_PERCENTAGE = 6; // 0x6
+ field public static final int RATING_THUMB_UP_DOWN = 2; // 0x2
+ }
+
public deprecated class RemoteControlClient {
ctor public RemoteControlClient(android.app.PendingIntent);
ctor public RemoteControlClient(android.app.PendingIntent, android.os.Looper);
@@ -24780,6 +25206,22 @@
field public static final int URI_COLUMN_INDEX = 2; // 0x2
}
+ public final class SessionToken2 {
+ ctor public SessionToken2(android.content.Context, java.lang.String, java.lang.String);
+ method public static android.media.SessionToken2 fromBundle(android.content.Context, android.os.Bundle);
+ method public java.lang.String getId();
+ method public java.lang.String getPackageName();
+ method public int getType();
+ method public int getUid();
+ method public android.os.Bundle toBundle();
+ field public static final int TYPE_LIBRARY_SERVICE = 2; // 0x2
+ field public static final int TYPE_SESSION = 0; // 0x0
+ field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
+ }
+
+ public static abstract class SessionToken2.TokenType implements java.lang.annotation.Annotation {
+ }
+
public class SoundPool {
ctor public deprecated SoundPool(int, int, int);
method public final void autoPause();
@@ -24983,6 +25425,19 @@
field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
}
+ public abstract class VolumeProvider2 {
+ ctor public VolumeProvider2(android.content.Context, int, int, int);
+ method public final int getControlType();
+ method public final int getCurrentVolume();
+ method public final int getMaxVolume();
+ method public void onAdjustVolume(int);
+ method public void onSetVolumeTo(int);
+ method public final void setCurrentVolume(int);
+ field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
+ field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0
+ field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1
+ }
+
public final class VolumeShaper implements java.lang.AutoCloseable {
method public void apply(android.media.VolumeShaper.Operation);
method public void close();
@@ -25729,14 +26184,23 @@
public final class MediaSessionManager {
method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName);
method public void addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler);
+ method public void addOnSessionTokensChangedListener(java.util.concurrent.Executor, android.media.session.MediaSessionManager.OnSessionTokensChangedListener);
+ method public java.util.List<android.media.SessionToken2> getActiveSessionTokens();
method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName);
+ method public java.util.List<android.media.SessionToken2> getAllSessionTokens();
+ method public java.util.List<android.media.SessionToken2> getSessionServiceTokens();
method public void removeOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener);
+ method public void removeOnSessionTokensChangedListener(android.media.session.MediaSessionManager.OnSessionTokensChangedListener);
}
public static abstract interface MediaSessionManager.OnActiveSessionsChangedListener {
method public abstract void onActiveSessionsChanged(java.util.List<android.media.session.MediaController>);
}
+ public static abstract interface MediaSessionManager.OnSessionTokensChangedListener {
+ method public abstract void onSessionTokensChanged(java.util.List<android.media.SessionToken2>);
+ }
+
public final class PlaybackState implements android.os.Parcelable {
method public int describeContents();
method public long getActions();
diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java
index 340be46..a7ae3234 100644
--- a/core/java/android/widget/VideoView2.java
+++ b/core/java/android/widget/VideoView2.java
@@ -23,7 +23,7 @@
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.MediaMetadata2;
-import android.media.MediaPlayerInterface;
+import android.media.MediaPlayerBase;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
@@ -277,7 +277,7 @@
* @hide
*/
public void setRouteAttributes(@NonNull List<String> routeCategories,
- @Nullable MediaPlayerInterface player) {
+ @Nullable MediaPlayerBase player) {
mProvider.setRouteAttributes_impl(routeCategories, player);
}
diff --git a/media/java/android/media/MediaBrowser2.java b/media/java/android/media/MediaBrowser2.java
index 3f9a4ef..dea38a8 100644
--- a/media/java/android/media/MediaBrowser2.java
+++ b/media/java/android/media/MediaBrowser2.java
@@ -31,7 +31,6 @@
/**
* Browses media content offered by a {@link MediaLibraryService2}.
- * @hide
*/
public class MediaBrowser2 extends MediaController2 {
// Equals to the ((MediaBrowser2Provider) getProvider())
diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java
index 6682e08..0114240 100644
--- a/media/java/android/media/MediaController2.java
+++ b/media/java/android/media/MediaController2.java
@@ -19,13 +19,13 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Context;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.ErrorCode;
import android.media.MediaSession2.PlaylistParams;
import android.media.session.MediaSessionManager;
import android.media.update.ApiLoader;
@@ -64,9 +64,8 @@
* <p>
* @see MediaSession2
* @see MediaSessionService2
- * @hide
*/
-public class MediaController2 implements AutoCloseable {
+public class MediaController2 implements AutoCloseable, MediaPlaylistController {
/**
* Interface for listening to change in activeness of the {@link MediaSession2}. It's
* active if and only if it has set a player.
@@ -126,19 +125,69 @@
/**
* Called when the playlist is changed.
+ * <p>
+ * When it's called, you should invalidate previous playback information such as position,
+ * player state, current item, etc.
*
* @param playlist A new playlist set by the session.
*/
+ // TODO(jaewan): Enhance doc
public void onPlaylistChanged(@NonNull List<MediaItem2> playlist) { }
/**
* Called when the playback state is changed.
*
* @param state latest playback state
+ * @hide
*/
+ // TODo(jaewan): Remove
public void onPlaybackStateChanged(@NonNull PlaybackState2 state) { }
/**
+ * Called when the player state is changed.
+ *
+ * @param state
+ */
+ public void onPlayerStateChanged(int state) { }
+
+ /**
+ * Called when the player's position is changed
+ *
+ * @param updateTimeMs timestamp when the position information is sent from the session
+ * @param positionMs position in millis
+ */
+ public void onPositionUpdated(long updateTimeMs, long positionMs) { }
+
+ /**
+ * Called when playback speed is changed.
+ *
+ * @param speed speed
+ */
+ public void onPlaybackSpeedChanged(float speed) { }
+
+ /**
+ * Called when the player's buffering position
+ *
+ * @param positionMs buffering position in millis
+ */
+ public void onBufferedPositionChanged(long positionMs) { }
+
+ /**
+ * Called when a error from
+ *
+ * @param errorCode error code
+ * @param extra extra information
+ */
+ public void onError(@ErrorCode int errorCode, int extra) { }
+
+ /**
+ * Called when the player's current playing item is changed
+ *
+ * @param item new item
+ */
+ public void onCurrentPlaylistItemChanged(MediaItem2 item) { }
+
+ /**
* Called when the playlist parameters are changed.
*
* @param params The new play list parameters.
@@ -166,7 +215,6 @@
/**
* @hide
*/
- @SystemApi
public PlaybackInfo(PlaybackInfoProvider provider) {
mProvider = provider;
}
@@ -174,7 +222,6 @@
/**
* @hide
*/
- @SystemApi
public PlaybackInfoProvider getProvider() {
return mProvider;
}
@@ -281,7 +328,6 @@
/**
* @hide
*/
- @SystemApi
public MediaController2Provider getProvider() {
return mProvider;
}
@@ -325,7 +371,7 @@
* Request that the player prepare its playback. In other words, other sessions can continue
* to play during the preparation of this session. This method can be used to speed up the
* start of the playback. Once the preparation is done, the session will change its playback
- * state to {@link PlaybackState2#STATE_PAUSED}. Afterwards, {@link #play} can be called to
+ * state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards, {@link #play} can be called to
* start playback.
*/
public void prepare() {
@@ -360,12 +406,13 @@
/**
* Sets the index of current DataSourceDesc in the play list to be played.
*
- * @param index the index of DataSourceDesc in the play list you want to play
+ * @param item the index of DataSourceDesc in the play list you want to play
* @throws IllegalArgumentException if the play list is null
* @throws NullPointerException if index is outside play list range
*/
- public void setCurrentPlaylistItem(int index) {
- mProvider.setCurrentPlaylistItem_impl(index);
+ @Override
+ public void skipToPlaylistItem(@NonNull MediaItem2 item) {
+ mProvider.skipToPlaylistItem_impl(item);
}
/**
@@ -375,7 +422,7 @@
* @param params A {@link PlaylistParams} object to set.
* @throws IllegalArgumentException if given {@param param} is null.
*/
- public void setPlaylistParams(PlaylistParams params) {
+ public void setPlaylistParams(@NonNull PlaylistParams params) {
mProvider.setPlaylistParams_impl(params);
}
@@ -428,12 +475,11 @@
mProvider.playFromUri_impl(uri, extras);
}
-
/**
* Request that the player prepare playback for a specific media id. In other words, other
* sessions can continue to play during the preparation of this session. This method can be
* used to speed up the start of the playback. Once the preparation is done, the session
- * will change its playback state to {@link PlaybackState2#STATE_PAUSED}. Afterwards,
+ * will change its playback state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards,
* {@link #play} can be called to start playback. If the preparation is not needed,
* {@link #playFromMediaId} can be directly called without this method.
*
@@ -450,7 +496,7 @@
* query should be treated as a request to prepare any music. In other words, other sessions
* can continue to play during the preparation of this session. This method can be used to
* speed up the start of the playback. Once the preparation is done, the session will
- * change its playback state to {@link PlaybackState2#STATE_PAUSED}. Afterwards,
+ * change its playback state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards,
* {@link #play} can be called to start playback. If the preparation is not needed,
* {@link #playFromSearch} can be directly called without this method.
*
@@ -466,7 +512,7 @@
* Request that the player prepare playback for a specific {@link Uri}. In other words,
* other sessions can continue to play during the preparation of this session. This method
* can be used to speed up the start of the playback. Once the preparation is done, the
- * session will change its playback state to {@link PlaybackState2#STATE_PAUSED}. Afterwards,
+ * session will change its playback state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards,
* {@link #play} can be called to start playback. If the preparation is not needed,
* {@link #playFromUri} can be directly called without this method.
*
@@ -537,12 +583,65 @@
* playback state.
*
* @return a playback state. Can be {@code null}
+ * @hide
*/
public @Nullable PlaybackState2 getPlaybackState() {
return mProvider.getPlaybackState_impl();
}
/**
+ * Get the lastly cached player state from {@link ControllerCallback#onPlayerStateChanged(int)}.
+ *
+ * @return player state
+ */
+ public int getPlayerState() {
+ return mProvider.getPlayerState_impl();
+ }
+
+ /**
+ * Get the lastly cached position from {@link ControllerCallback#onPositionUpdated(long, long)}.
+ * <p>
+ * This returns the calculated value of the position, based on the difference between the
+ * update time and current time.
+ *
+ * @return position
+ */
+ public long getPosition() {
+ return mProvider.getPosition_impl();
+ }
+
+ /**
+ * Get the lastly cached playback speed from
+ * {@link ControllerCallback#onPlaybackSpeedChanged(float)}.
+ *
+ * @return speed
+ */
+ public float getPlaybackSpeed() {
+ return mProvider.getPlaybackSpeed_impl();
+ }
+
+ /**
+ * Get the lastly cached buffered position from
+ * {@link ControllerCallback#onBufferedPositionChanged(long)}.
+ *
+ * @return buffering position in millis
+ */
+ public long getBufferedPosition() {
+ return mProvider.getBufferedPosition_impl();
+ }
+
+ /**
+ * Get the lastly cached current item from
+ * {@link ControllerCallback#onCurrentPlaylistItemChanged(MediaItem2)}.
+ *
+ * @return index of the current item
+ */
+ @Override
+ public MediaItem2 getCurrentPlaylistItem() {
+ return mProvider.getCurrentPlaylistItem_impl();
+ }
+
+ /**
* Get the current playback info for this session.
*
* @return The current playback info or null.
@@ -584,6 +683,7 @@
*
* @return playlist. Can be {@code null} if the controller doesn't have enough permission.
*/
+ @Override
public @Nullable List<MediaItem2> getPlaylist() {
return mProvider.getPlaylist_impl();
}
@@ -603,13 +703,11 @@
* If index is same as the current index of the playlist, current playback
* will be stopped and playback moves to next source in the list.
*
- * @return the removed DataSourceDesc at index in the play list
* @throws IllegalArgumentException if the play list is null
* @throws IndexOutOfBoundsException if index is outside play list range
*/
- // TODO(jaewan): Remove with index was previously rejected by council (b/36524925)
- // TODO(jaewan): Should we also add movePlaylistItem from index to index?
- public void removePlaylistItem(MediaItem2 item) {
+ @Override
+ public void removePlaylistItem(@NonNull MediaItem2 item) {
mProvider.removePlaylistItem_impl(item);
}
@@ -620,12 +718,12 @@
* If index is less than or equal to the current index of the play list,
* the current index of the play list will be incremented correspondingly.
*
- * @param index the index you want to add dsd to the play list
- * @param item the media item you want to add to the play list
+ * @param index the index you want to add
+ * @param item the media item you want to add
* @throws IndexOutOfBoundsException if index is outside play list range
- * @throws NullPointerException if dsd is null
*/
- public void addPlaylistItem(int index, MediaItem2 item) {
+ @Override
+ public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
mProvider.addPlaylistItem_impl(index, item);
}
}
diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java
index 667aac1..b7b75e4 100644
--- a/media/java/android/media/MediaItem2.java
+++ b/media/java/android/media/MediaItem2.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.MediaItem2Provider;
@@ -35,7 +34,6 @@
* When it's sent to a controller or browser, it's anonymized and data descriptor wouldn't be sent.
* <p>
* This object isn't a thread safe.
- * @hide
*/
public class MediaItem2 {
/** @hide */
@@ -64,7 +62,9 @@
* @param mediaId id of this item. It must be unique whithin this app
* @param metadata metadata with the media id.
* @param flags The flags for this item.
+ * @hide
*/
+ // TODO(jaewan): Remove this
public MediaItem2(@NonNull Context context, @NonNull String mediaId,
@NonNull DataSourceDesc dsd, @Nullable MediaMetadata2 metadata,
@Flags int flags) {
@@ -76,7 +76,6 @@
* Create a new media item
* @hide
*/
- @SystemApi
public MediaItem2(MediaItem2Provider provider) {
mProvider = provider;
}
@@ -156,4 +155,87 @@
public @Nullable DataSourceDesc getDataSourceDesc() {
return mProvider.getDataSourceDesc_impl();
}
+
+ /**
+ * Build {@link MediaItem2}
+ */
+ // TODO(jaewan): Move it to updatable
+ public static final class Builder {
+ private Context mContext;
+ private @Flags int mFlags;
+ private String mMediaId;
+ private MediaMetadata2 mMetadata;
+ private DataSourceDesc mDataSourceDesc;
+
+ /**
+ * Constructor for {@link Builder}
+ *
+ * @param context
+ * @param flags
+ */
+ public Builder(@NonNull Context context, @Flags int flags) {
+ mContext = context;
+ mFlags = flags;
+ }
+
+ /**
+ * Set the media id of this instance. {@code null} for unset.
+ * <p>
+ * Media id is used to identify a media contents between session and controller.
+ * <p>
+ * If the metadata is set with the {@link #setMetadata(MediaMetadata2)} and it has
+ * media id, id from {@link #setMediaId(String)} will be ignored and metadata's id will be
+ * used instead. If the id isn't set neither by {@link #setMediaId(String)} nor
+ * {@link #setMetadata(MediaMetadata2)}, id will be automatically generated.
+ *
+ * @param mediaId media id
+ * @return this instance for chaining
+ */
+ public Builder setMediaId(@Nullable String mediaId) {
+ mMediaId = mediaId;
+ return this;
+ }
+
+ /**
+ * Set the metadata of this instance. {@code null} for unset.
+ * <p>
+ * If the metadata is set with the {@link #setMetadata(MediaMetadata2)} and it has
+ * media id, id from {@link #setMediaId(String)} will be ignored and metadata's id will be
+ * used instead. If the id isn't set neither by {@link #setMediaId(String)} nor
+ * {@link #setMetadata(MediaMetadata2)}, id will be automatically generated.
+ *
+ * @param metadata metadata
+ * @return this instance for chaining
+ */
+ public Builder setMetadata(@Nullable MediaMetadata2 metadata) {
+ mMetadata = metadata;
+ return this;
+ }
+
+ /**
+ * Set the data source descriptor for this instance. {@code null} for unset.
+ *
+ * @param dataSourceDesc data source descriptor
+ * @return this instance for chaining
+ */
+ public Builder setDataSourceDesc(@Nullable DataSourceDesc dataSourceDesc) {
+ mDataSourceDesc = dataSourceDesc;
+ return this;
+ }
+
+ /**
+ * Build {@link MediaItem2}.
+ *
+ * @return a new {@link MediaItem2}.
+ */
+ public MediaItem2 build() {
+ String id = (mMetadata != null)
+ ? mMetadata.getString(MediaMetadata2.METADATA_KEY_MEDIA_ID) : null;
+ if (id == null) {
+ // TODO(jaewan): Double check if its sufficient (e.g. Use UUID instead?)
+ id = (mMediaId != null) ? mMediaId : toString();
+ }
+ return new MediaItem2(mContext, id, mDataSourceDesc, mMetadata, mFlags);
+ }
+ }
}
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
index 11b745a..768d044 100644
--- a/media/java/android/media/MediaLibraryService2.java
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -19,10 +19,10 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Context;
-import android.media.MediaSession2.BuilderBase;
+import android.media.MediaLibraryService2.MediaLibrarySession.Builder;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
import android.media.MediaSession2.ControllerInfo;
import android.media.update.ApiLoader;
import android.media.update.MediaLibraryService2Provider.LibraryRootProvider;
@@ -40,7 +40,7 @@
* and ask the application to start playing it. They may also be used to control content that
* is already playing by way of a {@link MediaSession2}.
* <p>
- * To extend this class, adding followings directly to your {@code AndroidManifest.xml}.
+ * When extending this class, also add the following to your {@code AndroidManifest.xml}.
* <pre>
* <service android:name="component_name_of_your_implementation" >
* <intent-filter>
@@ -48,11 +48,12 @@
* </intent-filter>
* </service></pre>
* <p>
- * A {@link MediaLibraryService2} is extension of {@link MediaSessionService2}. IDs shouldn't
+ * The {@link MediaLibraryService2} class derives from {@link MediaSessionService2}. IDs shouldn't
* be shared between the {@link MediaSessionService2} and {@link MediaSession2}. By
* default, an empty string will be used for ID of the service. If you want to specify an ID,
* declare metadata in the manifest as follows.
- * @hide
+ *
+ * @see MediaSessionService2
*/
public abstract class MediaLibraryService2 extends MediaSessionService2 {
/**
@@ -63,15 +64,178 @@
/**
* Session for the {@link MediaLibraryService2}. Build this object with
- * {@link MediaLibrarySessionBuilder} and return in {@link #onCreateSession(String)}.
+ * {@link Builder} and return in {@link #onCreateSession(String)}.
*/
- public static class MediaLibrarySession extends MediaSession2 {
+ public static final class MediaLibrarySession extends MediaSession2 {
private final MediaLibrarySessionProvider mProvider;
/**
+ * Callback for the {@link MediaLibrarySession}.
+ */
+ public static class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
+ public MediaLibrarySessionCallback(Context context) {
+ super(context);
+ }
+
+ /**
+ * Called to get the root information for browsing by a particular client.
+ * <p>
+ * The implementation should verify that the client package has permission
+ * to access browse media information before returning the root id; it
+ * should return null if the client is not allowed to access this
+ * information.
+ *
+ * @param controllerInfo information of the controller requesting access to browse media.
+ * @param rootHints An optional bundle of service-specific arguments to send
+ * to the media library service when connecting and retrieving the
+ * root id for browsing, or null if none. The contents of this
+ * bundle may affect the information returned when browsing.
+ * @return The {@link LibraryRoot} for accessing this app's content or null.
+ * @see LibraryRoot#EXTRA_RECENT
+ * @see LibraryRoot#EXTRA_OFFLINE
+ * @see LibraryRoot#EXTRA_SUGGESTED
+ */
+ public @Nullable LibraryRoot onGetLibraryRoot(@NonNull ControllerInfo controllerInfo,
+ @Nullable Bundle rootHints) {
+ return null;
+ }
+
+ /**
+ * Called to get an item. Return result here for the browser.
+ * <p>
+ * Return {@code null} for no result or error.
+ *
+ * @param mediaId item id to get media item.
+ * @return a media item. {@code null} for no result or error.
+ */
+ public @Nullable MediaItem2 onGetItem(@NonNull ControllerInfo controllerInfo,
+ @NonNull String mediaId) {
+ return null;
+ }
+
+ /**
+ * Called to get children of given parent id. Return the children here for the browser.
+ * <p>
+ * Return an empty list for no children, and return {@code null} for the error.
+ *
+ * @param parentId parent id to get children
+ * @param page number of page
+ * @param pageSize size of the page
+ * @param extras extra bundle
+ * @return list of children. Can be {@code null}.
+ */
+ public @Nullable List<MediaItem2> onGetChildren(@NonNull ControllerInfo controller,
+ @NonNull String parentId, int page, int pageSize, @Nullable Bundle extras) {
+ return null;
+ }
+
+ /**
+ * Called when a controller subscribes to the parent.
+ * <p>
+ * It's your responsibility to keep subscriptions by your own and call
+ * {@link MediaLibrarySession#notifyChildrenChanged(ControllerInfo, String, int, Bundle)}
+ * when the parent is changed.
+ *
+ * @param controller controller
+ * @param parentId parent id
+ * @param extras extra bundle
+ */
+ public void onSubscribe(@NonNull ControllerInfo controller, @NonNull String parentId,
+ @Nullable Bundle extras) {
+ }
+
+ /**
+ * Called when a controller unsubscribes to the parent.
+ *
+ * @param controller controller
+ * @param parentId parent id
+ */
+ public void onUnsubscribe(@NonNull ControllerInfo controller,
+ @NonNull String parentId) {
+ }
+
+ /**
+ * Called when a controller requests search.
+ *
+ * @param query The search query sent from the media browser. It contains keywords
+ * separated by space.
+ * @param extras The bundle of service-specific arguments sent from the media browser.
+ */
+ public void onSearch(@NonNull ControllerInfo controllerInfo, @NonNull String query,
+ @Nullable Bundle extras) {
+ }
+
+ /**
+ * Called to get the search result. Return search result here for the browser which has
+ * requested search previously.
+ * <p>
+ * Return an empty list for no search result, and return {@code null} for the error.
+ *
+ * @param controllerInfo Information of the controller requesting the search result.
+ * @param query The search query which was previously sent through
+ * {@link #onSearch(ControllerInfo, String, Bundle)} call.
+ * @param page page number. Starts from {@code 1}.
+ * @param pageSize page size. Should be greater or equal to {@code 1}.
+ * @param extras The bundle of service-specific arguments sent from the media browser.
+ * @return search result. {@code null} for error.
+ */
+ public @Nullable List<MediaItem2> onGetSearchResult(
+ @NonNull ControllerInfo controllerInfo, @NonNull String query, int page,
+ int pageSize, @Nullable Bundle extras) {
+ return null;
+ }
+ }
+
+ /**
+ * Builder for {@link MediaLibrarySession}.
+ */
+ // Override all methods just to show them with the type instead of generics in Javadoc.
+ // This workarounds javadoc issue described in the MediaSession2.BuilderBase.
+ public static final class Builder extends BuilderBase<MediaLibrarySession, Builder,
+ MediaLibrarySessionCallback> {
+ // Builder requires MediaLibraryService2 instead of Context just to ensure that the
+ // builder can be only instantiated within the MediaLibraryService2.
+ // Ideally it's better to make it inner class of service to enforce, it violates API
+ // guideline that Builders should be the inner class of the building target.
+ public Builder(@NonNull MediaLibraryService2 service,
+ @NonNull MediaPlayerBase player,
+ @NonNull @CallbackExecutor Executor callbackExecutor,
+ @NonNull MediaLibrarySessionCallback callback) {
+ super((instance) -> ApiLoader.getProvider(service)
+ .createMediaLibraryService2Builder(service, (Builder) instance, player,
+ callbackExecutor, callback));
+ }
+
+ @Override
+ public Builder setVolumeProvider(@Nullable VolumeProvider2 volumeProvider) {
+ return super.setVolumeProvider(volumeProvider);
+ }
+
+ @Override
+ public Builder setSessionActivity(@Nullable PendingIntent pi) {
+ return super.setSessionActivity(pi);
+ }
+
+ @Override
+ public Builder setId(String id) {
+ return super.setId(id);
+ }
+
+ @Override
+ public Builder setSessionCallback(@NonNull Executor executor,
+ @NonNull MediaLibrarySessionCallback callback) {
+ return super.setSessionCallback(executor, callback);
+ }
+
+ @Override
+ public MediaLibrarySession build() {
+ return super.build();
+ }
+ }
+
+ /**
* @hide
*/
- @SystemApi
public MediaLibrarySession(MediaLibrarySessionProvider provider) {
super(provider);
mProvider = provider;
@@ -124,166 +288,6 @@
}
}
- /**
- * Callback for the {@link MediaLibrarySession}.
- */
- public static class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
-
- public MediaLibrarySessionCallback(Context context) {
- super(context);
- }
-
- /**
- * Called to get the root information for browsing by a particular client.
- * <p>
- * The implementation should verify that the client package has permission
- * to access browse media information before returning the root id; it
- * should return null if the client is not allowed to access this
- * information.
- *
- * @param controllerInfo information of the controller requesting access to browse media.
- * @param rootHints An optional bundle of service-specific arguments to send
- * to the media library service when connecting and retrieving the
- * root id for browsing, or null if none. The contents of this
- * bundle may affect the information returned when browsing.
- * @return The {@link LibraryRoot} for accessing this app's content or null.
- * @see LibraryRoot#EXTRA_RECENT
- * @see LibraryRoot#EXTRA_OFFLINE
- * @see LibraryRoot#EXTRA_SUGGESTED
- */
- public @Nullable LibraryRoot onGetLibraryRoot(@NonNull ControllerInfo controllerInfo,
- @Nullable Bundle rootHints) {
- return null;
- }
-
- /**
- * Called to get an item. Return result here for the browser.
- * <p>
- * Return {@code null} for no result or error.
- *
- * @param mediaId item id to get media item.
- * @return a media item. {@code null} for no result or error.
- */
- public @Nullable MediaItem2 onGetItem(@NonNull ControllerInfo controllerInfo,
- @NonNull String mediaId) {
- return null;
- }
-
- /**
- * Called to get children of given parent id. Return the children here for the browser.
- * <p>
- * Return an empty list for no children, and return {@code null} for the error.
- *
- * @param parentId parent id to get children
- * @param page number of page
- * @param pageSize size of the page
- * @param extras extra bundle
- * @return list of children. Can be {@code null}.
- */
- public @Nullable List<MediaItem2> onGetChildren(@NonNull ControllerInfo controller,
- @NonNull String parentId, int page, int pageSize, @Nullable Bundle extras) {
- return null;
- }
-
- /**
- * Called when a controller subscribes to the parent.
- * <p>
- * It's your responsibility to keep subscriptions by your own and call
- * {@link MediaLibrarySession#notifyChildrenChanged(ControllerInfo, String, int, Bundle)}
- * when the parent is changed.
- *
- * @param controller controller
- * @param parentId parent id
- * @param extras extra bundle
- */
- public void onSubscribe(@NonNull ControllerInfo controller, @NonNull String parentId,
- @Nullable Bundle extras) {
- }
-
- /**
- * Called when a controller unsubscribes to the parent.
- *
- * @param controller controller
- * @param parentId parent id
- */
- public void onUnsubscribe(@NonNull ControllerInfo controller, @NonNull String parentId) {
- }
-
- /**
- * Called when a controller requests search.
- *
- * @param query The search query sent from the media browser. It contains keywords separated
- * by space.
- * @param extras The bundle of service-specific arguments sent from the media browser.
- */
- public void onSearch(@NonNull ControllerInfo controllerInfo, @NonNull String query,
- @Nullable Bundle extras) {
- }
-
- /**
- * Called to get the search result. Return search result here for the browser which has
- * requested search previously.
- * <p>
- * Return an empty list for no search result, and return {@code null} for the error.
- *
- * @param controllerInfo Information of the controller requesting the search result.
- * @param query The search query which was previously sent through
- * {@link #onSearch(ControllerInfo, String, Bundle)} call.
- * @param page page number. Starts from {@code 1}.
- * @param pageSize page size. Should be greater or equal to {@code 1}.
- * @param extras The bundle of service-specific arguments sent from the media browser.
- * @return search result. {@code null} for error.
- */
- public @Nullable List<MediaItem2> onGetSearchResult(@NonNull ControllerInfo controllerInfo,
- @NonNull String query, int page, int pageSize, @Nullable Bundle extras) {
- return null;
- }
- }
-
- /**
- * Builder for {@link MediaLibrarySession}.
- */
- // Override all methods just to show them with the type instead of generics in Javadoc.
- // This workarounds javadoc issue described in the MediaSession2.BuilderBase.
- public class MediaLibrarySessionBuilder extends BuilderBase<MediaLibrarySession,
- MediaLibrarySessionBuilder, MediaLibrarySessionCallback> {
- public MediaLibrarySessionBuilder(
- @NonNull Context context, @NonNull MediaPlayerInterface player,
- @NonNull @CallbackExecutor Executor callbackExecutor,
- @NonNull MediaLibrarySessionCallback callback) {
- super((instance) -> ApiLoader.getProvider(context).createMediaLibraryService2Builder(
- context, (MediaLibrarySessionBuilder) instance, player, callbackExecutor,
- callback));
- }
-
- @Override
- public MediaLibrarySessionBuilder setVolumeProvider(
- @Nullable VolumeProvider2 volumeProvider) {
- return super.setVolumeProvider(volumeProvider);
- }
-
- @Override
- public MediaLibrarySessionBuilder setSessionActivity(@Nullable PendingIntent pi) {
- return super.setSessionActivity(pi);
- }
-
- @Override
- public MediaLibrarySessionBuilder setId(String id) {
- return super.setId(id);
- }
-
- @Override
- public MediaLibrarySessionBuilder setSessionCallback(
- @NonNull Executor executor, @NonNull MediaLibrarySessionCallback callback) {
- return super.setSessionCallback(executor, callback);
- }
-
- @Override
- public MediaLibrarySession build() {
- return super.build();
- }
- }
-
@Override
MediaSessionService2Provider createProvider() {
return ApiLoader.getProvider(this).createMediaLibraryService2(this);
@@ -302,7 +306,7 @@
*
* @param sessionId session id written in the AndroidManifest.xml.
* @return a new library session
- * @see MediaLibrarySessionBuilder
+ * @see Builder
* @see #getSession()
* @throws RuntimeException if returned session is invalid
*/
diff --git a/media/java/android/media/MediaMetadata2.java b/media/java/android/media/MediaMetadata2.java
index 1f856bc..b363831 100644
--- a/media/java/android/media/MediaMetadata2.java
+++ b/media/java/android/media/MediaMetadata2.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
-import android.annotation.SystemApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.update.ApiLoader;
@@ -33,15 +32,13 @@
/**
* Contains metadata about an item, such as the title, artist, etc.
- *
- * @hide
*/
+// New version of MediaMetadata with following changes
+// - Don't implement Parcelable for updatable support.
+// - Also support MediaDescription features. MediaDescription is deprecated instead because
+// it was insufficient for controller to display media contents.
+// TODO(jaewan): Add @see for APIs from MediaDescription
public final class MediaMetadata2 {
- // New version of MediaMetadata that no longer implements Parcelable but added from/toBundle()
- // for updatable.
- // MediaDescription is deprecated because it was insufficient for controller to display media
- // contents. Added getExtra() here to support all the features from the MediaDescription.
-
/**
* The title of the media.
*/
@@ -389,7 +386,6 @@
/**
* @hide
*/
- @SystemApi
public MediaMetadata2(MediaMetadata2Provider provider) {
mProvider = provider;
}
@@ -568,7 +564,6 @@
/**
* @hide
*/
- @SystemApi
public Builder(@NonNull MediaMetadata2Provider.BuilderProvider provider) {
mProvider = provider;
}
diff --git a/media/java/android/media/MediaPlayerBase.java b/media/java/android/media/MediaPlayerBase.java
new file mode 100644
index 0000000..3181362
--- /dev/null
+++ b/media/java/android/media/MediaPlayerBase.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.MediaSession2.PlaylistParams;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Base class for all media players that want media session.
+ */
+public abstract class MediaPlayerBase implements AutoCloseable {
+ /**
+ * @hide
+ */
+ @IntDef({STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_ERROR})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {}
+
+ /**
+ * State when the player is idle, and needs configuration to start playback.
+ */
+ public static final int STATE_IDLE = 0;
+
+ /**
+ * State when the player's playback is paused
+ */
+ public static final int STATE_PAUSED = 0;
+
+ /**
+ * State when the player's playback is ongoing
+ */
+ public static final int STATE_PLAYING = 0;
+
+ /**
+ * State when the player is in error state and cannot be recovered self.
+ */
+ public static final int STATE_ERROR = 0;
+
+ /**
+ * Unspecified media player error.
+ * @hide
+ */
+ public static final int MEDIA_ERROR_UNKNOWN = MediaPlayer2.MEDIA_ERROR_UNKNOWN;
+
+ /**
+ * The video is streamed and its container is not valid for progressive
+ * playback i.e the video's index (e.g moov atom) is not at the start of the
+ * file.
+ * @hide
+ */
+ public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK =
+ MediaPlayer2.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK;
+
+ /**
+ * File or network related operation errors.
+ * @hide
+ */
+ public static final int MEDIA_ERROR_IO = MediaPlayer2.MEDIA_ERROR_IO;
+
+ /**
+ * Bitstream is not conforming to the related coding standard or file spec.
+ * @hide
+ */
+ public static final int MEDIA_ERROR_MALFORMED = MediaPlayer2.MEDIA_ERROR_MALFORMED;
+
+ /**
+ * Bitstream is conforming to the related coding standard or file spec, but
+ * the media framework does not support the feature.
+ * @hide
+ */
+ public static final int MEDIA_ERROR_UNSUPPORTED = MediaPlayer2.MEDIA_ERROR_UNSUPPORTED;
+
+ /**
+ * Some operation takes too long to complete, usually more than 3-5 seconds.
+ * @hide
+ */
+ public static final int MEDIA_ERROR_TIMED_OUT = MediaPlayer2.MEDIA_ERROR_TIMED_OUT;
+
+ /**
+ * Callbacks to listens to the changes in {@link PlaybackState2} and error.
+ * @hide
+ */
+ public static abstract class EventCallback {
+ /**
+ * Called when {@link PlaybackState2} for this player is changed.
+ */
+ public void onPlaybackStateChanged(PlaybackState2 state) { }
+
+ /**
+ * Called to indicate an error.
+ *
+ * @param mediaId optional mediaId to indicate error
+ * @param what what
+ * @param extra
+ */
+ public void onError(@Nullable String mediaId, int what, int extra) { }
+ }
+
+ // Transport controls that session will send command directly to this player.
+ /**
+ * Start or resumes playback
+ */
+ public abstract void play();
+
+ /**
+ * @hide
+ */
+ public abstract void prepare();
+
+ /**
+ * Pause playback
+ */
+ public abstract void pause();
+
+ /**
+ * @hide
+ */
+ public abstract void stop();
+
+ /**
+ * @hide
+ */
+ public abstract void skipToPrevious();
+
+ /**
+ * @hide
+ */
+ public abstract void skipToNext();
+
+ /**
+ * @hide
+ */
+ public abstract void seekTo(long pos);
+
+ /**
+ * @hide
+ */
+ public abstract void fastForward();
+
+ /**
+ * @hide
+ */
+ public abstract void rewind();
+
+ /**
+ * @hide
+ */
+ public abstract PlaybackState2 getPlaybackState();
+
+ /**
+ * Return player state.
+ *
+ * @return player state
+ * @see #STATE_IDLE
+ * @see #STATE_PLAYING
+ * @see #STATE_PAUSED
+ * @see #STATE_ERROR
+ */
+ public abstract @State int getPlayerState();
+
+ /**
+ * Sets the {@link AudioAttributes} to be used during the playback of the media.
+ *
+ * @param attributes non-null <code>AudioAttributes</code>.
+ */
+ public abstract void setAudioAttributes(@NonNull AudioAttributes attributes);
+
+ /**
+ * Returns AudioAttributes that media player has.
+ */
+ public abstract @Nullable AudioAttributes getAudioAttributes();
+
+ /**
+ * @hide
+ */
+ public abstract void addPlaylistItem(int index, MediaItem2 item);
+
+ /**
+ * @hide
+ */
+ public abstract void removePlaylistItem(MediaItem2 item);
+
+ /**
+ * @hide
+ */
+ public abstract void setPlaylist(List<MediaItem2> playlist);
+
+ /**
+ * @hide
+ */
+ public abstract List<MediaItem2> getPlaylist();
+
+ /**
+ * @hide
+ */
+ public abstract void setCurrentPlaylistItem(MediaItem2 item);
+
+ /**
+ * @hide
+ */
+ public abstract void setPlaylistParams(PlaylistParams params);
+
+ /**
+ * @hide
+ */
+ public abstract PlaylistParams getPlaylistParams();
+
+ /**
+ * Register a {@link EventCallback}.
+ *
+ * @param executor a callback executor
+ * @param callback a EventCallback
+ * @hide
+ */
+ public abstract void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull EventCallback callback);
+
+ /**
+ * Unregister previously registered {@link EventCallback}.
+ *
+ * @param callback a EventCallback
+ * @hide
+ */
+ public abstract void unregisterEventCallback(@NonNull EventCallback callback);
+}
diff --git a/media/java/android/media/MediaPlayerInterface.java b/media/java/android/media/MediaPlayerInterface.java
deleted file mode 100644
index b81c3d6..0000000
--- a/media/java/android/media/MediaPlayerInterface.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.media.MediaSession2.PlaylistParams;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * Base interfaces for all media players that want media session.
- * @hide
- */
-public interface MediaPlayerInterface {
- /**
- * Unspecified media player error.
- */
- int MEDIA_ERROR_UNKNOWN = MediaPlayer2.MEDIA_ERROR_UNKNOWN;
-
- /**
- * The video is streamed and its container is not valid for progressive
- * playback i.e the video's index (e.g moov atom) is not at the start of the
- * file.
- */
- int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK =
- MediaPlayer2.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK;
-
- /**
- * File or network related operation errors.
- */
- int MEDIA_ERROR_IO = MediaPlayer2.MEDIA_ERROR_IO;
-
- /**
- * Bitstream is not conforming to the related coding standard or file spec.
- */
- int MEDIA_ERROR_MALFORMED = MediaPlayer2.MEDIA_ERROR_MALFORMED;
-
- /**
- * Bitstream is conforming to the related coding standard or file spec, but
- * the media framework does not support the feature.
- */
- int MEDIA_ERROR_UNSUPPORTED = MediaPlayer2.MEDIA_ERROR_UNSUPPORTED;
-
- /**
- * Some operation takes too long to complete, usually more than 3-5 seconds.
- */
- int MEDIA_ERROR_TIMED_OUT = MediaPlayer2.MEDIA_ERROR_TIMED_OUT;
-
- /**
- * Callbacks to listens to the changes in {@link PlaybackState2} and error.
- */
- interface EventCallback {
- /**
- * Called when {@link PlaybackState2} for this player is changed.
- */
- default void onPlaybackStateChanged(PlaybackState2 state) { }
-
- /**
- * Called to indicate an error.
- *
- * @param mediaId optional mediaId to indicate error
- * @param what what
- * @param extra
- */
- default void onError(@Nullable String mediaId, int what, int extra) { }
- }
-
- // Transport controls that session will send command directly to this player.
- void play();
- void prepare();
- void pause();
- void stop();
- void skipToPrevious();
- void skipToNext();
- void seekTo(long pos);
- void fastForward();
- void rewind();
-
- PlaybackState2 getPlaybackState();
-
- /**
- * Sets the {@link AudioAttributes} to be used during the playback of the media.
- *
- * @param attributes non-null <code>AudioAttributes</code>.
- */
- void setAudioAttributes(@NonNull AudioAttributes attributes);
-
- /**
- * Returns AudioAttributes that media player has.
- */
- @Nullable
- AudioAttributes getAudioAttributes();
-
- void addPlaylistItem(int index, MediaItem2 item);
- void removePlaylistItem(MediaItem2 item);
-
- void setPlaylist(List<MediaItem2> playlist);
- List<MediaItem2> getPlaylist();
-
- void setCurrentPlaylistItem(int index);
- void setPlaylistParams(PlaylistParams params);
- PlaylistParams getPlaylistParams();
-
- /**
- * Register a {@link EventCallback}.
- *
- * @param executor a callback executor
- * @param callback a EventCallback
- */
- void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull EventCallback callback);
-
- /**
- * Unregister previously registered {@link EventCallback}.
- *
- * @param callback a EventCallback
- */
- void unregisterEventCallback(@NonNull EventCallback callback);
-}
diff --git a/media/java/android/media/MediaPlaylistController.java b/media/java/android/media/MediaPlaylistController.java
new file mode 100644
index 0000000..916c12a
--- /dev/null
+++ b/media/java/android/media/MediaPlaylistController.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+
+/**
+ * Controller interfaces for playlist management for both {@link MediaSession2} and
+ * {@link MediaController2} that related with metadata. This ensures that two classes share the same
+ * interface.
+ * <p>
+ * This class only includes methods that involves {@link MediaItem2}. Because other APIs are
+ * considered as the part of {@link MediaPlayerBase} (e.g. set/getPlaylistParams()}. Note that
+ * setPlaylist() isn't added on purpose because it's considered as session specific.
+ *
+ * @hide
+ */
+public interface MediaPlaylistController {
+ // TODO(jaewan): is Index correct here?
+ void addPlaylistItem(int index, @NonNull MediaItem2 item);
+ void removePlaylistItem(@NonNull MediaItem2 item);
+ MediaItem2 getCurrentPlaylistItem();
+ void skipToPlaylistItem(@NonNull MediaItem2 item);
+ List<MediaItem2> getPlaylist();
+}
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index 63e4e65..54b1f0e 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -20,11 +20,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.media.MediaPlayerInterface.EventCallback;
+import android.media.MediaPlayerBase.EventCallback;
import android.media.session.MediaSession;
import android.media.session.MediaSession.Callback;
import android.media.session.PlaybackState;
@@ -70,7 +69,7 @@
* <p>
* When a session receive transport control commands, the session sends the commands directly to
* the the underlying media player set by {@link Builder} or
- * {@link #setPlayer(MediaPlayerInterface)}.
+ * {@link #setPlayer(MediaPlayerBase)}.
* <p>
* When an app is finished performing playback it must call {@link #close()} to clean up the session
* and notify any controllers.
@@ -78,9 +77,8 @@
* {@link MediaSession2} objects should be used on the thread on the looper.
*
* @see MediaSessionService2
- * @hide
*/
-public class MediaSession2 implements AutoCloseable {
+public class MediaSession2 implements AutoCloseable, MediaPlaylistController {
private final MediaSession2Provider mProvider;
// TODO(jaewan): Should we define IntDef? Currently we don't have to allow subclass to add more.
@@ -143,7 +141,7 @@
public static final int COMMAND_CODE_PLAYBACK_PREPARE = 6;
/**
- * Command code for {@link MediaController2#fastForward()} ()}.
+ * Command code for {@link MediaController2#fastForward()}.
* <p>
* This is transport control command. Command would be sent directly to the player if the
* session doesn't reject the request through the
@@ -160,14 +158,14 @@
public static final int COMMAND_CODE_PLAYBACK_REWIND = 8;
/**
- * Command code for {@link MediaController2#seekTo(long)} ()}.
+ * Command code for {@link MediaController2#seekTo(long)}.
* <p>
* Command would be sent directly to the player if the session doesn't reject the request
* through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
*/
public static final int COMMAND_CODE_PLAYBACK_SEEK_TO = 9;
/**
- * Command code for {@link MediaController2#setCurrentPlaylistItem(int)} ()}.
+ * Command code for {@link MediaController2#skipToPlaylistItem(MediaItem2)}.
* <p>
* Command would be sent directly to the player if the session doesn't reject the request
* through the {@link SessionCallback#onCommandRequest(ControllerInfo, Command)}.
@@ -222,7 +220,7 @@
public static final int COMMAND_CODE_PLAY_FROM_MEDIA_ID = 16;
/**
- * Command code for {@link MediaController2#playFromUri(String, Bundle)}.
+ * Command code for {@link MediaController2#playFromUri(Uri, Bundle)}.
*/
public static final int COMMAND_CODE_PLAY_FROM_URI = 17;
@@ -256,6 +254,84 @@
public static final int COMMAND_CODE_BROWSER = 22;
/**
+ * @hide
+ */
+ @IntDef({ERROR_CODE_UNKNOWN_ERROR, ERROR_CODE_APP_ERROR, ERROR_CODE_NOT_SUPPORTED,
+ ERROR_CODE_AUTHENTICATION_EXPIRED, ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED,
+ ERROR_CODE_CONCURRENT_STREAM_LIMIT, ERROR_CODE_PARENTAL_CONTROL_RESTRICTED,
+ ERROR_CODE_NOT_AVAILABLE_IN_REGION, ERROR_CODE_CONTENT_ALREADY_PLAYING,
+ ERROR_CODE_SKIP_LIMIT_REACHED, ERROR_CODE_ACTION_ABORTED, ERROR_CODE_END_OF_QUEUE,
+ ERROR_CODE_SETUP_REQUIRED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ErrorCode {}
+
+ /**
+ * This is the default error code and indicates that none of the other error codes applies.
+ */
+ public static final int ERROR_CODE_UNKNOWN_ERROR = 0;
+
+ /**
+ * Error code when the application state is invalid to fulfill the request.
+ */
+ public static final int ERROR_CODE_APP_ERROR = 1;
+
+ /**
+ * Error code when the request is not supported by the application.
+ */
+ public static final int ERROR_CODE_NOT_SUPPORTED = 2;
+
+ /**
+ * Error code when the request cannot be performed because authentication has expired.
+ */
+ public static final int ERROR_CODE_AUTHENTICATION_EXPIRED = 3;
+
+ /**
+ * Error code when a premium account is required for the request to succeed.
+ */
+ public static final int ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED = 4;
+
+ /**
+ * Error code when too many concurrent streams are detected.
+ */
+ public static final int ERROR_CODE_CONCURRENT_STREAM_LIMIT = 5;
+
+ /**
+ * Error code when the content is blocked due to parental controls.
+ */
+ public static final int ERROR_CODE_PARENTAL_CONTROL_RESTRICTED = 6;
+
+ /**
+ * Error code when the content is blocked due to being regionally unavailable.
+ */
+ public static final int ERROR_CODE_NOT_AVAILABLE_IN_REGION = 7;
+
+ /**
+ * Error code when the requested content is already playing.
+ */
+ public static final int ERROR_CODE_CONTENT_ALREADY_PLAYING = 8;
+
+ /**
+ * Error code when the application cannot skip any more songs because skip limit is reached.
+ */
+ public static final int ERROR_CODE_SKIP_LIMIT_REACHED = 9;
+
+ /**
+ * Error code when the action is interrupted due to some external event.
+ */
+ public static final int ERROR_CODE_ACTION_ABORTED = 10;
+
+ /**
+ * Error code when the playback navigation (previous, next) is not possible because the queue
+ * was exhausted.
+ */
+ public static final int ERROR_CODE_END_OF_QUEUE = 11;
+
+ /**
+ * Error code when the session needs user's manual intervention.
+ */
+ public static final int ERROR_CODE_SETUP_REQUIRED = 12;
+
+ /**
* Define a command that a {@link MediaController2} can send to a {@link MediaSession2}.
* <p>
* If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
@@ -324,7 +400,7 @@
/**
* Represent set of {@link Command}.
*/
- public static class CommandGroup {
+ public static final class CommandGroup {
private final CommandGroupProvider mProvider;
public CommandGroup(Context context) {
@@ -360,7 +436,6 @@
/**
* @hide
*/
- @SystemApi
public CommandGroupProvider getProvider() {
return mProvider;
}
@@ -390,7 +465,7 @@
* default.
*/
// TODO(jaewan): Can we move this inside of the updatable for default implementation.
- public static class SessionCallback {
+ public static abstract class SessionCallback {
private final Context mContext;
public SessionCallback(Context context) {
@@ -587,7 +662,7 @@
/**
* Base builder class for MediaSession2 and its subclass. Any change in this class should be
* also applied to the subclasses {@link MediaSession2.Builder} and
- * {@link MediaLibraryService2.MediaLibrarySessionBuilder}.
+ * {@link MediaLibraryService2.MediaLibrarySession.Builder}.
* <p>
* APIs here should be package private, but should have documentations for developers.
* Otherwise, javadoc will generate documentation with the generic types such as follows.
@@ -684,7 +759,7 @@
// Override all methods just to show them with the type instead of generics in Javadoc.
// This workarounds javadoc issue described in the MediaSession2.BuilderBase.
public static final class Builder extends BuilderBase<MediaSession2, Builder, SessionCallback> {
- public Builder(Context context, @NonNull MediaPlayerInterface player) {
+ public Builder(Context context, @NonNull MediaPlayerBase player) {
super((instance) -> ApiLoader.getProvider(context).createMediaSession2Builder(
context, (Builder) instance, player));
}
@@ -725,7 +800,6 @@
/**
* @hide
*/
- // TODO(jaewan): SystemApi
// TODO(jaewan): Also accept componentName to check notificaiton listener.
public ControllerInfo(Context context, int uid, int pid, String packageName,
IInterface callback) {
@@ -762,7 +836,6 @@
/**
* @hide
*/
- @SystemApi
public ControllerInfoProvider getProvider() {
return mProvider;
}
@@ -794,13 +867,12 @@
* <p>
* It's up to the controller's decision to respect or ignore this customization request.
*/
- public static class CommandButton {
+ public static final class CommandButton {
private final CommandButtonProvider mProvider;
/**
* @hide
*/
- @SystemApi
public CommandButton(CommandButtonProvider provider) {
mProvider = provider;
}
@@ -856,7 +928,6 @@
/**
* @hide
*/
- @SystemApi
public CommandButtonProvider getProvider() {
return mProvider;
}
@@ -864,7 +935,7 @@
/**
* Builder for {@link CommandButton}.
*/
- public static class Builder {
+ public static final class Builder {
private final CommandButtonProvider.BuilderProvider mProvider;
public Builder(@NonNull Context context) {
@@ -1038,7 +1109,6 @@
* framework had to add heuristics to figure out if an app is
* @hide
*/
- @SystemApi
public MediaSession2(MediaSession2Provider provider) {
super();
mProvider = provider;
@@ -1047,39 +1117,34 @@
/**
* @hide
*/
- @SystemApi
public MediaSession2Provider getProvider() {
return mProvider;
}
/**
- * Set the underlying {@link MediaPlayerInterface} for this session to dispatch incoming event
+ * Set the underlying {@link MediaPlayerBase} for this session to dispatch incoming event
* to. Events from the {@link MediaController2} will be sent directly to the underlying
* player on the {@link Handler} where the session is created on.
* <p>
- * If the new player is successfully set,
- * {@link EventCallback#onPlaybackStateChanged(PlaybackState2)} will be called to tell the
- * current playback state of the new player.
- * <p>
* For the remote playback case which you want to handle volume by yourself, use
- * {@link #setPlayer(MediaPlayerInterface, VolumeProvider2)}.
+ * {@link #setPlayer(MediaPlayerBase, VolumeProvider2)}.
*
- * @param player a {@link MediaPlayerInterface} that handles actual media playback in your app.
+ * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
* @throws IllegalArgumentException if the player is {@code null}.
*/
- public void setPlayer(@NonNull MediaPlayerInterface player) {
+ public void setPlayer(@NonNull MediaPlayerBase player) {
mProvider.setPlayer_impl(player);
}
/**
- * Set the underlying {@link MediaPlayerInterface} with the volume provider for remote playback.
+ * Set the underlying {@link MediaPlayerBase} with the volume provider for remote playback.
*
- * @param player a {@link MediaPlayerInterface} that handles actual media playback in your app.
+ * @param player a {@link MediaPlayerBase} that handles actual media playback in your app.
* @param volumeProvider a volume provider
- * @see #setPlayer(MediaPlayerInterface)
+ * @see #setPlayer(MediaPlayerBase)
* @see Builder#setVolumeProvider(VolumeProvider2)
*/
- public void setPlayer(@NonNull MediaPlayerInterface player,
+ public void setPlayer(@NonNull MediaPlayerBase player,
@NonNull VolumeProvider2 volumeProvider) {
mProvider.setPlayer_impl(player, volumeProvider);
}
@@ -1093,7 +1158,7 @@
* @return player
*/
public @Nullable
- MediaPlayerInterface getPlayer() {
+ MediaPlayerBase getPlayer() {
return mProvider.getPlayer_impl();
}
@@ -1123,7 +1188,9 @@
* @param focusGain the type of audio focus gain that will be requested, or
* {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during
* playback.
+ * @hide
*/
+ // TODO(jaewan): Revisit
public void setAudioFocusRequest(int focusGain) {
mProvider.setAudioFocusRequest_impl(focusGain);
}
@@ -1164,14 +1231,6 @@
}
/**
- * Notify changes in metadata of previously set playlist. Controller will get the whole set of
- * playlist again.
- */
- public void notifyMetadataChanged() {
- mProvider.notifyMetadataChanged_impl();
- }
-
- /**
* Send custom command to all connected controllers.
*
* @param command a command
@@ -1264,14 +1323,14 @@
}
/**
- * Sets the index of current DataSourceDesc in the play list to be played.
+ * Skip to the item in the play list.
*
- * @param index the index of DataSourceDesc in the play list you want to play
+ * @param item item in the play list you want to play
* @throws IllegalArgumentException if the play list is null
* @throws NullPointerException if index is outside play list range
*/
- public void setCurrentPlaylistItem(int index) {
- mProvider.setCurrentPlaylistItem_impl(index);
+ public void skipToPlaylistItem(MediaItem2 item) {
+ mProvider.skipToPlaylistItem_impl(item);
}
/**
@@ -1289,7 +1348,7 @@
}
/**
- * Sets a list of {@link MediaItem2} as the current play list.
+ * Set a list of {@link MediaItem2} as the current play list.
*
* @param playlist A list of {@link MediaItem2} objects to set as a play list.
* @throws IllegalArgumentException if given {@param playlist} is null.
@@ -1299,13 +1358,68 @@
}
/**
- * Returns the playlist which is lastly set.
+ * Remove the media item at index in the play list.
+ * <p>
+ * If index is same as the current index of the playlist, current playback
+ * will be stopped and playback moves to next source in the list.
+ *
+ * @throws IllegalArgumentException if the play list is null
*/
+ // TODO(jaewan): Remove with index was previously rejected by council (b/36524925)
+ // TODO(jaewan): Should we also add movePlaylistItem from index to index?
+ public void removePlaylistItem(MediaItem2 item) {
+ mProvider.removePlaylistItem_impl(item);
+ }
+
+ /**
+ * Add the media item to the play list at position index.
+ * <p>
+ * This will not change the currently playing media item.
+ * If index is less than or equal to the current index of the play list,
+ * the current index of the play list will be incremented correspondingly.
+ *
+ * @param index the index you want to add
+ * @param item the media item you want to add
+ * @throws IndexOutOfBoundsException if index is outside play list range
+ */
+ @Override
+ public void addPlaylistItem(int index, @NonNull MediaItem2 item) {
+ mProvider.addPlaylistItem_impl(index, item);
+ }
+
+ /**
+ * Edit the media item to the play list at position index. This is expected to be called when
+ * the metadata information is updated.
+ * <p>
+ * This will not change the currently playing media item.
+ *
+ * @param item the media item you want to add to the play list
+ */
+ public void editPlaylistItem(@NonNull MediaItem2 item) {
+ mProvider.editPlaylistItem_impl(item);
+ }
+
+ /**
+ * Return the playlist which is lastly set.
+ *
+ * @return playlist
+ */
+ @Override
public List<MediaItem2> getPlaylist() {
return mProvider.getPlaylist_impl();
}
/**
+ * Return currently playing media item.
+ *
+ * @return currently playing media item
+ */
+ @Override
+ public MediaItem2 getCurrentPlaylistItem() {
+ return mProvider.getCurrentPlaylistItem_impl();
+ }
+
+ /**
* Sets the {@link PlaylistParams} for the current play list. Repeat/shuffle mode and metadata
* for the list can be set by calling this method.
*
@@ -1324,16 +1438,28 @@
return mProvider.getPlaylistParams_impl();
}
- /*
+ /**
+ * Notify errors to the connected controllers
+ *
+ * @param errorCode error code
+ * @param extra extra
+ */
+ public void notifyError(@ErrorCode int errorCode, int extra) {
+ mProvider.notifyError_impl(errorCode, extra);
+ }
+
+ /**
* Register {@link EventCallback} to listen changes in the underlying
- * {@link MediaPlayerInterface}, regardless of the change in the underlying player.
+ * {@link MediaPlayerBase}, regardless of the change in the underlying player.
* <p>
* Registered callbacks will be also called when the underlying player is changed.
*
* @param executor a callback Executor
* @param callback a EventCallback
* @throws IllegalArgumentException if executor or callback is {@code null}.
+ * @hide
*/
+ // TODO(jaewan): Unhide or remove
public void registerPlayerEventCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull EventCallback callback) {
mProvider.registerPlayerEventCallback_impl(executor, callback);
@@ -1344,7 +1470,9 @@
*
* @param callback the callback to be removed
* @throws IllegalArgumentException if the callback is {@code null}.
+ * @hide
*/
+ // TODO(jaewan): Unhide or remove
public void unregisterPlayerEventCallback(@NonNull EventCallback callback) {
mProvider.unregisterPlayerEventCallback_impl(callback);
}
@@ -1353,6 +1481,7 @@
* Return the {@link PlaybackState2} from the player.
*
* @return playback state
+ * @hide
*/
public PlaybackState2 getPlaybackState() {
return mProvider.getPlaybackState_impl();
diff --git a/media/java/android/media/MediaSessionService2.java b/media/java/android/media/MediaSessionService2.java
index 0b5dddf..56e8e5d 100644
--- a/media/java/android/media/MediaSessionService2.java
+++ b/media/java/android/media/MediaSessionService2.java
@@ -90,7 +90,7 @@
* rejected, the controller will unbind. If it's accepted, the controller will be available to use
* and keep binding.
* <p>
- * When playback is started for this session service, {@link #onUpdateNotification(PlaybackState2)}
+ * When playback is started for this session service, {@link #onUpdateNotification()}
* is called and service would become a foreground service. It's needed to keep playback after the
* controller is destroyed. The session service becomes background service when the playback is
* stopped.
@@ -100,7 +100,6 @@
* Any app can bind to the session service with controller, but the controller can be used only if
* the session service accepted the connection request through
* {@link MediaSession2.SessionCallback#onConnect(ControllerInfo)}.
- * @hide
*/
public abstract class MediaSessionService2 extends Service {
private final MediaSessionService2Provider mProvider;
@@ -158,17 +157,16 @@
public @NonNull abstract MediaSession2 onCreateSession(String sessionId);
/**
- * Called when the playback state of this session is changed, and notification needs update.
- * Override this method to show your own notification UI.
+ * Called when the playback state of this session is changed so notification needs update.
+ * Override this method to show or cancel your own notification UI.
* <p>
* With the notification returned here, the service become foreground service when the playback
* is started. It becomes background service after the playback is stopped.
*
- * @param state playback state
* @return a {@link MediaNotification}. If it's {@code null}, notification wouldn't be shown.
*/
- public MediaNotification onUpdateNotification(PlaybackState2 state) {
- return mProvider.onUpdateNotification_impl(state);
+ public MediaNotification onUpdateNotification() {
+ return mProvider.onUpdateNotification_impl();
}
/**
@@ -201,9 +199,9 @@
}
/**
- * Returned by {@link #onUpdateNotification(PlaybackState2)} for making session service
- * foreground service to keep playback running in the background. It's highly recommended to
- * show media style notification here.
+ * Returned by {@link #onUpdateNotification()} for making session service forground service
+ * to keep playback running in the background. It's highly recommended to show media style
+ * notification here.
*/
public static class MediaNotification {
private final MediaNotificationProvider mProvider;
diff --git a/media/java/android/media/PlaybackState2.java b/media/java/android/media/PlaybackState2.java
index a95b8f2..7afb579 100644
--- a/media/java/android/media/PlaybackState2.java
+++ b/media/java/android/media/PlaybackState2.java
@@ -28,11 +28,12 @@
import java.lang.annotation.RetentionPolicy;
/**
- * Playback state for a {@link MediaPlayerInterface}, to be shared between {@link MediaSession2} and
+ * Playback state for a {@link MediaPlayerBase}, to be shared between {@link MediaSession2} and
* {@link MediaController2}. This includes a playback state {@link #STATE_PLAYING},
* the current playback position and extra.
* @hide
*/
+// TODO(jaewan): Remove this.
public final class PlaybackState2 {
// Similar to the PlaybackState with following changes
// - Not implement Parcelable and added from/toBundle()
@@ -214,4 +215,4 @@
@Nullable Bundle bundle) {
return ApiLoader.getProvider(context).fromBundle_PlaybackState2(context, bundle);
}
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/Rating2.java b/media/java/android/media/Rating2.java
index 4f77ecd..e5b05fb 100644
--- a/media/java/android/media/Rating2.java
+++ b/media/java/android/media/Rating2.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.IntDef;
-import android.annotation.SystemApi;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.Rating2Provider;
@@ -36,12 +35,10 @@
* {@link #RATING_5_STARS} or {@link #RATING_PERCENTAGE}) and the actual rating value (which may
* be defined as "unrated"), both of which are defined when the rating instance is constructed
* through one of the factory methods.
- * @hide
*/
+// New version of Rating with following change
+// - Don't implement Parcelable for updatable support.
public final class Rating2 {
- // Mostly same as the android.media.Rating, but it's no longer implements Parcelable for
- // updatable support.
-
/**
* @hide
*/
@@ -100,7 +97,6 @@
/**
* @hide
*/
- @SystemApi
public Rating2(@NonNull Rating2Provider provider) {
mProvider = provider;
}
@@ -113,7 +109,6 @@
/**
* @hide
*/
- @SystemApi
public Rating2Provider getProvider() {
return mProvider;
}
diff --git a/media/java/android/media/SessionToken2.java b/media/java/android/media/SessionToken2.java
index 2c2090c..fdfa43a 100644
--- a/media/java/android/media/SessionToken2.java
+++ b/media/java/android/media/SessionToken2.java
@@ -18,7 +18,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.content.Context;
import android.media.session.MediaSessionManager;
import android.media.update.ApiLoader;
@@ -36,8 +35,11 @@
* {@link MediaController2} to communicate with the session.
* <p>
* It can be also obtained by {@link MediaSessionManager}.
- * @hide
*/
+// New version of MediaSession.Token for following reasons
+// - Stop implementing Parcelable for updatable support
+// - Represent session and library service (formerly browser service) in one class.
+// Previously MediaSession.Token was for session and ComponentName was for service.
public final class SessionToken2 {
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {TYPE_SESSION, TYPE_SESSION_SERVICE, TYPE_LIBRARY_SERVICE})
@@ -86,7 +88,6 @@
* Constructor for the token.
* @hide
*/
- @SystemApi
public SessionToken2(@NonNull SessionToken2Provider provider) {
mProvider = provider;
}
@@ -106,7 +107,9 @@
return mProvider.toString_impl();
}
- @SystemApi
+ /**
+ * @hide
+ */
public SessionToken2Provider getProvider() {
return mProvider;
}
@@ -147,7 +150,7 @@
* @return
*/
public static SessionToken2 fromBundle(@NonNull Context context, @NonNull Bundle bundle) {
- return ApiLoader.getProvider(context).SessionToken2_fromBundle(context, bundle);
+ return ApiLoader.getProvider(context).fromBundle_SessionToken2(context, bundle);
}
/**
diff --git a/media/java/android/media/VolumeProvider2.java b/media/java/android/media/VolumeProvider2.java
index 53ba466..8e1cfbf 100644
--- a/media/java/android/media/VolumeProvider2.java
+++ b/media/java/android/media/VolumeProvider2.java
@@ -18,7 +18,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.VolumeProvider2Provider;
@@ -32,12 +31,11 @@
* {@link #setCurrentVolume(int)} each time the volume being provided changes.
* <p>
* You can set a volume provider on a session by calling
- * {@link MediaSession2#setPlayer(MediaPlayerInterface, VolumeProvider2)}.
- *
- * @hide
+ * {@link MediaSession2#setPlayer(MediaPlayerBase, VolumeProvider2)}.
*/
+// New version of VolumeProvider with following changes
+// - Don't implement Parcelable for updatable support.
public abstract class VolumeProvider2 {
-
/**
* @hide
*/
@@ -85,7 +83,6 @@
/**
* @hide
*/
- @SystemApi
public VolumeProvider2Provider getProvider() {
return mProvider;
}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index e7fcc7f..d079b7a 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -343,7 +343,6 @@
* Called when a {@link MediaSession2} is created.
* @hide
*/
- // TODO(jaewan): System API
public boolean createSession2(@NonNull SessionToken2 token) {
if (token == null) {
return false;
@@ -356,10 +355,10 @@
return false;
}
- /** Called when a {@link MediaSession2} is destroyed.
+ /**
+ * Called when a {@link MediaSession2} is destroyed.
* @hide
*/
- // TODO(jaewan): System API
public void destroySession2(@NonNull SessionToken2 token) {
if (token == null) {
return;
@@ -381,9 +380,7 @@
* using the {@link NotificationListenerService} APIs.
*
* @return list of tokens
- * @hide
*/
- // TODO(jaewan): Unhide
public List<SessionToken2> getActiveSessionTokens() {
try {
List<Bundle> bundles = mService.getSessionTokens(
@@ -404,9 +401,7 @@
* using the {@link NotificationListenerService} APIs.
*
* @return list of tokens
- * @hide
*/
- // TODO(jaewan): Unhide
public List<SessionToken2> getSessionServiceTokens() {
try {
List<Bundle> bundles = mService.getSessionTokens(
@@ -429,9 +424,7 @@
* @return list of tokens
* @see #getActiveSessionTokens
* @see #getSessionServiceTokens
- * @hide
*/
- // TODO(jaewan): Unhide
public List<SessionToken2> getAllSessionTokens() {
try {
List<Bundle> bundles = mService.getSessionTokens(
@@ -452,9 +445,7 @@
*
* @param executor executor to run this command
* @param listener The listener to add.
- * @hide
*/
- // TODO(jaewan): Unhide
public void addOnSessionTokensChangedListener(@NonNull @CallbackExecutor Executor executor,
@NonNull OnSessionTokensChangedListener listener) {
addOnSessionTokensChangedListener(UserHandle.myUserId(), executor, listener);
@@ -501,9 +492,7 @@
* Stop receiving session token updates on the specified listener.
*
* @param listener The listener to remove.
- * @hide
*/
- // TODO(jaewan): Unhide
public void removeOnSessionTokensChangedListener(
@NonNull OnSessionTokensChangedListener listener) {
if (listener == null) {
@@ -660,9 +649,7 @@
/**
* Listens for changes to the {@link #getAllSessionTokens()}. This can be added
* using {@link #addOnActiveSessionsChangedListener}.
- * @hide
*/
- // TODO(jaewan): Unhide
public interface OnSessionTokensChangedListener {
void onSessionTokensChanged(@NonNull List<SessionToken2> tokens);
}
diff --git a/media/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaController2Provider.java
index 8d9efd5..ca5c16d 100644
--- a/media/java/android/media/update/MediaController2Provider.java
+++ b/media/java/android/media/update/MediaController2Provider.java
@@ -16,7 +16,6 @@
package android.media.update;
-import android.annotation.SystemApi;
import android.app.PendingIntent;
import android.media.AudioAttributes;
import android.media.MediaController2.PlaybackInfo;
@@ -65,6 +64,11 @@
PlaylistParams getPlaylistParams_impl();
void setPlaylistParams_impl(PlaylistParams params);
PlaybackState2 getPlaybackState_impl();
+ int getPlayerState_impl();
+ long getPosition_impl();
+ float getPlaybackSpeed_impl();
+ long getBufferedPosition_impl();
+ MediaItem2 getCurrentPlaylistItem_impl();
interface PlaybackInfoProvider {
int getPlaybackType_impl();
diff --git a/media/java/android/media/update/MediaItem2Provider.java b/media/java/android/media/update/MediaItem2Provider.java
index 2970f0e..1d5b414 100644
--- a/media/java/android/media/update/MediaItem2Provider.java
+++ b/media/java/android/media/update/MediaItem2Provider.java
@@ -23,7 +23,6 @@
/**
* @hide
*/
-// TODO(jaewan): SystemApi
public interface MediaItem2Provider {
Bundle toBundle_impl();
String toString_impl();
diff --git a/media/java/android/media/update/MediaLibraryService2Provider.java b/media/java/android/media/update/MediaLibraryService2Provider.java
index 7489f76..9a0d693 100644
--- a/media/java/android/media/update/MediaLibraryService2Provider.java
+++ b/media/java/android/media/update/MediaLibraryService2Provider.java
@@ -16,16 +16,12 @@
package android.media.update;
-import android.annotation.SystemApi;
-import android.media.MediaLibraryService2.MediaLibrarySession;
-import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
import android.media.MediaSession2.ControllerInfo;
import android.os.Bundle;
/**
* @hide
*/
-// TODO: @SystemApi
public interface MediaLibraryService2Provider extends MediaSessionService2Provider {
// Nothing new for now
diff --git a/media/java/android/media/update/MediaMetadata2Provider.java b/media/java/android/media/update/MediaMetadata2Provider.java
index b6e5c8a..22463e9 100644
--- a/media/java/android/media/update/MediaMetadata2Provider.java
+++ b/media/java/android/media/update/MediaMetadata2Provider.java
@@ -11,7 +11,6 @@
/**
* @hide
*/
-// TODO(jaewan): SystemApi
public interface MediaMetadata2Provider {
boolean containsKey_impl(String key);
CharSequence getText_impl(String key);
diff --git a/media/java/android/media/update/MediaSession2Provider.java b/media/java/android/media/update/MediaSession2Provider.java
index fc1f671..dbd4a0a 100644
--- a/media/java/android/media/update/MediaSession2Provider.java
+++ b/media/java/android/media/update/MediaSession2Provider.java
@@ -19,8 +19,8 @@
import android.app.PendingIntent;
import android.media.MediaItem2;
import android.media.MediaMetadata2;
-import android.media.MediaPlayerInterface;
-import android.media.MediaPlayerInterface.EventCallback;
+import android.media.MediaPlayerBase;
+import android.media.MediaPlayerBase.EventCallback;
import android.media.MediaSession2;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
@@ -40,27 +40,28 @@
/**
* @hide
*/
-// TODO: @SystemApi
public interface MediaSession2Provider extends TransportControlProvider {
void close_impl();
- void setPlayer_impl(MediaPlayerInterface player);
- void setPlayer_impl(MediaPlayerInterface player, VolumeProvider2 volumeProvider);
- MediaPlayerInterface getPlayer_impl();
+ void setPlayer_impl(MediaPlayerBase player);
+ void setPlayer_impl(MediaPlayerBase player, VolumeProvider2 volumeProvider);
+ MediaPlayerBase getPlayer_impl();
SessionToken2 getToken_impl();
List<ControllerInfo> getConnectedControllers_impl();
void setCustomLayout_impl(ControllerInfo controller, List<CommandButton> layout);
void setAudioFocusRequest_impl(int focusGain);
-
void setAllowedCommands_impl(ControllerInfo controller, CommandGroup commands);
- void notifyMetadataChanged_impl();
void sendCustomCommand_impl(ControllerInfo controller, Command command, Bundle args,
ResultReceiver receiver);
void sendCustomCommand_impl(Command command, Bundle args);
void setPlaylist_impl(List<MediaItem2> playlist);
+ void addPlaylistItem_impl(int index, MediaItem2 item);
+ void removePlaylistItem_impl(MediaItem2 item);
+ void editPlaylistItem_impl(MediaItem2 item);
List<MediaItem2> getPlaylist_impl();
+ MediaItem2 getCurrentPlaylistItem_impl();
void setPlaylistParams_impl(PlaylistParams params);
PlaylistParams getPlaylistParams_impl();
-
+ void notifyError_impl(int errorCode, int extra);
void registerPlayerEventCallback_impl(Executor executor, EventCallback callback);
void unregisterPlayerEventCallback_impl(EventCallback callback);
diff --git a/media/java/android/media/update/MediaSessionService2Provider.java b/media/java/android/media/update/MediaSessionService2Provider.java
index 42e7587..8697e70 100644
--- a/media/java/android/media/update/MediaSessionService2Provider.java
+++ b/media/java/android/media/update/MediaSessionService2Provider.java
@@ -16,7 +16,6 @@
package android.media.update;
-import android.annotation.SystemApi;
import android.app.Notification;
import android.content.Intent;
import android.media.MediaSession2;
@@ -29,7 +28,7 @@
*/
public interface MediaSessionService2Provider {
MediaSession2 getSession_impl();
- MediaNotification onUpdateNotification_impl(PlaybackState2 state);
+ MediaNotification onUpdateNotification_impl();
// Service
void onCreate_impl();
diff --git a/media/java/android/media/update/PlaybackState2Provider.java b/media/java/android/media/update/PlaybackState2Provider.java
index 93f769c..66b8fa5 100644
--- a/media/java/android/media/update/PlaybackState2Provider.java
+++ b/media/java/android/media/update/PlaybackState2Provider.java
@@ -21,7 +21,6 @@
/**
* @hide
*/
-// TODO(jaewan): @SystemApi
public interface PlaybackState2Provider {
String toString_impl();
diff --git a/media/java/android/media/update/Rating2Provider.java b/media/java/android/media/update/Rating2Provider.java
index 8966196..28ad273 100644
--- a/media/java/android/media/update/Rating2Provider.java
+++ b/media/java/android/media/update/Rating2Provider.java
@@ -22,7 +22,6 @@
/**
* @hide
*/
-// TODO(jaewan): @SystemApi
public interface Rating2Provider {
String toString_impl();
boolean equals_impl(Object obj);
@@ -34,4 +33,4 @@
boolean isThumbUp_impl();
float getStarRating_impl();
float getPercentRating_impl();
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index 29a30343..62759eb 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -28,10 +28,9 @@
import android.media.MediaLibraryService2;
import android.media.MediaLibraryService2.LibraryRoot;
import android.media.MediaLibraryService2.MediaLibrarySession;
-import android.media.MediaLibraryService2.MediaLibrarySessionBuilder;
-import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
+import android.media.MediaLibraryService2.MediaLibrarySession.MediaLibrarySessionCallback;
import android.media.MediaMetadata2;
-import android.media.MediaPlayerInterface;
+import android.media.MediaPlayerBase;
import android.media.MediaSession2;
import android.media.MediaSession2.CommandButton.Builder;
import android.media.MediaSession2.PlaylistParams;
@@ -44,7 +43,7 @@
import android.media.VolumeProvider2;
import android.media.update.MediaLibraryService2Provider.LibraryRootProvider;
import android.media.update.MediaSession2Provider.BuilderBaseProvider;
-import android.media.update.MediaSession2Provider.CommandButtonProvider.BuilderProvider;
+import android.media.update.MediaSession2Provider.CommandButtonProvider;
import android.media.update.MediaSession2Provider.CommandGroupProvider;
import android.media.update.MediaSession2Provider.CommandProvider;
import android.media.update.MediaSession2Provider.ControllerInfoProvider;
@@ -86,9 +85,10 @@
PlaylistParams playlistParams, int repeatMode, int shuffleMode,
MediaMetadata2 playlistMetadata);
PlaylistParams fromBundle_PlaylistParams(Context context, Bundle bundle);
- BuilderProvider createMediaSession2CommandButtonBuilder(Context context, Builder builder);
+ CommandButtonProvider.BuilderProvider createMediaSession2CommandButtonBuilder(Context context,
+ MediaSession2.CommandButton.Builder builder);
BuilderBaseProvider<MediaSession2, SessionCallback> createMediaSession2Builder(
- Context context, MediaSession2.Builder instance, MediaPlayerInterface player);
+ Context context, MediaSession2.Builder instance, MediaPlayerBase player);
MediaController2Provider createMediaController2(Context context, MediaController2 instance,
SessionToken2 token, Executor executor, ControllerCallback callback);
@@ -103,14 +103,15 @@
MediaSessionService2Provider createMediaLibraryService2(MediaLibraryService2 instance);
BuilderBaseProvider<MediaLibrarySession, MediaLibrarySessionCallback>
createMediaLibraryService2Builder(
- Context context, MediaLibrarySessionBuilder instance, MediaPlayerInterface player,
- Executor callbackExecutor, MediaLibrarySessionCallback callback);
+ MediaLibraryService2 service, MediaLibrarySession.Builder instance,
+ MediaPlayerBase player, Executor callbackExecutor,
+ MediaLibrarySessionCallback callback);
LibraryRootProvider createMediaLibraryService2LibraryRoot(Context context, LibraryRoot instance,
String rootId, Bundle extras);
SessionToken2Provider createSessionToken2(Context context, SessionToken2 instance,
String packageName, String serviceName, int uid);
- SessionToken2 SessionToken2_fromBundle(Context context, Bundle bundle);
+ SessionToken2 fromBundle_SessionToken2(Context context, Bundle bundle);
MediaItem2Provider createMediaItem2(Context context, MediaItem2 mediaItem2,
String mediaId, DataSourceDesc dsd, MediaMetadata2 metadata, int flags);
diff --git a/media/java/android/media/update/TransportControlProvider.java b/media/java/android/media/update/TransportControlProvider.java
index 44f82b29..9af8ada 100644
--- a/media/java/android/media/update/TransportControlProvider.java
+++ b/media/java/android/media/update/TransportControlProvider.java
@@ -16,6 +16,7 @@
package android.media.update;
+import android.media.MediaItem2;
import android.media.PlaybackState2;
/**
@@ -32,7 +33,7 @@
void fastForward_impl();
void rewind_impl();
void seekTo_impl(long pos);
- void setCurrentPlaylistItem_impl(int index);
+ void skipToPlaylistItem_impl(MediaItem2 item);
PlaybackState2 getPlaybackState_impl();
}
diff --git a/media/java/android/media/update/VideoView2Provider.java b/media/java/android/media/update/VideoView2Provider.java
index 4333c96..152ace9 100644
--- a/media/java/android/media/update/VideoView2Provider.java
+++ b/media/java/android/media/update/VideoView2Provider.java
@@ -19,7 +19,7 @@
import android.annotation.SystemApi;
import android.media.AudioAttributes;
import android.media.MediaMetadata2;
-import android.media.MediaPlayerInterface;
+import android.media.MediaPlayerBase;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
import android.media.session.MediaSession;
@@ -65,7 +65,7 @@
/**
* @hide
*/
- void setRouteAttributes_impl(List<String> routeCategories, MediaPlayerInterface player);
+ void setRouteAttributes_impl(List<String> routeCategories, MediaPlayerBase player);
// TODO: remove setRouteAttributes_impl with MediaSession.Callback once MediaSession2 is ready.
void setRouteAttributes_impl(List<String> routeCategories, MediaSession.Callback sessionPlayer);
void setVideoPath_impl(String path);
diff --git a/media/java/android/media/update/VolumeProvider2Provider.java b/media/java/android/media/update/VolumeProvider2Provider.java
index 5657af6..5b5cfd3 100644
--- a/media/java/android/media/update/VolumeProvider2Provider.java
+++ b/media/java/android/media/update/VolumeProvider2Provider.java
@@ -18,7 +18,6 @@
/**
* @hide
*/
-// TODO(jaewan): @SystemApi
public interface VolumeProvider2Provider {
int getControlType_impl();
int getMaxVolume_impl();