MediaControllerCompat.java revision 165261b30365e1186c7a754d946b87ca65e52b83
1c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/*
2c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * Copyright (C) 2014 The Android Open Source Project
3c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel *
4c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * Licensed under the Apache License, Version 2.0 (the "License");
5c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * you may not use this file except in compliance with the License.
6c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * You may obtain a copy of the License at
7c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel *
8c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel *      http://www.apache.org/licenses/LICENSE-2.0
9c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel *
10c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * Unless required by applicable law or agreed to in writing, software
11c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * distributed under the License is distributed on an "AS IS" BASIS,
12c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * See the License for the specific language governing permissions and
14c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * limitations under the License.
15c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel */
16c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
17c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielpackage android.support.v4.media.session;
18c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
19c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.app.Activity;
20c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.app.PendingIntent;
21c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.content.Context;
22c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.media.AudioManager;
23c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.net.Uri;
24c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.os.Bundle;
25c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.os.Handler;
26c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.os.IBinder;
27c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.os.Looper;
28c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.os.Message;
29c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.os.RemoteException;
30c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.os.ResultReceiver;
31c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.annotation.VisibleForTesting;
32c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.app.BundleCompat;
33c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.app.SupportActivity;
34c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.media.MediaDescriptionCompat;
35c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.media.MediaMetadataCompat;
36c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.media.RatingCompat;
37c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.media.VolumeProviderCompat;
38c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.media.session.MediaSessionCompat.QueueItem;
39c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.support.v4.media.session.PlaybackStateCompat.CustomAction;
40c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.text.TextUtils;
41c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.util.Log;
42c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport android.view.KeyEvent;
43c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
44c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport java.lang.ref.WeakReference;
45c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport java.util.ArrayList;
46c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport java.util.HashMap;
47c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielimport java.util.List;
48c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
49c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel/**
50c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * Allows an app to interact with an ongoing media session. Media buttons and
51c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * other commands can be sent to the session. A callback may be registered to
52c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * receive updates from the session, such as metadata and play state changes.
53c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * <p>
54c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * A MediaController can be created if you have a {@link MediaSessionCompat.Token}
55c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * from the session owner.
56c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * <p>
57c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * MediaController objects are thread-safe.
58c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * <p>
59c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * This is a helper for accessing features in {@link android.media.session.MediaSession}
60c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel * introduced after API level 4 in a backwards compatible fashion.
61c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel */
62c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDanielpublic final class MediaControllerCompat {
63c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String TAG = "MediaControllerCompat";
64c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
65c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String COMMAND_GET_EXTRA_BINDER =
66c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "android.support.v4.media.session.command.GET_EXTRA_BINDER";
67c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String COMMAND_ADD_QUEUE_ITEM =
68c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "android.support.v4.media.session.command.ADD_QUEUE_ITEM";
69c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String COMMAND_ADD_QUEUE_ITEM_AT =
70c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "android.support.v4.media.session.command.ADD_QUEUE_ITEM_AT";
71c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String COMMAND_REMOVE_QUEUE_ITEM =
72c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "android.support.v4.media.session.command.REMOVE_QUEUE_ITEM";
73c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String COMMAND_REMOVE_QUEUE_ITEM_AT =
74c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "android.support.v4.media.session.command.REMOVE_QUEUE_ITEM_AT";
75c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
76c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String COMMAND_ARGUMENT_MEDIA_DESCRIPTION =
77c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "android.support.v4.media.session.command.ARGUMENT_MEDIA_DESCRIPTION";
78c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static final String COMMAND_ARGUMENT_INDEX =
79c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            "android.support.v4.media.session.command.ARGUMENT_INDEX";
80c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
81c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    private static class MediaControllerExtraData extends SupportActivity.ExtraData {
82c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private final MediaControllerCompat mMediaController;
83c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
84c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        MediaControllerExtraData(MediaControllerCompat mediaController) {
85c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mMediaController = mediaController;
86c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
87c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
88c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        MediaControllerCompat getMediaController() {
89c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return mMediaController;
90c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
91c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
92c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
93c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
94c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Sets a {@link MediaControllerCompat} for later retrieval via
95c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link #getMediaController()}.
96c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
97c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <p>On API 21 and later, this controller will be tied to the window of the activity and
98c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * media key and volume events which are received while the Activity is in the foreground
99c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * will be forwarded to the controller and used to invoke transport controls or adjust the
100c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * volume. Prior to API 21, the global handling of media key and volume events through an
101c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * active {@link android.support.v4.media.session.MediaSessionCompat} and media button receiver
102c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * will still be respected.</p>
103c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
104c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param mediaController The controller for the session which should receive
105c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *     media keys and volume changes on API 21 and later.
106c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see #getMediaController()
107c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see Activity#setMediaController(android.media.session.MediaController)
108c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
109c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public static void setMediaController(Activity activity,
110c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            MediaControllerCompat mediaController) {
111c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (activity instanceof  SupportActivity) {
112c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            ((SupportActivity) activity).putExtraData(
113c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    new MediaControllerExtraData(mediaController));
114c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
115c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (android.os.Build.VERSION.SDK_INT >= 21) {
116c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Object controllerObj = null;
117c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mediaController != null) {
118c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Object sessionTokenObj = mediaController.getSessionToken().getToken();
119c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                controllerObj = MediaControllerCompatApi21.fromToken(activity, sessionTokenObj);
120c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
121c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            MediaControllerCompatApi21.setMediaController(activity, controllerObj);
122c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
123c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
124c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
125c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
126c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Retrieves the current {@link MediaControllerCompat} for sending media key and volume events.
127c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
128c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The controller which should receive events.
129c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see #setMediaController(Activity,MediaControllerCompat)
130c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see #getMediaController()
131c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
132c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public static MediaControllerCompat getMediaController(Activity activity) {
133c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (activity instanceof SupportActivity) {
134c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            MediaControllerExtraData extraData =
135c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    ((SupportActivity) activity).getExtraData(MediaControllerExtraData.class);
136c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return extraData != null ? extraData.getMediaController() : null;
137c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
138c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Object controllerObj = MediaControllerCompatApi21.getMediaController(activity);
139c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (controllerObj == null) {
140c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return null;
141c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
142c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Object sessionTokenObj = MediaControllerCompatApi21.getSessionToken(controllerObj);
143c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
144c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return new MediaControllerCompat(activity,
145c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        MediaSessionCompat.Token.fromToken(sessionTokenObj));
146c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
147c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getMediaController.", e);
148c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
149c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
150c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return null;
151c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
152c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
153c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    private final MediaControllerImpl mImpl;
154c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    private final MediaSessionCompat.Token mToken;
155c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
156c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
157c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Creates a media controller from a session.
158c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
159c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param session The session to be controlled.
160c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
161c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public MediaControllerCompat(Context context, MediaSessionCompat session) {
162c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (session == null) {
163c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            throw new IllegalArgumentException("session must not be null");
164c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
165c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mToken = session.getSessionToken();
166c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
167c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (android.os.Build.VERSION.SDK_INT >= 24) {
168c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplApi24(context, session);
169c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        } else if (android.os.Build.VERSION.SDK_INT >= 23) {
170c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplApi23(context, session);
171c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
172c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplApi21(context, session);
173c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        } else {
174c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplBase(mToken);
175c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
176c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
177c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
178c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
179c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Creates a media controller from a session token which may have
180c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * been obtained from another process.
181c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
182c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param sessionToken The token of the session to be controlled.
183c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @throws RemoteException if the session is not accessible.
184c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
185c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public MediaControllerCompat(Context context, MediaSessionCompat.Token sessionToken)
186c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            throws RemoteException {
187c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (sessionToken == null) {
188c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            throw new IllegalArgumentException("sessionToken must not be null");
189c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
190c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mToken = sessionToken;
191c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
192c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (android.os.Build.VERSION.SDK_INT >= 24) {
193c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplApi24(context, sessionToken);
194c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        } else if (android.os.Build.VERSION.SDK_INT >= 23) {
195c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplApi23(context, sessionToken);
196c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
197c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplApi21(context, sessionToken);
198c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        } else {
199c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mImpl = new MediaControllerImplBase(mToken);
200c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
201c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
202c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
203c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
204c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get a {@link TransportControls} instance for this session.
205c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
206c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return A controls instance
207c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
208c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public TransportControls getTransportControls() {
209c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getTransportControls();
210c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
211c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
212c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
213c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Send the specified media button event to the session. Only media keys can
214c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * be sent by this method, other keys will be ignored.
215c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
216c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param keyEvent The media button event to dispatch.
217c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return true if the event was sent to the session, false otherwise.
218c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
219c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public boolean dispatchMediaButtonEvent(KeyEvent keyEvent) {
220c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (keyEvent == null) {
221c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            throw new IllegalArgumentException("KeyEvent may not be null");
222c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
223c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.dispatchMediaButtonEvent(keyEvent);
224c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
225c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
226c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
227c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the current playback state for this session.
228c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
229c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The current PlaybackState or null
230c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
231c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public PlaybackStateCompat getPlaybackState() {
232c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getPlaybackState();
233c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
234c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
235c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
236c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the current metadata for this session.
237c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
238c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The current MediaMetadata or null.
239c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
240c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public MediaMetadataCompat getMetadata() {
241c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getMetadata();
242c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
243c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
244c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
245c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the current play queue for this session if one is set. If you only
246c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * care about the current item {@link #getMetadata()} should be used.
247c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
248c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The current play queue or null.
249c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
250c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public List<MediaSessionCompat.QueueItem> getQueue() {
251c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getQueue();
252c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
253c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
254c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
255c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Add a queue item from the given {@code description} at the end of the play queue
256c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * of this session. Not all sessions may support this.
257c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
258c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param description The {@link MediaDescriptionCompat} for creating the
259c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *            {@link MediaSessionCompat.QueueItem} to be inserted.
260c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @throws UnsupportedOperationException If this session doesn't support this.
261c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
262c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
263c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void addQueueItem(MediaDescriptionCompat description) {
264c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.addQueueItem(description);
265c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
266c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
267c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
268c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Add a queue item from the given {@code description} at the specified position
269c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * in the play queue of this session. Shifts the queue item currently at that position
270c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * (if any) and any subsequent queue items to the right (adds one to their indices).
271c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Not all sessions may support this.
272c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
273c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param description The {@link MediaDescriptionCompat} for creating the
274c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *            {@link MediaSessionCompat.QueueItem} to be inserted.
275c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param index The index at which the created {@link MediaSessionCompat.QueueItem}
276c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *            is to be inserted.
277c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @throws UnsupportedOperationException If this session doesn't support this.
278c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
279c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
280c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void addQueueItem(MediaDescriptionCompat description, int index) {
281c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.addQueueItem(description, index);
282c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
283c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
284c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
285c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Remove the first occurrence of the specified {@link MediaSessionCompat.QueueItem}
286c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * with the given {@link MediaDescriptionCompat description} in the play queue of the
287c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * associated session. Not all sessions may support this.
288c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
289c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param description The {@link MediaDescriptionCompat} for denoting the
290c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *            {@link MediaSessionCompat.QueueItem} to be removed.
291c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @throws UnsupportedOperationException If this session doesn't support this.
292c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
293c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
294c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void removeQueueItem(MediaDescriptionCompat description) {
295c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.removeQueueItem(description);
296c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
297c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
298c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
299c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Remove an queue item at the specified position in the play queue
300c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * of this session. Not all sessions may support this.
301c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
302c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param index The index of the element to be removed.
303c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @throws UnsupportedOperationException If this session doesn't support this.
304c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
305c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
306c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void removeQueueItemAt(int index) {
307c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.removeQueueItemAt(index);
308c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
309c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
310c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
311c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the queue title for this session.
312c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
313c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public CharSequence getQueueTitle() {
314c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getQueueTitle();
315c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
316c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
317c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
318c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the extras for this session.
319c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
320c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public Bundle getExtras() {
321c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getExtras();
322c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
323c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
324c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
325c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the rating type supported by the session. One of:
326c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <ul>
327c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <li>{@link RatingCompat#RATING_NONE}</li>
328c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <li>{@link RatingCompat#RATING_HEART}</li>
329c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <li>{@link RatingCompat#RATING_THUMB_UP_DOWN}</li>
330c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <li>{@link RatingCompat#RATING_3_STARS}</li>
331c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <li>{@link RatingCompat#RATING_4_STARS}</li>
332c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <li>{@link RatingCompat#RATING_5_STARS}</li>
333c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <li>{@link RatingCompat#RATING_PERCENTAGE}</li>
334c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * </ul>
335c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
336c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The supported rating type
337c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
338c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public int getRatingType() {
339c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getRatingType();
340c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
341c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
342c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
343c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the repeat mode for this session.
344c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
345c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The latest repeat mode set to the session, or
346c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *         {@link PlaybackStateCompat#REPEAT_MODE_NONE} if not set.
347c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
348c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public int getRepeatMode() {
349c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getRepeatMode();
350c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
351c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
352c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
353c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Return whether the shuffle mode is enabled for this session.
354c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
355c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return {@code true} if the shuffle mode is enabled, {@code false} if disabled or not set.
356c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
357c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public boolean isShuffleModeEnabled() {
358c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.isShuffleModeEnabled();
359c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
360c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
361c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
362c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the flags for this session. Flags are defined in
363c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link MediaSessionCompat}.
364c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
365c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The current set of flags for the session.
366c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
367c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public long getFlags() {
368c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getFlags();
369c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
370c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
371c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
372c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the current playback info for this session.
373c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
374c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The current playback info or null.
375c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
376c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public PlaybackInfo getPlaybackInfo() {
377c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getPlaybackInfo();
378c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
379c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
380c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
381c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get an intent for launching UI associated with this session if one
382c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * exists.
383c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
384c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return A {@link PendingIntent} to launch UI or null.
385c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
386c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public PendingIntent getSessionActivity() {
387c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getSessionActivity();
388c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
389c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
390c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
391c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the token for the session this controller is connected to.
392c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
393c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The session's token.
394c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
395c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public MediaSessionCompat.Token getSessionToken() {
396c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mToken;
397c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
398c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
399c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
400c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Set the volume of the output this session is playing on. The command will
401c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * be ignored if it does not support
402c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in
403c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link AudioManager} may be used to affect the handling.
404c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
405c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see #getPlaybackInfo()
406c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param value The value to set it to, between 0 and the reported max.
407c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param flags Flags from {@link AudioManager} to include with the volume
408c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *            request.
409c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
410c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void setVolumeTo(int value, int flags) {
411c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.setVolumeTo(value, flags);
412c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
413c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
414c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
415c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Adjust the volume of the output this session is playing on. The direction
416c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * must be one of {@link AudioManager#ADJUST_LOWER},
417c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}.
418c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * The command will be ignored if the session does not support
419c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE} or
420c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in
421c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link AudioManager} may be used to affect the handling.
422c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
423c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @see #getPlaybackInfo()
424c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param direction The direction to adjust the volume in.
425c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param flags Any flags to pass with the command.
426c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
427c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void adjustVolume(int direction, int flags) {
428c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.adjustVolume(direction, flags);
429c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
430c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
431c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
432c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Adds a callback to receive updates from the Session. Updates will be
433c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * posted on the caller's thread.
434c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
435c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param callback The callback object, must not be null.
436c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
437c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void registerCallback(Callback callback) {
438c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        registerCallback(callback, null);
439c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
440c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
441c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
442c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Adds a callback to receive updates from the session. Updates will be
443c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * posted on the specified handler's thread.
444c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
445c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param callback The callback object, must not be null.
446c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param handler The handler to post updates on. If null the callers thread
447c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *            will be used.
448c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
449c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void registerCallback(Callback callback, Handler handler) {
450c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (callback == null) {
451c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            throw new IllegalArgumentException("callback cannot be null");
452c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
453c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (handler == null) {
454c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            handler = new Handler();
455c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
456c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.registerCallback(callback, handler);
457c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
458c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
459c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
460c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Stop receiving updates on the specified callback. If an update has
461c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * already been posted you may still receive it after calling this method.
462c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
463c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param callback The callback to remove
464c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
465c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void unregisterCallback(Callback callback) {
466c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (callback == null) {
467c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            throw new IllegalArgumentException("callback cannot be null");
468c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
469c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.unregisterCallback(callback);
470c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
471c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
472c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
473c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Sends a generic command to the session. It is up to the session creator
474c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * to decide what commands and parameters they will support. As such,
475c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * commands should only be sent to sessions that the controller owns.
476c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
477c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param command The command to send
478c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param params Any parameters to include with the command
479c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @param cb The callback to receive the result on
480c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
481c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public void sendCommand(String command, Bundle params, ResultReceiver cb) {
482c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        if (TextUtils.isEmpty(command)) {
483c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            throw new IllegalArgumentException("command cannot be null or empty");
484c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
485c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        mImpl.sendCommand(command, params, cb);
486c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
487c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
488c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
489c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Get the session owner's package name.
490c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
491c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The package name of of the session owner.
492c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
493c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public String getPackageName() {
494c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getPackageName();
495c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
496c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
497c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
498c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Gets the underlying framework
499c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * {@link android.media.session.MediaController} object.
500c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * <p>
501c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * This method is only supported on API 21+.
502c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * </p>
503c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *
504c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * @return The underlying {@link android.media.session.MediaController}
505c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     *         object, or null if none.
506c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
507c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public Object getMediaController() {
508c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        return mImpl.getMediaController();
509c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
510c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
511c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
512c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Callback for receiving updates on from the session. A Callback can be
513c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * registered using {@link #registerCallback}
514c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
515c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public static abstract class Callback implements IBinder.DeathRecipient {
516c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private final Object mCallbackObj;
517c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        MessageHandler mHandler;
518c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        boolean mHasExtraCallback;
519c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
520c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        boolean mRegistered = false;
521c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
522c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public Callback() {
523c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (android.os.Build.VERSION.SDK_INT >= 21) {
524c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mCallbackObj = MediaControllerCompatApi21.createCallback(new StubApi21());
525c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } else {
526c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mCallbackObj = new StubCompat();
527c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
528c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
529c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
530c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
531c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle the session being destroyed. The session is no
532c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * longer valid after this call and calls to it will be ignored.
533c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
534c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onSessionDestroyed() {
535c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
536c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
537c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
538c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle custom events sent by the session owner without a
539c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * specified interface. Controllers should only handle these for
540c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * sessions they own.
541c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
542c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param event The event from the session.
543c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras Optional parameters for the event.
544c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
545c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onSessionEvent(String event, Bundle extras) {
546c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
547c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
548c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
549c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle changes in playback state.
550c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
551c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param state The new playback state of the session
552c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
553c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onPlaybackStateChanged(PlaybackStateCompat state) {
554c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
555c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
556c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
557c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle changes to the current metadata.
558c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
559c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param metadata The current metadata for the session or null if none.
560c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @see MediaMetadataCompat
561c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
562c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onMetadataChanged(MediaMetadataCompat metadata) {
563c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
564c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
565c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
566c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle changes to items in the queue.
567c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
568c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @see MediaSessionCompat.QueueItem
569c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param queue A list of items in the current play queue. It should
570c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            include the currently playing item as well as previous and
571c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            upcoming items if applicable.
572c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
573c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
574c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
575c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
576c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
577c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle changes to the queue title.
578c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
579c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param title The title that should be displayed along with the play
580c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            queue such as "Now Playing". May be null if there is no
581c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            such title.
582c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
583c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onQueueTitleChanged(CharSequence title) {
584c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
585c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
586c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
587c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle chagnes to the {@link MediaSessionCompat} extras.
588c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
589c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras The extras that can include other information
590c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            associated with the {@link MediaSessionCompat}.
591c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
592c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onExtrasChanged(Bundle extras) {
593c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
594c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
595c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
596c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle changes to the audio info.
597c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
598c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param info The current audio info for this session.
599c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
600c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onAudioInfoChanged(PlaybackInfo info) {
601c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
602c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
603c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
604c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle changes to the repeat mode.
605c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
606c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param repeatMode The repeat mode. It should be one of followings:
607c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *                   {@link PlaybackStateCompat#REPEAT_MODE_NONE},
608c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *                   {@link PlaybackStateCompat#REPEAT_MODE_ONE},
609c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *                   {@link PlaybackStateCompat#REPEAT_MODE_ALL}
610c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
611c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onRepeatModeChanged(@PlaybackStateCompat.RepeatMode int repeatMode) {
612c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
613c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
614c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
615c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Override to handle changes to the shuffle mode.
616c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
617c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param enabled {@code true} if the shuffle mode is enabled, {@code false} otherwise.
618c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
619c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void onShuffleModeChanged(boolean enabled) {
620c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
621c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
622c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
623c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void binderDied() {
624c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            onSessionDestroyed();
625c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
626c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
627c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
628c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Set the handler to use for pre 21 callbacks.
629c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
630c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private void setHandler(Handler handler) {
631c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mHandler = new MessageHandler(handler.getLooper());
632c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
633c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
634c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private class StubApi21 implements MediaControllerCompatApi21.Callback {
635c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            StubApi21() {
636c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
637c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
638c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
639c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onSessionDestroyed() {
640c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Callback.this.onSessionDestroyed();
641c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
642c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
643c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
644c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onSessionEvent(String event, Bundle extras) {
645c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if (mHasExtraCallback && android.os.Build.VERSION.SDK_INT < 23) {
646c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    // Ignore. ExtraCallback will handle this.
647c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } else {
648c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Callback.this.onSessionEvent(event, extras);
649c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
650c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
651c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
652c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
653c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onPlaybackStateChanged(Object stateObj) {
654c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if (mHasExtraCallback) {
655c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    // Ignore. ExtraCallback will handle this.
656c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } else {
657c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Callback.this.onPlaybackStateChanged(
658c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                            PlaybackStateCompat.fromPlaybackState(stateObj));
659c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
660c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
661c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
662c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
663c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onMetadataChanged(Object metadataObj) {
664c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Callback.this.onMetadataChanged(MediaMetadataCompat.fromMediaMetadata(metadataObj));
665c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
666c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
667c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
668c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onQueueChanged(List<?> queue) {
669c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Callback.this.onQueueChanged(QueueItem.fromQueueItemList(queue));
670c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
671c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
672c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
673c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onQueueTitleChanged(CharSequence title) {
674c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Callback.this.onQueueTitleChanged(title);
675c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
676c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
677c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
678c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onExtrasChanged(Bundle extras) {
679c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Callback.this.onExtrasChanged(extras);
680c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
681c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
682c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
683c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onAudioInfoChanged(
684c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    int type, int stream, int control, int max, int current) {
685c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Callback.this.onAudioInfoChanged(
686c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        new PlaybackInfo(type, stream, control, max, current));
687c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
688c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
689c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
690c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private class StubCompat extends IMediaControllerCallback.Stub {
691c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
692c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            StubCompat() {
693c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
694c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
695c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
696c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onEvent(String event, Bundle extras) throws RemoteException {
697c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_EVENT, event, extras);
698c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
699c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
700c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
701c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onSessionDestroyed() throws RemoteException {
702c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_DESTROYED, null, null);
703c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
704c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
705c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
706c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onPlaybackStateChanged(PlaybackStateCompat state) throws RemoteException {
707c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_PLAYBACK_STATE, state, null);
708c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
709c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
710c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
711c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onMetadataChanged(MediaMetadataCompat metadata) throws RemoteException {
712c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_METADATA, metadata, null);
713c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
714c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
715c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
716c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onQueueChanged(List<QueueItem> queue) throws RemoteException {
717c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_QUEUE, queue, null);
718c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
719c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
720c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
721c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onQueueTitleChanged(CharSequence title) throws RemoteException {
722c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_QUEUE_TITLE, title, null);
723c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
724c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
725c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
726c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onRepeatModeChanged(int repeatMode) throws RemoteException {
727c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_REPEAT_MODE, repeatMode, null);
728c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
729c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
730c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
731c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onShuffleModeChanged(boolean enabled) throws RemoteException {
732c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_SHUFFLE_MODE, enabled, null);
733c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
734c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
735c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
736c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onExtrasChanged(Bundle extras) throws RemoteException {
737c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_EXTRAS, extras, null);
738c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
739c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
740c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
741c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException {
742c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PlaybackInfo pi = null;
743c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if (info != null) {
744c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    pi = new PlaybackInfo(info.volumeType, info.audioStream, info.controlType,
745c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                            info.maxVolume, info.currentVolume);
746c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
747c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mHandler.post(MessageHandler.MSG_UPDATE_VOLUME, pi, null);
748c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
749c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
750c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
751c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private class MessageHandler extends Handler {
752c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_EVENT = 1;
753c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
754c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_METADATA = 3;
755c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_VOLUME = 4;
756c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_QUEUE = 5;
757c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_QUEUE_TITLE = 6;
758c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_EXTRAS = 7;
759c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_DESTROYED = 8;
760c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_REPEAT_MODE = 9;
761c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            private static final int MSG_UPDATE_SHUFFLE_MODE = 10;
762c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
763c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public MessageHandler(Looper looper) {
764c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                super(looper);
765c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
766c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
767c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            @Override
768c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void handleMessage(Message msg) {
769c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if (!mRegistered) {
770c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    return;
771c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
772c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                switch (msg.what) {
773c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_EVENT:
774c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onSessionEvent((String) msg.obj, msg.getData());
775c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
776c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_PLAYBACK_STATE:
777c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onPlaybackStateChanged((PlaybackStateCompat) msg.obj);
778c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
779c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_METADATA:
780c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onMetadataChanged((MediaMetadataCompat) msg.obj);
781c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
782c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_QUEUE:
783c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onQueueChanged((List<MediaSessionCompat.QueueItem>) msg.obj);
784c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
785c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_QUEUE_TITLE:
786c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onQueueTitleChanged((CharSequence) msg.obj);
787c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
788c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_REPEAT_MODE:
789c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onRepeatModeChanged((int) msg.obj);
790c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
791c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_SHUFFLE_MODE:
792c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onShuffleModeChanged((boolean) msg.obj);
793c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
794c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_EXTRAS:
795c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onExtrasChanged((Bundle) msg.obj);
796c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
797c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_UPDATE_VOLUME:
798c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onAudioInfoChanged((PlaybackInfo) msg.obj);
799c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
800c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    case MSG_DESTROYED:
801c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        onSessionDestroyed();
802c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        break;
803c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
804c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
805c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
806c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            public void post(int what, Object obj, Bundle data) {
807c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Message msg = obtainMessage(what, obj);
808c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                msg.setData(data);
809c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                msg.sendToTarget();
810c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
811c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
812c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
813c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
814c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
815c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Interface for controlling media playback on a session. This allows an app
816c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * to send media transport commands to the session.
817c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
818c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public static abstract class TransportControls {
819c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        TransportControls() {
820c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
821c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
822c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
823c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player prepare its playback without audio focus. In other words, other
824c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * session can continue to play during the preparation of this session. This method can be
825c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * used to speed up the start of the playback. Once the preparation is done, the session
826c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * will change its playback state to {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards,
827c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * {@link #play} can be called to start playback. If the preparation is not needed,
828c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * {@link #play} can be directly called without this method.
829c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
830c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void prepare();
831c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
832c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
833c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player prepare playback for a specific media id. In other words, other
834c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * session can continue to play during the preparation of this session. This method can be
835c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * used to speed up the start of the playback. Once the preparation is
836c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * done, the session will change its playback state to
837c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
838c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * start playback. If the preparation is not needed, {@link #playFromMediaId} can
839c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * be directly called without this method.
840c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
841c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param mediaId The id of the requested media.
842c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras Optional extras that can include extra information about the media item
843c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *               to be prepared.
844c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
845c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void prepareFromMediaId(String mediaId, Bundle extras);
846c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
847c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
848c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player prepare playback for a specific search query.
849c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * An empty or null query should be treated as a request to prepare any
850c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * music. In other words, other session can continue to play during
851c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * the preparation of this session. This method can be used to speed up the start of the
852c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * playback. Once the preparation is done, the session will change its playback state to
853c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
854c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * start playback. If the preparation is not needed, {@link #playFromSearch} can be directly
855c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * called without this method.
856c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
857c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param query The search query.
858c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras Optional extras that can include extra information
859c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *               about the query.
860c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
861c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void prepareFromSearch(String query, Bundle extras);
862c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
863c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
864c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player prepare playback for a specific {@link Uri}.
865c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * In other words, other session can continue to play during the preparation of this
866c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * session. This method can be used to speed up the start of the playback.
867c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Once the preparation is done, the session will change its playback state to
868c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
869c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * start playback. If the preparation is not needed, {@link #playFromUri} can be directly
870c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * called without this method.
871c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
872c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param uri The URI of the requested media.
873c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras Optional extras that can include extra information about the media item
874c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *               to be prepared.
875c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
876c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void prepareFromUri(Uri uri, Bundle extras);
877c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
878c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
879c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player start its playback at its current position.
880c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
881c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void play();
882c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
883c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
884c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player start playback for a specific {@link Uri}.
885c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
886c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param mediaId The uri of the requested media.
887c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras Optional extras that can include extra information
888c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            about the media item to be played.
889c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
890c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void playFromMediaId(String mediaId, Bundle extras);
891c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
892c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
893c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player start playback for a specific search query.
894c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * An empty or null query should be treated as a request to play any
895c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * music.
896c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
897c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param query The search query.
898c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras Optional extras that can include extra information
899c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            about the query.
900c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
901c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void playFromSearch(String query, Bundle extras);
902c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
903c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
904c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player start playback for a specific {@link Uri}.
905c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
906c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param uri  The URI of the requested media.
907c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param extras Optional extras that can include extra information about the media item
908c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *               to be played.
909c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
910c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void playFromUri(Uri uri, Bundle extras);
911c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
912c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
913c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Play an item with a specific id in the play queue. If you specify an
914c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * id that is not in the play queue, the behavior is undefined.
915c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
916c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void skipToQueueItem(long id);
917c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
918c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
919c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player pause its playback and stay at its current
920c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * position.
921c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
922c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void pause();
923c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
924c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
925c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Request that the player stop its playback; it may clear its state in
926c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * whatever way is appropriate.
927c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
928c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void stop();
929c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
930c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
931c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Move to a new location in the media stream.
932c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
933c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param pos Position to move to, in milliseconds.
934c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
935c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void seekTo(long pos);
936c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
937c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
938c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Start fast forwarding. If playback is already fast forwarding this
939c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * may increase the rate.
940c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
941c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void fastForward();
942c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
943c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
944c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Skip to the next item.
945c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
946c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void skipToNext();
947c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
948c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
949c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Start rewinding. If playback is already rewinding this may increase
950c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * the rate.
951c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
952c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void rewind();
953c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
954c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
955c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Skip to the previous item.
956c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
957c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void skipToPrevious();
958c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
959c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
960c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Rate the current content. This will cause the rating to be set for
961c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * the current user. The Rating type must match the type returned by
962c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * {@link #getRatingType()}.
963c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
964c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param rating The rating to set for the current content
965c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
966c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void setRating(RatingCompat rating);
967c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
968c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
969c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Set the repeat mode for this session.
970c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
971c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param repeatMode The repeat mode. Must be one of the followings:
972c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *                   {@link PlaybackStateCompat#REPEAT_MODE_NONE},
973c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *                   {@link PlaybackStateCompat#REPEAT_MODE_ONE},
974c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *                   {@link PlaybackStateCompat#REPEAT_MODE_ALL}
975c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
976c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode);
977c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
978c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
979c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Set the shuffle mode for this session.
980c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
981c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable.
982c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
983c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void setShuffleModeEnabled(boolean enabled);
984c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
985c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
986c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Send a custom action for the {@link MediaSessionCompat} to perform.
987c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
988c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param customAction The action to perform.
989c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param args Optional arguments to supply to the
990c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            {@link MediaSessionCompat} for this custom action.
991c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
992c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void sendCustomAction(PlaybackStateCompat.CustomAction customAction,
993c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Bundle args);
994c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
995c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
996c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Send the id and args from a custom action for the
997c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * {@link MediaSessionCompat} to perform.
998c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
999c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @see #sendCustomAction(PlaybackStateCompat.CustomAction action,
1000c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *      Bundle args)
1001c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param action The action identifier of the
1002c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            {@link PlaybackStateCompat.CustomAction} as specified by
1003c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            the {@link MediaSessionCompat}.
1004c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @param args Optional arguments to supply to the
1005c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *            {@link MediaSessionCompat} for this custom action.
1006c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1007c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public abstract void sendCustomAction(String action, Bundle args);
1008c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
1009c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1010c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    /**
1011c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     * Holds information about the way volume is handled for this session.
1012c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel     */
1013c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    public static final class PlaybackInfo {
1014c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
1015c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * The session uses local playback.
1016c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1017c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public static final int PLAYBACK_TYPE_LOCAL = 1;
1018c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
1019c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * The session uses remote playback.
1020c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1021c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public static final int PLAYBACK_TYPE_REMOTE = 2;
1022c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1023c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private final int mPlaybackType;
1024c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        // TODO update audio stream with AudioAttributes support version
1025c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private final int mAudioStream;
1026c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private final int mVolumeControl;
1027c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private final int mMaxVolume;
1028c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private final int mCurrentVolume;
1029c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1030c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PlaybackInfo(int type, int stream, int control, int max, int current) {
1031c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mPlaybackType = type;
1032c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mAudioStream = stream;
1033c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mVolumeControl = control;
1034c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mMaxVolume = max;
1035c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mCurrentVolume = current;
1036c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1037c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1038c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
1039c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Get the type of volume handling, either local or remote. One of:
1040c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * <ul>
1041c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * <li>{@link PlaybackInfo#PLAYBACK_TYPE_LOCAL}</li>
1042c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * <li>{@link PlaybackInfo#PLAYBACK_TYPE_REMOTE}</li>
1043c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * </ul>
1044c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
1045c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @return The type of volume handling this session is using.
1046c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1047c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getPlaybackType() {
1048c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return mPlaybackType;
1049c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1050c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1051c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
1052c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Get the stream this is currently controlling volume on. When the volume
1053c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * type is {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} this value does not
1054c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * have meaning and should be ignored.
1055c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
1056c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @return The stream this session is playing on.
1057c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1058c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getAudioStream() {
1059c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            // TODO switch to AudioAttributesCompat when it is added.
1060c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return mAudioStream;
1061c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1062c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1063c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
1064c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Get the type of volume control that can be used. One of:
1065c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * <ul>
1066c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}</li>
1067c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE}</li>
1068c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_FIXED}</li>
1069c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * </ul>
1070c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
1071c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @return The type of volume control that may be used with this
1072c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *         session.
1073c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1074c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getVolumeControl() {
1075c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return mVolumeControl;
1076c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1077c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1078c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
1079c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Get the maximum volume that may be set for this session.
1080c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
1081c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @return The maximum allowed volume where this session is playing.
1082c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1083c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getMaxVolume() {
1084c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return mMaxVolume;
1085c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1086c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1087c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        /**
1088c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * Get the current volume for this session.
1089c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         *
1090c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         * @return The current volume where this session is playing.
1091c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel         */
1092c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getCurrentVolume() {
1093c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return mCurrentVolume;
1094c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1095c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
1096c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1097c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    interface MediaControllerImpl {
1098c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void registerCallback(Callback callback, Handler handler);
1099c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1100c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void unregisterCallback(Callback callback);
1101c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        boolean dispatchMediaButtonEvent(KeyEvent keyEvent);
1102c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        TransportControls getTransportControls();
1103c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PlaybackStateCompat getPlaybackState();
1104c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        MediaMetadataCompat getMetadata();
1105c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1106c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        List<MediaSessionCompat.QueueItem> getQueue();
1107c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void addQueueItem(MediaDescriptionCompat description);
1108c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void addQueueItem(MediaDescriptionCompat description, int index);
1109c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void removeQueueItem(MediaDescriptionCompat description);
1110c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void removeQueueItemAt(int index);
1111c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        CharSequence getQueueTitle();
1112c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Bundle getExtras();
1113c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        int getRatingType();
1114c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        int getRepeatMode();
1115c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        boolean isShuffleModeEnabled();
1116c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        long getFlags();
1117c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PlaybackInfo getPlaybackInfo();
1118c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        PendingIntent getSessionActivity();
1119c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1120c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void setVolumeTo(int value, int flags);
1121c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void adjustVolume(int direction, int flags);
1122c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        void sendCommand(String command, Bundle params, ResultReceiver cb);
1123c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1124c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        String getPackageName();
1125c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        Object getMediaController();
1126c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
1127c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1128c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static class MediaControllerImplBase implements MediaControllerImpl {
1129c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private IMediaSession mBinder;
1130c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private TransportControls mTransportControls;
1131c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1132c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public MediaControllerImplBase(MediaSessionCompat.Token token) {
1133c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mBinder = IMediaSession.Stub.asInterface((IBinder) token.getToken());
1134c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1135c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1136c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1137c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void registerCallback(Callback callback, Handler handler) {
1138c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (callback == null) {
1139c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                throw new IllegalArgumentException("callback may not be null.");
1140c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1141c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1142c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.asBinder().linkToDeath(callback, 0);
1143c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.registerCallbackListener((IMediaControllerCallback) callback.mCallbackObj);
1144c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                callback.setHandler(handler);
1145c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                callback.mRegistered = true;
1146c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1147c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in registerCallback.", e);
1148c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                callback.onSessionDestroyed();
1149c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1150c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1151c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1152c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1153c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void unregisterCallback(Callback callback) {
1154c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (callback == null) {
1155c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                throw new IllegalArgumentException("callback may not be null.");
1156c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1157c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1158c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.unregisterCallbackListener(
1159c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        (IMediaControllerCallback) callback.mCallbackObj);
1160c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.asBinder().unlinkToDeath(callback, 0);
1161c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                callback.mRegistered = false;
1162c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1163c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in unregisterCallback.", e);
1164c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1165c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1166c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1167c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1168c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public boolean dispatchMediaButtonEvent(KeyEvent event) {
1169c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (event == null) {
1170c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                throw new IllegalArgumentException("event may not be null.");
1171c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1172c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1173c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.sendMediaButton(event);
1174c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1175c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in dispatchMediaButtonEvent.", e);
1176c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1177c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return false;
1178c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1179c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1180c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1181c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public TransportControls getTransportControls() {
1182c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mTransportControls == null) {
1183c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mTransportControls = new TransportControlsBase(mBinder);
1184c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1185c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1186c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return mTransportControls;
1187c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1188c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1189c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1190c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public PlaybackStateCompat getPlaybackState() {
1191c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1192c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getPlaybackState();
1193c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1194c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getPlaybackState.", e);
1195c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1196c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1197c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1198c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1199c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1200c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public MediaMetadataCompat getMetadata() {
1201c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1202c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getMetadata();
1203c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1204c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getMetadata.", e);
1205c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1206c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1207c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1208c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1209c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1210c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public List<MediaSessionCompat.QueueItem> getQueue() {
1211c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1212c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getQueue();
1213c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1214c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getQueue.", e);
1215c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1216c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1217c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1218c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1219c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1220c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void addQueueItem(MediaDescriptionCompat description) {
1221c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1222c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                long flags = mBinder.getFlags();
1223c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1224c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    throw new UnsupportedOperationException(
1225c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                            "This session doesn't support queue management operations");
1226c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1227c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.addQueueItem(description);
1228c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1229c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in addQueueItem.", e);
1230c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1231c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1232c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1233c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1234c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void addQueueItem(MediaDescriptionCompat description, int index) {
1235c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1236c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                long flags = mBinder.getFlags();
1237c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1238c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    throw new UnsupportedOperationException(
1239c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                            "This session doesn't support queue management operations");
1240c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1241c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.addQueueItemAt(description, index);
1242c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1243c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in addQueueItemAt.", e);
1244c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1245c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1246c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1247c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1248c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void removeQueueItem(MediaDescriptionCompat description) {
1249c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1250c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                long flags = mBinder.getFlags();
1251c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1252c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    throw new UnsupportedOperationException(
1253c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                            "This session doesn't support queue management operations");
1254c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1255c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.removeQueueItem(description);
1256c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1257c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in removeQueueItem.", e);
1258c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1259c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1260c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1261c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1262c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void removeQueueItemAt(int index) {
1263c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1264c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                long flags = mBinder.getFlags();
1265c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1266c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    throw new UnsupportedOperationException(
1267c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                            "This session doesn't support queue management operations");
1268c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1269c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.removeQueueItemAt(index);
1270c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1271c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in removeQueueItemAt.", e);
1272c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1273c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1274c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1275c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1276c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public CharSequence getQueueTitle() {
1277c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1278c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getQueueTitle();
1279c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1280c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getQueueTitle.", e);
1281c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1282c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1283c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1284c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1285c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1286c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public Bundle getExtras() {
1287c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1288c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getExtras();
1289c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1290c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getExtras.", e);
1291c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1292c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1293c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1294c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1295c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1296c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getRatingType() {
1297c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1298c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getRatingType();
1299c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1300c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getRatingType.", e);
1301c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1302c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return 0;
1303c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1304c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1305c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1306c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getRepeatMode() {
1307c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1308c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getRepeatMode();
1309c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1310c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getRepeatMode.", e);
1311c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1312c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return 0;
1313c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1314c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1315c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1316c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public boolean isShuffleModeEnabled() {
1317c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1318c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.isShuffleModeEnabled();
1319c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1320c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in isShuffleModeEnabled.", e);
1321c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1322c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return false;
1323c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1324c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1325c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1326c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public long getFlags() {
1327c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1328c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getFlags();
1329c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1330c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getFlags.", e);
1331c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1332c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return 0;
1333c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1334c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1335c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1336c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public PlaybackInfo getPlaybackInfo() {
1337c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1338c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ParcelableVolumeInfo info = mBinder.getVolumeAttributes();
1339c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                PlaybackInfo pi = new PlaybackInfo(info.volumeType, info.audioStream,
1340c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        info.controlType, info.maxVolume, info.currentVolume);
1341c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return pi;
1342c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1343c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getPlaybackInfo.", e);
1344c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1345c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1346c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1347c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1348c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1349c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public PendingIntent getSessionActivity() {
1350c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1351c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getLaunchPendingIntent();
1352c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1353c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getSessionActivity.", e);
1354c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1355c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1356c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1357c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1358c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1359c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void setVolumeTo(int value, int flags) {
1360c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1361c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.setVolumeTo(value, flags, null);
1362c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1363c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in setVolumeTo.", e);
1364c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1365c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1366c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1367c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1368c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void adjustVolume(int direction, int flags) {
1369c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1370c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.adjustVolume(direction, flags, null);
1371c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1372c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in adjustVolume.", e);
1373c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1374c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1375c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1376c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1377c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void sendCommand(String command, Bundle params, ResultReceiver cb) {
1378c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1379c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.sendCommand(command, params,
1380c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        new MediaSessionCompat.ResultReceiverWrapper(cb));
1381c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1382c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in sendCommand.", e);
1383c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1384c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1385c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1386c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1387c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public String getPackageName() {
1388c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1389c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                return mBinder.getPackageName();
1390c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1391c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in getPackageName.", e);
1392c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1393c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1394c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1395c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1396c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1397c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public Object getMediaController() {
1398c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return null;
1399c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1400c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
1401c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1402c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static class TransportControlsBase extends TransportControls {
1403c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private IMediaSession mBinder;
1404c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1405c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public TransportControlsBase(IMediaSession binder) {
1406c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mBinder = binder;
1407c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1408c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1409c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1410c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void prepare() {
1411c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1412c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.prepare();
1413c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1414c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in prepare.", e);
1415c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1416c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1417c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1418c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1419c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void prepareFromMediaId(String mediaId, Bundle extras) {
1420c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1421c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.prepareFromMediaId(mediaId, extras);
1422c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1423c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in prepareFromMediaId.", e);
1424c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1425c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1426c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1427c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1428c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void prepareFromSearch(String query, Bundle extras) {
1429c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1430c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.prepareFromSearch(query, extras);
1431c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1432c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in prepareFromSearch.", e);
1433c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1434c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1435c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1436c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1437c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void prepareFromUri(Uri uri, Bundle extras) {
1438c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1439c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.prepareFromUri(uri, extras);
1440c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1441c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in prepareFromUri.", e);
1442c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1443c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1444c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1445c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1446c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void play() {
1447c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1448c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.play();
1449c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1450c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in play.", e);
1451c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1452c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1453c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1454c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1455c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void playFromMediaId(String mediaId, Bundle extras) {
1456c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1457c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.playFromMediaId(mediaId, extras);
1458c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1459c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in playFromMediaId.", e);
1460c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1461c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1462c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1463c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1464c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void playFromSearch(String query, Bundle extras) {
1465c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1466c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.playFromSearch(query, extras);
1467c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1468c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in playFromSearch.", e);
1469c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1470c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1471c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1472c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1473c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void playFromUri(Uri uri, Bundle extras) {
1474c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1475c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.playFromUri(uri, extras);
1476c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1477c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in playFromUri.", e);
1478c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1479c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1480c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1481c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1482c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void skipToQueueItem(long id) {
1483c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1484c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.skipToQueueItem(id);
1485c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1486c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in skipToQueueItem.", e);
1487c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1488c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1489c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1490c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1491c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void pause() {
1492c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1493c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.pause();
1494c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1495c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in pause.", e);
1496c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1497c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1498c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1499c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1500c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void stop() {
1501c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1502c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.stop();
1503c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1504c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in stop.", e);
1505c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1506c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1507c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1508c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1509c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void seekTo(long pos) {
1510c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1511c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.seekTo(pos);
1512c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1513c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in seekTo.", e);
1514c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1515c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1516c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1517c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1518c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void fastForward() {
1519c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1520c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.fastForward();
1521c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1522c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in fastForward.", e);
1523c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1524c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1525c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1526c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1527c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void skipToNext() {
1528c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1529c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.next();
1530c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1531c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in skipToNext.", e);
1532c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1533c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1534c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1535c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1536c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void rewind() {
1537c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1538c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.rewind();
1539c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1540c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in rewind.", e);
1541c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1542c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1543c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1544c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1545c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void skipToPrevious() {
1546c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1547c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.previous();
1548c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1549c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in skipToPrevious.", e);
1550c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1551c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1552c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1553c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1554c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void setRating(RatingCompat rating) {
1555c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1556c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.rate(rating);
1557c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1558c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in setRating.", e);
1559c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1560c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1561c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1562c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1563c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode) {
1564c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1565c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.setRepeatMode(repeatMode);
1566c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1567c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in setRepeatMode.", e);
1568c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1569c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1570c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1571c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1572c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void setShuffleModeEnabled(boolean enabled) {
1573c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1574c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.setShuffleModeEnabled(enabled);
1575c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1576c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in setShuffleModeEnabled.", e);
1577c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1578c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1579c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1580c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1581c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void sendCustomAction(CustomAction customAction, Bundle args) {
1582c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            sendCustomAction(customAction.getAction(), args);
1583c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1584c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1585c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1586c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void sendCustomAction(String action, Bundle args) {
1587c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            try {
1588c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mBinder.sendCustomAction(action, args);
1589c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } catch (RemoteException e) {
1590c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                Log.e(TAG, "Dead object in sendCustomAction.", e);
1591c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1592c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1593c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    }
1594c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1595c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel    static class MediaControllerImplApi21 implements MediaControllerImpl {
1596c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        protected final Object mControllerObj;
1597c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1598c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        // Extra binder is used for applying the framework change of new APIs and bug fixes
1599c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        // after API 21.
1600c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private IMediaSession mExtraBinder;
1601c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private HashMap<Callback, ExtraCallback> mCallbackMap = new HashMap<>();
1602c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        private List<Callback> mPendingCallbacks = new ArrayList<>();
1603c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1604c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public MediaControllerImplApi21(Context context, MediaSessionCompat session) {
1605c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mControllerObj = MediaControllerCompatApi21.fromToken(context,
1606c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    session.getSessionToken().getToken());
1607c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mExtraBinder = session.getSessionToken().getExtraBinder();
1608c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mExtraBinder == null) {
1609c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                requestExtraBinder();
1610c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1611c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1612c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1613c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public MediaControllerImplApi21(Context context, MediaSessionCompat.Token sessionToken)
1614c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                throws RemoteException {
1615c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mControllerObj = MediaControllerCompatApi21.fromToken(context,
1616c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    sessionToken.getToken());
1617c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mControllerObj == null) throw new RemoteException();
1618c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            mExtraBinder = sessionToken.getExtraBinder();
1619c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mExtraBinder == null) {
1620c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                requestExtraBinder();
1621c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1622c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1623c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1624c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1625c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public final void registerCallback(Callback callback, Handler handler) {
1626c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            MediaControllerCompatApi21.registerCallback(
1627c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    mControllerObj, callback.mCallbackObj, handler);
1628c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mExtraBinder != null) {
1629c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                callback.setHandler(handler);
1630c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                ExtraCallback extraCallback = new ExtraCallback(callback);
1631c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                mCallbackMap.put(callback, extraCallback);
1632c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                callback.mHasExtraCallback = true;
1633c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                try {
1634c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    mExtraBinder.registerCallbackListener(extraCallback);
1635c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } catch (RemoteException e) {
1636c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Log.e(TAG, "Dead object in registerCallback.", e);
1637c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1638c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } else {
1639c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                callback.setHandler(handler);
1640c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                synchronized (mPendingCallbacks) {
1641c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    mPendingCallbacks.add(callback);
1642c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1643c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1644c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1645c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1646c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1647c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public final void unregisterCallback(Callback callback) {
1648c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            MediaControllerCompatApi21.unregisterCallback(mControllerObj, callback.mCallbackObj);
1649c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mExtraBinder != null) {
1650c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                try {
1651c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    ExtraCallback extraCallback = mCallbackMap.remove(callback);
1652c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    if (extraCallback != null) {
1653c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                        mExtraBinder.unregisterCallbackListener(extraCallback);
1654c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    }
1655c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } catch (RemoteException e) {
1656c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Log.e(TAG, "Dead object in unregisterCallback.", e);
1657c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1658c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            } else {
1659c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                synchronized (mPendingCallbacks) {
1660c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    mPendingCallbacks.remove(callback);
1661c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1662c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1663c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1664c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1665c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1666c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public boolean dispatchMediaButtonEvent(KeyEvent event) {
1667c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return MediaControllerCompatApi21.dispatchMediaButtonEvent(mControllerObj, event);
1668c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1669c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1670c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1671c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public TransportControls getTransportControls() {
1672c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
1673c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return controlsObj != null ? new TransportControlsApi21(controlsObj) : null;
1674c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1675c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1676c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1677c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public PlaybackStateCompat getPlaybackState() {
1678c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mExtraBinder != null) {
1679c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                try {
1680c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    return mExtraBinder.getPlaybackState();
1681c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } catch (RemoteException e) {
1682c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Log.e(TAG, "Dead object in getPlaybackState.", e);
1683c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1684c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1685c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Object stateObj = MediaControllerCompatApi21.getPlaybackState(mControllerObj);
1686c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return stateObj != null ? PlaybackStateCompat.fromPlaybackState(stateObj) : null;
1687c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1688c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1689c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1690c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public MediaMetadataCompat getMetadata() {
1691c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Object metadataObj = MediaControllerCompatApi21.getMetadata(mControllerObj);
1692c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return metadataObj != null ? MediaMetadataCompat.fromMediaMetadata(metadataObj) : null;
1693c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1694c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1695c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1696c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public List<MediaSessionCompat.QueueItem> getQueue() {
1697c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            List<Object> queueObjs = MediaControllerCompatApi21.getQueue(mControllerObj);
1698c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return queueObjs != null ? MediaSessionCompat.QueueItem.fromQueueItemList(queueObjs)
1699c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    : null;
1700c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1701c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1702c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1703c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void addQueueItem(MediaDescriptionCompat description) {
1704c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Bundle params = new Bundle();
1705c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
1706c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            sendCommand(COMMAND_ADD_QUEUE_ITEM, params, null);
1707c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1708c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1709c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1710c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void addQueueItem(MediaDescriptionCompat description, int index) {
1711c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Bundle params = new Bundle();
1712c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
1713c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            params.putInt(COMMAND_ARGUMENT_INDEX, index);
1714c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            sendCommand(COMMAND_ADD_QUEUE_ITEM_AT, params, null);
1715c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1716c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1717c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1718c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void removeQueueItem(MediaDescriptionCompat description) {
1719c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Bundle params = new Bundle();
1720c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
1721c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            sendCommand(COMMAND_REMOVE_QUEUE_ITEM, params, null);
1722c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1723c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1724c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1725c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void removeQueueItemAt(int index) {
1726c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Bundle params = new Bundle();
1727c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            params.putInt(COMMAND_ARGUMENT_INDEX, index);
1728c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            sendCommand(COMMAND_REMOVE_QUEUE_ITEM_AT, params, null);
1729c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1730c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1731c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1732c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public CharSequence getQueueTitle() {
1733c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return MediaControllerCompatApi21.getQueueTitle(mControllerObj);
1734c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1735c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1736c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1737c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public Bundle getExtras() {
1738c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return MediaControllerCompatApi21.getExtras(mControllerObj);
1739c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1740c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1741c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1742c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getRatingType() {
1743c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (android.os.Build.VERSION.SDK_INT < 22 && mExtraBinder != null) {
1744c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                try {
1745c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    return mExtraBinder.getRatingType();
1746c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } catch (RemoteException e) {
1747c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Log.e(TAG, "Dead object in getRatingType.", e);
1748c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1749c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1750c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return MediaControllerCompatApi21.getRatingType(mControllerObj);
1751c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1752c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1753c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1754c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public int getRepeatMode() {
1755c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mExtraBinder != null) {
1756c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                try {
1757c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    return mExtraBinder.getRepeatMode();
1758c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } catch (RemoteException e) {
1759c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Log.e(TAG, "Dead object in getRepeatMode.", e);
1760c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1761c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1762c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return PlaybackStateCompat.REPEAT_MODE_NONE;
1763c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1764c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1765c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1766c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public boolean isShuffleModeEnabled() {
1767c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            if (mExtraBinder != null) {
1768c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                try {
1769c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    return mExtraBinder.isShuffleModeEnabled();
1770c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                } catch (RemoteException e) {
1771c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    Log.e(TAG, "Dead object in isShuffleModeEnabled.", e);
1772c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                }
1773c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            }
1774c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return false;
1775c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1776c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1777c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1778c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public long getFlags() {
1779c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return MediaControllerCompatApi21.getFlags(mControllerObj);
1780c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1781c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1782c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1783c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public PlaybackInfo getPlaybackInfo() {
1784c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            Object volumeInfoObj = MediaControllerCompatApi21.getPlaybackInfo(mControllerObj);
1785c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return volumeInfoObj != null ? new PlaybackInfo(
1786c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    MediaControllerCompatApi21.PlaybackInfo.getPlaybackType(volumeInfoObj),
1787c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    MediaControllerCompatApi21.PlaybackInfo.getLegacyAudioStream(volumeInfoObj),
1788c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    MediaControllerCompatApi21.PlaybackInfo.getVolumeControl(volumeInfoObj),
1789c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    MediaControllerCompatApi21.PlaybackInfo.getMaxVolume(volumeInfoObj),
1790c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel                    MediaControllerCompatApi21.PlaybackInfo.getCurrentVolume(volumeInfoObj)) : null;
1791c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1792c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1793c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1794c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public PendingIntent getSessionActivity() {
1795c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            return MediaControllerCompatApi21.getSessionActivity(mControllerObj);
1796c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        }
1797c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel
1798c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        @Override
1799c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel        public void setVolumeTo(int value, int flags) {
1800c8042e10763bca064df257547d04ae3dfcdfaf91Daryl McDaniel            MediaControllerCompatApi21.setVolumeTo(mControllerObj, value, flags);
1801        }
1802
1803        @Override
1804        public void adjustVolume(int direction, int flags) {
1805            MediaControllerCompatApi21.adjustVolume(mControllerObj, direction, flags);
1806        }
1807
1808        @Override
1809        public void sendCommand(String command, Bundle params, ResultReceiver cb) {
1810            MediaControllerCompatApi21.sendCommand(mControllerObj, command, params, cb);
1811        }
1812
1813        @Override
1814        public String getPackageName() {
1815            return MediaControllerCompatApi21.getPackageName(mControllerObj);
1816        }
1817
1818        @Override
1819        public Object getMediaController() {
1820            return mControllerObj;
1821        }
1822
1823        private void requestExtraBinder() {
1824            sendCommand(COMMAND_GET_EXTRA_BINDER, null,
1825                    new ExtraBinderRequestResultReceiver(this, new Handler()));
1826        }
1827
1828        private void processPendingCallbacks() {
1829            if (mExtraBinder == null) {
1830                return;
1831            }
1832            synchronized (mPendingCallbacks) {
1833                for (Callback callback : mPendingCallbacks) {
1834                    ExtraCallback extraCallback = new ExtraCallback(callback);
1835                    mCallbackMap.put(callback, extraCallback);
1836                    callback.mHasExtraCallback = true;
1837                    try {
1838                        mExtraBinder.registerCallbackListener(extraCallback);
1839                    } catch (RemoteException e) {
1840                        Log.e(TAG, "Dead object in registerCallback.", e);
1841                        break;
1842                    }
1843                }
1844                mPendingCallbacks.clear();
1845            }
1846        }
1847
1848        private static class ExtraBinderRequestResultReceiver extends ResultReceiver {
1849            private WeakReference<MediaControllerImplApi21> mMediaControllerImpl;
1850
1851            public ExtraBinderRequestResultReceiver(MediaControllerImplApi21 mediaControllerImpl,
1852                    Handler handler) {
1853                super(handler);
1854                mMediaControllerImpl = new WeakReference<>(mediaControllerImpl);
1855            }
1856
1857            @Override
1858            protected void onReceiveResult(int resultCode, Bundle resultData) {
1859                MediaControllerImplApi21 mediaControllerImpl = mMediaControllerImpl.get();
1860                if (mediaControllerImpl == null || resultData == null) {
1861                    return;
1862                }
1863                mediaControllerImpl.mExtraBinder = IMediaSession.Stub.asInterface(
1864                        BundleCompat.getBinder(resultData, MediaSessionCompat.EXTRA_BINDER));
1865                mediaControllerImpl.processPendingCallbacks();
1866            }
1867        }
1868
1869        private class ExtraCallback extends IMediaControllerCallback.Stub {
1870            private Callback mCallback;
1871
1872            ExtraCallback(Callback callback) {
1873                mCallback = callback;
1874            }
1875
1876            @Override
1877            public void onEvent(final String event, final Bundle extras) throws RemoteException {
1878                mCallback.mHandler.post(new Runnable() {
1879                    @Override
1880                    public void run() {
1881                        mCallback.onSessionEvent(event, extras);
1882                    }
1883                });
1884            }
1885
1886            @Override
1887            public void onSessionDestroyed() throws RemoteException {
1888                // Will not be called.
1889                throw new AssertionError();
1890            }
1891
1892            @Override
1893            public void onPlaybackStateChanged(final PlaybackStateCompat state)
1894                    throws RemoteException {
1895                mCallback.mHandler.post(new Runnable() {
1896                    @Override
1897                    public void run() {
1898                        mCallback.onPlaybackStateChanged(state);
1899                    }
1900                });
1901            }
1902
1903            @Override
1904            public void onMetadataChanged(MediaMetadataCompat metadata) throws RemoteException {
1905                // Will not be called.
1906                throw new AssertionError();
1907            }
1908
1909            @Override
1910            public void onQueueChanged(List<QueueItem> queue) throws RemoteException {
1911                // Will not be called.
1912                throw new AssertionError();
1913            }
1914
1915            @Override
1916            public void onQueueTitleChanged(CharSequence title) throws RemoteException {
1917                // Will not be called.
1918                throw new AssertionError();
1919            }
1920
1921            @Override
1922            public void onRepeatModeChanged(final int repeatMode) throws RemoteException {
1923                mCallback.mHandler.post(new Runnable() {
1924                    @Override
1925                    public void run() {
1926                        mCallback.onRepeatModeChanged(repeatMode);
1927                    }
1928                });
1929            }
1930
1931            @Override
1932            public void onShuffleModeChanged(final boolean enabled) throws RemoteException {
1933                mCallback.mHandler.post(new Runnable() {
1934                    @Override
1935                    public void run() {
1936                        mCallback.onShuffleModeChanged(enabled);
1937                    }
1938                });
1939            }
1940
1941            @Override
1942            public void onExtrasChanged(Bundle extras) throws RemoteException {
1943                // Will not be called.
1944                throw new AssertionError();
1945            }
1946
1947            @Override
1948            public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException {
1949                // Will not be called.
1950                throw new AssertionError();
1951            }
1952        }
1953    }
1954
1955    static class TransportControlsApi21 extends TransportControls {
1956        protected final Object mControlsObj;
1957
1958        public TransportControlsApi21(Object controlsObj) {
1959            mControlsObj = controlsObj;
1960        }
1961
1962        @Override
1963        public void prepare() {
1964            sendCustomAction(MediaSessionCompat.ACTION_PREPARE, null);
1965        }
1966
1967        @Override
1968        public void prepareFromMediaId(String mediaId, Bundle extras) {
1969            Bundle bundle = new Bundle();
1970            bundle.putString(MediaSessionCompat.ACTION_ARGUMENT_MEDIA_ID, mediaId);
1971            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
1972            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_MEDIA_ID, bundle);
1973        }
1974
1975        @Override
1976        public void prepareFromSearch(String query, Bundle extras) {
1977            Bundle bundle = new Bundle();
1978            bundle.putString(MediaSessionCompat.ACTION_ARGUMENT_QUERY, query);
1979            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
1980            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_SEARCH, bundle);
1981        }
1982
1983        @Override
1984        public void prepareFromUri(Uri uri, Bundle extras) {
1985            Bundle bundle = new Bundle();
1986            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_URI, uri);
1987            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
1988            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_URI, bundle);
1989        }
1990
1991        @Override
1992        public void play() {
1993            MediaControllerCompatApi21.TransportControls.play(mControlsObj);
1994        }
1995
1996        @Override
1997        public void pause() {
1998            MediaControllerCompatApi21.TransportControls.pause(mControlsObj);
1999        }
2000
2001        @Override
2002        public void stop() {
2003            MediaControllerCompatApi21.TransportControls.stop(mControlsObj);
2004        }
2005
2006        @Override
2007        public void seekTo(long pos) {
2008            MediaControllerCompatApi21.TransportControls.seekTo(mControlsObj, pos);
2009        }
2010
2011        @Override
2012        public void fastForward() {
2013            MediaControllerCompatApi21.TransportControls.fastForward(mControlsObj);
2014        }
2015
2016        @Override
2017        public void rewind() {
2018            MediaControllerCompatApi21.TransportControls.rewind(mControlsObj);
2019        }
2020
2021        @Override
2022        public void skipToNext() {
2023            MediaControllerCompatApi21.TransportControls.skipToNext(mControlsObj);
2024        }
2025
2026        @Override
2027        public void skipToPrevious() {
2028            MediaControllerCompatApi21.TransportControls.skipToPrevious(mControlsObj);
2029        }
2030
2031        @Override
2032        public void setRating(RatingCompat rating) {
2033            MediaControllerCompatApi21.TransportControls.setRating(mControlsObj,
2034                    rating != null ? rating.getRating() : null);
2035        }
2036
2037        @Override
2038        public void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode) {
2039            Bundle bundle = new Bundle();
2040            bundle.putInt(MediaSessionCompat.ACTION_ARGUMENT_REPEAT_MODE, repeatMode);
2041            sendCustomAction(MediaSessionCompat.ACTION_SET_REPEAT_MODE, bundle);
2042        }
2043
2044        @Override
2045        public void setShuffleModeEnabled(boolean enabled) {
2046            Bundle bundle = new Bundle();
2047            bundle.putBoolean(MediaSessionCompat.ACTION_ARGUMENT_SHUFFLE_MODE_ENABLED, enabled);
2048            sendCustomAction(MediaSessionCompat.ACTION_SET_SHUFFLE_MODE_ENABLED, bundle);
2049        }
2050
2051        @Override
2052        public void playFromMediaId(String mediaId, Bundle extras) {
2053            MediaControllerCompatApi21.TransportControls.playFromMediaId(mControlsObj, mediaId,
2054                    extras);
2055        }
2056
2057        @Override
2058        public void playFromSearch(String query, Bundle extras) {
2059            MediaControllerCompatApi21.TransportControls.playFromSearch(mControlsObj, query,
2060                    extras);
2061        }
2062
2063        @Override
2064        public void playFromUri(Uri uri, Bundle extras) {
2065            if (uri == null || Uri.EMPTY.equals(uri)) {
2066                throw new IllegalArgumentException(
2067                        "You must specify a non-empty Uri for playFromUri.");
2068            }
2069            Bundle bundle = new Bundle();
2070            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_URI, uri);
2071            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
2072            sendCustomAction(MediaSessionCompat.ACTION_PLAY_FROM_URI, bundle);
2073        }
2074
2075        @Override
2076        public void skipToQueueItem(long id) {
2077            MediaControllerCompatApi21.TransportControls.skipToQueueItem(mControlsObj, id);
2078        }
2079
2080        @Override
2081        public void sendCustomAction(CustomAction customAction, Bundle args) {
2082            MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj,
2083                    customAction.getAction(), args);
2084        }
2085
2086        @Override
2087        public void sendCustomAction(String action, Bundle args) {
2088            MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj, action,
2089                    args);
2090        }
2091    }
2092
2093    static class MediaControllerImplApi23 extends MediaControllerImplApi21 {
2094
2095        public MediaControllerImplApi23(Context context, MediaSessionCompat session) {
2096            super(context, session);
2097        }
2098
2099        public MediaControllerImplApi23(Context context, MediaSessionCompat.Token sessionToken)
2100                throws RemoteException {
2101            super(context, sessionToken);
2102        }
2103
2104        @Override
2105        public TransportControls getTransportControls() {
2106            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
2107            return controlsObj != null ? new TransportControlsApi23(controlsObj) : null;
2108        }
2109    }
2110
2111    static class TransportControlsApi23 extends TransportControlsApi21 {
2112
2113        public TransportControlsApi23(Object controlsObj) {
2114            super(controlsObj);
2115        }
2116
2117        @Override
2118        public void playFromUri(Uri uri, Bundle extras) {
2119            MediaControllerCompatApi23.TransportControls.playFromUri(mControlsObj, uri,
2120                    extras);
2121        }
2122    }
2123
2124    static class MediaControllerImplApi24 extends MediaControllerImplApi23 {
2125
2126        public MediaControllerImplApi24(Context context, MediaSessionCompat session) {
2127            super(context, session);
2128        }
2129
2130        public MediaControllerImplApi24(Context context, MediaSessionCompat.Token sessionToken)
2131                throws RemoteException {
2132            super(context, sessionToken);
2133        }
2134
2135        @Override
2136        public TransportControls getTransportControls() {
2137            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
2138            return controlsObj != null ? new TransportControlsApi24(controlsObj) : null;
2139        }
2140    }
2141
2142    static class TransportControlsApi24 extends TransportControlsApi23 {
2143
2144        public TransportControlsApi24(Object controlsObj) {
2145            super(controlsObj);
2146        }
2147
2148        @Override
2149        public void prepare() {
2150            MediaControllerCompatApi24.TransportControls.prepare(mControlsObj);
2151        }
2152
2153        @Override
2154        public void prepareFromMediaId(String mediaId, Bundle extras) {
2155            MediaControllerCompatApi24.TransportControls.prepareFromMediaId(
2156                    mControlsObj, mediaId, extras);
2157        }
2158
2159        @Override
2160        public void prepareFromSearch(String query, Bundle extras) {
2161            MediaControllerCompatApi24.TransportControls.prepareFromSearch(
2162                    mControlsObj, query, extras);
2163        }
2164
2165        @Override
2166        public void prepareFromUri(Uri uri, Bundle extras) {
2167            MediaControllerCompatApi24.TransportControls.prepareFromUri(mControlsObj, uri, extras);
2168        }
2169    }
2170}
2171