Revert "Backport MediaBrowser and MediaBrowserService"

This reverts commit b113d491f3aaba7f508fc0045382bb1344c3c609.

Change-Id: If45c6f458c37b9d79f4218f6b1c4213278f83c83
diff --git a/v4/java/android/support/v4/media/IMediaBrowserService.aidl b/v4/java/android/support/v4/media/IMediaBrowserService.aidl
deleted file mode 100644
index 01516fd..0000000
--- a/v4/java/android/support/v4/media/IMediaBrowserService.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-
-package android.support.v4.media;
-
-import android.content.res.Configuration;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.v4.media.IMediaBrowserServiceCallbacks;
-import android.support.v4.os.ResultReceiver;
-
-/**
- * Media API allows clients to browse through hierarchy of a user’s media collection,
- * playback a specific media entry and interact with the now playing queue.
- * @hide
- */
-oneway interface IMediaBrowserService {
-    void connect(String pkg, in Bundle rootHints, IMediaBrowserServiceCallbacks callbacks);
-    void disconnect(IMediaBrowserServiceCallbacks callbacks);
-
-    void addSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
-    void removeSubscription(String uri, IMediaBrowserServiceCallbacks callbacks);
-    void getMediaItem(String uri, in ResultReceiver cb);
-}
\ No newline at end of file
diff --git a/v4/java/android/support/v4/media/IMediaBrowserServiceCallbacks.aidl b/v4/java/android/support/v4/media/IMediaBrowserServiceCallbacks.aidl
deleted file mode 100644
index 6e46968..0000000
--- a/v4/java/android/support/v4/media/IMediaBrowserServiceCallbacks.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-
-package android.support.v4.media;
-
-import android.graphics.Bitmap;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.os.Bundle;
-
-import java.util.List;
-
-/**
- * Media API allows clients to browse through hierarchy of a user’s media collection,
- * playback a specific media entry and interact with the now playing queue.
- * @hide
- */
-oneway interface IMediaBrowserServiceCallbacks {
-    /**
-     * Invoked when the connected has been established.
-     * @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(String root, in MediaSessionCompat.Token session, in Bundle extras);
-    void onConnectFailed();
-    void onLoadChildren(String mediaId, in List list);
-}
diff --git a/v4/java/android/support/v4/media/MediaBrowser.aidl b/v4/java/android/support/v4/media/MediaBrowser.aidl
deleted file mode 100644
index 23e9d6a..0000000
--- a/v4/java/android/support/v4/media/MediaBrowser.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2015, 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.browse;
-
-parcelable MediaBrowser.MediaItem;
\ No newline at end of file
diff --git a/v4/java/android/support/v4/media/MediaBrowser.java b/v4/java/android/support/v4/media/MediaBrowser.java
deleted file mode 100644
index 27be143..0000000
--- a/v4/java/android/support/v4/media/MediaBrowser.java
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- * Copyright (C) 2015 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.support.v4.media;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.support.annotation.IntDef;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.media.IMediaBrowserService;
-import android.support.v4.media.IMediaBrowserServiceCallbacks;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.os.ResultReceiver;
-import android.support.v4.util.ArrayMap;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Browses media content offered by a link MediaBrowserService.
- * <p>
- * This object is not thread-safe. All calls should happen on the thread on which the browser
- * was constructed.
- * </p>
- * @hide
- */
-public final class MediaBrowser {
-    private static final String TAG = "MediaBrowser";
-    private static final boolean DBG = false;
-
-    private static final int CONNECT_STATE_DISCONNECTED = 0;
-    private static final int CONNECT_STATE_CONNECTING = 1;
-    private static final int CONNECT_STATE_CONNECTED = 2;
-    private static final int CONNECT_STATE_SUSPENDED = 3;
-
-    private final Context mContext;
-    private final ComponentName mServiceComponent;
-    private final ConnectionCallback mCallback;
-    private final Bundle mRootHints;
-    private final Handler mHandler = new Handler();
-    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 String mRootId;
-    private MediaSessionCompat.Token mMediaSessionToken;
-    private Bundle mExtras;
-
-    /**
-     * Creates a media browser for the specified media browse service.
-     *
-     * @param context The context.
-     * @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 id
-     * for browsing, or null if none.  The contents of this bundle may affect
-     * the information returned when browsing.
-     */
-    public MediaBrowser(Context context, ComponentName serviceComponent,
-            ConnectionCallback callback, Bundle rootHints) {
-        if (context == null) {
-            throw new IllegalArgumentException("context must not be null");
-        }
-        if (serviceComponent == null) {
-            throw new IllegalArgumentException("service component must not be null");
-        }
-        if (callback == null) {
-            throw new IllegalArgumentException("connection callback must not be null");
-        }
-        mContext = context;
-        mServiceComponent = serviceComponent;
-        mCallback = callback;
-        mRootHints = rootHints;
-    }
-
-    /**
-     * Connects to the media browse service.
-     * <p>
-     * The connection callback specified in the constructor will be invoked
-     * when the connection completes or fails.
-     * </p>
-     */
-    public void connect() {
-        if (mState != CONNECT_STATE_DISCONNECTED) {
-            throw new IllegalStateException("connect() called while not disconnected (state="
-                    + getStateLabel(mState) + ")");
-        }
-        // TODO: remove this extra check.
-        if (DBG) {
-            if (mServiceConnection != null) {
-                throw new RuntimeException("mServiceConnection should be null. Instead it is "
-                        + mServiceConnection);
-            }
-        }
-        if (mServiceBinder != null) {
-            throw new RuntimeException("mServiceBinder should be null. Instead it is "
-                    + mServiceBinder);
-        }
-        if (mServiceCallbacks != null) {
-            throw new RuntimeException("mServiceCallbacks should be null. Instead it is "
-                    + mServiceCallbacks);
-        }
-
-        mState = CONNECT_STATE_CONNECTING;
-
-        final Intent intent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
-        intent.setComponent(mServiceComponent);
-
-        final ServiceConnection thisConnection = mServiceConnection = new MediaServiceConnection();
-
-        boolean bound = false;
-        try {
-            bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
-        } catch (Exception ex) {
-            Log.e(TAG, "Failed binding to service " + mServiceComponent);
-        }
-
-        if (!bound) {
-            // Tell them that it didn't work.  We are already on the main thread,
-            // but we don't want to do callbacks inside of connect().  So post it,
-            // and then check that we are on the same ServiceConnection.  We know
-            // we won't also get an onServiceConnected or onServiceDisconnected,
-            // so we won't be doing double callbacks.
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    // Ensure that nobody else came in or tried to connect again.
-                    if (thisConnection == mServiceConnection) {
-                        forceCloseConnection();
-                        mCallback.onConnectionFailed();
-                    }
-                }
-            });
-        }
-
-        if (DBG) {
-            Log.d(TAG, "connect...");
-            dump();
-        }
-    }
-
-    /**
-     * Disconnects from the media browse service.
-     * After this, no more callbacks will be received.
-     */
-    public void disconnect() {
-        // It's ok to call this any state, because allowing this lets apps not have
-        // to check isConnected() unnecessarily.  They won't appreciate the extra
-        // assertions for this.  We do everything we can here to go back to a sane state.
-        if (mServiceCallbacks != null) {
-            try {
-                mServiceBinder.disconnect(mServiceCallbacks);
-            } catch (RemoteException ex) {
-                // We are disconnecting anyway.  Log, just for posterity but it's not
-                // a big problem.
-                Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
-            }
-        }
-        forceCloseConnection();
-
-        if (DBG) {
-            Log.d(TAG, "disconnect...");
-            dump();
-        }
-    }
-
-    /**
-     * Null out the variables and unbind from the service.  This doesn't include
-     * calling disconnect on the service, because we only try to do that in the
-     * clean shutdown cases.
-     * <p>
-     * Everywhere that calls this EXCEPT for disconnect() should follow it with
-     * a call to mCallback.onConnectionFailed().  Disconnect doesn't do that callback
-     * for a clean shutdown, but everywhere else is a dirty shutdown and should
-     * notify the app.
-     */
-    private void forceCloseConnection() {
-        if (mServiceConnection != null) {
-            mContext.unbindService(mServiceConnection);
-        }
-        mState = CONNECT_STATE_DISCONNECTED;
-        mServiceConnection = null;
-        mServiceBinder = null;
-        mServiceCallbacks = null;
-        mRootId = null;
-        mMediaSessionToken = null;
-    }
-
-    /**
-     * Returns whether the browser is connected to the service.
-     */
-    public boolean isConnected() {
-        return mState == CONNECT_STATE_CONNECTED;
-    }
-
-    /**
-     * Gets the service component that the media browser is connected to.
-     */
-    public @NonNull
-    ComponentName getServiceComponent() {
-        if (!isConnected()) {
-            throw new IllegalStateException("getServiceComponent() called while not connected" +
-                    " (state=" + mState + ")");
-        }
-        return mServiceComponent;
-    }
-
-    /**
-     * Gets the root id.
-     * <p>
-     * Note that the root id may become invalid or change when when the
-     * browser is disconnected.
-     * </p>
-     *
-     * @throws IllegalStateException if not connected.
-     */
-    public @NonNull String getRoot() {
-        if (!isConnected()) {
-            throw new IllegalStateException("getSessionToken() called while not connected (state="
-                    + getStateLabel(mState) + ")");
-        }
-        return mRootId;
-    }
-
-    /**
-     * Gets any extras for the media service.
-     *
-     * @throws IllegalStateException if not connected.
-     */
-    public @Nullable
-    Bundle getExtras() {
-        if (!isConnected()) {
-            throw new IllegalStateException("getExtras() called while not connected (state="
-                    + getStateLabel(mState) + ")");
-        }
-        return mExtras;
-    }
-
-    /**
-     * Gets the media session token associated with the media browser.
-     * <p>
-     * Note that the session token may become invalid or change when when the
-     * browser is disconnected.
-     * </p>
-     *
-     * @return The session token for the browser, never null.
-     *
-     * @throws IllegalStateException if not connected.
-     */
-     public @NonNull MediaSessionCompat.Token getSessionToken() {
-        if (!isConnected()) {
-            throw new IllegalStateException("getSessionToken() called while not connected (state="
-                    + mState + ")");
-        }
-        return mMediaSessionToken;
-    }
-
-    /**
-     * Queries for information about the media items that are contained within
-     * 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 id is already subscribed with a different callback then the new
-     * callback will replace the previous one and the child data will be
-     * reloaded.
-     * </p>
-     *
-     * @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 String parentId, @NonNull SubscriptionCallback callback) {
-        // Check arguments.
-        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(parentId);
-        boolean newSubscription = sub == null;
-        if (newSubscription) {
-            sub = new Subscription(parentId);
-            mSubscriptions.put(parentId, sub);
-        }
-        sub.callback = callback;
-
-        // If we are connected, tell the service that we are watching.  If we aren't
-        // connected, the service will be told when we connect.
-        if (mState == CONNECT_STATE_CONNECTED) {
-            try {
-                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 parentId=" + parentId);
-            }
-        }
-    }
-
-    /**
-     * 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 id once this method returns.
-     * </p>
-     *
-     * @param parentId The id of the parent media item whose list of children
-     * will be unsubscribed.
-     */
-    public void unsubscribe(@NonNull String parentId) {
-        // Check arguments.
-        if (TextUtils.isEmpty(parentId)) {
-            throw new IllegalArgumentException("parentId is empty.");
-        }
-
-        // Remove from our list.
-        final Subscription sub = mSubscriptions.remove(parentId);
-
-        // Tell the service if necessary.
-        if (mState == CONNECT_STATE_CONNECTED && sub != null) {
-            try {
-                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 parentId=" + parentId);
-            }
-        }
-    }
-
-    /**
-     * Retrieves a specific {@link MediaItem} from the connected service. Not
-     * all services may support this, so falling back to subscribing to the
-     * parent's id should be used when unavailable.
-     *
-     * @param mediaId The id of the item to retrieve.
-     * @param cb The callback to receive the result on.
-     */
-    public void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb) {
-        if (TextUtils.isEmpty(mediaId)) {
-            throw new IllegalArgumentException("mediaId is empty.");
-        }
-        if (cb == null) {
-            throw new IllegalArgumentException("cb is null.");
-        }
-        if (mState != CONNECT_STATE_CONNECTED) {
-            Log.i(TAG, "Not connected, unable to retrieve the MediaItem.");
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    cb.onError(mediaId);
-                }
-            });
-            return;
-        }
-        ResultReceiver receiver = new ResultReceiver(mHandler) {
-            @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                if (resultCode != 0 || resultData == null
-                        || !resultData.containsKey(MediaBrowserService.KEY_MEDIA_ITEM)) {
-                    cb.onError(mediaId);
-                    return;
-                }
-                Parcelable item = resultData.getParcelable(MediaBrowserService.KEY_MEDIA_ITEM);
-                if (!(item instanceof MediaItem)) {
-                    cb.onError(mediaId);
-                    return;
-                }
-                cb.onItemLoaded((MediaItem)item);
-            }
-        };
-        try {
-            mServiceBinder.getMediaItem(mediaId, receiver);
-        } catch (RemoteException e) {
-            Log.i(TAG, "Remote error getting media item.");
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    cb.onError(mediaId);
-                }
-            });
-        }
-    }
-
-    /**
-     * For debugging.
-     */
-    private static String getStateLabel(int state) {
-        switch (state) {
-            case CONNECT_STATE_DISCONNECTED:
-                return "CONNECT_STATE_DISCONNECTED";
-            case CONNECT_STATE_CONNECTING:
-                return "CONNECT_STATE_CONNECTING";
-            case CONNECT_STATE_CONNECTED:
-                return "CONNECT_STATE_CONNECTED";
-            case CONNECT_STATE_SUSPENDED:
-                return "CONNECT_STATE_SUSPENDED";
-            default:
-                return "UNKNOWN/" + state;
-        }
-    }
-
-    private final void onServiceConnected(final IMediaBrowserServiceCallbacks callback,
-            final String root, final MediaSessionCompat.Token session, final Bundle extra) {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                // Check to make sure there hasn't been a disconnect or a different
-                // ServiceConnection.
-                if (!isCurrent(callback, "onConnect")) {
-                    return;
-                }
-                // Don't allow them to call us twice.
-                if (mState != CONNECT_STATE_CONNECTING) {
-                    Log.w(TAG, "onConnect from service while mState="
-                            + getStateLabel(mState) + "... ignoring");
-                    return;
-                }
-                mRootId = root;
-                mMediaSessionToken = session;
-                mExtras = extra;
-                mState = CONNECT_STATE_CONNECTED;
-
-                if (DBG) {
-                    Log.d(TAG, "ServiceCallbacks.onConnect...");
-                    dump();
-                }
-                mCallback.onConnected();
-
-                // we may receive some subscriptions before we are connected, so re-subscribe
-                // everything now
-                for (String id : mSubscriptions.keySet()) {
-                    try {
-                        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 parentId=" + id);
-                    }
-                }
-            }
-        });
-    }
-
-    private final void onConnectionFailed(final IMediaBrowserServiceCallbacks callback) {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                Log.e(TAG, "onConnectFailed for " + mServiceComponent);
-
-                // Check to make sure there hasn't been a disconnect or a different
-                // ServiceConnection.
-                if (!isCurrent(callback, "onConnectFailed")) {
-                    return;
-                }
-                // Don't allow them to call us twice.
-                if (mState != CONNECT_STATE_CONNECTING) {
-                    Log.w(TAG, "onConnect from service while mState="
-                            + getStateLabel(mState) + "... ignoring");
-                    return;
-                }
-
-                // Clean up
-                forceCloseConnection();
-
-                // Tell the app.
-                mCallback.onConnectionFailed();
-            }
-        });
-    }
-
-    private final void onLoadChildren(final IMediaBrowserServiceCallbacks callback,
-            final String parentId, final List list) {
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                // Check that there hasn't been a disconnect or a different
-                // ServiceConnection.
-                if (!isCurrent(callback, "onLoadChildren")) {
-                    return;
-                }
-
-                List<MediaItem> data = list;
-                if (DBG) {
-                    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(parentId);
-                if (subscription == null) {
-                    if (DBG) {
-                        Log.d(TAG, "onLoadChildren for id that isn't subscribed id="
-                                + parentId);
-                    }
-                    return;
-                }
-
-                // Tell the app.
-                subscription.callback.onChildrenLoaded(parentId, data);
-            }
-        });
-    }
-
-    /**
-     * Return true if {@code callback} is the current ServiceCallbacks.  Also logs if it's not.
-     */
-    private boolean isCurrent(IMediaBrowserServiceCallbacks callback, String funcName) {
-        if (mServiceCallbacks != callback) {
-            if (mState != CONNECT_STATE_DISCONNECTED) {
-                Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
-                        + mServiceCallbacks + " this=" + this);
-            }
-            return false;
-        }
-        return true;
-    }
-
-    private ServiceCallbacks getNewServiceCallbacks() {
-        return new ServiceCallbacks(this);
-    }
-
-    /**
-     * Log internal state.
-     * @hide
-     */
-    void dump() {
-        Log.d(TAG, "MediaBrowser...");
-        Log.d(TAG, "  mServiceComponent=" + mServiceComponent);
-        Log.d(TAG, "  mCallback=" + mCallback);
-        Log.d(TAG, "  mRootHints=" + mRootHints);
-        Log.d(TAG, "  mState=" + getStateLabel(mState));
-        Log.d(TAG, "  mServiceConnection=" + mServiceConnection);
-        Log.d(TAG, "  mServiceBinder=" + mServiceBinder);
-        Log.d(TAG, "  mServiceCallbacks=" + mServiceCallbacks);
-        Log.d(TAG, "  mRootId=" + mRootId);
-        Log.d(TAG, "  mMediaSessionToken=" + mMediaSessionToken);
-    }
-
-    public static class MediaItem implements Parcelable {
-        private final int mFlags;
-        private final MediaDescriptionCompat mDescription;
-
-        /** @hide */
-        @Retention(RetentionPolicy.SOURCE)
-        @IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE })
-        public @interface Flags { }
-
-        /**
-         * Flag: Indicates that the item has children of its own.
-         */
-        public static final int FLAG_BROWSABLE = 1 << 0;
-
-        /**
-         * Flag: Indicates that the item is playable.
-         * <p>
-         * The id of this item may be passed to
-         * {@link MediaController.TransportControls#playFromMediaId(String, Bundle)}
-         * to start playing it.
-         * </p>
-         */
-        public static final int FLAG_PLAYABLE = 1 << 1;
-
-        /**
-         * Create a new MediaItem for use in browsing media.
-         * @param description The description of the media, which must include a
-         *            media id.
-         * @param flags The flags for this item.
-         */
-        public MediaItem(@NonNull MediaDescriptionCompat description, @Flags int flags) {
-            if (description == null) {
-                throw new IllegalArgumentException("description cannot be null");
-            }
-            if (TextUtils.isEmpty(description.getMediaId())) {
-                throw new IllegalArgumentException("description must have a non-empty media id");
-            }
-            mFlags = flags;
-            mDescription = description;
-        }
-
-        /**
-         * Private constructor.
-         */
-        private MediaItem(Parcel in) {
-            mFlags = in.readInt();
-            mDescription = MediaDescriptionCompat.CREATOR.createFromParcel(in);
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flags) {
-            out.writeInt(mFlags);
-            mDescription.writeToParcel(out, flags);
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder sb = new StringBuilder("MediaItem{");
-            sb.append("mFlags=").append(mFlags);
-            sb.append(", mDescription=").append(mDescription);
-            sb.append('}');
-            return sb.toString();
-        }
-
-        public static final Parcelable.Creator<MediaItem> CREATOR =
-                new Parcelable.Creator<MediaItem>() {
-                    @Override
-                    public MediaItem createFromParcel(Parcel in) {
-                        return new MediaItem(in);
-                    }
-
-                    @Override
-                    public MediaItem[] newArray(int size) {
-                        return new MediaItem[size];
-                    }
-                };
-
-        /**
-         * Gets the flags of the item.
-         */
-        public @Flags int getFlags() {
-            return mFlags;
-        }
-
-        /**
-         * Returns whether this item is browsable.
-         * @see #FLAG_BROWSABLE
-         */
-        public boolean isBrowsable() {
-            return (mFlags & FLAG_BROWSABLE) != 0;
-        }
-
-        /**
-         * Returns whether this item is playable.
-         * @see #FLAG_PLAYABLE
-         */
-        public boolean isPlayable() {
-            return (mFlags & FLAG_PLAYABLE) != 0;
-        }
-
-        /**
-         * Returns the description of the media.
-         */
-        public @NonNull MediaDescriptionCompat getDescription() {
-            return mDescription;
-        }
-
-        /**
-         * Returns the media id for this item.
-         */
-        public @NonNull String getMediaId() {
-            return mDescription.getMediaId();
-        }
-    }
-
-
-    /**
-     * Callbacks for connection related events.
-     */
-    public static class ConnectionCallback {
-        /**
-         * Invoked after {@link MediaBrowser#connect()} when the request has successfully completed.
-         */
-        public void onConnected() {
-        }
-
-        /**
-         * Invoked when the client is disconnected from the media browser.
-         */
-        public void onConnectionSuspended() {
-        }
-
-        /**
-         * Invoked when the connection to the media browser failed.
-         */
-        public void onConnectionFailed() {
-        }
-    }
-
-    /**
-     * Callbacks for subscription related events.
-     */
-    public static abstract class SubscriptionCallback {
-        /**
-         * Called when the list of children is loaded or updated.
-         *
-         * @param parentId The media id of the parent media item.
-         * @param children The children which were loaded.
-         */
-        public void onChildrenLoaded(@NonNull String parentId,
-                                     @NonNull List<MediaItem> children) {
-        }
-
-        /**
-         * 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>
-         *
-         * @param parentId The media id of the parent media item whose children could
-         * not be loaded.
-         */
-        public void onError(@NonNull String parentId) {
-        }
-    }
-
-    /**
-     * Callback for receiving the result of {@link #getItem}.
-     */
-    public static abstract class ItemCallback {
-        /**
-         * Called when the item has been returned by the browser service.
-         *
-         * @param item The item that was returned or null if it doesn't exist.
-         */
-        public void onItemLoaded(MediaItem item) {
-        }
-
-        /**
-         * Called when the item doesn't exist or there was an error retrieving it.
-         *
-         * @param itemId The media id of the media item which could not be loaded.
-         */
-        public void onError(@NonNull String itemId) {
-        }
-    }
-
-    /**
-     * ServiceConnection to the other app.
-     */
-    private class MediaServiceConnection implements ServiceConnection {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder binder) {
-            if (DBG) {
-                Log.d(TAG, "MediaServiceConnection.onServiceConnected name=" + name
-                        + " binder=" + binder);
-                dump();
-            }
-
-            // Make sure we are still the current connection, and that they haven't called
-            // disconnect().
-            if (!isCurrent("onServiceConnected")) {
-                return;
-            }
-
-            // Save their binder
-            mServiceBinder = IMediaBrowserService.Stub.asInterface(binder);
-
-            // We make a new mServiceCallbacks each time we connect so that we can drop
-            // responses from previous connections.
-            mServiceCallbacks = getNewServiceCallbacks();
-            mState = CONNECT_STATE_CONNECTING;
-
-            // Call connect, which is async. When we get a response from that we will
-            // say that we're connected.
-            try {
-                if (DBG) {
-                    Log.d(TAG, "ServiceCallbacks.onConnect...");
-                    dump();
-                }
-                mServiceBinder.connect(mContext.getPackageName(), mRootHints, mServiceCallbacks);
-            } catch (RemoteException ex) {
-                // Connect failed, which isn't good. But the auto-reconnect on the service
-                // will take over and we will come back.  We will also get the
-                // onServiceDisconnected, which has all the cleanup code.  So let that do it.
-                Log.w(TAG, "RemoteException during connect for " + mServiceComponent);
-                if (DBG) {
-                    Log.d(TAG, "ServiceCallbacks.onConnect...");
-                    dump();
-                }
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            if (DBG) {
-                Log.d(TAG, "MediaServiceConnection.onServiceDisconnected name=" + name
-                        + " this=" + this + " mServiceConnection=" + mServiceConnection);
-                dump();
-            }
-
-            // Make sure we are still the current connection, and that they haven't called
-            // disconnect().
-            if (!isCurrent("onServiceDisconnected")) {
-                return;
-            }
-
-            // Clear out what we set in onServiceConnected
-            mServiceBinder = null;
-            mServiceCallbacks = null;
-
-            // And tell the app that it's suspended.
-            mState = CONNECT_STATE_SUSPENDED;
-            mCallback.onConnectionSuspended();
-        }
-
-        /**
-         * Return true if this is the current ServiceConnection.  Also logs if it's not.
-         */
-        private boolean isCurrent(String funcName) {
-            if (mServiceConnection != this) {
-                if (mState != CONNECT_STATE_DISCONNECTED) {
-                    // Check mState, because otherwise this log is noisy.
-                    Log.i(TAG, funcName + " for " + mServiceComponent + " with mServiceConnection="
-                            + mServiceConnection + " this=" + this);
-                }
-                return false;
-            }
-            return true;
-        }
-    }
-
-    /**
-     * Callbacks from the service.
-     */
-    private static class ServiceCallbacks extends IMediaBrowserServiceCallbacks.Stub {
-        private WeakReference<MediaBrowser> mMediaBrowser;
-
-        public ServiceCallbacks(MediaBrowser mediaBrowser) {
-            mMediaBrowser = new WeakReference<MediaBrowser>(mediaBrowser);
-        }
-
-        /**
-         * The other side has acknowledged our connection.  The parameters to this function
-         * are the initial data as requested.
-         */
-        @Override
-        public void onConnect(final String root, final MediaSessionCompat.Token session,
-                final Bundle extras) {
-            MediaBrowser mediaBrowser = mMediaBrowser.get();
-            if (mediaBrowser != null) {
-                mediaBrowser.onServiceConnected(this, root, session, extras);
-            }
-        }
-
-        /**
-         * The other side does not like us.  Tell the app via onConnectionFailed.
-         */
-        @Override
-        public void onConnectFailed() {
-            MediaBrowser mediaBrowser = mMediaBrowser.get();
-            if (mediaBrowser != null) {
-                mediaBrowser.onConnectionFailed(this);
-            }
-        }
-
-        @Override
-        public void onLoadChildren(final String parentId, final List list) {
-            MediaBrowser mediaBrowser = mMediaBrowser.get();
-            if (mediaBrowser != null) {
-                mediaBrowser.onLoadChildren(this, parentId, list);
-            }
-        }
-    }
-
-    private static class Subscription {
-        final String id;
-        SubscriptionCallback callback;
-
-        Subscription(String id) {
-            this.id = id;
-        }
-    }
-}
diff --git a/v4/java/android/support/v4/media/MediaBrowserService.java b/v4/java/android/support/v4/media/MediaBrowserService.java
deleted file mode 100644
index d32e70b..0000000
--- a/v4/java/android/support/v4/media/MediaBrowserService.java
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * Copyright (C) 2015 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.support.v4.media;
-
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.media.IMediaBrowserService;
-import android.support.v4.media.IMediaBrowserServiceCallbacks;
-import android.support.v4.media.session.MediaSessionCompat;
-import android.support.v4.os.ResultReceiver;
-import android.support.v4.util.ArrayMap;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * Base class for media browse services.
- * <p>
- * Media browse services enable applications to browse media content provided by an application
- * 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 MediaSession}.
- * </p>
- *
- * To extend this class, you must declare the service in your manifest file with
- * an intent filter with the {@link #SERVICE_INTERFACE} action.
- *
- * For example:
- * </p><pre>
- * &lt;service android:name=".MyMediaBrowserService"
- *          android:label="&#64;string/service_name" >
- *     &lt;intent-filter>
- *         &lt;action android:name="android.media.browse.MediaBrowserService" />
- *     &lt;/intent-filter>
- * &lt;/service>
- * </pre>
- * @hide
- */
-public abstract class MediaBrowserService extends Service {
-    private static final String TAG = "MediaBrowserService";
-    private static final boolean DBG = false;
-
-    /**
-     * The {@link Intent} that must be declared as handled by the service.
-     */
-    public static final String SERVICE_INTERFACE = "android.media.browse.MediaBrowserService";
-
-    /**
-     * A key for passing the MediaItem to the ResultReceiver in getItem.
-     *
-     * @hide
-     */
-    public static final String KEY_MEDIA_ITEM = "media_item";
-
-    private final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap();
-    private final Handler mHandler = new Handler();
-    private ServiceBinder mBinder;
-    MediaSessionCompat.Token mSession;
-
-    /**
-     * All the info about a connection.
-     */
-    private class ConnectionRecord {
-        String pkg;
-        Bundle rootHints;
-        IMediaBrowserServiceCallbacks callbacks;
-        BrowserRoot root;
-        HashSet<String> subscriptions = new HashSet();
-    }
-
-    /**
-     * Completion handler for asynchronous callback methods in {@link MediaBrowserService}.
-     * <p>
-     * Each of the methods that takes one of these to send the result must call
-     * {@link #sendResult} to respond to the caller with the given results.  If those
-     * functions return without calling {@link #sendResult}, they must instead call
-     * {@link #detach} before returning, and then may call {@link #sendResult} when
-     * they are done.  If more than one of those methods is called, an exception will
-     * be thrown.
-     *
-     * @see MediaBrowserService#onLoadChildren
-     * @see MediaBrowserService#onGetMediaItem
-     */
-    public class Result<T> {
-        private Object mDebug;
-        private boolean mDetachCalled;
-        private boolean mSendResultCalled;
-
-        Result(Object debug) {
-            mDebug = debug;
-        }
-
-        /**
-         * Send the result back to the caller.
-         */
-        public void sendResult(T result) {
-            if (mSendResultCalled) {
-                throw new IllegalStateException("sendResult() called twice for: " + mDebug);
-            }
-            mSendResultCalled = true;
-            onResultSent(result);
-        }
-
-        /**
-         * Detach this message from the current thread and allow the {@link #sendResult}
-         * call to happen later.
-         */
-        public void detach() {
-            if (mDetachCalled) {
-                throw new IllegalStateException("detach() called when detach() had already"
-                        + " been called for: " + mDebug);
-            }
-            if (mSendResultCalled) {
-                throw new IllegalStateException("detach() called when sendResult() had already"
-                        + " been called for: " + mDebug);
-            }
-            mDetachCalled = true;
-        }
-
-        boolean isDone() {
-            return mDetachCalled || mSendResultCalled;
-        }
-
-        /**
-         * Called when the result is sent, after assertions about not being called twice
-         * have happened.
-         */
-        void onResultSent(T result) {
-        }
-    }
-
-    private class ServiceBinder extends IMediaBrowserService.Stub {
-        @Override
-        public void connect(final String pkg, final Bundle rootHints,
-                final IMediaBrowserServiceCallbacks callbacks) {
-
-            final int uid = Binder.getCallingUid();
-            if (!isValidPackage(pkg, uid)) {
-                throw new IllegalArgumentException("Package/uid mismatch: uid=" + uid
-                        + " package=" + pkg);
-            }
-
-            mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        final IBinder b = callbacks.asBinder();
-
-                        // Clear out the old subscriptions.  We are getting new ones.
-                        mConnections.remove(b);
-
-                        final ConnectionRecord connection = new ConnectionRecord();
-                        connection.pkg = pkg;
-                        connection.rootHints = rootHints;
-                        connection.callbacks = callbacks;
-
-                        connection.root = MediaBrowserService.this.onGetRoot(pkg, uid, rootHints);
-
-                        // If they didn't return something, don't allow this client.
-                        if (connection.root == null) {
-                            Log.i(TAG, "No root for client " + pkg + " from service "
-                                    + getClass().getName());
-                            try {
-                                callbacks.onConnectFailed();
-                            } catch (RemoteException ex) {
-                                Log.w(TAG, "Calling onConnectFailed() failed. Ignoring. "
-                                        + "pkg=" + pkg);
-                            }
-                        } else {
-                            try {
-                                mConnections.put(b, connection);
-                                if (mSession != null) {
-                                    callbacks.onConnect(connection.root.getRootId(),
-                                            mSession, connection.root.getExtras());
-                                }
-                            } catch (RemoteException ex) {
-                                Log.w(TAG, "Calling onConnect() failed. Dropping client. "
-                                        + "pkg=" + pkg);
-                                mConnections.remove(b);
-                            }
-                        }
-                    }
-                });
-        }
-
-        @Override
-        public void disconnect(final IMediaBrowserServiceCallbacks callbacks) {
-            mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        final IBinder b = callbacks.asBinder();
-
-                        // Clear out the old subscriptions.  We are getting new ones.
-                        final ConnectionRecord old = mConnections.remove(b);
-                        if (old != null) {
-                            // TODO
-                        }
-                    }
-                });
-        }
-
-
-        @Override
-        public void addSubscription(final String id, final IMediaBrowserServiceCallbacks callbacks) {
-            mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        final IBinder b = callbacks.asBinder();
-
-                        // 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 id="
-                                + id);
-                            return;
-                        }
-
-                        MediaBrowserService.this.addSubscription(id, connection);
-                    }
-                });
-        }
-
-        @Override
-        public void removeSubscription(final String id,
-                final IMediaBrowserServiceCallbacks callbacks) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    final IBinder b = callbacks.asBinder();
-
-                    ConnectionRecord connection = mConnections.get(b);
-                    if (connection == null) {
-                        Log.w(TAG, "removeSubscription for callback that isn't registered id="
-                                + id);
-                        return;
-                    }
-                    if (!connection.subscriptions.remove(id)) {
-                        Log.w(TAG, "removeSubscription called for " + id
-                                + " which is not subscribed");
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void getMediaItem(final String mediaId, final ResultReceiver receiver) {
-            if (TextUtils.isEmpty(mediaId) || receiver == null) {
-                return;
-            }
-
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    performLoadItem(mediaId, receiver);
-                }
-            });
-        }
-    }
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        mBinder = new ServiceBinder();
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        if (SERVICE_INTERFACE.equals(intent.getAction())) {
-            return mBinder;
-        }
-        return null;
-    }
-
-    @Override
-    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-    }
-
-    /**
-     * 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.
-     * </p>
-     *
-     * @param clientPackageName The package name of the application which is
-     *            requesting access to browse media.
-     * @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 id for browsing, or null if none. The contents of this
-     *            bundle may affect the information returned when browsing.
-     * @return The {@link BrowserRoot} for accessing this app's content or null.
-     */
-    public abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
-            int clientUid, @Nullable Bundle rootHints);
-
-    /**
-     * Called to get information about the children of a media item.
-     * <p>
-     * Implementations must call {@link Result#sendResult result.sendResult}
-     * with the list of children. If loading the children will be an expensive
-     * operation that should be performed on another thread,
-     * {@link Result#detach result.detach} may be called before returning from
-     * this function, and then {@link Result#sendResult result.sendResult}
-     * called when the loading is complete.
-     *
-     * @param parentId The id of the parent media item whose children are to be
-     *            queried.
-     * @param result The Result to send the list of children to, or null if the
-     *            id is invalid.
-     */
-    public abstract void onLoadChildren(@NonNull String parentId,
-            @NonNull Result<List<MediaBrowser.MediaItem>> result);
-
-    /**
-     * Called to get information about a specific media item.
-     * <p>
-     * Implementations must call {@link Result#sendResult result.sendResult}. If
-     * loading the item will be an expensive operation {@link Result#detach
-     * result.detach} may be called before returning from this function, and
-     * then {@link Result#sendResult result.sendResult} called when the item has
-     * been loaded.
-     * <p>
-     * The default implementation sends a null result.
-     *
-     * @param itemId The id for the specific
-     *            {@link android.media.browse.MediaBrowser.MediaItem}.
-     * @param result The Result to send the item to, or null if the id is
-     *            invalid.
-     */
-    public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
-        result.sendResult(null);
-    }
-
-    /**
-     * Call to set the media session.
-     * <p>
-     * This should be called as soon as possible during the service's startup.
-     * It may only be called once.
-     *
-     * @param token The token for the service's {@link MediaSession}.
-     */
-    public void setSessionToken(final MediaSessionCompat.Token token) {
-        if (token == null) {
-            throw new IllegalArgumentException("Session token may not be null.");
-        }
-        if (mSession != null) {
-            throw new IllegalStateException("The session token has already been set.");
-        }
-        mSession = token;
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                for (IBinder key : mConnections.keySet()) {
-                    ConnectionRecord connection = mConnections.get(key);
-                    try {
-                        connection.callbacks.onConnect(connection.root.getRootId(), token,
-                                connection.root.getExtras());
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Connection for " + connection.pkg + " is no longer valid.");
-                        mConnections.remove(key);
-                    }
-                }
-            }
-        });
-    }
-
-    /**
-     * Gets the session token, or null if it has not yet been created
-     * or if it has been destroyed.
-     */
-    public @Nullable MediaSessionCompat.Token getSessionToken() {
-        return mSession;
-    }
-
-    /**
-     * Notifies all connected media browsers that the children of
-     * the specified parent id have changed in some way.
-     * This will cause browsers to fetch subscribed content again.
-     *
-     * @param parentId The id of the parent media item whose
-     * children changed.
-     */
-    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(parentId)) {
-                        performLoadChildren(parentId, connection);
-                    }
-                }
-            }
-        });
-    }
-
-    /**
-     * Return whether the given package is one of the ones that is owned by the uid.
-     */
-    private boolean isValidPackage(String pkg, int uid) {
-        if (pkg == null) {
-            return false;
-        }
-        final PackageManager pm = getPackageManager();
-        final String[] packages = pm.getPackagesForUid(uid);
-        final int N = packages.length;
-        for (int i=0; i<N; i++) {
-            if (packages[i].equals(pkg)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Save the subscription and if it is a new subscription send the results.
-     */
-    private void addSubscription(String id, ConnectionRecord connection) {
-        // Save the subscription
-        connection.subscriptions.add(id);
-
-        // send the results
-        performLoadChildren(id, connection);
-    }
-
-    /**
-     * Call onLoadChildren and then send the results back to the connection.
-     * <p>
-     * Callers must make sure that this connection is still connected.
-     */
-    private void performLoadChildren(final String parentId, final ConnectionRecord connection) {
-        final Result<List<MediaBrowser.MediaItem>> result
-                = new Result<List<MediaBrowser.MediaItem>>(parentId) {
-            @Override
-            void onResultSent(List<MediaBrowser.MediaItem> list) {
-                if (list == null) {
-                    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 + " id=" + parentId);
-                    }
-                    return;
-                }
-
-                try {
-                    connection.callbacks.onLoadChildren(parentId, list);
-                } catch (RemoteException ex) {
-                    // The other side is in the process of crashing.
-                    Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
-                            + " package=" + connection.pkg);
-                }
-            }
-        };
-
-        onLoadChildren(parentId, result);
-
-        if (!result.isDone()) {
-            throw new IllegalStateException("onLoadChildren must call detach() or sendResult()"
-                    + " before returning for package=" + connection.pkg + " id=" + parentId);
-        }
-    }
-
-    private void performLoadItem(String itemId, final ResultReceiver receiver) {
-        final Result<MediaBrowser.MediaItem> result =
-                new Result<MediaBrowser.MediaItem>(itemId) {
-            @Override
-            void onResultSent(MediaBrowser.MediaItem item) {
-                Bundle bundle = new Bundle();
-                bundle.putParcelable(KEY_MEDIA_ITEM, item);
-                receiver.send(0, bundle);
-            }
-        };
-
-        MediaBrowserService.this.onLoadItem(itemId, result);
-
-        if (!result.isDone()) {
-            throw new IllegalStateException("onLoadItem must call detach() or sendResult()"
-                    + " before returning for id=" + itemId);
-        }
-    }
-
-    /**
-     * Contains information that the browser service needs to send to the client
-     * when first connected.
-     */
-    public static final class BrowserRoot {
-        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 brwoser service.
-         */
-        public Bundle getExtras() {
-            return mExtras;
-        }
-    }
-}
diff --git a/v4/java/android/support/v4/os/IResultReceiver.aidl b/v4/java/android/support/v4/os/IResultReceiver.aidl
deleted file mode 100644
index 5e5e626..0000000
--- a/v4/java/android/support/v4/os/IResultReceiver.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* //device/java/android/android/app/IActivityPendingResult.aidl
-**
-** Copyright 2015, 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.support.v4.os;
-
-import android.os.Bundle;
-
-/** @hide */
-oneway interface IResultReceiver {
-    void send(int resultCode, in Bundle resultData);
-}
diff --git a/v4/java/android/support/v4/os/ResultReceiver.aidl b/v4/java/android/support/v4/os/ResultReceiver.aidl
deleted file mode 100644
index 4a8268c..0000000
--- a/v4/java/android/support/v4/os/ResultReceiver.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/os/ParcelFileDescriptor.aidl
-**
-** Copyright 2015, 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.support.v4.os;
-
-parcelable ResultReceiver;
diff --git a/v4/java/android/support/v4/os/ResultReceiver.java b/v4/java/android/support/v4/os/ResultReceiver.java
deleted file mode 100644
index f0dc001..0000000
--- a/v4/java/android/support/v4/os/ResultReceiver.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2015 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.support.v4.os;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.support.v4.os.IResultReceiver;
-
-/**
- * Generic interface for receiving a callback result from someone.  Use this
- * by creating a subclass and implement {@link #onReceiveResult}, which you can
- * then pass to others and send through IPC, and receive results they
- * supply with {@link #send}.
- *
- * <p>Note: the implementation underneath is just a simple wrapper around
- * a {@link Binder} that is used to perform the communication.  This means
- * semantically you should treat it as such: this class does not impact process
- * lifecycle management (you must be using some higher-level component to tell
- * the system that your process needs to continue running), the connection will
- * break if your process goes away for any reason, etc.</p>
- * @hide
- */
-public class ResultReceiver implements Parcelable {
-    final boolean mLocal;
-    final Handler mHandler;
-    
-    IResultReceiver mReceiver;
-    
-    class MyRunnable implements Runnable {
-        final int mResultCode;
-        final Bundle mResultData;
-        
-        MyRunnable(int resultCode, Bundle resultData) {
-            mResultCode = resultCode;
-            mResultData = resultData;
-        }
-        
-        public void run() {
-            onReceiveResult(mResultCode, mResultData);
-        }
-    }
-    
-    class MyResultReceiver extends IResultReceiver.Stub {
-        public void send(int resultCode, Bundle resultData) {
-            if (mHandler != null) {
-                mHandler.post(new MyRunnable(resultCode, resultData));
-            } else {
-                onReceiveResult(resultCode, resultData);
-            }
-        }
-    }
-    
-    /**
-     * Create a new ResultReceive to receive results.  Your
-     * {@link #onReceiveResult} method will be called from the thread running
-     * <var>handler</var> if given, or from an arbitrary thread if null.
-     */
-    public ResultReceiver(Handler handler) {
-        mLocal = true;
-        mHandler = handler;
-    }
-    
-    /**
-     * Deliver a result to this receiver.  Will call {@link #onReceiveResult},
-     * always asynchronously if the receiver has supplied a Handler in which
-     * to dispatch the result.
-     * @param resultCode Arbitrary result code to deliver, as defined by you.
-     * @param resultData Any additional data provided by you.
-     */
-    public void send(int resultCode, Bundle resultData) {
-        if (mLocal) {
-            if (mHandler != null) {
-                mHandler.post(new MyRunnable(resultCode, resultData));
-            } else {
-                onReceiveResult(resultCode, resultData);
-            }
-            return;
-        }
-        
-        if (mReceiver != null) {
-            try {
-                mReceiver.send(resultCode, resultData);
-            } catch (RemoteException e) {
-            }
-        }
-    }
-    
-    /**
-     * Override to receive results delivered to this object.
-     * 
-     * @param resultCode Arbitrary result code delivered by the sender, as
-     * defined by the sender.
-     * @param resultData Any additional data provided by the sender.
-     */
-    protected void onReceiveResult(int resultCode, Bundle resultData) {
-    }
-    
-    public int describeContents() {
-        return 0;
-    }
-
-    public void writeToParcel(Parcel out, int flags) {
-        synchronized (this) {
-            if (mReceiver == null) {
-                mReceiver = new MyResultReceiver();
-            }
-            out.writeStrongBinder(mReceiver.asBinder());
-        }
-    }
-
-    ResultReceiver(Parcel in) {
-        mLocal = false;
-        mHandler = null;
-        mReceiver = IResultReceiver.Stub.asInterface(in.readStrongBinder());
-    }
-    
-    public static final Parcelable.Creator<ResultReceiver> CREATOR
-            = new Parcelable.Creator<ResultReceiver>() {
-        public ResultReceiver createFromParcel(Parcel in) {
-            return new ResultReceiver(in);
-        }
-        public ResultReceiver[] newArray(int size) {
-            return new ResultReceiver[size];
-        }
-    };
-}