Merge "Update MediaBrowser to use String ids instead of Uris" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 009b534..fa21be1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16250,12 +16250,12 @@
     method public void connect();
     method public void disconnect();
     method public android.os.Bundle getExtras();
-    method public android.net.Uri getRoot();
+    method public java.lang.String getRoot();
     method public android.content.ComponentName getServiceComponent();
     method public android.media.session.MediaSession.Token getSessionToken();
     method public boolean isConnected();
-    method public void subscribe(android.net.Uri, android.media.browse.MediaBrowser.SubscriptionCallback);
-    method public void unsubscribe(android.net.Uri);
+    method public void subscribe(java.lang.String, android.media.browse.MediaBrowser.SubscriptionCallback);
+    method public void unsubscribe(java.lang.String);
   }
 
   public static class MediaBrowser.ConnectionCallback {
@@ -16281,8 +16281,8 @@
 
   public static abstract class MediaBrowser.SubscriptionCallback {
     ctor public MediaBrowser.SubscriptionCallback();
-    method public void onChildrenLoaded(android.net.Uri, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
-    method public void onError(android.net.Uri);
+    method public void onChildrenLoaded(java.lang.String, java.util.List<android.media.browse.MediaBrowser.MediaItem>);
+    method public void onError(java.lang.String);
   }
 
 }
@@ -27063,18 +27063,18 @@
     ctor public MediaBrowserService();
     method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
     method public android.media.session.MediaSession.Token getSessionToken();
-    method public void notifyChildrenChanged(android.net.Uri);
+    method public void notifyChildrenChanged(java.lang.String);
     method public android.os.IBinder onBind(android.content.Intent);
     method public abstract android.service.media.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
-    method public abstract void onLoadChildren(android.net.Uri, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
+    method public abstract void onLoadChildren(java.lang.String, android.service.media.MediaBrowserService.Result<java.util.List<android.media.browse.MediaBrowser.MediaItem>>);
     method public void setSessionToken(android.media.session.MediaSession.Token);
     field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
   }
 
   public static final class MediaBrowserService.BrowserRoot {
-    ctor public MediaBrowserService.BrowserRoot(android.net.Uri, android.os.Bundle);
+    ctor public MediaBrowserService.BrowserRoot(java.lang.String, android.os.Bundle);
     method public android.os.Bundle getExtras();
-    method public android.net.Uri getRootUri();
+    method public java.lang.String getRootId();
   }
 
   public class MediaBrowserService.Result {
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index debaf45..338c711 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -25,8 +25,8 @@
 import android.content.ServiceConnection;
 import android.content.pm.ParceledListSlice;
 import android.media.MediaDescription;
+import android.media.session.MediaController;
 import android.media.session.MediaSession;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -67,14 +67,14 @@
     private final ConnectionCallback mCallback;
     private final Bundle mRootHints;
     private final Handler mHandler = new Handler();
-    private final ArrayMap<Uri,Subscription> mSubscriptions =
-            new ArrayMap<Uri, MediaBrowser.Subscription>();
+    private final ArrayMap<String,Subscription> mSubscriptions =
+            new ArrayMap<String, MediaBrowser.Subscription>();
 
     private int mState = CONNECT_STATE_DISCONNECTED;
     private MediaServiceConnection mServiceConnection;
     private IMediaBrowserService mServiceBinder;
     private IMediaBrowserServiceCallbacks mServiceCallbacks;
-    private Uri mRootUri;
+    private String mRootId;
     private MediaSession.Token mMediaSessionToken;
     private Bundle mExtras;
 
@@ -85,7 +85,7 @@
      * @param serviceComponent The component name of the media browse service.
      * @param callback The connection callback.
      * @param rootHints An optional bundle of service-specific arguments to send
-     * to the media browse service when connecting and retrieving the root uri
+     * to the media browse 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.
      */
@@ -212,7 +212,7 @@
         mServiceConnection = null;
         mServiceBinder = null;
         mServiceCallbacks = null;
-        mRootUri = null;
+        mRootId = null;
         mMediaSessionToken = null;
     }
 
@@ -235,20 +235,20 @@
     }
 
     /**
-     * Gets the root Uri.
+     * Gets the root id.
      * <p>
-     * Note that the root uri may become invalid or change when when the
+     * Note that the root id may become invalid or change when when the
      * browser is disconnected.
      * </p>
      *
      * @throws IllegalStateException if not connected.
      */
