MediaSession2: Public APIs for MediaBrowser2 and MediaLibraryService2
Test: Run MediaComponents test once
Change-Id: Icea9f7db7f13ed8354c7ce36b069f45ad7ddbfa8
diff --git a/media/java/android/media/MediaBrowser2.java b/media/java/android/media/MediaBrowser2.java
index fa00902..33377bc 100644
--- a/media/java/android/media/MediaBrowser2.java
+++ b/media/java/android/media/MediaBrowser2.java
@@ -16,12 +16,14 @@
package android.media;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.media.update.ApiLoader;
import android.media.update.MediaBrowser2Provider;
import android.os.Bundle;
+import java.util.List;
import java.util.concurrent.Executor;
/**
@@ -35,7 +37,7 @@
/**
* Callback to listen events from {@link MediaLibraryService2}.
*/
- public abstract static class BrowserCallback extends MediaController2.ControllerCallback {
+ public static class BrowserCallback extends MediaController2.ControllerCallback {
/**
* Called with the result of {@link #getBrowserRoot(Bundle)}.
* <p>
@@ -46,8 +48,55 @@
* @param rootMediaId media id of the browser root. Can be {@code null}
* @param rootExtra extra of the browser root. Can be {@code null}
*/
- public abstract void onGetRootResult(Bundle rootHints, @Nullable String rootMediaId,
- @Nullable Bundle rootExtra);
+ public void onGetRootResult(Bundle rootHints, @Nullable String rootMediaId,
+ @Nullable Bundle rootExtra) { }
+
+ /**
+ * Called when the item has been returned by the library service for the previous
+ * {@link MediaBrowser2#getItem} call.
+ * <p>
+ * Result can be null if there had been error.
+ *
+ * @param mediaId media id
+ * @param result result. Can be {@code null}
+ */
+ public void onItemLoaded(@NonNull String mediaId, @Nullable MediaItem2 result) { }
+
+ /**
+ * Called when the list of items has been returned by the library service for the previous
+ * {@link MediaBrowser2#getChildren(String, int, int, Bundle)}.
+ *
+ * @param parentId parent id
+ * @param page page number that you've specified
+ * @param pageSize page size that you've specified
+ * @param options optional bundle that you've specified
+ * @param result result. Can be {@code null}
+ */
+ public void onChildrenLoaded(@NonNull String parentId, int page, int pageSize,
+ @Nullable Bundle options, @Nullable List<MediaItem2> result) { }
+
+ /**
+ * Called when there's change in the parent's children.
+ *
+ * @param parentId parent id that you've specified with subscribe
+ * @param options optional bundle that you've specified with subscribe
+ */
+ public void onChildrenChanged(@NonNull String parentId, @Nullable Bundle options) { }
+
+ /**
+ * Called when the search result has been returned by the library service for the previous
+ * {@link MediaBrowser2#search(String, int, int, Bundle)}.
+ * <p>
+ * Result can be null if there had been error.
+ *
+ * @param query query string that you've specified
+ * @param page page number that you've specified
+ * @param pageSize page size that you've specified
+ * @param options optional bundle that you've specified
+ * @param result result. Can be {@code null}
+ */
+ public void onSearchResult(@NonNull String query, int page, int pageSize,
+ @Nullable Bundle options, @Nullable List<MediaItem2> result) { }
}
public MediaBrowser2(Context context, SessionToken token, BrowserCallback callback,
@@ -66,4 +115,62 @@
public void getBrowserRoot(Bundle rootHints) {
mProvider.getBrowserRoot_impl(rootHints);
}
+
+ /**
+ * Subscribe to a parent id for the change in its children. When there's a change,
+ * {@link BrowserCallback#onChildrenChanged(String, Bundle)} will be called with the bundle
+ * that you've specified. You should call {@link #getChildren(String, int, int, Bundle)} to get
+ * the actual contents for the parent.
+ *
+ * @param parentId parent id
+ * @param options optional bundle
+ */
+ public void subscribe(String parentId, @Nullable Bundle options) {
+ mProvider.subscribe_impl(parentId, options);
+ }
+
+ /**
+ * Unsubscribe for changes to the children of the parent, which was previously subscribed with
+ * {@link #subscribe(String, Bundle)}.
+ *
+ * @param parentId parent id
+ * @param options optional bundle
+ */
+ public void unsubscribe(String parentId, @Nullable Bundle options) {
+ mProvider.unsubscribe_impl(parentId, options);
+ }
+
+ /**
+ * Get the media item with the given media id. Result would be sent back asynchronously with the
+ * {@link BrowserCallback#onItemLoaded(String, MediaItem2)}.
+ *
+ * @param mediaId media id
+ */
+ public void getItem(String mediaId) {
+ mProvider.getItem_impl(mediaId);
+ }
+
+ /**
+ * Get list of children under the parent. Result would be sent back asynchronously with the
+ * {@link BrowserCallback#onChildrenLoaded(String, int, int, Bundle, List)}.
+ *
+ * @param parentId
+ * @param page
+ * @param pageSize
+ * @param options
+ */
+ public void getChildren(String parentId, int page, int pageSize, @Nullable Bundle options) {
+ mProvider.getChildren_impl(parentId, page, pageSize, options);
+ }
+
+ /**
+ *
+ * @param query search query deliminated by string
+ * @param page page number to get search result. Starts from {@code 1}
+ * @param pageSize page size. Should be greater or equal to {@code 1}
+ * @param extras extra bundle
+ */
+ public void search(String query, int page, int pageSize, Bundle extras) {
+ mProvider.search_impl(query, page, pageSize, extras);
+ }
}
diff --git a/media/java/android/media/MediaLibraryService2.java b/media/java/android/media/MediaLibraryService2.java
index 44b1917..b98936e 100644
--- a/media/java/android/media/MediaLibraryService2.java
+++ b/media/java/android/media/MediaLibraryService2.java
@@ -23,10 +23,14 @@
import android.media.MediaSession2.BuilderBase;
import android.media.MediaSession2.ControllerInfo;
import android.media.update.ApiLoader;
+import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider;
+import android.media.update.MediaSession2Provider;
import android.media.update.MediaSessionService2Provider;
import android.os.Bundle;
import android.service.media.MediaBrowserService.BrowserRoot;
+import java.util.List;
+
/**
* Base class for media library services.
* <p>
@@ -60,16 +64,50 @@
* Session for the media library service.
*/
public class MediaLibrarySession extends MediaSession2 {
+ private final MediaLibrarySessionProvider mProvider;
MediaLibrarySession(Context context, MediaPlayerBase player, String id,
SessionCallback callback, VolumeProvider volumeProvider,
int ratingType, PendingIntent sessionActivity) {
super(context, player, id, callback, volumeProvider, ratingType, sessionActivity);
+ mProvider = (MediaLibrarySessionProvider) getProvider();
}
- // TODO(jaewan): Place public methods here.
+
+ @Override
+ MediaSession2Provider createProvider(Context context, MediaPlayerBase player, String id,
+ SessionCallback callback, VolumeProvider volumeProvider, int ratingType,
+ PendingIntent sessionActivity) {
+ return ApiLoader.getProvider(context)
+ .createMediaLibraryService2MediaLibrarySession(this, context, player, id,
+ (MediaLibrarySessionCallback) callback, volumeProvider, ratingType,
+ sessionActivity);
+ }
+
+ /**
+ * Notify subscribed controller about change in a parent's children.
+ *
+ * @param controller controller to notify
+ * @param parentId
+ * @param options
+ */
+ public void notifyChildrenChanged(@NonNull ControllerInfo controller,
+ @NonNull String parentId, @NonNull Bundle options) {
+ mProvider.notifyChildrenChanged_impl(controller, parentId, options);
+ }
+
+ /**
+ * Notify subscribed controller about change in a parent's children.
+ *
+ * @param parentId parent id
+ * @param options optional bundle
+ */
+ // This is for the backward compatibility.
+ public void notifyChildrenChanged(@NonNull String parentId, @Nullable Bundle options) {
+ mProvider.notifyChildrenChanged_impl(parentId, options);
+ }
}
- public static abstract class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
+ public static class MediaLibrarySessionCallback extends MediaSession2.SessionCallback {
/**
* Called to get the root information for browsing by a particular client.
* <p>
@@ -88,8 +126,76 @@
* @see BrowserRoot#EXTRA_OFFLINE
* @see BrowserRoot#EXTRA_SUGGESTED
*/
- public abstract @Nullable BrowserRoot onGetRoot(
- @NonNull ControllerInfo controllerInfo, @Nullable Bundle rootHints);
+ public @Nullable BrowserRoot onGetRoot(@NonNull ControllerInfo controllerInfo,
+ @Nullable Bundle rootHints) {
+ return null;
+ }
+
+ /**
+ * Called to get the search result. Return search result here for the browser.
+ * <p>
+ * Return an empty list for no search result, and return {@code null} for the error.
+ *
+ * @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.
+ * @return search result. {@code null} for error.
+ */
+ public @Nullable List<MediaItem2> onSearch(@NonNull ControllerInfo controllerInfo,
+ @NonNull String query, @Nullable Bundle extras) {
+ return null;
+ }
+
+ /**
+ * Called to get the search result . Return result here for the browser.
+ * <p>
+ * Return an empty list for no search result, and return {@code null} for the error.
+ *
+ * @param itemId item id to get media item.
+ * @return media item2. {@code null} for error.
+ */
+ public @Nullable MediaItem2 onLoadItem(@NonNull ControllerInfo controllerInfo,
+ @NonNull String itemId) {
+ return null;
+ }
+
+ /**
+ * Called to get the search result. Return search result here for the browser.
+ * <p>
+ * Return an empty list for no search result, 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 options
+ * @return list of children. Can be {@code null}.
+ */
+ public @Nullable List<MediaItem2> onLoadChildren(@NonNull ControllerInfo controller,
+ @NonNull String parentId, int page, int pageSize, @Nullable Bundle options) {
+ return null;
+ }
+
+ /**
+ * Called when a controller subscribes to the parent.
+ *
+ * @param controller controller
+ * @param parentId parent id
+ * @param options optional bundle
+ */
+ public void onSubscribed(@NonNull ControllerInfo controller,
+ String parentId, @Nullable Bundle options) {
+ }
+
+ /**
+ * Called when a controller unsubscribes to the parent.
+ *
+ * @param controller controller
+ * @param parentId parent id
+ * @param options optional bundle
+ */
+ public void onUnsubscribed(@NonNull ControllerInfo controller,
+ String parentId, @Nullable Bundle options) {
+ }
}
/**
@@ -145,4 +251,95 @@
*/
@Override
public @NonNull abstract MediaLibrarySession onCreateSession(String sessionId);
+
+ /**
+ * Contains information that the browser service needs to send to the client
+ * when first connected.
+ */
+ public static final class BrowserRoot {
+ /**
+ * The lookup key for a boolean that indicates whether the browser service should return a
+ * browser root for recently played media items.
+ *
+ * <p>When creating a media browser for a given media browser service, this key can be
+ * supplied as a root hint for retrieving media items that are recently played.
+ * If the media browser service can provide such media items, the implementation must return
+ * the key in the root hint when
+ * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back.
+ *
+ * <p>The root hint may contain multiple keys.
+ *
+ * @see #EXTRA_OFFLINE
+ * @see #EXTRA_SUGGESTED
+ */
+ public static final String EXTRA_RECENT = "android.service.media.extra.RECENT";
+
+ /**
+ * The lookup key for a boolean that indicates whether the browser service should return a
+ * browser root for offline media items.
+ *
+ * <p>When creating a media browser for a given media browser service, this key can be
+ * supplied as a root hint for retrieving media items that are can be played without an
+ * internet connection.
+ * If the media browser service can provide such media items, the implementation must return
+ * the key in the root hint when
+ * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back.
+ *
+ * <p>The root hint may contain multiple keys.
+ *
+ * @see #EXTRA_RECENT
+ * @see #EXTRA_SUGGESTED
+ */
+ public static final String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE";
+
+ /**
+ * The lookup key for a boolean that indicates whether the browser service should return a
+ * browser root for suggested media items.
+ *
+ * <p>When creating a media browser for a given media browser service, this key can be
+ * supplied as a root hint for retrieving the media items suggested by the media browser
+ * service. The list of media items passed in {@link android.media.browse.MediaBrowser.SubscriptionCallback#onChildrenLoaded(String, List)}
+ * is considered ordered by relevance, first being the top suggestion.
+ * If the media browser service can provide such media items, the implementation must return
+ * the key in the root hint when
+ * {@link MediaLibrarySessionCallback#onGetRoot(ControllerInfo, Bundle)} is called back.
+ *
+ * <p>The root hint may contain multiple keys.
+ *
+ * @see #EXTRA_RECENT
+ * @see #EXTRA_OFFLINE
+ */
+ public static final String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED";
+
+ final private String mRootId;
+ final private Bundle mExtras;
+
+ /**
+ * Constructs a browser root.
+ * @param rootId The root id for browsing.
+ * @param extras Any extras about the browser service.
+ */
+ public BrowserRoot(@NonNull String rootId, @Nullable Bundle extras) {
+ if (rootId == null) {
+ throw new IllegalArgumentException("The root id in BrowserRoot cannot be null. " +
+ "Use null for BrowserRoot instead.");
+ }
+ mRootId = rootId;
+ mExtras = extras;
+ }
+
+ /**
+ * Gets the root id for browsing.
+ */
+ public String getRootId() {
+ return mRootId;
+ }
+
+ /**
+ * Gets any extras about the browser service.
+ */
+ public Bundle getExtras() {
+ return mExtras;
+ }
+ }
}
diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java
index eeac75a..6fdf7a8 100644
--- a/media/java/android/media/MediaSession2.java
+++ b/media/java/android/media/MediaSession2.java
@@ -889,7 +889,14 @@
SessionCallback callback, VolumeProvider volumeProvider, int ratingType,
PendingIntent sessionActivity) {
super();
- mProvider = ApiLoader.getProvider(context)
+ mProvider = createProvider(context, player, id, callback,
+ volumeProvider, ratingType, sessionActivity);
+ }
+
+ MediaSession2Provider createProvider(Context context, MediaPlayerBase player, String id,
+ SessionCallback callback, VolumeProvider volumeProvider, int ratingType,
+ PendingIntent sessionActivity) {
+ return ApiLoader.getProvider(context)
.createMediaSession2(this, context, player, id, callback,
volumeProvider, ratingType, sessionActivity);
}
diff --git a/media/java/android/media/update/MediaBrowser2Provider.java b/media/java/android/media/update/MediaBrowser2Provider.java
index 355dbc9..e48711d 100644
--- a/media/java/android/media/update/MediaBrowser2Provider.java
+++ b/media/java/android/media/update/MediaBrowser2Provider.java
@@ -23,4 +23,11 @@
*/
public interface MediaBrowser2Provider extends MediaController2Provider {
void getBrowserRoot_impl(Bundle rootHints);
+
+ void subscribe_impl(String parentId, Bundle options);
+ void unsubscribe_impl(String parentId, Bundle options);
+
+ void getItem_impl(String mediaId);
+ void getChildren_impl(String parentId, int page, int pageSize, Bundle options);
+ void search_impl(String query, int page, int pageSize, Bundle extras);
}
diff --git a/media/java/android/media/update/MediaLibraryService2Provider.java b/media/java/android/media/update/MediaLibraryService2Provider.java
index 7e3444f..dac5784 100644
--- a/media/java/android/media/update/MediaLibraryService2Provider.java
+++ b/media/java/android/media/update/MediaLibraryService2Provider.java
@@ -16,9 +16,15 @@
package android.media.update;
-/**
+import android.media.MediaSession2.ControllerInfo;
+import android.os.Bundle; /**
* @hide
*/
public interface MediaLibraryService2Provider extends MediaSessionService2Provider {
// Nothing new for now
+
+ interface MediaLibrarySessionProvider extends MediaSession2Provider {
+ void notifyChildrenChanged_impl(ControllerInfo controller, String parentId, Bundle options);
+ void notifyChildrenChanged_impl(String parentId, Bundle options);
+ }
}
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index 80e2402..64968d6 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -25,12 +25,16 @@
import android.media.MediaController2;
import android.media.MediaController2.ControllerCallback;
import android.media.MediaLibraryService2;
+import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
import android.media.MediaPlayerBase;
import android.media.MediaSession2;
import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
import android.media.SessionToken;
import android.media.VolumeProvider;
+import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider;
+import android.media.update.MediaSession2Provider.ControllerInfoProvider;
import android.util.AttributeSet;
import android.widget.MediaControlView2;
import android.widget.VideoView2;
@@ -57,7 +61,7 @@
MediaPlayerBase player, String id, SessionCallback callback,
VolumeProvider volumeProvider, int ratingType,
PendingIntent sessionActivity);
- MediaSession2Provider.ControllerInfoProvider createMediaSession2ControllerInfoProvider(
+ ControllerInfoProvider createMediaSession2ControllerInfoProvider(
MediaSession2.ControllerInfo instance, Context context, int uid, int pid,
String packageName, IMediaSession2Callback callback);
MediaController2Provider createMediaController2(
@@ -70,4 +74,8 @@
MediaSessionService2 instance);
MediaSessionService2Provider createMediaLibraryService2(
MediaLibraryService2 instance);
+ MediaLibrarySessionProvider createMediaLibraryService2MediaLibrarySession(
+ MediaLibrarySession instance, Context context, MediaPlayerBase player, String id,
+ MediaLibrarySessionCallback callback, VolumeProvider volumeProvider, int ratingType,
+ PendingIntent sessionActivity);
}