/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.media;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_ADD_SUBSCRIPTION;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_CONNECT;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_DISCONNECT;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_GET_MEDIA_ITEM;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_REGISTER_CALLBACK_MESSENGER;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_REMOVE_SUBSCRIPTION;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_SEARCH;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_SEND_CUSTOM_ACTION;
import static androidx.media.MediaBrowserProtocol.CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER;
import static androidx.media.MediaBrowserProtocol.DATA_CALLBACK_TOKEN;
import static androidx.media.MediaBrowserProtocol.DATA_CALLING_UID;
import static androidx.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION;
import static androidx.media.MediaBrowserProtocol.DATA_CUSTOM_ACTION_EXTRAS;
import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_ITEM_ID;
import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_ITEM_LIST;
import static androidx.media.MediaBrowserProtocol.DATA_MEDIA_SESSION_TOKEN;
import static androidx.media.MediaBrowserProtocol.DATA_OPTIONS;
import static androidx.media.MediaBrowserProtocol.DATA_PACKAGE_NAME;
import static androidx.media.MediaBrowserProtocol.DATA_RESULT_RECEIVER;
import static androidx.media.MediaBrowserProtocol.DATA_ROOT_HINTS;
import static androidx.media.MediaBrowserProtocol.DATA_SEARCH_EXTRAS;
import static androidx.media.MediaBrowserProtocol.DATA_SEARCH_QUERY;
import static androidx.media.MediaBrowserProtocol.EXTRA_CLIENT_VERSION;
import static androidx.media.MediaBrowserProtocol.EXTRA_MESSENGER_BINDER;
import static androidx.media.MediaBrowserProtocol.EXTRA_SERVICE_VERSION;
import static androidx.media.MediaBrowserProtocol.EXTRA_SESSION_BINDER;
import static androidx.media.MediaBrowserProtocol.SERVICE_MSG_ON_CONNECT;
import static androidx.media.MediaBrowserProtocol.SERVICE_MSG_ON_CONNECT_FAILED;
import static androidx.media.MediaBrowserProtocol.SERVICE_MSG_ON_LOAD_CHILDREN;
import static androidx.media.MediaBrowserProtocol.SERVICE_VERSION_CURRENT;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.Build;
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.RemoteException;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.session.IMediaSession;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.os.ResultReceiver;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.collection.ArrayMap;
import androidx.core.app.BundleCompat;
import androidx.core.util.Pair;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
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 MediaSessionCompat}.
 * </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=".MyMediaBrowserServiceCompat"
 *          android:label="&#64;string/service_name" >
 *     &lt;intent-filter>
 *         &lt;action android:name="android.media.browse.MediaBrowserService" />
 *     &lt;/intent-filter>
 * &lt;/service>
 * </pre>
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For information about building your media application, read the
 * <a href="{@docRoot}guide/topics/media-apps/index.html">Media Apps</a> developer guide.</p>
 * </div>
 */
public abstract class MediaBrowserServiceCompat extends Service {
    static final String TAG = "MBServiceCompat";
    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private static final float EPSILON = 0.00001f;

    private MediaBrowserServiceImpl mImpl;

    /**
     * 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
     */
    @RestrictTo(LIBRARY)
    public static final String KEY_MEDIA_ITEM = "media_item";

    /**
     * A key for passing the list of MediaItems to the ResultReceiver in search.
     *
     * @hide
     */
    @RestrictTo(LIBRARY)
    public static final String KEY_SEARCH_RESULTS = "search_results";

    static final int RESULT_FLAG_OPTION_NOT_HANDLED = 1 << 0;
    static final int RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED = 1 << 1;
    static final int RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED = 1 << 2;

    /**
     * @hide
     */
    @RestrictTo(LIBRARY)
    public static final int RESULT_ERROR = -1;
    /**
     * @hide
     */
    @RestrictTo(LIBRARY)
    public static final int RESULT_OK = 0;

    /**
     * @hide
     */
    @RestrictTo(LIBRARY)
    public static final int RESULT_PROGRESS_UPDATE = 1;