-    public @NonNull Uri getRoot() {
+    public @NonNull String getRoot() {
         if (!isConnected()) {
             throw new IllegalStateException("getSessionToken() called while not connected (state="
                     + getStateLabel(mState) + ")");
         }
-        return mRootUri;
+        return mRootId;
     }
 
     /**
@@ -285,35 +285,35 @@
 
     /**
      * Queries for information about the media items that are contained within
-     * the specified Uri and subscribes to receive updates when they change.
+     * the specified id and subscribes to receive updates when they change.
      * <p>
      * The list of subscriptions is maintained even when not connected and is
      * restored after reconnection.  It is ok to subscribe while not connected
      * but the results will not be returned until the connection completes.
      * </p><p>
-     * If the uri is already subscribed with a different callback then the new
+     * If the id is already subscribed with a different callback then the new
      * callback will replace the previous one.
      * </p>
      *
-     * @param parentUri The uri of the parent media item whose list of children
+     * @param parentId The id of the parent media item whose list of children
      * will be subscribed.
      * @param callback The callback to receive the list of children.
      */
-    public void subscribe(@NonNull Uri parentUri, @NonNull SubscriptionCallback callback) {
+    public void subscribe(@NonNull String parentId, @NonNull SubscriptionCallback callback) {
         // Check arguments.
-        if (parentUri == null) {
-            throw new IllegalArgumentException("parentUri is null");
+        if (parentId == null) {
+            throw new IllegalArgumentException("parentId is null");
         }
         if (callback == null) {
             throw new IllegalArgumentException("callback is null");
         }
 
         // Update or create the subscription.
-        Subscription sub = mSubscriptions.get(parentUri);
+        Subscription sub = mSubscriptions.get(parentId);
         boolean newSubscription = sub == null;
         if (newSubscription) {
-            sub = new Subscription(parentUri);
-            mSubscriptions.put(parentUri, sub);
+            sub = new Subscription(parentId);
+            mSubscriptions.put(parentId, sub);
         }
         sub.callback = callback;
 
@@ -321,42 +321,42 @@
         // connected, the service will be told when we connect.
         if (mState == CONNECT_STATE_CONNECTED && newSubscription) {
             try {
-                mServiceBinder.addSubscription(parentUri, mServiceCallbacks);
+                mServiceBinder.addSubscription(parentId, mServiceCallbacks);
             } catch (RemoteException ex) {
                 // Process is crashing.  We will disconnect, and upon reconnect we will
                 // automatically reregister. So nothing to do here.
-                Log.d(TAG, "addSubscription failed with RemoteException parentUri=" + parentUri);
+                Log.d(TAG, "addSubscription failed with RemoteException parentId=" + parentId);
             }
         }
     }
 
     /**
-     * Unsubscribes for changes to the children of the specified Uri.
+     * Unsubscribes for changes to the children of the specified media id.
      * <p>
      * The query callback will no longer be invoked for results associated with
-     * this Uri once this method returns.
+     * this id once this method returns.
      * </p>
      *
-     * @param parentUri The uri of the parent media item whose list of children
+     * @param parentId The id of the parent media item whose list of children
      * will be unsubscribed.
      */
-    public void unsubscribe(@NonNull Uri parentUri) {
+    public void unsubscribe(@NonNull String parentId) {
         // Check arguments.
-        if (parentUri == null) {
-            throw new IllegalArgumentException("parentUri is null");
+        if (parentId == null) {
+            throw new IllegalArgumentException("parentId is null");
         }
 
         // Remove from our list.
-        final Subscription sub = mSubscriptions.remove(parentUri);
+        final Subscription sub = mSubscriptions.remove(parentId);
 
         // Tell the service if necessary.
         if (mState == CONNECT_STATE_CONNECTED && sub != null) {
             try {
-                mServiceBinder.removeSubscription(parentUri, mServiceCallbacks);
+                mServiceBinder.removeSubscription(parentId, mServiceCallbacks);
             } catch (RemoteException ex) {
                 // Process is crashing.  We will disconnect, and upon reconnect we will
                 // automatically reregister. So nothing to do here.
-                Log.d(TAG, "removeSubscription failed with RemoteException parentUri=" + parentUri);
+                Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId);
             }
         }
     }
@@ -380,7 +380,7 @@
     }
 
     private final void onServiceConnected(final IMediaBrowserServiceCallbacks callback,
-            final Uri root, final MediaSession.Token session, final Bundle extra) {
+            final String root, final MediaSession.Token session, final Bundle extra) {
         mHandler.post(new Runnable() {
             @Override
             public void run() {
@@ -395,7 +395,7 @@
                             + getStateLabel(mState) + "... ignoring");
                     return;
                 }
-                mRootUri = root;
+                mRootId = root;
                 mMediaSessionToken = session;
                 mExtras = extra;
                 mState = CONNECT_STATE_CONNECTED;
@@ -408,13 +408,13 @@
 
                 // we may receive some subscriptions before we are connected, so re-subscribe
                 // everything now
-                for (Uri uri : mSubscriptions.keySet()) {
+                for (String id : mSubscriptions.keySet()) {
                     try {
-                        mServiceBinder.addSubscription(uri, mServiceCallbacks);
+                        mServiceBinder.addSubscription(id, mServiceCallbacks);
                     } catch (RemoteException ex) {
                         // Process is crashing.  We will disconnect, and upon reconnect we will
                         // automatically reregister. So nothing to do here.
-                        Log.d(TAG, "addSubscription failed with RemoteException parentUri=" + uri);
+                        Log.d(TAG, "addSubscription failed with RemoteException parentId=" + id);
                     }
                 }
             }
@@ -448,8 +448,8 @@
         });
     }
 
-    private final void onLoadChildren(final IMediaBrowserServiceCallbacks callback, final Uri uri,
-            final ParceledListSlice list) {
+    private final void onLoadChildren(final IMediaBrowserServiceCallbacks callback,
+            final String parentId, final ParceledListSlice list) {
         mHandler.post(new Runnable() {
             @Override
             public void run() {
@@ -461,24 +461,24 @@
 
                 List<MediaItem> data = list.getList();
                 if (DBG) {
-                    Log.d(TAG, "onLoadChildren for " + mServiceComponent + " uri=" + uri);
+                    Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId);
                 }
                 if (data == null) {
                     data = Collections.emptyList();
                 }
 
                 // Check that the subscription is still subscribed.
-                final Subscription subscription = mSubscriptions.get(uri);
+                final Subscription subscription = mSubscriptions.get(parentId);
                 if (subscription == null) {
                     if (DBG) {
-                        Log.d(TAG, "onLoadChildren for uri that isn't subscribed uri="
-                                + uri);
+                        Log.d(TAG, "onLoadChildren for id that isn't subscribed id="
+                                + parentId);
                     }
                     return;
                 }
 
                 // Tell the app.
-                subscription.callback.onChildrenLoaded(uri, data);
+                subscription.callback.onChildrenLoaded(parentId, data);
             }
         });
     }
@@ -514,7 +514,7 @@
         Log.d(TAG, "  mServiceConnection=" + mServiceConnection);
         Log.d(TAG, "  mServiceBinder=" + mServiceBinder);
         Log.d(TAG, "  mServiceCallbacks=" + mServiceCallbacks);
-        Log.d(TAG, "  mRootUri=" + mRootUri);
+        Log.d(TAG, "  mRootId=" + mRootId);
         Log.d(TAG, "  mMediaSessionToken=" + mMediaSessionToken);
     }
 
@@ -535,7 +535,8 @@
         /**
          * Flag: Indicates that the item is playable.
          * <p>
-         * The Uri of this item may be passed to link android.media.session.MediaController#play(Uri)
+         * The id of this item may be passed to
+         * {@link MediaController.TransportControls#playFromMediaId(String, Bundle)}
          * to start playing it.
          * </p>
          */
@@ -669,18 +670,18 @@
         /**
          * Called when the list of children is loaded or updated.
          */
-        public void onChildrenLoaded(@NonNull Uri parentUri,
+        public void onChildrenLoaded(@NonNull String parentId,
                                      @NonNull List<MediaItem> children) {
         }
 
         /**
-         * Called when the Uri doesn't exist or other errors in subscribing.
+         * Called when the id doesn't exist or other errors in subscribing.
          * <p>
          * If this is called, the subscription remains until {@link MediaBrowser#unsubscribe}
          * called, because some errors may heal themselves.
          * </p>
          */
-        public void onError(@NonNull Uri uri) {
+        public void onError(@NonNull String id) {
         }
     }
 
@@ -783,7 +784,7 @@
          * are the initial data as requested.
          */
         @Override
-        public void onConnect(final Uri root, final MediaSession.Token session,
+        public void onConnect(final String root, final MediaSession.Token session,
                 final Bundle extras) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
@@ -803,20 +804,20 @@
         }
 
         @Override
-        public void onLoadChildren(final Uri uri, final ParceledListSlice list) {
+        public void onLoadChildren(final String parentId, final ParceledListSlice list) {
             MediaBrowser mediaBrowser = mMediaBrowser.get();
             if (mediaBrowser != null) {
-                mediaBrowser.onLoadChildren(this, uri, list);
+                mediaBrowser.onLoadChildren(this, parentId, list);
             }
         }
     }
 
     private static class Subscription {
-        final Uri uri;
+        final String id;
         SubscriptionCallback callback;
 
-        Subscription(Uri u) {
-            this.uri = u;
+        Subscription(String id) {
+            this.id = id;
         }
     }
 }
diff --git a/media/java/android/service/media/IMediaBrowserService.aidl b/media/java/android/service/media/IMediaBrowserService.aidl
index 2631ddd..01285ee 100644
--- a/media/java/android/service/media/IMediaBrowserService.aidl
+++ b/media/java/android/service/media/IMediaBrowserService.aidl
@@ -16,6 +16,6 @@
     void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
     void disconnect(IMediaBrowserServiceCallbacks callbacks);
 
-    void addSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks);
-    void removeSubscription(in Uri uri, IMediaBrowserServiceCallbacks callbacks);
+    void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
+    void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
 }
