/*
 * 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.Message;
import android.os.Messenger;
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.app.BundleCompat;
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.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static android.support.v4.media.MediaBrowserProtocol.*;

/**
 * Browses media content offered by a {@link MediaBrowserServiceCompat}.
 * <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 MediaBrowserCompat {
    private static final String TAG = "MediaBrowserCompat";

    private final MediaBrowserImpl mImpl;

    /**
     * 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 MediaBrowserCompat(Context context, ComponentName serviceComponent,
            ConnectionCallback callback, Bundle rootHints) {
        if (android.os.Build.VERSION.SDK_INT >= 23) {
            mImpl = new MediaBrowserImplApi23(context, serviceComponent, callback, rootHints);
        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
            mImpl = new MediaBrowserImplApi21(context, serviceComponent, callback, rootHints);
        } else {
            mImpl = new MediaBrowserImplBase(context, serviceComponent, callback, 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() {
        mImpl.connect();
    }

    /**
     * Disconnects from the media browse service.
     * After this, no more callbacks will be received.
     */
    public void disconnect() {
        mImpl.disconnect();
    }

    /**
     * Returns whether the browser is connected to the service.
     */
    public boolean isConnected() {
        return mImpl.isConnected();
    }

    /**
     * Gets the service component that the media browser is connected to.
     */
    public @NonNull
    ComponentName getServiceComponent() {
        return mImpl.getServiceComponent();
    }

    /**
     * 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() {
        return mImpl.getRoot();
    }

    /**
     * Gets any extras for the media service.
     *
     * @throws IllegalStateException if not connected.
     */
    public @Nullable
    Bundle getExtras() {
        return mImpl.getExtras();
    }

    /**
     * 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() {
        return mImpl.getSessionToken();
    }

    /**
     * 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) {
        mImpl.subscribe(parentId, callback);
    }

    /**
     * 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) {
        mImpl.unsubscribe(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) {
        mImpl.getItem(mediaId, cb);
    }

    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 {
        final Object mConnectionCallbackObj;

        public ConnectionCallback() {
            if (android.os.Build.VERSION.SDK_INT >= 21) {
                mConnectionCallbackObj =
                        MediaBrowserCompatApi21.createConnectionCallback(new StubApi21());
            } else {
                mConnectionCallbackObj = null;
            }
        }

        /**
         * Invoked after {@link MediaBrowserCompat#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() {
        }


        private class StubApi21 implements MediaBrowserCompatApi21.ConnectionCallback {
            @Override
            public void onConnected() {
                ConnectionCallback.this.onConnected();
            }

            @Override
            public void onConnectionSuspended() {
                ConnectionCallback.this.onConnectionSuspended();
            }

            @Override
            public void onConnectionFailed() {
                ConnectionCallback.this.onConnectionFailed();
            }
        }
    }

    /**
     * Callbacks for subscription related events.
     */
    public static abstract class SubscriptionCallback {
        final Object mSubscriptionCallbackObj;

        public SubscriptionCallback() {
            if (android.os.Build.VERSION.SDK_INT >= 21) {
                mSubscriptionCallbackObj =
                        MediaBrowserCompatApi21.createSubscriptionCallback(new StubApi21());
            } else {
                mSubscriptionCallbackObj = null;
            }
        }

        /**
         * 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 MediaBrowserCompat#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) {
        }

        private class StubApi21 implements MediaBrowserCompatApi21.SubscriptionCallback {
            @Override
            public void onChildrenLoaded(@NonNull String parentId, @NonNull List<Parcel> children) {
                List<MediaBrowserCompat.MediaItem> mediaItems = null;
                if (children != null) {
                    mediaItems = new ArrayList<>();
                    for (Parcel parcel : children) {
                        parcel.setDataPosition(0);
                        mediaItems.add(
                                MediaBrowserCompat.MediaItem.CREATOR.createFromParcel(parcel));
                        parcel.recycle();
                    }
                }
                SubscriptionCallback.this.onChildrenLoaded(parentId, mediaItems);
            }

            @Override
            public void onError(@NonNull String parentId) {
                SubscriptionCallback.this.onError(parentId);
            }
        }
    }

    /**
     * Callback for receiving the result of {@link #getItem}.
     */
    public static abstract class ItemCallback {
        final Object mItemCallbackObj;

        public ItemCallback() {
            if (android.os.Build.VERSION.SDK_INT >= 23) {
                mItemCallbackObj = MediaBrowserCompatApi23.createItemCallback(new StubApi23());
            } else {
                mItemCallbackObj = null;
            }
        }

        /**
         * 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) {
        }

        private class StubApi23 implements MediaBrowserCompatApi23.ItemCallback {
            @Override
            public void onItemLoaded(Parcel itemParcel) {
                itemParcel.setDataPosition(0);
                MediaItem item = MediaBrowserCompat.MediaItem.CREATOR.createFromParcel(itemParcel);
                itemParcel.recycle();
                ItemCallback.this.onItemLoaded(item);
            }

            @Override
            public void onError(@NonNull String itemId) {
                ItemCallback.this.onError(itemId);
            }
        }
    }

    interface MediaBrowserImpl {
        void connect();
        void disconnect();
        boolean isConnected();
        ComponentName getServiceComponent();
        @NonNull String getRoot();
        @Nullable Bundle getExtras();
        @NonNull MediaSessionCompat.Token getSessionToken();
        void subscribe(@NonNull String parentId, @NonNull SubscriptionCallback callback);
        void unsubscribe(@NonNull String parentId);
        void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb);
    }

    static class MediaBrowserImplBase implements MediaBrowserImpl {
        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 CallbackHandler mHandler = new CallbackHandler();
        private final ArrayMap<String,Subscription> mSubscriptions = new ArrayMap<>();

        private int mState = CONNECT_STATE_DISCONNECTED;
        private MediaServiceConnection mServiceConnection;
        private ServiceBinderWrapper mServiceBinderWrapper;
        private Messenger mCallbacksMessenger;
        private String mRootId;
        private MediaSessionCompat.Token mMediaSessionToken;
        private Bundle mExtras;

        public MediaBrowserImplBase(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;
        }

        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 (mServiceBinderWrapper != null) {
                throw new RuntimeException("mServiceBinderWrapper should be null. Instead it is "
                        + mServiceBinderWrapper);
            }
            if (mCallbacksMessenger != null) {
                throw new RuntimeException("mCallbacksMessenger should be null. Instead it is "
                        + mCallbacksMessenger);
            }

            mState = CONNECT_STATE_CONNECTING;

            final Intent intent = new Intent(MediaBrowserServiceCompat.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();
            }
        }

        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 (mCallbacksMessenger != null) {
                try {
                    mServiceBinderWrapper.disconnect();
                } 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;
            mServiceBinderWrapper = null;
            mCallbacksMessenger = null;
            mRootId = null;
            mMediaSessionToken = null;
        }

        public boolean isConnected() {
            return mState == CONNECT_STATE_CONNECTED;
        }

        public @NonNull
        ComponentName getServiceComponent() {
            if (!isConnected()) {
                throw new IllegalStateException("getServiceComponent() called while not connected" +
                        " (state=" + mState + ")");
            }
            return mServiceComponent;
        }

        public @NonNull String getRoot() {
            if (!isConnected()) {
                throw new IllegalStateException("getRoot() called while not connected"
                        + "(state=" + getStateLabel(mState) + ")");
            }
            return mRootId;
        }

        public @Nullable
        Bundle getExtras() {
            if (!isConnected()) {
                throw new IllegalStateException("getExtras() called while not connected (state="
                        + getStateLabel(mState) + ")");
            }
            return mExtras;
        }

        public @NonNull MediaSessionCompat.Token getSessionToken() {
            if (!isConnected()) {
                throw new IllegalStateException("getSessionToken() called while not connected"
                        + "(state=" + mState + ")");
            }
            return mMediaSessionToken;
        }

        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 {
                    mServiceBinderWrapper.addSubscription(parentId);
                } 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);
                }
            }
        }

        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 {
                    mServiceBinderWrapper.removeSubscription(parentId);
                } 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);
                }
            }
        }

        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(MediaBrowserServiceCompat.KEY_MEDIA_ITEM)) {
                        cb.onError(mediaId);
                        return;
                    }
                    Parcelable item =
                            resultData.getParcelable(MediaBrowserServiceCompat.KEY_MEDIA_ITEM);
                    if (!(item instanceof MediaItem)) {
                        cb.onError(mediaId);
                        return;
                    }
                    cb.onItemLoaded((MediaItem)item);
                }
            };
            try {
                mServiceBinderWrapper.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 Messenger callback, final String root,
                final MediaSessionCompat.Token session, final Bundle extra) {
            // 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 {
                    mServiceBinderWrapper.addSubscription(id);
                } 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 Messenger callback) {
            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 Messenger callback, final String parentId,
                final List list) {
            // 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(Messenger callback, String funcName) {
            if (mCallbacksMessenger != callback) {
                if (mState != CONNECT_STATE_DISCONNECTED) {
                    Log.i(TAG, funcName + " for " + mServiceComponent + " with mCallbacksMessenger="
                            + mCallbacksMessenger + " this=" + this);
                }
                return false;
            }
            return true;
        }

        /**
         * Log internal state.
         * @hide
         */
        void dump() {
            Log.d(TAG, "MediaBrowserCompat...");
            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, "  mServiceBinderWrapper=" + mServiceBinderWrapper);
            Log.d(TAG, "  mCallbacksMessenger=" + mCallbacksMessenger);
            Log.d(TAG, "  mRootId=" + mRootId);
            Log.d(TAG, "  mMediaSessionToken=" + mMediaSessionToken);
        }

        private class ServiceBinderWrapper {
            private Messenger mMessenger;

            public ServiceBinderWrapper(IBinder target) {
                mMessenger = new Messenger(target);
            }

            void connect() throws RemoteException {
                sendRequest(CLIENT_MSG_CONNECT, mContext.getPackageName(), mRootHints,
                        mCallbacksMessenger);
            }

            void disconnect() throws RemoteException {
                sendRequest(CLIENT_MSG_DISCONNECT, null, null, mCallbacksMessenger);
            }

            void addSubscription(String parentId) throws RemoteException {
                sendRequest(CLIENT_MSG_ADD_SUBSCRIPTION, parentId, null, mCallbacksMessenger);
            }

            void removeSubscription(String parentId) throws RemoteException {
                sendRequest(CLIENT_MSG_REMOVE_SUBSCRIPTION, parentId, null, mCallbacksMessenger);
            }

            void getMediaItem(String mediaId, ResultReceiver receiver) throws RemoteException {
                Bundle data = new Bundle();
                data.putParcelable(SERVICE_DATA_RESULT_RECEIVER, receiver);
                sendRequest(CLIENT_MSG_GET_MEDIA_ITEM, mediaId, data, null);
            }

            private void sendRequest(int what, Object obj, Bundle data, Messenger cbMessenger)
                    throws RemoteException {
                Message msg = Message.obtain();
                msg.what = what;
                msg.arg1 = CLIENT_VERSION_CURRENT;
                msg.obj = obj;
                msg.setData(data);
                msg.replyTo = cbMessenger;
                mMessenger.send(msg);
            }
        }

        /**
         * 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
                mServiceBinderWrapper = new ServiceBinderWrapper(binder);

                // We make a new mServiceCallbacks each time we connect so that we can drop
                // responses from previous connections.
                mCallbacksMessenger = new Messenger(mHandler);

                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();
                    }
                    mServiceBinderWrapper.connect();
                } 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
                mServiceBinderWrapper = null;
                mCallbacksMessenger = 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;
            }
        }

        private class CallbackHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                Bundle data = msg.getData();
                switch (msg.what) {
                    case SERVICE_MSG_ON_CONNECT:
                        onServiceConnected(mCallbacksMessenger, (String) msg.obj,
                                (MediaSessionCompat.Token) data.getParcelable(
                                        SERVICE_DATA_MEDIA_SESSION_TOKEN),
                                data.getBundle(SERVICE_DATA_EXTRAS));
                        break;
                    case SERVICE_MSG_ON_CONNECT_FAILED:
                        onConnectionFailed(mCallbacksMessenger);
                        break;
                    case SERVICE_MSG_ON_LOAD_CHILDREN:
                        onLoadChildren(mCallbacksMessenger,  (String) msg.obj,
                                data.getParcelableArrayList(SERVICE_DATA_MEDIA_ITEM_LIST));
                        break;
                    default:
                        Log.w(TAG, "Unhandled message: " + msg
                                + "\n  Client version: " + CLIENT_VERSION_CURRENT
                                + "\n  Service version: " + msg.arg1);
                }
            }
        }

        private static class Subscription {
            final String id;
            SubscriptionCallback callback;

            Subscription(String id) {
                this.id = id;
            }
        }
    }

    static class MediaBrowserImplApi21 implements MediaBrowserImpl {
        protected Object mBrowserObj;
        protected Messenger mMessenger;
        protected Handler mHandler = new Handler();

        public MediaBrowserImplApi21(Context context, ComponentName serviceComponent,
                ConnectionCallback callback, Bundle rootHints) {
            mBrowserObj = MediaBrowserCompatApi21.createBrowser(context, serviceComponent,
                    callback.mConnectionCallbackObj, rootHints);
        }

        @Override
        public void connect() {
            MediaBrowserCompatApi21.connect(mBrowserObj);
        }

        @Override
        public void disconnect() {
            MediaBrowserCompatApi21.disconnect(mBrowserObj);
        }

        @Override
        public boolean isConnected() {
            return MediaBrowserCompatApi21.isConnected(mBrowserObj);
        }

        @Override
        public ComponentName getServiceComponent() {
            return MediaBrowserCompatApi21.getServiceComponent(mBrowserObj);
        }

        @NonNull
        @Override
        public String getRoot() {
            return MediaBrowserCompatApi21.getRoot(mBrowserObj);
        }

        @Nullable
        @Override
        public Bundle getExtras() {
            return MediaBrowserCompatApi21.getExtras(mBrowserObj);
        }

        @NonNull
        @Override
        public MediaSessionCompat.Token getSessionToken() {
            return MediaSessionCompat.Token.fromToken(
                    MediaBrowserCompatApi21.getSessionToken(mBrowserObj));
        }

        @Override
        public void subscribe(@NonNull String parentId, @NonNull SubscriptionCallback callback) {
            MediaBrowserCompatApi21.subscribe(
                    mBrowserObj, parentId, callback.mSubscriptionCallbackObj);
        }

        @Override
        public void unsubscribe(@NonNull String parentId) {
            MediaBrowserCompatApi21.unsubscribe(mBrowserObj, parentId);
        }

        @Override
        public void getItem(@NonNull final 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 (!MediaBrowserCompatApi21.isConnected(mBrowserObj)) {
                Log.i(TAG, "Not connected, unable to retrieve the MediaItem.");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        cb.onError(mediaId);
                    }
                });
                return;
            }
            if (mMessenger == null) {
                Bundle extras = MediaBrowserCompatApi21.getExtras(mBrowserObj);
                IBinder serviceBinder = BundleCompat.getBinder(extras, EXTRA_MESSENGER_BINDER);
                if (serviceBinder != null) {
                    mMessenger = new Messenger(serviceBinder);
                }
            }
            if (mMessenger == null) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        // Default framework implementation.
                        cb.onItemLoaded(null);
                    }
                });
                return;
            }
            ResultReceiver receiver = new ResultReceiver(mHandler) {
                @Override
                protected void onReceiveResult(int resultCode, Bundle resultData) {
                    if (resultCode != 0 || resultData == null
                            || !resultData.containsKey(MediaBrowserServiceCompat.KEY_MEDIA_ITEM)) {
                        cb.onError(mediaId);
                        return;
                    }
                    Parcelable item =
                            resultData.getParcelable(MediaBrowserServiceCompat.KEY_MEDIA_ITEM);
                    if (!(item instanceof MediaItem)) {
                        cb.onError(mediaId);
                        return;
                    }
                    cb.onItemLoaded((MediaItem)item);
                }
            };
            try {
                Bundle data = new Bundle();
                data.putParcelable(SERVICE_DATA_RESULT_RECEIVER, receiver);
                sendRequest(CLIENT_MSG_GET_MEDIA_ITEM, mediaId, data, null);
            } catch (RemoteException e) {
                Log.i(TAG, "Remote error getting media item.");
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        cb.onError(mediaId);
                    }
                });
            }
        }

        private void sendRequest(int what, Object obj, Bundle data, Messenger cbMessenger)
                throws RemoteException {
            Message msg = Message.obtain();
            msg.what = what;
            msg.arg1 = CLIENT_VERSION_CURRENT;
            msg.obj = obj;
            msg.setData(data);
            msg.replyTo = cbMessenger;
            mMessenger.send(msg);
        }
    }

    static class MediaBrowserImplApi23 extends MediaBrowserImplApi21 {
        public MediaBrowserImplApi23(Context context, ComponentName serviceComponent,
                ConnectionCallback callback, Bundle rootHints) {
            super(context, serviceComponent, callback, rootHints);
        }

        @Override
        public void getItem(@NonNull String mediaId, @NonNull ItemCallback cb) {
            MediaBrowserCompatApi23.getItem(mBrowserObj, mediaId, cb.mItemCallbackObj);
        }
    }
}