    /** @hide */
    @RestrictTo(LIBRARY)
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag=true, value = { RESULT_FLAG_OPTION_NOT_HANDLED,
            RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED, RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED })
    private @interface ResultFlags { }

    final ArrayMap<IBinder, ConnectionRecord> mConnections = new ArrayMap<>();
    ConnectionRecord mCurConnection;
    final ServiceHandler mHandler = new ServiceHandler();
    MediaSessionCompat.Token mSession;

    interface MediaBrowserServiceImpl {
        void onCreate();
        IBinder onBind(Intent intent);
        void setSessionToken(MediaSessionCompat.Token token);
        void notifyChildrenChanged(final String parentId, final Bundle options);
        Bundle getBrowserRootHints();
    }

    class MediaBrowserServiceImplBase implements MediaBrowserServiceImpl {
        private Messenger mMessenger;

        @Override
        public void onCreate() {
            mMessenger = new Messenger(mHandler);
        }

        @Override
        public IBinder onBind(Intent intent) {
            if (SERVICE_INTERFACE.equals(intent.getAction())) {
                return mMessenger.getBinder();
            }
            return null;
        }

        @Override
        public void setSessionToken(final MediaSessionCompat.Token token) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Iterator<ConnectionRecord> iter = mConnections.values().iterator();
                    while (iter.hasNext()){
                        ConnectionRecord connection = iter.next();
                        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.");
                            iter.remove();
                        }
                    }
                }
            });
        }

        @Override
        public void notifyChildrenChanged(@NonNull final String parentId, final Bundle options) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    for (IBinder binder : mConnections.keySet()) {
                        ConnectionRecord connection = mConnections.get(binder);
                        List<Pair<IBinder, Bundle>> callbackList =
                                connection.subscriptions.get(parentId);
                        if (callbackList != null) {
                            for (Pair<IBinder, Bundle> callback : callbackList) {
                                if (MediaBrowserCompatUtils.hasDuplicatedItems(
                                        options, callback.second)) {
                                    performLoadChildren(parentId, connection, callback.second);
                                }
                            }
                        }
                    }
                }
            });
        }

        @Override
        public Bundle getBrowserRootHints() {
            if (mCurConnection == null) {
                throw new IllegalStateException("This should be called inside of onLoadChildren,"
                        + " onLoadItem or onSearch methods");
            }
            return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
        }
    }

    @RequiresApi(21)
    class MediaBrowserServiceImplApi21 implements MediaBrowserServiceImpl,
            MediaBrowserServiceCompatApi21.ServiceCompatProxy {
        final List<Bundle> mRootExtrasList = new ArrayList<>();
        Object mServiceObj;
        Messenger mMessenger;

        @Override
        public void onCreate() {
            mServiceObj = MediaBrowserServiceCompatApi21.createService(
                    MediaBrowserServiceCompat.this, this);
            MediaBrowserServiceCompatApi21.onCreate(mServiceObj);
        }

        @Override
        public IBinder onBind(Intent intent) {
            return MediaBrowserServiceCompatApi21.onBind(mServiceObj, intent);
        }

        @Override
        public void setSessionToken(final MediaSessionCompat.Token token) {
            mHandler.postOrRun(new Runnable() {
                @Override
                public void run() {
                    if (!mRootExtrasList.isEmpty()) {
                        IMediaSession extraBinder = token.getExtraBinder();
                        if (extraBinder != null) {
                            for (Bundle rootExtras : mRootExtrasList) {
                                BundleCompat.putBinder(rootExtras, EXTRA_SESSION_BINDER,
                                        extraBinder.asBinder());
                            }
                        }
                        mRootExtrasList.clear();
                    }
                    MediaBrowserServiceCompatApi21.setSessionToken(mServiceObj, token.getToken());
                }
            });
        }

        @Override
        public void notifyChildrenChanged(final String parentId, final Bundle options) {
            notifyChildrenChangedForFramework(parentId, options);
            notifyChildrenChangedForCompat(parentId, options);
        }

        @Override
        public Bundle getBrowserRootHints() {
            if (mMessenger == null) {
                // TODO: Handle getBrowserRootHints when connected with framework MediaBrowser.
                return null;
            }
            if (mCurConnection == null) {
                throw new IllegalStateException("This should be called inside of onLoadChildren,"
                        + " onLoadItem or onSearch methods");
            }
            return mCurConnection.rootHints == null ? null : new Bundle(mCurConnection.rootHints);
        }

        @Override
        public MediaBrowserServiceCompatApi21.BrowserRoot onGetRoot(
                String clientPackageName, int clientUid, Bundle rootHints) {
            Bundle rootExtras = null;
            if (rootHints != null && rootHints.getInt(EXTRA_CLIENT_VERSION, 0) != 0) {
                rootHints.remove(EXTRA_CLIENT_VERSION);
                mMessenger = new Messenger(mHandler);
                rootExtras = new Bundle();
                rootExtras.putInt(EXTRA_SERVICE_VERSION, SERVICE_VERSION_CURRENT);
                BundleCompat.putBinder(rootExtras, EXTRA_MESSENGER_BINDER, mMessenger.getBinder());
                if (mSession != null) {
                    IMediaSession extraBinder = mSession.getExtraBinder();
                    BundleCompat.putBinder(rootExtras, EXTRA_SESSION_BINDER,
                            extraBinder == null ? null : extraBinder.asBinder());
                } else {
                    mRootExtrasList.add(rootExtras);
                }
            }
            BrowserRoot root = MediaBrowserServiceCompat.this.onGetRoot(
                    clientPackageName, clientUid, rootHints);
            if (root == null) {
                return null;
            }
            if (rootExtras == null) {
                rootExtras = root.getExtras();
            } else if (root.getExtras() != null) {
                rootExtras.putAll(root.getExtras());
            }
            return new MediaBrowserServiceCompatApi21.BrowserRoot(
                    root.getRootId(), rootExtras);
        }

        @Override
        public void onLoadChildren(String parentId,
                final MediaBrowserServiceCompatApi21.ResultWrapper<List<Parcel>> resultWrapper) {
            final Result<List<MediaBrowserCompat.MediaItem>> result
                    = new Result<List<MediaBrowserCompat.MediaItem>>(parentId) {
                @Override
                void onResultSent(List<MediaBrowserCompat.MediaItem> list) {
                    List<Parcel> parcelList = null;
                    if (list != null) {
                        parcelList = new ArrayList<>();
                        for (MediaBrowserCompat.MediaItem item : list) {
                            Parcel parcel = Parcel.obtain();
                            item.writeToParcel(parcel, 0);
                            parcelList.add(parcel);
                        }
                    }
                    resultWrapper.sendResult(parcelList);
                }

                @Override
                public void detach() {
                    resultWrapper.detach();
                }
            };
            MediaBrowserServiceCompat.this.onLoadChildren(parentId, result);
        }

        void notifyChildrenChangedForFramework(final String parentId, final Bundle options) {
            MediaBrowserServiceCompatApi21.notifyChildrenChanged(mServiceObj, parentId);
        }

        void notifyChildrenChangedForCompat(final String parentId, final Bundle options) {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    for (IBinder binder : mConnections.keySet()) {
                        ConnectionRecord connection = mConnections.get(binder);
                        List<Pair<IBinder, Bundle>> callbackList =
                                connection.subscriptions.get(parentId);
                        if (callbackList != null) {
                            for (Pair<IBinder, Bundle> callback : callbackList) {
                                if (MediaBrowserCompatUtils.hasDuplicatedItems(
                                        options, callback.second)) {
                                    performLoadChildren(parentId, connection, callback.second);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    @RequiresApi(23)
    class MediaBrowserServiceImplApi23 extends MediaBrowserServiceImplApi21 implements
            MediaBrowserServiceCompatApi23.ServiceCompatProxy {
        @Override
        public void onCreate() {
            mServiceObj = MediaBrowserServiceCompatApi23.createService(
                    MediaBrowserServiceCompat.this, this);
            MediaBrowserServiceCompatApi21.onCreate(mServiceObj);
        }

        @Override
        public void onLoadItem(String itemId,
                final MediaBrowserServiceCompatApi21.ResultWrapper<Parcel> resultWrapper) {
            final Result<MediaBrowserCompat.MediaItem> result
                    = new Result<MediaBrowserCompat.MediaItem>(itemId) {
                @Override
                void onResultSent(MediaBrowserCompat.MediaItem item) {
                    if (item == null) {
                        resultWrapper.sendResult(null);
                    } else {
                        Parcel parcelItem = Parcel.obtain();
                        item.writeToParcel(parcelItem, 0);
                        resultWrapper.sendResult(parcelItem);
                    }
                }

                @Override
                public void detach() {
                    resultWrapper.detach();
                }
            };
            MediaBrowserServiceCompat.this.onLoadItem(itemId, result);
        }
    }

    @RequiresApi(26)
    class MediaBrowserServiceImplApi26 extends MediaBrowserServiceImplApi23 implements
            MediaBrowserServiceCompatApi26.ServiceCompatProxy {
        @Override
        public void onCreate() {
            mServiceObj = MediaBrowserServiceCompatApi26.createService(
                    MediaBrowserServiceCompat.this, this);
            MediaBrowserServiceCompatApi21.onCreate(mServiceObj);
        }

        @Override
        public void onLoadChildren(String parentId,
                final MediaBrowserServiceCompatApi26.ResultWrapper resultWrapper, Bundle options) {
            final Result<List<MediaBrowserCompat.MediaItem>> result
                    = new Result<List<MediaBrowserCompat.MediaItem>>(parentId) {
                @Override
                void onResultSent(List<MediaBrowserCompat.MediaItem> list) {
                    List<Parcel> parcelList = null;
                    if (list != null) {
                        parcelList = new ArrayList<>();
                        for (MediaBrowserCompat.MediaItem item : list) {
                            Parcel parcel = Parcel.obtain();
                            item.writeToParcel(parcel, 0);
                            parcelList.add(parcel);
                        }
                    }
                    resultWrapper.sendResult(parcelList, getFlags());
                }

                @Override
                public void detach() {
                    resultWrapper.detach();
                }
            };
            MediaBrowserServiceCompat.this.onLoadChildren(parentId, result, options);
        }

        @Override
        public Bundle getBrowserRootHints() {
            // If EXTRA_MESSENGER_BINDER is used, mCurConnection is not null.
            if (mCurConnection != null) {
                return mCurConnection.rootHints == null ? null
                        : new Bundle(mCurConnection.rootHints);
            }
            return MediaBrowserServiceCompatApi26.getBrowserRootHints(mServiceObj);
        }

        @Override
        void notifyChildrenChangedForFramework(final String parentId, final Bundle options) {
            if (options != null) {
                MediaBrowserServiceCompatApi26.notifyChildrenChanged(mServiceObj, parentId,
                        options);
            } else {
                super.notifyChildrenChangedForFramework(parentId, options);
            }
        }
    }

    private final class ServiceHandler extends Handler {
        private final ServiceBinderImpl mServiceBinderImpl = new ServiceBinderImpl();

        ServiceHandler() {
        }

        @Override
        public void handleMessage(Message msg) {
            Bundle data = msg.getData();
            switch (msg.what) {
                case CLIENT_MSG_CONNECT:
                    mServiceBinderImpl.connect(data.getString(DATA_PACKAGE_NAME),
                            data.getInt(DATA_CALLING_UID), data.getBundle(DATA_ROOT_HINTS),
                            new ServiceCallbacksCompat(msg.replyTo));
                    break;
                case CLIENT_MSG_DISCONNECT:
                    mServiceBinderImpl.disconnect(new ServiceCallbacksCompat(msg.replyTo));
                    break;
                case CLIENT_MSG_ADD_SUBSCRIPTION:
                    mServiceBinderImpl.addSubscription(data.getString(DATA_MEDIA_ITEM_ID),
                            BundleCompat.getBinder(data, DATA_CALLBACK_TOKEN),
                            data.getBundle(DATA_OPTIONS),
                            new ServiceCallbacksCompat(msg.replyTo));
                    break;
                case CLIENT_MSG_REMOVE_SUBSCRIPTION:
                    mServiceBinderImpl.removeSubscription(data.getString(DATA_MEDIA_ITEM_ID),
                            BundleCompat.getBinder(data, DATA_CALLBACK_TOKEN),
                            new ServiceCallbacksCompat(msg.replyTo));
                    break;
                case CLIENT_MSG_GET_MEDIA_ITEM:
                    mServiceBinderImpl.getMediaItem(data.getString(DATA_MEDIA_ITEM_ID),
                            (ResultReceiver) data.getParcelable(DATA_RESULT_RECEIVER),
                            new ServiceCallbacksCompat(msg.replyTo));
                    break;
                case CLIENT_MSG_REGISTER_CALLBACK_MESSENGER:
                    mServiceBinderImpl.registerCallbacks(new ServiceCallbacksCompat(msg.replyTo),
                            data.getBundle(DATA_ROOT_HINTS));
                    break;
                case CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER:
                    mServiceBinderImpl.unregisterCallbacks(new ServiceCallbacksCompat(msg.replyTo));
                    break;
                case CLIENT_MSG_SEARCH:
                    mServiceBinderImpl.search(data.getString(DATA_SEARCH_QUERY),
                            data.getBundle(DATA_SEARCH_EXTRAS),
                            (ResultReceiver) data.getParcelable(DATA_RESULT_RECEIVER),
                            new ServiceCallbacksCompat(msg.replyTo));
                    break;
                case CLIENT_MSG_SEND_CUSTOM_ACTION:
                    mServiceBinderImpl.sendCustomAction(data.getString(DATA_CUSTOM_ACTION),
                            data.getBundle(DATA_CUSTOM_ACTION_EXTRAS),
                            (ResultReceiver) data.getParcelable(DATA_RESULT_RECEIVER),
                            new ServiceCallbacksCompat(msg.replyTo));
                    break;
                default:
                    Log.w(TAG, "Unhandled message: " + msg
                            + "\n  Service version: " + SERVICE_VERSION_CURRENT
                            + "\n  Client version: " + msg.arg1);
            }
        }

        @Override
        public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
            // Binder.getCallingUid() in handleMessage will return the uid of this process.
            // In order to get the right calling uid, Binder.getCallingUid() should be called here.
            Bundle data = msg.getData();
            data.setClassLoader(MediaBrowserCompat.class.getClassLoader());
            data.putInt(DATA_CALLING_UID, Binder.getCallingUid());
            return super.sendMessageAtTime(msg, uptimeMillis);
        }

        public void postOrRun(Runnable r) {
            if (Thread.currentThread() == getLooper().getThread()) {
                r.run();
            } else {
                post(r);
            }
        }
    }

    /**
     * All the info about a connection.
     */
    private class ConnectionRecord implements IBinder.DeathRecipient {
        String pkg;
        Bundle rootHints;
        ServiceCallbacks callbacks;
        BrowserRoot root;
        HashMap<String, List<Pair<IBinder, Bundle>>> subscriptions = new HashMap<>();

        ConnectionRecord() {
        }

        @Override
        public void binderDied() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mConnections.remove(callbacks.asBinder());
                }
            });
        }
    }

    /**
     * Completion handler for asynchronous callback methods in {@link MediaBrowserServiceCompat}.
     * <p>
     * Each of the methods that takes one of these to send the result must call either
     * {@link #sendResult} or {@link #sendError} to respond to the caller with the given results or
     * errors. If those functions return without calling {@link #sendResult} or {@link #sendError},
     * they must instead call {@link #detach} before returning, and then may call
     * {@link #sendResult} or {@link #sendError} when they are done. If {@link #sendResult},
     * {@link #sendError}, or {@link #detach} is called twice, an exception will be thrown.
     * </p><p>
     * Those functions might also want to call {@link #sendProgressUpdate} to send interim updates
     * to the caller. If it is called after calling {@link #sendResult} or {@link #sendError}, an
     * exception will be thrown.
     * </p>
     *
     * @see MediaBrowserServiceCompat#onLoadChildren
     * @see MediaBrowserServiceCompat#onLoadItem
     * @see MediaBrowserServiceCompat#onSearch
     * @see MediaBrowserServiceCompat#onCustomAction
     */
    public static class Result<T> {
        private final Object mDebug;
        private boolean mDetachCalled;
        private boolean mSendResultCalled;
        private boolean mSendProgressUpdateCalled;
        private boolean mSendErrorCalled;
        private int mFlags;

        Result(Object debug) {
            mDebug = debug;
        }

        /**
         * Send the result back to the caller.
         */
        public void sendResult(T result) {
            if (mSendResultCalled || mSendErrorCalled) {
                throw new IllegalStateException("sendResult() called when either sendResult() or "
                        + "sendError() had already been called for: " + mDebug);
            }
            mSendResultCalled = true;
            onResultSent(result);
        }

        /**
         * Send an interim update to the caller. This method is supported only when it is used in
         * {@link #onCustomAction}.
         *
         * @param extras A bundle that contains extra data.
         */
        public void sendProgressUpdate(Bundle extras) {
            if (mSendResultCalled || mSendErrorCalled) {
                throw new IllegalStateException("sendProgressUpdate() called when either "
                        + "sendResult() or sendError() had already been called for: " + mDebug);
            }
            checkExtraFields(extras);
            mSendProgressUpdateCalled = true;
            onProgressUpdateSent(extras);
        }

        /**
         * Notify the caller of a failure. This is supported only when it is used in
         * {@link #onCustomAction}.
         *
         * @param extras A bundle that contains extra data.
         */
        public void sendError(Bundle extras) {
            if (mSendResultCalled || mSendErrorCalled) {
                throw new IllegalStateException("sendError() called when either sendResult() or "
                        + "sendError() had already been called for: " + mDebug);
            }
            mSendErrorCalled = true;
            onErrorSent(extras);
        }

        /**
         * 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);
            }
            if (mSendErrorCalled) {
                throw new IllegalStateException("detach() called when sendError() had already"
                        + " been called for: " + mDebug);
            }
            mDetachCalled = true;
        }

        boolean isDone() {
            return mDetachCalled || mSendResultCalled || mSendErrorCalled;
        }

        void setFlags(@ResultFlags int flags) {
            mFlags = flags;
        }

        int getFlags() {
            return mFlags;
        }

        /**
         * Called when the result is sent, after assertions about not being called twice have
         * happened.
         */
        void onResultSent(T result) {
        }

        /**
         * Called when an interim update is sent.
         */
        void onProgressUpdateSent(Bundle extras) {
            throw new UnsupportedOperationException("It is not supported to send an interim update "
                    + "for " + mDebug);
        }

        /**
         * Called when an error is sent, after assertions about not being called twice have
         * happened.
         */
        void onErrorSent(Bundle extras) {
            throw new UnsupportedOperationException("It is not supported to send an error for "
                    + mDebug);
        }

        private void checkExtraFields(Bundle extras) {
            if (extras == null) {
                return;
            }
            if (extras.containsKey(MediaBrowserCompat.EXTRA_DOWNLOAD_PROGRESS)) {
                float value = extras.getFloat(MediaBrowserCompat.EXTRA_DOWNLOAD_PROGRESS);
                if (value < -EPSILON || value > 1.0f + EPSILON) {
                    throw new IllegalArgumentException("The value of the EXTRA_DOWNLOAD_PROGRESS "
                            + "field must be a float number within [0.0, 1.0].");
                }
            }
        }
    }

    private class ServiceBinderImpl {
        ServiceBinderImpl() {
        }

        public void connect(final String pkg, final int uid, final Bundle rootHints,
                final ServiceCallbacks callbacks) {

            if (!isValidPackage(pkg, uid)) {
                throw new IllegalArgumentException("Package/uid mismatch: uid=" + uid
                        + " package=" + pkg);
            }

            mHandler.postOrRun(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 =
                            MediaBrowserServiceCompat.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);
                            b.linkToDeath(connection, 0);
                            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);
                        }
                    }
                }
            });
        }

        public void disconnect(final ServiceCallbacks callbacks) {
            mHandler.postOrRun(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
                        old.callbacks.asBinder().unlinkToDeath(old, 0);
                    }
                }
            });
        }

        public void addSubscription(final String id, final IBinder token, final Bundle options,
                final ServiceCallbacks callbacks) {
            mHandler.postOrRun(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;
                    }

                    MediaBrowserServiceCompat.this.addSubscription(id, connection, token, options);
                }
            });
        }

        public void removeSubscription(final String id, final IBinder token,
                final ServiceCallbacks callbacks) {
            mHandler.postOrRun(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 (!MediaBrowserServiceCompat.this.removeSubscription(
                            id, connection, token)) {
                        Log.w(TAG, "removeSubscription called for " + id
                                + " which is not subscribed");
                    }
                }
            });
        }

        public void getMediaItem(final String mediaId, final ResultReceiver receiver,
                final ServiceCallbacks callbacks) {
            if (TextUtils.isEmpty(mediaId) || receiver == null) {
                return;
            }

            mHandler.postOrRun(new Runnable() {
                @Override
                public void run() {
                    final IBinder b = callbacks.asBinder();

                    ConnectionRecord connection = mConnections.get(b);
                    if (connection == null) {
                        Log.w(TAG, "getMediaItem for callback that isn't registered id=" + mediaId);
                        return;
                    }
                    performLoadItem(mediaId, connection, receiver);
                }
            });
        }

        // Used when {@link MediaBrowserProtocol#EXTRA_MESSENGER_BINDER} is used.
        public void registerCallbacks(final ServiceCallbacks callbacks, final Bundle rootHints) {
            mHandler.postOrRun(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.callbacks = callbacks;
                    connection.rootHints = rootHints;
                    mConnections.put(b, connection);
                    try {
                        b.linkToDeath(connection, 0);
                    } catch (RemoteException e) {
                        Log.w(TAG, "IBinder is already dead.");
                    }
                }
            });
        }

        // Used when {@link MediaBrowserProtocol#EXTRA_MESSENGER_BINDER} is used.
        public void unregisterCallbacks(final ServiceCallbacks callbacks) {
            mHandler.postOrRun(new Runnable() {
                @Override
                public void run() {
                    final IBinder b = callbacks.asBinder();
                    ConnectionRecord old = mConnections.remove(b);
                    if (old != null) {
                        b.unlinkToDeath(old, 0);
                    }
                }
            });
        }

        public void search(final String query, final Bundle extras, final ResultReceiver receiver,
                final ServiceCallbacks callbacks) {
            if (TextUtils.isEmpty(query) || receiver == null) {
                return;
            }

            mHandler.postOrRun(new Runnable() {
                @Override
                public void run() {
                    final IBinder b = callbacks.asBinder();

                    ConnectionRecord connection = mConnections.get(b);
                    if (connection == null) {
                        Log.w(TAG, "search for callback that isn't registered query=" + query);
                        return;
                    }
                    performSearch(query, extras, connection, receiver);
                }
            });
        }

        public void sendCustomAction(final String action, final Bundle extras,
                final ResultReceiver receiver, final ServiceCallbacks callbacks) {
            if (TextUtils.isEmpty(action) || receiver == null) {
                return;
            }

            mHandler.postOrRun(new Runnable() {
                @Override
                public void run() {
                    final IBinder b = callbacks.asBinder();

                    ConnectionRecord connection = mConnections.get(b);
                    if (connection == null) {
                        Log.w(TAG, "sendCustomAction for callback that isn't registered action="
                                + action + ", extras=" + extras);
                        return;
                    }
                    performCustomAction(action, extras, connection, receiver);
                }
            });
        }
    }

    private interface ServiceCallbacks {
        IBinder asBinder();
        void onConnect(String root, MediaSessionCompat.Token session, Bundle extras)
                throws RemoteException;
        void onConnectFailed() throws RemoteException;
        void onLoadChildren(String mediaId, List<MediaBrowserCompat.MediaItem> list, Bundle options)
                throws RemoteException;
    }

    private static class ServiceCallbacksCompat implements ServiceCallbacks {
        final Messenger mCallbacks;

        ServiceCallbacksCompat(Messenger callbacks) {
            mCallbacks = callbacks;
        }

        @Override
        public IBinder asBinder() {
            return mCallbacks.getBinder();
        }

        @Override
        public void onConnect(String root, MediaSessionCompat.Token session, Bundle extras)
                throws RemoteException {
            if (extras == null) {
                extras = new Bundle();
            }
            extras.putInt(EXTRA_SERVICE_VERSION, SERVICE_VERSION_CURRENT);
            Bundle data = new Bundle();
            data.putString(DATA_MEDIA_ITEM_ID, root);
            data.putParcelable(DATA_MEDIA_SESSION_TOKEN, session);
            data.putBundle(DATA_ROOT_HINTS, extras);
            sendRequest(SERVICE_MSG_ON_CONNECT, data);
        }

        @Override
        public void onConnectFailed() throws RemoteException {
            sendRequest(SERVICE_MSG_ON_CONNECT_FAILED, null);
        }

        @Override
        public void onLoadChildren(String mediaId, List<MediaBrowserCompat.MediaItem> list,
                Bundle options) throws RemoteException {
            Bundle data = new Bundle();
            data.putString(DATA_MEDIA_ITEM_ID, mediaId);
            data.putBundle(DATA_OPTIONS, options);
            if (list != null) {
                data.putParcelableArrayList(DATA_MEDIA_ITEM_LIST,
                        list instanceof ArrayList ? (ArrayList) list : new ArrayList<>(list));
            }
            sendRequest(SERVICE_MSG_ON_LOAD_CHILDREN, data);
        }

        private void sendRequest(int what, Bundle data) throws RemoteException {
            Message msg = Message.obtain();
            msg.what = what;
            msg.arg1 = SERVICE_VERSION_CURRENT;
            msg.setData(data);
            mCallbacks.send(msg);
        }
    }

    /**
     * Attaches to the base context. This method is added to change the visibility of
     * {@link Service#attachBaseContext(Context)}.
     * <p>
     * Note that we cannot simply override {@link Service#attachBaseContext(Context)} and hide it
     * because lint checks considers the overriden method as the new public API that needs update
     * of current.txt.
     */
    void attachToBaseContext(Context base) {
        attachBaseContext(base);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (Build.VERSION.SDK_INT >= 26) {
            mImpl = new MediaBrowserServiceImplApi26();
        } else if (Build.VERSION.SDK_INT >= 23) {
            mImpl = new MediaBrowserServiceImplApi23();
        } else if (Build.VERSION.SDK_INT >= 21) {
            mImpl = new MediaBrowserServiceImplApi21();
        } else {
            mImpl = new MediaBrowserServiceImplBase();
        }
        mImpl.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mImpl.onBind(intent);
    }

    @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.
     * @see BrowserRoot#EXTRA_RECENT
     * @see BrowserRoot#EXTRA_OFFLINE
     * @see BrowserRoot#EXTRA_SUGGESTED
     */
    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.
     * </p><p>
     * In case the media item does not have any children, call {@link Result#sendResult}
     * with an empty list. When the given {@code parentId} is invalid, implementations must
     * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
     * {@link MediaBrowserCompat.SubscriptionCallback#onError}.
     * </p>
     *
     * @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.
     */
    public abstract void onLoadChildren(@NonNull String parentId,
            @NonNull Result<List<MediaBrowserCompat.MediaItem>> result);

    /**
     * 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.
     * </p><p>
     * In case the media item does not have any children, call {@link Result#sendResult}
     * with an empty list. When the given {@code parentId} is invalid, implementations must
     * call {@link Result#sendResult result.sendResult} with {@code null}, which will invoke
     * {@link MediaBrowserCompat.SubscriptionCallback#onError}.
     * </p>
     *
     * @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.
     * @param options A bundle of service-specific arguments sent from the media
     *            browse. The information returned through the result should be
     *            affected by the contents of this bundle.
     */
    public void onLoadChildren(@NonNull String parentId,
            @NonNull Result<List<MediaBrowserCompat.MediaItem>> result, @NonNull Bundle options) {
        // To support backward compatibility, when the implementation of MediaBrowserService doesn't
        // override onLoadChildren() with options, onLoadChildren() without options will be used
        // instead, and the options will be applied in the implementation of result.onResultSent().
        result.setFlags(RESULT_FLAG_OPTION_NOT_HANDLED);
        onLoadChildren(parentId, 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><p>
     * When the given {@code itemId} is invalid, implementations must call
     * {@link Result#sendResult result.sendResult} with {@code null}.
     * </p><p>
     * The default implementation will invoke {@link MediaBrowserCompat.ItemCallback#onError}.
     *
     * @param itemId The id for the specific {@link MediaBrowserCompat.MediaItem}.
     * @param result The Result to send the item to, or null if the id is
     *            invalid.
     */
    public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result) {
        result.setFlags(RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED);
        result.sendResult(null);
    }

    /**
     * Called to get the search result.
     * <p>
     * Implementations must call {@link Result#sendResult result.sendResult}. If the search 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
     * search has been completed.
     * </p><p>
     * In case there are no search results, call {@link Result#sendResult result.sendResult} with an
     * empty list. In case there are some errors happened, call {@link Result#sendResult
     * result.sendResult} with {@code null}, which will invoke {@link
     * MediaBrowserCompat.SearchCallback#onError}.
     * </p><p>
     * The default implementation will invoke {@link MediaBrowserCompat.SearchCallback#onError}.
     * </p>
     *
     * @param query The search query sent from the media browser. It contains keywords separated
     *            by space.
     * @param extras The bundle of service-specific arguments sent from the media browser.
     * @param result The {@link Result} to send the search result.
     */
    public void onSearch(@NonNull String query, Bundle extras,
            @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
        result.setFlags(RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED);
        result.sendResult(null);
    }

    /**
     * Called to request a custom action to this service.
     * <p>
     * Implementations must call either {@link Result#sendResult} or {@link Result#sendError}. If
     * the requested custom action will be an expensive operation {@link Result#detach} may be
     * called before returning from this function, and then the service can send the result later
     * when the custom action is completed. Implementation can also call
     * {@link Result#sendProgressUpdate} to send an interim update to the requester.
     * </p><p>
     * If the requested custom action is not supported by this service, call
     * {@link Result#sendError}. The default implementation will invoke {@link Result#sendError}.
     * </p>
     *
     * @param action The custom action sent from the media browser.
     * @param extras The bundle of service-specific arguments sent from the media browser.
     * @param result The {@link Result} to send the result of the requested custom action.
     * @see MediaBrowserCompat#CUSTOM_ACTION_DOWNLOAD
     * @see MediaBrowserCompat#CUSTOM_ACTION_REMOVE_DOWNLOADED_FILE
     */
    public void onCustomAction(@NonNull String action, Bundle extras,
            @NonNull Result<Bundle> result) {
        result.sendError(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 MediaSessionCompat}.
     */
    public void setSessionToken(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;
        mImpl.setSessionToken(token);
    }

    /**
     * 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;
    }

    /**
     * Gets the root hints sent from the currently connected {@link MediaBrowserCompat}.
     * The root hints are service-specific arguments included in an optional bundle sent to the
     * media browser 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.
     * <p>
     * Note that this will return null when connected to {@link android.media.browse.MediaBrowser}
     * and running on API 23 or lower.
     *
     * @throws IllegalStateException If this method is called outside of {@link #onLoadChildren},
     *             {@link #onLoadItem} or {@link #onSearch}.
     * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_RECENT
     * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_OFFLINE
     * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_SUGGESTED
     */
    public final Bundle getBrowserRootHints() {
        return mImpl.getBrowserRootHints();
    }

    /**
     * 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 String parentId) {
        if (parentId == null) {
            throw new IllegalArgumentException("parentId cannot be null in notifyChildrenChanged");
        }
        mImpl.notifyChildrenChanged(parentId, null);
    }

    /**
     * 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.
     * @param options A bundle of service-specific arguments to send
     *            to the media browse. The contents of this bundle may
     *            contain the information about the change.
     */
    public void notifyChildrenChanged(@NonNull String parentId, @NonNull Bundle options) {
        if (parentId == null) {
            throw new IllegalArgumentException("parentId cannot be null in notifyChildrenChanged");
        }
        if (options == null) {
            throw new IllegalArgumentException("options cannot be null in notifyChildrenChanged");
        }
        mImpl.notifyChildrenChanged(parentId, options);
    }

    /**
     * Return whether the given package is one of the ones that is owned by the uid.
     */
    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.
     */
    void addSubscription(String id, ConnectionRecord connection, IBinder token,
            Bundle options) {
        // Save the subscription
        List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
        if (callbackList == null) {
            callbackList = new ArrayList<>();
        }
        for (Pair<IBinder, Bundle> callback : callbackList) {
            if (token == callback.first
                    && MediaBrowserCompatUtils.areSameOptions(options, callback.second)) {
                return;
            }
        }
        callbackList.add(new Pair<>(token, options));
        connection.subscriptions.put(id, callbackList);
        // send the results
        performLoadChildren(id, connection, options);
    }

    /**
     * Remove the subscription.
     */
    boolean removeSubscription(String id, ConnectionRecord connection, IBinder token) {
        if (token == null) {
            return connection.subscriptions.remove(id) != null;
        }
        boolean removed = false;
        List<Pair<IBinder, Bundle>> callbackList = connection.subscriptions.get(id);
        if (callbackList != null) {
            Iterator<Pair<IBinder, Bundle>> iter = callbackList.iterator();
            while (iter.hasNext()){
                if (token == iter.next().first) {
                    removed = true;
                    iter.remove();
                }
            }
            if (callbackList.size() == 0) {
                connection.subscriptions.remove(id);
            }
        }
        return removed;
    }

    /**
     * Call onLoadChildren and then send the results back to the connection.
     * <p>
     * Callers must make sure that this connection is still connected.
     */
    void performLoadChildren(final String parentId, final ConnectionRecord connection,
            final Bundle options) {
        final Result<List<MediaBrowserCompat.MediaItem>> result
                = new Result<List<MediaBrowserCompat.MediaItem>>(parentId) {
            @Override
            void onResultSent(List<MediaBrowserCompat.MediaItem> list) {
                if (mConnections.get(connection.callbacks.asBinder()) != connection) {
                    if (DEBUG) {
                        Log.d(TAG, "Not sending onLoadChildren result for connection that has"
                                + " been disconnected. pkg=" + connection.pkg + " id=" + parentId);
                    }
                    return;
                }

                List<MediaBrowserCompat.MediaItem> filteredList =
                        (getFlags() & RESULT_FLAG_OPTION_NOT_HANDLED) != 0
                                ? applyOptions(list, options) : list;
                try {
                    connection.callbacks.onLoadChildren(parentId, filteredList, options);
                } catch (RemoteException ex) {
                    // The other side is in the process of crashing.
                    Log.w(TAG, "Calling onLoadChildren() failed for id=" + parentId
                            + " package=" + connection.pkg);
                }
            }
        };

        mCurConnection = connection;
        if (options == null) {
            onLoadChildren(parentId, result);
        } else {
            onLoadChildren(parentId, result, options);
        }
        mCurConnection = null;

        if (!result.isDone()) {
            throw new IllegalStateException("onLoadChildren must call detach() or sendResult()"
                    + " before returning for package=" + connection.pkg + " id=" + parentId);
        }
    }

    List<MediaBrowserCompat.MediaItem> applyOptions(List<MediaBrowserCompat.MediaItem> list,
            final Bundle options) {
        if (list == null) {
            return null;
        }
        int page = options.getInt(MediaBrowserCompat.EXTRA_PAGE, -1);
        int pageSize = options.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1);
        if (page == -1 && pageSize == -1) {
            return list;
        }
        int fromIndex = pageSize * page;
        int toIndex = fromIndex + pageSize;
        if (page < 0 || pageSize < 1 || fromIndex >= list.size()) {
            return Collections.EMPTY_LIST;
        }
        if (toIndex > list.size()) {
            toIndex = list.size();
        }
        return list.subList(fromIndex, toIndex);
    }

    void performLoadItem(String itemId, ConnectionRecord connection,
            final ResultReceiver receiver) {
        final Result<MediaBrowserCompat.MediaItem> result =
                new Result<MediaBrowserCompat.MediaItem>(itemId) {
                    @Override
                    void onResultSent(MediaBrowserCompat.MediaItem item) {
                        if ((getFlags() & RESULT_FLAG_ON_LOAD_ITEM_NOT_IMPLEMENTED) != 0) {
                            receiver.send(RESULT_ERROR, null);
                            return;
                        }
                        Bundle bundle = new Bundle();
                        bundle.putParcelable(KEY_MEDIA_ITEM, item);
                        receiver.send(RESULT_OK, bundle);
                    }
                };

        mCurConnection = connection;
        onLoadItem(itemId, result);
        mCurConnection = null;

        if (!result.isDone()) {
            throw new IllegalStateException("onLoadItem must call detach() or sendResult()"
                    + " before returning for id=" + itemId);
        }
    }

    void performSearch(final String query, Bundle extras, ConnectionRecord connection,
            final ResultReceiver receiver) {
        final Result<List<MediaBrowserCompat.MediaItem>> result =
                new Result<List<MediaBrowserCompat.MediaItem>>(query) {
            @Override
            void onResultSent(List<MediaBrowserCompat.MediaItem> items) {
                if ((getFlags() & RESULT_FLAG_ON_SEARCH_NOT_IMPLEMENTED) != 0
                        || items == null) {
                    receiver.send(RESULT_ERROR, null);
                    return;
                }
                Bundle bundle = new Bundle();
                bundle.putParcelableArray(KEY_SEARCH_RESULTS,
                        items.toArray(new MediaBrowserCompat.MediaItem[0]));
                receiver.send(RESULT_OK, bundle);
            }
        };

        mCurConnection = connection;
        onSearch(query, extras, result);
        mCurConnection = null;

        if (!result.isDone()) {
            throw new IllegalStateException("onSearch must call detach() or sendResult()"
                    + " before returning for query=" + query);
        }
    }

    void performCustomAction(final String action, Bundle extras, ConnectionRecord connection,
            final ResultReceiver receiver) {
        final Result<Bundle> result = new Result<Bundle>(action) {
                @Override
                void onResultSent(Bundle result) {
                    receiver.send(RESULT_OK, result);
                }

                @Override
                void onProgressUpdateSent(Bundle data) {
                    receiver.send(RESULT_PROGRESS_UPDATE, data);
                }

                @Override
                void onErrorSent(Bundle data) {
                    receiver.send(RESULT_ERROR, data);
                }
            };

        mCurConnection = connection;
        onCustomAction(action, extras, result);
        mCurConnection = null;

        if (!result.isDone()) {
            throw new IllegalStateException("onCustomAction must call detach() or sendResult() or "
                    + "sendError() before returning for action=" + action + " extras="
                    + extras);
        }
    }

    /**
     * Contains information that the browser service needs to send to the client
     * when first connected.
     */
    public static final class BrowserRoot {
        /**
         * The lookup key for a boolean that indicates whether the browser service should return a
         * browser root for recently played media items.
         *
         * <p>When creating a media browser for a given media browser service, this key can be
         * supplied as a root hint for retrieving media items that are recently played.
         * If the media browser service can provide such media items, the implementation must return
         * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back.
         *
         * <p>The root hint may contain multiple keys.
         *
         * @see #EXTRA_OFFLINE
         * @see #EXTRA_SUGGESTED
         */
        public static final String EXTRA_RECENT = "android.service.media.extra.RECENT";

        /**
         * The lookup key for a boolean that indicates whether the browser service should return a
         * browser root for offline media items.
         *
         * <p>When creating a media browser for a given media browser service, this key can be
         * supplied as a root hint for retrieving media items that are can be played without an
         * internet connection.
         * If the media browser service can provide such media items, the implementation must return
         * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back.
         *
         * <p>The root hint may contain multiple keys.
         *
         * @see #EXTRA_RECENT
         * @see #EXTRA_SUGGESTED
         */
        public static final String EXTRA_OFFLINE = "android.service.media.extra.OFFLINE";

        /**
         * The lookup key for a boolean that indicates whether the browser service should return a
         * browser root for suggested media items.
         *
         * <p>When creating a media browser for a given media browser service, this key can be
         * supplied as a root hint for retrieving the media items suggested by the media browser
         * service. The list of media items passed in {@link MediaBrowserCompat.SubscriptionCallback#onChildrenLoaded(String, List)}
         * is considered ordered by relevance, first being the top suggestion.
         * If the media browser service can provide such media items, the implementation must return
         * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back.
         *
         * <p>The root hint may contain multiple keys.
         *
         * @see #EXTRA_RECENT
         * @see #EXTRA_OFFLINE
         */
        public static final String EXTRA_SUGGESTED = "android.service.media.extra.SUGGESTED";

        /**
         * The lookup key for a string that indicates specific keywords which will be considered
         * when the browser service suggests media items.
         *
         * <p>When creating a media browser for a given media browser service, this key can be
         * supplied as a root hint together with {@link #EXTRA_SUGGESTED} for retrieving suggested
         * media items related with the keywords. The list of media items passed in
         * {@link android.media.browse.MediaBrowser.SubscriptionCallback#onChildrenLoaded(String, List)}
         * is considered ordered by relevance, first being the top suggestion.
         * If the media browser service can provide such media items, the implementation must return
         * the key in the root hint when {@link #onGetRoot(String, int, Bundle)} is called back.
         *
         * <p>The root hint may contain multiple keys.
         *
         * @see #EXTRA_RECENT
         * @see #EXTRA_OFFLINE
         * @see #EXTRA_SUGGESTED
         * @deprecated The search functionality is now supported by the methods
         *             {@link MediaBrowserCompat#search} and {@link #onSearch}. Use those methods
         *             instead.
         */
        @Deprecated
        public static final String EXTRA_SUGGESTION_KEYWORDS
                = "android.service.media.extra.SUGGESTION_KEYWORDS";

        final private String mRootId;
        final private Bundle mExtras;

        /**
         * Constructs a browser root.
         * @param rootId The root id for browsing.
         * @param extras Any extras about the browser service.
         */
        public BrowserRoot(@NonNull String rootId, @Nullable Bundle extras) {
            if (rootId == null) {
                throw new IllegalArgumentException("The root id in BrowserRoot cannot be null. " +
                        "Use null for BrowserRoot instead.");
            }
            mRootId = rootId;
            mExtras = extras;
        }

        /**
         * Gets the root id for browsing.
         */
        public String getRootId() {
            return mRootId;
        }

        /**
         * Gets any extras about the browser service.
         */
        public Bundle getExtras() {
            return mExtras;
        }
    }
}