\ No newline at end of file
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index 7702a50..2a37ada 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -5,7 +5,6 @@
 import android.content.pm.ParceledListSlice;
 import android.graphics.Bitmap;
 import android.media.session.MediaSession;
-import android.net.Uri;
 import android.os.Bundle;
 
 /**
@@ -16,12 +15,12 @@
 oneway interface IMediaBrowserServiceCallbacks {
     /**
      * Invoked when the connected has been established.
-     * @param root The root Uri for browsing.
+     * @param root The root media id for browsing.
      * @param session The {@link MediaSession.Token media session token} that can be used to control
      *         the playback of the media app.
      * @param extra Extras returned by the media service.
      */
-    void onConnect(in Uri root, in MediaSession.Token session, in Bundle extras);
+    void onConnect(String root, in MediaSession.Token session, in Bundle extras);
     void onConnectFailed();
-    void onLoadChildren(in Uri uri, in ParceledListSlice list);
+    void onLoadChildren(String mediaId, in ParceledListSlice list);
 }
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 4d6fd7b..317cb96 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -25,12 +25,8 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
 import android.media.browse.MediaBrowser;
-import android.media.browse.MediaBrowser.MediaItem;
 import android.media.session.MediaSession;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -38,18 +34,13 @@
 import android.os.RemoteException;
 import android.service.media.IMediaBrowserService;
 import android.service.media.IMediaBrowserServiceCallbacks;
-import android.service.media.IMediaBrowserService.Stub;
 import android.util.ArrayMap;
 import android.util.Log;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 /**
  * Base class for media browse services.
@@ -96,7 +87,7 @@
         Bundle rootHints;
         IMediaBrowserServiceCallbacks callbacks;
         BrowserRoot root;
-        HashSet<Uri> subscriptions = new HashSet();
+        HashSet<String> subscriptions = new HashSet();
     }
 
     /**
@@ -199,7 +190,7 @@
                         } else {
                             try {
                                 mConnections.put(b, connection);
-                                callbacks.onConnect(connection.root.getRootUri(),
+                                callbacks.onConnect(connection.root.getRootId(),
                                         mSession, connection.root.getExtras());
                             } catch (RemoteException ex) {
                                 Log.w(TAG, "Calling onConnect() failed. Dropping client. "
@@ -229,7 +220,7 @@
 
 
         @Override
-        public void addSubscription(final Uri uri, final IMediaBrowserServiceCallbacks callbacks) {
+        public void addSubscription(final String id, final IMediaBrowserServiceCallbacks callbacks) {
             mHandler.post(new Runnable() {
                     @Override
                     public void run() {
@@ -238,18 +229,18 @@
                         // Get the record for the connection
                         final ConnectionRecord connection = mConnections.get(b);
                         if (connection == null) {
-                            Log.w(TAG, "addSubscription for callback that isn't registered uri="
-                                + uri);
+                            Log.w(TAG, "addSubscription for callback that isn't registered id="
+                                + id);
                             return;
                         }
 
-                        MediaBrowserService.this.addSubscription(uri, connection);
+                        MediaBrowserService.this.addSubscription(id, connection);
                     }
                 });
         }
 
         @Override
-        public void removeSubscription(final Uri uri,
+        public void removeSubscription(final String id,
                 final IMediaBrowserServiceCallbacks callbacks) {
             mHandler.post(new Runnable() {
                 @Override
@@ -258,12 +249,12 @@
 
                     ConnectionRecord connection = mConnections.get(b);
                     if (connection == null) {
-                        Log.w(TAG, "removeSubscription for callback that isn't registered uri="
-                                + uri);
+                        Log.w(TAG, "removeSubscription for callback that isn't registered id="
+                                + id);
                         return;
                     }
-                    if (!connection.subscriptions.remove(uri)) {
-                        Log.w(TAG, "removeSubscription called for " + uri
+                    if (!connection.subscriptions.remove(id)) {
+                        Log.w(TAG, "removeSubscription called for " + id
                                 + " which is not subscribed");
                     }
                 }
@@ -294,7 +285,7 @@
      * <p>
      * The implementation should verify that the client package has
      * permission to access browse media information before returning
-     * the root uri; it should return null if the client is not
+     * the root id; it should return null if the client is not
      * allowed to access this information.
      * </p>
      *
@@ -303,7 +294,7 @@
      * @param clientUid The uid of the application which is requesting
      * access to browse media.
      * @param rootHints An optional bundle of service-specific arguments to send
-     * to the media browse service when connecting and retrieving the root uri
+     * to the media browse 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.
      */
@@ -319,11 +310,11 @@
      * from this function, and then {@link Result#sendResult result.sendResult} called when
      * the loading is complete.
      *
-     * @param parentUri The uri of the parent media item whose
+     * @param parentId The id of the parent media item whose
      * children are to be queried.
-     * @return The list of children, or null if the uri is invalid.
+     * @return The list of children, or null if the id is invalid.
      */
-    public abstract void onLoadChildren(@NonNull Uri parentUri,
+    public abstract void onLoadChildren(@NonNull String parentId,
             @NonNull Result<List<MediaBrowser.MediaItem>> result);
 
     /**
@@ -351,23 +342,23 @@
 
     /**
      * Notifies all connected media browsers that the children of
-     * the specified Uri have changed in some way.
+     * the specified parent id have changed in some way.
      * This will cause browsers to fetch subscribed content again.
      *
-     * @param parentUri The uri of the parent media item whose
+     * @param parentId The id of the parent media item whose
      * children changed.
      */
-    public void notifyChildrenChanged(@NonNull final Uri parentUri) {
-        if (parentUri == null) {
-            throw new IllegalArgumentException("parentUri cannot be null in notifyChildrenChanged");
+    public void notifyChildrenChanged(@NonNull final String parentId) {
+        if (parentId == null) {
+            throw new IllegalArgumentException("parentId cannot be null in notifyChildrenChanged");
         }
         mHandler.post(new Runnable() {
             @Override
             public void run() {
                 for (IBinder binder : mConnections.keySet()) {
                     ConnectionRecord connection = mConnections.get(binder);
-                    if (connection.subscriptions.contains(parentUri)) {
-                        performLoadChildren(parentUri, connection);
+                    if (connection.subscriptions.contains(parentId)) {
+                        performLoadChildren(parentId, connection);
                     }
                 }
             }
@@ -395,13 +386,13 @@
     /**
      * Save the subscription and if it is a new subscription send the results.
      */
-    private void addSubscription(Uri uri, ConnectionRecord connection) {
+    private void addSubscription(String id, ConnectionRecord connection) {
         // Save the subscription
-        final boolean added = connection.subscriptions.add(uri);
+        final boolean added = connection.subscriptions.add(id);
 
         // If this is a new subscription, send the results
         if (added) {
-            performLoadChildren(uri, connection);
+            performLoadChildren(id, connection);
         }
     }
 
@@ -410,39 +401,39 @@
      * <p>
      * Callers must make sure that this connection is still connected.
      */
-    private void performLoadChildren(final Uri uri, final ConnectionRecord connection) {
+    private void performLoadChildren(final String parentId, final ConnectionRecord connection) {
         final Result<List<MediaBrowser.MediaItem>> result
- = new Result<List<MediaBrowser.MediaItem>>(
-                uri) {
+                = new Result<List<MediaBrowser.MediaItem>>(parentId) {
             @Override
             void onResultSent(List<MediaBrowser.MediaItem> list) {
                 if (list == null) {
-                    throw new IllegalStateException("onLoadChildren sent null list for uri " + uri);
+                    throw new IllegalStateException("onLoadChildren sent null list for id "
+                            + parentId);
                 }
                 if (mConnections.get(connection.callbacks.asBinder()) != connection) {
                     if (DBG) {
                         Log.d(TAG, "Not sending onLoadChildren result for connection that has"
-                                + " been disconnected. pkg=" + connection.pkg + " uri=" + uri);
+                                + " been disconnected. pkg=" + connection.pkg + " id=" + parentId);
                     }
                     return;
                 }
 
                 final ParceledListSlice<MediaBrowser.MediaItem> pls = new ParceledListSlice(list);
                 try {
-                    connection.callbacks.onLoadChildren(uri, pls);
+                    connection.callbacks.onLoadChildren(parentId, pls);
                 } catch (RemoteException ex) {
                     // The other side is in the process of crashing.
-                    Log.w(TAG, "Calling onLoadChildren() failed for uri=" + uri
+                    Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
                             + " package=" + connection.pkg);
                 }
             }
         };
 
-        onLoadChildren(uri, result);
+        onLoadChildren(parentId, result);
 
         if (!result.isDone()) {
             throw new IllegalStateException("onLoadChildren must call detach() or sendResult()"
-                    + " before returning for package=" + connection.pkg + " uri=" + uri);
+                    + " before returning for package=" + connection.pkg + " id=" + parentId);
         }
     }
 
@@ -451,28 +442,28 @@
      * when first connected.
      */
     public static final class BrowserRoot {
-        final private Uri mUri;
+        final private String mRootId;
         final private Bundle mExtras;
 
         /**
          * Constructs a browser root.
-         * @param uri The root Uri for browsing.
+         * @param rootId The root id for browsing.
          * @param extras Any extras about the browser service.
          */
-        public BrowserRoot(@NonNull Uri uri, @Nullable Bundle extras) {
-            if (uri == null) {
-                throw new IllegalArgumentException("The root uri in BrowserRoot cannot be null. " +
+        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.");
             }
-            mUri = uri;
+            mRootId = rootId;
             mExtras = extras;
         }
 
         /**
-         * Gets the root uri for browsing.
+         * Gets the root id for browsing.
          */
-        public Uri getRootUri() {
-            return mUri;
+        public String getRootId() {
+            return mRootId;
         }
 
         /**
diff --git a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
index 64602d52..8cc9b97 100644
--- a/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
+++ b/tests/MusicBrowserDemo/src/com/example/android/musicbrowserdemo/BrowserListFragment.java
@@ -47,12 +47,12 @@
 
     // For args
     public static final String ARG_COMPONENT = "component";
-    public static final String ARG_URI = "uri";
+    public static final String ARG_ID = "uri";
 
     private Adapter mAdapter;
     private List<Item> mItems = new ArrayList();
     private ComponentName mComponent;
-    private Uri mUri;
+    private String mNodeId;
     private MediaBrowser mBrowser;
 
     private static class Item {
@@ -76,7 +76,7 @@
         // Get our arguments
         final Bundle args = getArguments();
         mComponent = args.getParcelable(ARG_COMPONENT);
-        mUri = args.getParcelable(ARG_URI);
+        mNodeId = args.getString(ARG_ID);
 
         // A hint about who we are, so the service can customize the results if it wants to.
         final Bundle rootHints = new Bundle();
@@ -108,7 +108,7 @@
 
         final Bundle args = new Bundle();
         args.putParcelable(BrowserListFragment.ARG_COMPONENT, mComponent);
-        args.putParcelable(BrowserListFragment.ARG_URI, item.media.getDescription().getIconUri());
+        args.putParcelable(BrowserListFragment.ARG_ID, item.media.getDescription().getIconUri());
         fragment.setArguments(args);
 
         getFragmentManager().beginTransaction()
@@ -124,14 +124,14 @@
         @Override
         public void onConnected() {
             Log.d(TAG, "mConnectionCallbacks.onConnected");
-            if (mUri == null) {
-                mUri = mBrowser.getRoot();
+            if (mNodeId == null) {
+                mNodeId = mBrowser.getRoot();
             }
-            mBrowser.subscribe(mUri, new MediaBrowser.SubscriptionCallback() {
+            mBrowser.subscribe(mNodeId, new MediaBrowser.SubscriptionCallback() {
                     @Override
-                    public void onChildrenLoaded(Uri parentUri,
+                public void onChildrenLoaded(String parentId,
                             List<MediaBrowser.MediaItem> children) {
-                        Log.d(TAG, "onChildrenLoaded parentUri=" + parentUri
+                    Log.d(TAG, "onChildrenLoaded parentId=" + parentId
                                 + " children= " + children);
                         mItems.clear();
                         final int N = children.size();
@@ -142,8 +142,8 @@
                     }
 
                     @Override
-                    public void onError(Uri parentUri) {
-                        Log.d(TAG, "onError parentUri=" + parentUri);
+                public void onError(String parentId) {
+                    Log.d(TAG, "onError parentId=" + parentId);
                     }
                 });
         }
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
index 845db6c..a216a32 100644
--- a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
@@ -118,11 +118,11 @@
 
     @Override
     public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
-        return new BrowserRoot(BROWSE_URI, null);
+        return new BrowserRoot(BROWSE_URI.toString(), null);
     }
 
     @Override
-    public void onLoadChildren(final Uri parentUri,
+    public void onLoadChildren(final String parentId,
             final Result<List<MediaBrowser.MediaItem>> result) {
         new Handler().postDelayed(new Runnable() {
                 public void run() {