124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown/*
224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Copyright (C) 2014 The Android Open Source Project
324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *
424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * you may not use this file except in compliance with the License.
624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * You may obtain a copy of the License at
724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *
824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown *
1024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Unless required by applicable law or agreed to in writing, software
1124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * See the License for the specific language governing permissions and
1424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * limitations under the License.
1524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */
1624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
1724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownpackage android.support.v4.media.session;
1824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
19583beae8a1d75c7c821b65c8adc8812928424eecIan Lakeimport android.app.Activity;
20aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.app.PendingIntent;
2124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.content.Context;
22aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.media.AudioManager;
2394cfd171726b86d5d52ff835dde5d62402af5a7eSungsooimport android.media.session.MediaController;
24aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.net.Uri;
2524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Bundle;
2624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Handler;
27e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.IBinder;
28e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.Looper;
29e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.Message;
3024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.RemoteException;
3124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.ResultReceiver;
3294cfd171726b86d5d52ff835dde5d62402af5a7eSungsooimport android.support.annotation.NonNull;
33c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viveretteimport android.support.annotation.RequiresApi;
3424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsooimport android.support.v4.app.BundleCompat;
35583beae8a1d75c7c821b65c8adc8812928424eecIan Lakeimport android.support.v4.app.SupportActivity;
36db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moonimport android.support.v4.media.MediaDescriptionCompat;
3724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.MediaMetadataCompat;
3824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.RatingCompat;
3924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.VolumeProviderCompat;
40e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.support.v4.media.session.MediaSessionCompat.QueueItem;
41aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.support.v4.media.session.PlaybackStateCompat.CustomAction;
4224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.text.TextUtils;
43e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.util.Log;
4424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.view.KeyEvent;
4524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
46208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Choimport java.lang.ref.WeakReference;
4724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsooimport java.util.ArrayList;
4824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsooimport java.util.HashMap;
49aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport java.util.List;
50aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
5124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown/**
5224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Allows an app to interact with an ongoing media session. Media buttons and
5324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * other commands can be sent to the session. A callback may be registered to
5424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * receive updates from the session, such as metadata and play state changes.
5524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p>
5624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * A MediaController can be created if you have a {@link MediaSessionCompat.Token}
5724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * from the session owner.
5824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p>
5924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * MediaController objects are thread-safe.
6024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p>
6124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * This is a helper for accessing features in {@link android.media.session.MediaSession}
6224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * introduced after API level 4 in a backwards compatible fashion.
636fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * <p class="note">
646fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * If MediaControllerCompat is created with a {@link MediaSessionCompat.Token session token}
656fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * from another process, following methods will not work directly after the creation if the
666fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * {@link MediaSessionCompat.Token session token} is not passed through a
676fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * {@link android.support.v4.media.MediaBrowserCompat}:
686fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * <ul>
696fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * <li>{@link #getPlaybackState()}.{@link PlaybackStateCompat#getExtras() getExtras()}</li>
706fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * <li>{@link #isCaptioningEnabled()}</li>
716fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * <li>{@link #getRepeatMode()}</li>
726fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * <li>{@link #isShuffleModeEnabled()}</li>
736fe8c057782fde8c30f6c89832eaa15701e8fefeSungsoo * </ul></p>
7494cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo *
7594cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo * <div class="special reference">
7694cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo * <h3>Developer Guides</h3>
7794cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo * <p>For information about building your media application, read the
7894cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo * <a href="{@docRoot}guide/topics/media-apps/index.html">Media Apps</a> developer guide.</p>
7994cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo * </div>
8024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */
8124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownpublic final class MediaControllerCompat {
82b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas    static final String TAG = "MediaControllerCompat";
83e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
8424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo    static final String COMMAND_GET_EXTRA_BINDER =
8524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            "android.support.v4.media.session.command.GET_EXTRA_BINDER";
86db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    static final String COMMAND_ADD_QUEUE_ITEM =
87db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            "android.support.v4.media.session.command.ADD_QUEUE_ITEM";
88db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    static final String COMMAND_ADD_QUEUE_ITEM_AT =
89db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            "android.support.v4.media.session.command.ADD_QUEUE_ITEM_AT";
90db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    static final String COMMAND_REMOVE_QUEUE_ITEM =
91db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            "android.support.v4.media.session.command.REMOVE_QUEUE_ITEM";
92db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    static final String COMMAND_REMOVE_QUEUE_ITEM_AT =
93db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            "android.support.v4.media.session.command.REMOVE_QUEUE_ITEM_AT";
94db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
95db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    static final String COMMAND_ARGUMENT_MEDIA_DESCRIPTION =
96db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            "android.support.v4.media.session.command.ARGUMENT_MEDIA_DESCRIPTION";
97db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    static final String COMMAND_ARGUMENT_INDEX =
98db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            "android.support.v4.media.session.command.ARGUMENT_INDEX";
9924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
100583beae8a1d75c7c821b65c8adc8812928424eecIan Lake    private static class MediaControllerExtraData extends SupportActivity.ExtraData {
101583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        private final MediaControllerCompat mMediaController;
102583beae8a1d75c7c821b65c8adc8812928424eecIan Lake
103583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        MediaControllerExtraData(MediaControllerCompat mediaController) {
104583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            mMediaController = mediaController;
105583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        }
106583beae8a1d75c7c821b65c8adc8812928424eecIan Lake
107583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        MediaControllerCompat getMediaController() {
108583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            return mMediaController;
109583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        }
110583beae8a1d75c7c821b65c8adc8812928424eecIan Lake    }
111583beae8a1d75c7c821b65c8adc8812928424eecIan Lake
112583beae8a1d75c7c821b65c8adc8812928424eecIan Lake    /**
11394cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * Sets a {@link MediaControllerCompat} in the {@code activity} for later retrieval via
11494cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * {@link #getMediaController(Activity)}.
115583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     *
11694cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * <p>This is compatible with {@link Activity#setMediaController(MediaController)}.
11794cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * If {@code activity} inherits {@link android.support.v4.app.FragmentActivity}, the
11894cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * {@code mediaController} will be saved in the {@code activity}. In addition to that,
11994cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * on API 21 and later, {@link Activity#setMediaController(MediaController)} will be
12094cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * called.</p>
121583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     *
12294cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * @param activity The activity to set the {@code mediaController} in, must not be null.
123583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     * @param mediaController The controller for the session which should receive
124583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     *     media keys and volume changes on API 21 and later.
12594cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * @see #getMediaController(Activity)
126583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     * @see Activity#setMediaController(android.media.session.MediaController)
127583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     */
12894cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public static void setMediaController(@NonNull Activity activity,
129583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            MediaControllerCompat mediaController) {
13094cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo        if (activity instanceof SupportActivity) {
131583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            ((SupportActivity) activity).putExtraData(
132583beae8a1d75c7c821b65c8adc8812928424eecIan Lake                    new MediaControllerExtraData(mediaController));
133583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        }
134583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        if (android.os.Build.VERSION.SDK_INT >= 21) {
135583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            Object controllerObj = null;
136583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            if (mediaController != null) {
137583beae8a1d75c7c821b65c8adc8812928424eecIan Lake                Object sessionTokenObj = mediaController.getSessionToken().getToken();
138583beae8a1d75c7c821b65c8adc8812928424eecIan Lake                controllerObj = MediaControllerCompatApi21.fromToken(activity, sessionTokenObj);
139583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            }
140583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            MediaControllerCompatApi21.setMediaController(activity, controllerObj);
141583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        }
142583beae8a1d75c7c821b65c8adc8812928424eecIan Lake    }
143583beae8a1d75c7c821b65c8adc8812928424eecIan Lake
144583beae8a1d75c7c821b65c8adc8812928424eecIan Lake    /**
14594cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * Retrieves the {@link MediaControllerCompat} set in the activity by
14694cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * {@link #setMediaController(Activity, MediaControllerCompat)} for sending media key and volume
14794cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * events.
14894cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     *
14994cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * <p>This is compatible with {@link Activity#getMediaController()}.</p>
150583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     *
15194cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * @param activity The activity to get the media controller from, must not be null.
152583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     * @return The controller which should receive events.
15394cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo     * @see #setMediaController(Activity, MediaControllerCompat)
154583beae8a1d75c7c821b65c8adc8812928424eecIan Lake     */
15594cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public static MediaControllerCompat getMediaController(@NonNull Activity activity) {
156583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        if (activity instanceof SupportActivity) {
157583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            MediaControllerExtraData extraData =
158583beae8a1d75c7c821b65c8adc8812928424eecIan Lake                    ((SupportActivity) activity).getExtraData(MediaControllerExtraData.class);
159583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            return extraData != null ? extraData.getMediaController() : null;
160583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
161583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            Object controllerObj = MediaControllerCompatApi21.getMediaController(activity);
162583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            if (controllerObj == null) {
163583beae8a1d75c7c821b65c8adc8812928424eecIan Lake                return null;
164583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            }
165583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            Object sessionTokenObj = MediaControllerCompatApi21.getSessionToken(controllerObj);
166583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            try {
167583beae8a1d75c7c821b65c8adc8812928424eecIan Lake                return new MediaControllerCompat(activity,
168583beae8a1d75c7c821b65c8adc8812928424eecIan Lake                        MediaSessionCompat.Token.fromToken(sessionTokenObj));
169583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            } catch (RemoteException e) {
170e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getMediaController.", e);
171583beae8a1d75c7c821b65c8adc8812928424eecIan Lake            }
172583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        }
173583beae8a1d75c7c821b65c8adc8812928424eecIan Lake        return null;
174583beae8a1d75c7c821b65c8adc8812928424eecIan Lake    }
175583beae8a1d75c7c821b65c8adc8812928424eecIan Lake
176fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho    private static void validateCustomAction(String action, Bundle args) {
177fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho        if (action == null) {
178fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho            return;
179fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho        }
180fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho        switch(action) {
181fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho            case MediaSessionCompat.ACTION_FOLLOW:
182fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho            case MediaSessionCompat.ACTION_UNFOLLOW:
183fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho                if (args == null
184fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho                        || !args.containsKey(MediaSessionCompat.ACTION_ARGUMENT_MEDIA_ATTRIBUTE)) {
185fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho                    throw new IllegalArgumentException("An extra field "
186fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho                            + MediaSessionCompat.ACTION_ARGUMENT_MEDIA_ATTRIBUTE + " is required "
187fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho                            + "for this action " + action + ".");
188fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho                }
189fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho                break;
190fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho        }
191fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho    }
192fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho
19324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    private final MediaControllerImpl mImpl;
19494be6100218126ce6a08bf1f56209578500b361fRoboErik    private final MediaSessionCompat.Token mToken;
19524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
19624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
19724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Creates a media controller from a session.
19824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
19924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param session The session to be controlled.
20024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
20194cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public MediaControllerCompat(Context context, @NonNull MediaSessionCompat session) {
20224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (session == null) {
20324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("session must not be null");
20424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
20594be6100218126ce6a08bf1f56209578500b361fRoboErik        mToken = session.getSessionToken();
20624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
2079e5baa1de936eed92b7a41d1e291ef37d46bd1b9Sungsoo        if (android.os.Build.VERSION.SDK_INT >= 24) {
208bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            mImpl = new MediaControllerImplApi24(context, session);
209bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        } else if (android.os.Build.VERSION.SDK_INT >= 23) {
210b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            mImpl = new MediaControllerImplApi23(context, session);
211b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
21224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mImpl = new MediaControllerImplApi21(context, session);
21324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        } else {
214e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mImpl = new MediaControllerImplBase(mToken);
21524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
21624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
21724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
21824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
21924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Creates a media controller from a session token which may have
22024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * been obtained from another process.
22124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
22224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param sessionToken The token of the session to be controlled.
22324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @throws RemoteException if the session is not accessible.
22424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
22594cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public MediaControllerCompat(Context context, @NonNull MediaSessionCompat.Token sessionToken)
22624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throws RemoteException {
22724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (sessionToken == null) {
22824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("sessionToken must not be null");
22924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
23094be6100218126ce6a08bf1f56209578500b361fRoboErik        mToken = sessionToken;
23124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
2329e5baa1de936eed92b7a41d1e291ef37d46bd1b9Sungsoo        if (android.os.Build.VERSION.SDK_INT >= 24) {
233bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            mImpl = new MediaControllerImplApi24(context, sessionToken);
234bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        } else if (android.os.Build.VERSION.SDK_INT >= 23) {
235bbc4b0e06a9e5868cf0c44b2b3ec24fb6ca00b2cDonghyun Cho            mImpl = new MediaControllerImplApi23(context, sessionToken);
236bbc4b0e06a9e5868cf0c44b2b3ec24fb6ca00b2cDonghyun Cho        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
23724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mImpl = new MediaControllerImplApi21(context, sessionToken);
23824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        } else {
239e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mImpl = new MediaControllerImplBase(mToken);
24024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
24124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
24224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
24324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
24424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get a {@link TransportControls} instance for this session.
24524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
24624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return A controls instance
24724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
24824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public TransportControls getTransportControls() {
24924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getTransportControls();
25024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
25124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
25224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
25324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Send the specified media button event to the session. Only media keys can
25424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * be sent by this method, other keys will be ignored.
25524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
25624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param keyEvent The media button event to dispatch.
25724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return true if the event was sent to the session, false otherwise.
25824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
25924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public boolean dispatchMediaButtonEvent(KeyEvent keyEvent) {
26024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (keyEvent == null) {
26124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("KeyEvent may not be null");
26224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
26324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.dispatchMediaButtonEvent(keyEvent);
26424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
26524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
26624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
26724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get the current playback state for this session.
26824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
26924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return The current PlaybackState or null
27024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
27124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public PlaybackStateCompat getPlaybackState() {
27224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getPlaybackState();
27324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
27424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
27524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
27624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get the current metadata for this session.
27724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
27824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return The current MediaMetadata or null.
27924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
28024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public MediaMetadataCompat getMetadata() {
28124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getMetadata();
28224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
28324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
28424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
285aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the current play queue for this session if one is set. If you only
286aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * care about the current item {@link #getMetadata()} should be used.
287aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
288aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The current play queue or null.
289aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
29065cde2c4554985493a2e7560b5e71c5f24969287Sungsoo    public List<QueueItem> getQueue() {
291aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getQueue();
292aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
293aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
294aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
295db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * Add a queue item from the given {@code description} at the end of the play queue
296c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * of this session. Not all sessions may support this. To know whether the session supports
297c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * this, get the session's flags with {@link #getFlags()} and check that the flag
298c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * {@link MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS} is set.
299db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *
300db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @param description The {@link MediaDescriptionCompat} for creating the
301db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *            {@link MediaSessionCompat.QueueItem} to be inserted.
302db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @throws UnsupportedOperationException If this session doesn't support this.
303c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * @see #getFlags()
304db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
305db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     */
306db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    public void addQueueItem(MediaDescriptionCompat description) {
307db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        mImpl.addQueueItem(description);
308db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    }
309db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
310db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    /**
311db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * Add a queue item from the given {@code description} at the specified position
312db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * in the play queue of this session. Shifts the queue item currently at that position
313db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * (if any) and any subsequent queue items to the right (adds one to their indices).
314c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * Not all sessions may support this. To know whether the session supports this,
315c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * get the session's flags with {@link #getFlags()} and check that the flag
316c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * {@link MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS} is set.
317db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *
318db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @param description The {@link MediaDescriptionCompat} for creating the
319db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *            {@link MediaSessionCompat.QueueItem} to be inserted.
320db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @param index The index at which the created {@link MediaSessionCompat.QueueItem}
321db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *            is to be inserted.
322db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @throws UnsupportedOperationException If this session doesn't support this.
323c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * @see #getFlags()
324db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
325db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     */
326db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    public void addQueueItem(MediaDescriptionCompat description, int index) {
327db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        mImpl.addQueueItem(description, index);
328db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    }
329db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
330db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    /**
331db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * Remove the first occurrence of the specified {@link MediaSessionCompat.QueueItem}
332db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * with the given {@link MediaDescriptionCompat description} in the play queue of the
333c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * associated session. Not all sessions may support this. To know whether the session supports
334c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * this, get the session's flags with {@link #getFlags()} and check that the flag
335c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * {@link MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS} is set.
336db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *
337db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @param description The {@link MediaDescriptionCompat} for denoting the
338db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *            {@link MediaSessionCompat.QueueItem} to be removed.
339db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @throws UnsupportedOperationException If this session doesn't support this.
340c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * @see #getFlags()
341db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
342db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     */
343db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    public void removeQueueItem(MediaDescriptionCompat description) {
344db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        mImpl.removeQueueItem(description);
345db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    }
346db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
347db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    /**
348db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * Remove an queue item at the specified position in the play queue
349c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * of this session. Not all sessions may support this. To know whether the session supports
350c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * this, get the session's flags with {@link #getFlags()} and check that the flag
351c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * {@link MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS} is set.
352db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     *
353db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @param index The index of the element to be removed.
354db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @throws UnsupportedOperationException If this session doesn't support this.
355c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon     * @see #getFlags()
356db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     * @see MediaSessionCompat#FLAG_HANDLES_QUEUE_COMMANDS
35765cde2c4554985493a2e7560b5e71c5f24969287Sungsoo     * @deprecated Use {@link #removeQueueItem(MediaDescriptionCompat)} instead.
358db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon     */
35965cde2c4554985493a2e7560b5e71c5f24969287Sungsoo    @Deprecated
360db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    public void removeQueueItemAt(int index) {
36165cde2c4554985493a2e7560b5e71c5f24969287Sungsoo        List<QueueItem> queue = getQueue();
36265cde2c4554985493a2e7560b5e71c5f24969287Sungsoo        if (queue != null && index >= 0 && index < queue.size()) {
36365cde2c4554985493a2e7560b5e71c5f24969287Sungsoo            QueueItem item = queue.get(index);
36465cde2c4554985493a2e7560b5e71c5f24969287Sungsoo            if (item != null) {
36565cde2c4554985493a2e7560b5e71c5f24969287Sungsoo                removeQueueItem(item.getDescription());
36665cde2c4554985493a2e7560b5e71c5f24969287Sungsoo            }
36765cde2c4554985493a2e7560b5e71c5f24969287Sungsoo        }
368db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    }
369db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
370db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon    /**
371aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the queue title for this session.
372aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
373aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public CharSequence getQueueTitle() {
374aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getQueueTitle();
375aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
376aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
377aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
378aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the extras for this session.
379aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
380aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public Bundle getExtras() {
381aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getExtras();
382aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
383aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
384aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
38524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get the rating type supported by the session. One of:
38624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <ul>
38724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_NONE}</li>
38824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_HEART}</li>
38924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_THUMB_UP_DOWN}</li>
39024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_3_STARS}</li>
39124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_4_STARS}</li>
39224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_5_STARS}</li>
39324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_PERCENTAGE}</li>
39424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * </ul>
39524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
39624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return The supported rating type
39724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
39824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public int getRatingType() {
39924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getRatingType();
40024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
40124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
40224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
403e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho     * Return whether captioning is enabled for this session.
404e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho     *
405e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho     * @return {@code true} if captioning is enabled, {@code false} if disabled or not set.
406e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho     */
407e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho    public boolean isCaptioningEnabled() {
408e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        return mImpl.isCaptioningEnabled();
409e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho    }
410e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
411e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho    /**
41221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * Get the repeat mode for this session.
41321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     *
41421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * @return The latest repeat mode set to the session, or
41521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     *         {@link PlaybackStateCompat#REPEAT_MODE_NONE} if not set.
41621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     */
41721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    public int getRepeatMode() {
41821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        return mImpl.getRepeatMode();
41921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    }
42021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
42121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    /**
42221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * Return whether the shuffle mode is enabled for this session.
42321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     *
42421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * @return {@code true} if the shuffle mode is enabled, {@code false} if disabled or not set.
42574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon     * @deprecated Use {@link #getShuffleMode} instead.
42621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     */
42774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon    @Deprecated
42821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    public boolean isShuffleModeEnabled() {
42921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        return mImpl.isShuffleModeEnabled();
43021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    }
43121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
43221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    /**
43374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon     * Get the shuffle mode for this session.
43474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon     *
43574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon     * @return The latest shuffle mode set to the session, or
43674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon     *         {@link PlaybackStateCompat#SHUFFLE_MODE_NONE} if not set.
43774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon     */
43874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon    public int getShuffleMode() {
43974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        return mImpl.getShuffleMode();
44074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon    }
44174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
44274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon    /**
443aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the flags for this session. Flags are defined in
444aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link MediaSessionCompat}.
445aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
446aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The current set of flags for the session.
447aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
448aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public long getFlags() {
449aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getFlags();
450aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
451aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
452aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
453312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik     * Get the current playback info for this session.
45424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
455312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik     * @return The current playback info or null.
45624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
457312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik    public PlaybackInfo getPlaybackInfo() {
458312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        return mImpl.getPlaybackInfo();
45924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
46024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
46124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
462aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get an intent for launching UI associated with this session if one
463aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * exists.
464aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
465aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return A {@link PendingIntent} to launch UI or null.
466aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
467aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public PendingIntent getSessionActivity() {
468aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getSessionActivity();
469aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
470aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
471aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
47294be6100218126ce6a08bf1f56209578500b361fRoboErik     * Get the token for the session this controller is connected to.
47394be6100218126ce6a08bf1f56209578500b361fRoboErik     *
47494be6100218126ce6a08bf1f56209578500b361fRoboErik     * @return The session's token.
47594be6100218126ce6a08bf1f56209578500b361fRoboErik     */
47694be6100218126ce6a08bf1f56209578500b361fRoboErik    public MediaSessionCompat.Token getSessionToken() {
47794be6100218126ce6a08bf1f56209578500b361fRoboErik        return mToken;
47894be6100218126ce6a08bf1f56209578500b361fRoboErik    }
47994be6100218126ce6a08bf1f56209578500b361fRoboErik
48094be6100218126ce6a08bf1f56209578500b361fRoboErik    /**
481aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Set the volume of the output this session is playing on. The command will
482aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * be ignored if it does not support
483aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in
484aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link AudioManager} may be used to affect the handling.
485aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
486aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @see #getPlaybackInfo()
487aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param value The value to set it to, between 0 and the reported max.
488aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param flags Flags from {@link AudioManager} to include with the volume
489aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *            request.
490aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
491aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public void setVolumeTo(int value, int flags) {
492aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        mImpl.setVolumeTo(value, flags);
493aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
494aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
495aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
496aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Adjust the volume of the output this session is playing on. The direction
497aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * must be one of {@link AudioManager#ADJUST_LOWER},
498aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}.
499aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * The command will be ignored if the session does not support
500aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE} or
501aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in
502aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link AudioManager} may be used to affect the handling.
503aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
504aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @see #getPlaybackInfo()
505aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param direction The direction to adjust the volume in.
506aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param flags Any flags to pass with the command.
507aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
508aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public void adjustVolume(int direction, int flags) {
509aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        mImpl.adjustVolume(direction, flags);
510aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
511aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
512aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
51324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Adds a callback to receive updates from the Session. Updates will be
51424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * posted on the caller's thread.
51524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
51624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param callback The callback object, must not be null.
51724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
51894cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public void registerCallback(@NonNull Callback callback) {
51916ac83bebda2a19930b9d692789f3b507c49951bRoboErik        registerCallback(callback, null);
52024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
52124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
52224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
52324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Adds a callback to receive updates from the session. Updates will be
52424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * posted on the specified handler's thread.
52524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
52624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param callback The callback object, must not be null.
52724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param handler The handler to post updates on. If null the callers thread
52824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *            will be used.
52924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
53094cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public void registerCallback(@NonNull Callback callback, Handler handler) {
53124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (callback == null) {
53294cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo            throw new IllegalArgumentException("callback must not be null");
53324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
53424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (handler == null) {
53524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            handler = new Handler();
53624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
53716ac83bebda2a19930b9d692789f3b507c49951bRoboErik        mImpl.registerCallback(callback, handler);
53824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
53924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
54024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
54124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Stop receiving updates on the specified callback. If an update has
54224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * already been posted you may still receive it after calling this method.
54324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
54424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param callback The callback to remove
54524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
54694cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public void unregisterCallback(@NonNull Callback callback) {
54724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (callback == null) {
54894cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo            throw new IllegalArgumentException("callback must not be null");
54924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
55016ac83bebda2a19930b9d692789f3b507c49951bRoboErik        mImpl.unregisterCallback(callback);
55124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
55224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
55324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
55424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Sends a generic command to the session. It is up to the session creator
55524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * to decide what commands and parameters they will support. As such,
55624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * commands should only be sent to sessions that the controller owns.
55724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
55824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param command The command to send
55924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param params Any parameters to include with the command
56024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param cb The callback to receive the result on
56124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
56294cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo    public void sendCommand(@NonNull String command, Bundle params, ResultReceiver cb) {
56324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (TextUtils.isEmpty(command)) {
56494cfd171726b86d5d52ff835dde5d62402af5a7eSungsoo            throw new IllegalArgumentException("command must neither be null nor empty");
56524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
566b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        mImpl.sendCommand(command, params, cb);
56724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
56824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
56924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
570aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the session owner's package name.
571aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
572aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The package name of of the session owner.
573aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
574aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public String getPackageName() {
575aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getPackageName();
576aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
577aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
578aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
579aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Gets the underlying framework
580aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link android.media.session.MediaController} object.
58124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <p>
58224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * This method is only supported on API 21+.
58324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * </p>
58424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
585aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The underlying {@link android.media.session.MediaController}
586aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *         object, or null if none.
58724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
58824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public Object getMediaController() {
58924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getMediaController();
59024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
59124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
59224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
59324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Callback for receiving updates on from the session. A Callback can be
59416ac83bebda2a19930b9d692789f3b507c49951bRoboErik     * registered using {@link #registerCallback}
59524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
596e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    public static abstract class Callback implements IBinder.DeathRecipient {
597e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private final Object mCallbackObj;
598b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas        MessageHandler mHandler;
59924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        boolean mHasExtraCallback;
600e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
601b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas        boolean mRegistered = false;
60224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
60324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public Callback() {
6049e5baa1de936eed92b7a41d1e291ef37d46bd1b9Sungsoo            if (android.os.Build.VERSION.SDK_INT >= 21) {
60524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                mCallbackObj = MediaControllerCompatApi21.createCallback(new StubApi21());
60624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            } else {
607e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mCallbackObj = new StubCompat();
60824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            }
60924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
61024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
61124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
61223138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik         * Override to handle the session being destroyed. The session is no
61323138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik         * longer valid after this call and calls to it will be ignored.
61423138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik         */
61523138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik        public void onSessionDestroyed() {
61623138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik        }
61723138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik
61823138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik        /**
61924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Override to handle custom events sent by the session owner without a
62024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * specified interface. Controllers should only handle these for
62124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * sessions they own.
62224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
62324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param event The event from the session.
62424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param extras Optional parameters for the event.
62524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
62624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onSessionEvent(String event, Bundle extras) {
62724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
62824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
62924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
63024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Override to handle changes in playback state.
63124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
63224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param state The new playback state of the session
63324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
63424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onPlaybackStateChanged(PlaybackStateCompat state) {
63524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
63624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
63724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
63824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Override to handle changes to the current metadata.
63924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
64024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param metadata The current metadata for the session or null if none.
6419d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim         * @see MediaMetadataCompat
64224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
64324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onMetadataChanged(MediaMetadataCompat metadata) {
64424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
64524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
646aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
647aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle changes to items in the queue.
648aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
649aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @see MediaSessionCompat.QueueItem
650aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param queue A list of items in the current play queue. It should
651aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            include the currently playing item as well as previous and
652aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            upcoming items if applicable.
653aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
65465cde2c4554985493a2e7560b5e71c5f24969287Sungsoo        public void onQueueChanged(List<QueueItem> queue) {
655aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
656aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
657aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
658aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle changes to the queue title.
659aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
660aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param title The title that should be displayed along with the play
661aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            queue such as "Now Playing". May be null if there is no
662aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            such title.
663aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
664aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void onQueueTitleChanged(CharSequence title) {
665aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
666aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
667aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
668aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle chagnes to the {@link MediaSessionCompat} extras.
669aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
670aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param extras The extras that can include other information
671aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            associated with the {@link MediaSessionCompat}.
672aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
673aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void onExtrasChanged(Bundle extras) {
674aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
675aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
676aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
677aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle changes to the audio info.
678aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
679aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param info The current audio info for this session.
680aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
681aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void onAudioInfoChanged(PlaybackInfo info) {
682aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
683aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
68421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
685e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         * Override to handle changes to the captioning enabled status.
686e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         *
687e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         * @param enabled {@code true} if captioning is enabled, {@code false} otherwise.
688e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         */
689e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        public void onCaptioningEnabledChanged(boolean enabled) {
690e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        }
691e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
692e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        /**
69321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Override to handle changes to the repeat mode.
69421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
69521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param repeatMode The repeat mode. It should be one of followings:
69674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_NONE},
69774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_ONE},
69874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_ALL},
69974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_GROUP}
70021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
70121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void onRepeatModeChanged(@PlaybackStateCompat.RepeatMode int repeatMode) {
70221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
70321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
70421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
70521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Override to handle changes to the shuffle mode.
70621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
70721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param enabled {@code true} if the shuffle mode is enabled, {@code false} otherwise.
70874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         * @deprecated Use {@link #onShuffleModeChanged(int)} instead.
70921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
71074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        @Deprecated
71121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void onShuffleModeChanged(boolean enabled) {
71221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
71321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
71474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        /**
71574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         * Override to handle changes to the shuffle mode.
71674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *
71774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         * @param shuffleMode The shuffle mode. Must be one of the followings:
71874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                    {@link PlaybackStateCompat#SHUFFLE_MODE_NONE},
71974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                    {@link PlaybackStateCompat#SHUFFLE_MODE_ALL},
72074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                    {@link PlaybackStateCompat#SHUFFLE_MODE_GROUP}
72174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         */
72274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        public void onShuffleModeChanged(@PlaybackStateCompat.ShuffleMode int shuffleMode) {
72374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        }
72474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
725e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
726e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void binderDied() {
727e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            onSessionDestroyed();
728e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
729e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
730e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        /**
731e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik         * Set the handler to use for pre 21 callbacks.
732e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik         */
733e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private void setHandler(Handler handler) {
734e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mHandler = new MessageHandler(handler.getLooper());
735e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
736e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
73724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private class StubApi21 implements MediaControllerCompatApi21.Callback {
738b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            StubApi21() {
739b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            }
740b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas
74124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            @Override
74223138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik            public void onSessionDestroyed() {
74323138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik                Callback.this.onSessionDestroyed();
74423138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik            }
74523138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik
74623138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik            @Override
74724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            public void onSessionEvent(String event, Bundle extras) {
74824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                if (mHasExtraCallback && android.os.Build.VERSION.SDK_INT < 23) {
74924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    // Ignore. ExtraCallback will handle this.
75024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                } else {
75124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    Callback.this.onSessionEvent(event, extras);
75224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
75324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            }
75424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
75524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            @Override
75624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            public void onPlaybackStateChanged(Object stateObj) {
757a627c31cf8b6e99db03842dfc6864133bedd0f88Donghyun Cho                if (mHasExtraCallback) {
75824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    // Ignore. ExtraCallback will handle this.
75924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                } else {
76024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    Callback.this.onPlaybackStateChanged(
76124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                            PlaybackStateCompat.fromPlaybackState(stateObj));
76224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
76324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            }
76424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
76524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            @Override
76624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            public void onMetadataChanged(Object metadataObj) {
7679d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onMetadataChanged(MediaMetadataCompat.fromMediaMetadata(metadataObj));
7689d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
7699d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
7709d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
771203a34227e8fa3bd16721fb7ff450fb6feba7c50Hyundo Moon            public void onQueueChanged(List<?> queue) {
772203a34227e8fa3bd16721fb7ff450fb6feba7c50Hyundo Moon                Callback.this.onQueueChanged(QueueItem.fromQueueItemList(queue));
7739d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
7749d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
7759d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
7769d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            public void onQueueTitleChanged(CharSequence title) {
7779d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onQueueTitleChanged(title);
7789d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
7799d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
7809d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
7819d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            public void onExtrasChanged(Bundle extras) {
7829d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onExtrasChanged(extras);
7839d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
7849d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
7859d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
7869d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            public void onAudioInfoChanged(
7879d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                    int type, int stream, int control, int max, int current) {
7889d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onAudioInfoChanged(
7899d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                        new PlaybackInfo(type, stream, control, max, current));
7909d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
79124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
792e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
793e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private class StubCompat extends IMediaControllerCallback.Stub {
794e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
795b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            StubCompat() {
796b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            }
797b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas
798e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
799e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onEvent(String event, Bundle extras) throws RemoteException {
800e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_EVENT, event, extras);
801e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
802e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
803e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
804e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onSessionDestroyed() throws RemoteException {
805e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_DESTROYED, null, null);
806e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
807e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
808e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
809e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onPlaybackStateChanged(PlaybackStateCompat state) throws RemoteException {
810e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_PLAYBACK_STATE, state, null);
811e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
812e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
813e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
814e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onMetadataChanged(MediaMetadataCompat metadata) throws RemoteException {
815e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_METADATA, metadata, null);
816e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
817e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
818e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
819e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onQueueChanged(List<QueueItem> queue) throws RemoteException {
820e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_QUEUE, queue, null);
821e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
822e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
823e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
824e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onQueueTitleChanged(CharSequence title) throws RemoteException {
825e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_QUEUE_TITLE, title, null);
826e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
827e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
828e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
829e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            public void onCaptioningEnabledChanged(boolean enabled) throws RemoteException {
830e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                mHandler.post(MessageHandler.MSG_UPDATE_CAPTIONING_ENABLED, enabled, null);
831e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            }
832e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
833e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            @Override
8348955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            public void onRepeatModeChanged(int repeatMode) throws RemoteException {
8358955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                mHandler.post(MessageHandler.MSG_UPDATE_REPEAT_MODE, repeatMode, null);
8368955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            }
8378955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon
8388955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            @Override
83974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            public void onShuffleModeChangedDeprecated(boolean enabled) throws RemoteException {
84074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                mHandler.post(MessageHandler.MSG_UPDATE_SHUFFLE_MODE_DEPRECATED, enabled, null);
84174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            }
84274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
84374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            @Override
84474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            public void onShuffleModeChanged(int shuffleMode) throws RemoteException {
84574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                mHandler.post(MessageHandler.MSG_UPDATE_SHUFFLE_MODE, shuffleMode, null);
8468955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            }
8478955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon
8488955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            @Override
849e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onExtrasChanged(Bundle extras) throws RemoteException {
850e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_EXTRAS, extras, null);
851e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
852e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
853e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
854e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException {
855e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                PlaybackInfo pi = null;
856e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                if (info != null) {
857e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    pi = new PlaybackInfo(info.volumeType, info.audioStream, info.controlType,
858e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                            info.maxVolume, info.currentVolume);
859e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                }
860e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_VOLUME, pi, null);
861e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
862e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
863e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
864e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private class MessageHandler extends Handler {
865e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_EVENT = 1;
866e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
867e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_METADATA = 3;
868e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_VOLUME = 4;
869e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_QUEUE = 5;
870e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_QUEUE_TITLE = 6;
871e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_EXTRAS = 7;
872e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_DESTROYED = 8;
8738955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            private static final int MSG_UPDATE_REPEAT_MODE = 9;
87474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            private static final int MSG_UPDATE_SHUFFLE_MODE_DEPRECATED = 10;
875e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            private static final int MSG_UPDATE_CAPTIONING_ENABLED = 11;
87674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            private static final int MSG_UPDATE_SHUFFLE_MODE = 12;
877e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
878e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public MessageHandler(Looper looper) {
879e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                super(looper);
880e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
881e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
882e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
883e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void handleMessage(Message msg) {
884e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                if (!mRegistered) {
885e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    return;
886e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                }
887e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                switch (msg.what) {
888e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_EVENT:
889e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onSessionEvent((String) msg.obj, msg.getData());
890e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
891e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_PLAYBACK_STATE:
892e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onPlaybackStateChanged((PlaybackStateCompat) msg.obj);
893e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
894e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_METADATA:
895e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onMetadataChanged((MediaMetadataCompat) msg.obj);
896e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
897e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_QUEUE:
89865cde2c4554985493a2e7560b5e71c5f24969287Sungsoo                        onQueueChanged((List<QueueItem>) msg.obj);
899e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
900e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_QUEUE_TITLE:
901e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onQueueTitleChanged((CharSequence) msg.obj);
902e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
903e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                    case MSG_UPDATE_CAPTIONING_ENABLED:
904e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                        onCaptioningEnabledChanged((boolean) msg.obj);
905e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                        break;
9068955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                    case MSG_UPDATE_REPEAT_MODE:
9078955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                        onRepeatModeChanged((int) msg.obj);
9088955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                        break;
90974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    case MSG_UPDATE_SHUFFLE_MODE_DEPRECATED:
9108955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                        onShuffleModeChanged((boolean) msg.obj);
9118955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                        break;
91274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    case MSG_UPDATE_SHUFFLE_MODE:
91374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                        onShuffleModeChanged((int) msg.obj);
91474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                        break;
915e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_EXTRAS:
916e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onExtrasChanged((Bundle) msg.obj);
917e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
918e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_VOLUME:
919e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onAudioInfoChanged((PlaybackInfo) msg.obj);
920e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
921e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_DESTROYED:
922e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onSessionDestroyed();
923e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
924e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                }
925e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
926e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
927e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void post(int what, Object obj, Bundle data) {
928ecc231b11c9e6c1813bf12232559ea372cf02ea7Sungsoo Lim                Message msg = obtainMessage(what, obj);
929ecc231b11c9e6c1813bf12232559ea372cf02ea7Sungsoo Lim                msg.setData(data);
930ecc231b11c9e6c1813bf12232559ea372cf02ea7Sungsoo Lim                msg.sendToTarget();
931e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
932e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
93324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
93424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
93524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
93624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Interface for controlling media playback on a session. This allows an app
93724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * to send media transport commands to the session.
93824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
93924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static abstract class TransportControls {
94024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        TransportControls() {
94124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
94224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
94324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
944bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare its playback without audio focus. In other words, other
945bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * session can continue to play during the preparation of this session. This method can be
946bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * used to speed up the start of the playback. Once the preparation is done, the session
947bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * will change its playback state to {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards,
948bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link #play} can be called to start playback. If the preparation is not needed,
949bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link #play} can be directly called without this method.
950bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
951bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepare();
952bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
953bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
954bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare playback for a specific media id. In other words, other
955bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * session can continue to play during the preparation of this session. This method can be
956bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * used to speed up the start of the playback. Once the preparation is
957bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * done, the session will change its playback state to
958bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
959bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * start playback. If the preparation is not needed, {@link #playFromMediaId} can
960bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * be directly called without this method.
961bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *
962bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param mediaId The id of the requested media.
963bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param extras Optional extras that can include extra information about the media item
964bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *               to be prepared.
965bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
966bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepareFromMediaId(String mediaId, Bundle extras);
967bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
968bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
969bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare playback for a specific search query.
970bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * An empty or null query should be treated as a request to prepare any
971bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * music. In other words, other session can continue to play during
972bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * the preparation of this session. This method can be used to speed up the start of the
973bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * playback. Once the preparation is done, the session will change its playback state to
974bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
975bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * start playback. If the preparation is not needed, {@link #playFromSearch} can be directly
976bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * called without this method.
977bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *
978bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param query The search query.
979bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param extras Optional extras that can include extra information
980bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *               about the query.
981bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
982bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepareFromSearch(String query, Bundle extras);
983bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
984bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
985bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare playback for a specific {@link Uri}.
986bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * In other words, other session can continue to play during the preparation of this
987bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * session. This method can be used to speed up the start of the playback.
988bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Once the preparation is done, the session will change its playback state to
989bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
990bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * start playback. If the preparation is not needed, {@link #playFromUri} can be directly
991bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * called without this method.
992bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *
993bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param uri The URI of the requested media.
994bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param extras Optional extras that can include extra information about the media item
995bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *               to be prepared.
996bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
997bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepareFromUri(Uri uri, Bundle extras);
998bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
999bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
100024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Request that the player start its playback at its current position.
100124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
100224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void play();
100324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
100424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
1005aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Request that the player start playback for a specific {@link Uri}.
1006aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
1007aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param mediaId The uri of the requested media.
1008aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param extras Optional extras that can include extra information
1009aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            about the media item to be played.
1010aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
1011aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void playFromMediaId(String mediaId, Bundle extras);
1012aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1013aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
1014aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Request that the player start playback for a specific search query.
1015aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * An empty or null query should be treated as a request to play any
1016aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * music.
1017aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
1018aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param query The search query.
1019aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param extras Optional extras that can include extra information
1020aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            about the query.
1021aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
1022aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void playFromSearch(String query, Bundle extras);
1023aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1024aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
1025b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         * Request that the player start playback for a specific {@link Uri}.
1026b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         *
1027b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         * @param uri  The URI of the requested media.
1028b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         * @param extras Optional extras that can include extra information about the media item
1029b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         *               to be played.
1030b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         */
1031b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public abstract void playFromUri(Uri uri, Bundle extras);
1032b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1033b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        /**
1034aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Play an item with a specific id in the play queue. If you specify an
1035aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * id that is not in the play queue, the behavior is undefined.
1036aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
1037aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void skipToQueueItem(long id);
1038aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1039aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
104024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Request that the player pause its playback and stay at its current
104124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * position.
104224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
104324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void pause();
104424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
104524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
104624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Request that the player stop its playback; it may clear its state in
104724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * whatever way is appropriate.
104824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
104924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void stop();
105024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
105124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
105224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Move to a new location in the media stream.
105324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
105424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param pos Position to move to, in milliseconds.
105524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
105624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void seekTo(long pos);
105724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
105824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
105924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Start fast forwarding. If playback is already fast forwarding this
106024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * may increase the rate.
106124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
106224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void fastForward();
106324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
106424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
106524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Skip to the next item.
106624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
106724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void skipToNext();
106824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
106924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
107024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Start rewinding. If playback is already rewinding this may increase
107124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * the rate.
107224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
107324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void rewind();
107424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
107524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
107624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Skip to the previous item.
107724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
107824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void skipToPrevious();
107924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
108024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
108124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Rate the current content. This will cause the rating to be set for
108224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * the current user. The Rating type must match the type returned by
108324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * {@link #getRatingType()}.
108424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
108524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param rating The rating to set for the current content
108624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
108724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void setRating(RatingCompat rating);
1088aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1089aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
1090e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         * Enable/disable captioning for this session.
1091e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         *
1092e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         * @param enabled {@code true} to enable captioning, {@code false} to disable.
1093e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho         */
1094e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        public abstract void setCaptioningEnabled(boolean enabled);
1095e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
1096e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        /**
109721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Set the repeat mode for this session.
109821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
109921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param repeatMode The repeat mode. Must be one of the followings:
110074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_NONE},
110174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_ONE},
110274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_ALL},
110374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                   {@link PlaybackStateCompat#REPEAT_MODE_GROUP}
110421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
110521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public abstract void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode);
110621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
110721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
110821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Set the shuffle mode for this session.
110921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
111021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable.
111174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         * @deprecated Use {@link #setShuffleMode} instead.
111221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
111374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        @Deprecated
111421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public abstract void setShuffleModeEnabled(boolean enabled);
111521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
111621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
111774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         * Set the shuffle mode for this session.
111874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *
111974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         * @param shuffleMode The shuffle mode. Must be one of the followings:
112074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                    {@link PlaybackStateCompat#SHUFFLE_MODE_NONE},
112174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                    {@link PlaybackStateCompat#SHUFFLE_MODE_ALL},
112274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         *                    {@link PlaybackStateCompat#SHUFFLE_MODE_GROUP}
112374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon         */
112474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        public abstract void setShuffleMode(@PlaybackStateCompat.ShuffleMode int shuffleMode);
112574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
112674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        /**
1127aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Send a custom action for the {@link MediaSessionCompat} to perform.
1128aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
1129aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param customAction The action to perform.
1130aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param args Optional arguments to supply to the
1131aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            {@link MediaSessionCompat} for this custom action.
1132aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
1133aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void sendCustomAction(PlaybackStateCompat.CustomAction customAction,
1134aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                Bundle args);
1135aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1136aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
1137aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Send the id and args from a custom action for the
1138aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * {@link MediaSessionCompat} to perform.
1139aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
1140aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @see #sendCustomAction(PlaybackStateCompat.CustomAction action,
1141aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *      Bundle args)
11426b5f430ef841ca6a04ceb9296c581acc10feaa36Donghyun Cho         * @see MediaSessionCompat#ACTION_FLAG_AS_INAPPROPRIATE
11436b5f430ef841ca6a04ceb9296c581acc10feaa36Donghyun Cho         * @see MediaSessionCompat#ACTION_SKIP_AD
1144fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho         * @see MediaSessionCompat#ACTION_FOLLOW
1145fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho         * @see MediaSessionCompat#ACTION_UNFOLLOW
1146aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param action The action identifier of the
1147aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            {@link PlaybackStateCompat.CustomAction} as specified by
1148aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            the {@link MediaSessionCompat}.
1149aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param args Optional arguments to supply to the
1150aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            {@link MediaSessionCompat} for this custom action.
1151aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
1152aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void sendCustomAction(String action, Bundle args);
115324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
115424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
115524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
115624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Holds information about the way volume is handled for this session.
115724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
1158312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik    public static final class PlaybackInfo {
1159312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        /**
1160312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * The session uses local playback.
1161312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         */
1162312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public static final int PLAYBACK_TYPE_LOCAL = 1;
1163312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        /**
1164312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * The session uses remote playback.
1165312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         */
1166312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public static final int PLAYBACK_TYPE_REMOTE = 2;
1167312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik
1168312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        private final int mPlaybackType;
11691435afe32073dee10e721dfb6122ce6a194a6412RoboErik        // TODO update audio stream with AudioAttributes support version
117024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mAudioStream;
117124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mVolumeControl;
117224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mMaxVolume;
117324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mCurrentVolume;
117424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
1175312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        PlaybackInfo(int type, int stream, int control, int max, int current) {
1176312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            mPlaybackType = type;
117724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mAudioStream = stream;
117824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mVolumeControl = control;
117924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mMaxVolume = max;
118024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCurrentVolume = current;
118124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
118224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
118324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
118424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the type of volume handling, either local or remote. One of:
118524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <ul>
1186312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * <li>{@link PlaybackInfo#PLAYBACK_TYPE_LOCAL}</li>
1187312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * <li>{@link PlaybackInfo#PLAYBACK_TYPE_REMOTE}</li>
118824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * </ul>
118924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
119024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The type of volume handling this session is using.
119124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
1192312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public int getPlaybackType() {
1193312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            return mPlaybackType;
119424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
119524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
119624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
119724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the stream this is currently controlling volume on. When the volume
1198312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * type is {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} this value does not
119924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * have meaning and should be ignored.
120024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
120124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The stream this session is playing on.
120224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
120324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getAudioStream() {
1204aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            // TODO switch to AudioAttributesCompat when it is added.
120524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mAudioStream;
120624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
120724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
120824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
120924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the type of volume control that can be used. One of:
121024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <ul>
121124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}</li>
121224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE}</li>
121324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_FIXED}</li>
121424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * </ul>
121524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
121624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The type of volume control that may be used with this
121724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *         session.
121824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
121924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getVolumeControl() {
122024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mVolumeControl;
122124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
122224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
122324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
122424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the maximum volume that may be set for this session.
122524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
122624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The maximum allowed volume where this session is playing.
122724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
122824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getMaxVolume() {
122924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mMaxVolume;
123024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
123124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
123224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
123324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the current volume for this session.
123424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
123524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The current volume where this session is playing.
123624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
123724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getCurrentVolume() {
123824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mCurrentVolume;
123924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
124024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
124124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
124224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    interface MediaControllerImpl {
124316ac83bebda2a19930b9d692789f3b507c49951bRoboErik        void registerCallback(Callback callback, Handler handler);
124416ac83bebda2a19930b9d692789f3b507c49951bRoboErik
124516ac83bebda2a19930b9d692789f3b507c49951bRoboErik        void unregisterCallback(Callback callback);
124624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        boolean dispatchMediaButtonEvent(KeyEvent keyEvent);
124724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        TransportControls getTransportControls();
124824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        PlaybackStateCompat getPlaybackState();
124924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        MediaMetadataCompat getMetadata();
1250aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
125165cde2c4554985493a2e7560b5e71c5f24969287Sungsoo        List<QueueItem> getQueue();
1252db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        void addQueueItem(MediaDescriptionCompat description);
1253db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        void addQueueItem(MediaDescriptionCompat description, int index);
1254db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        void removeQueueItem(MediaDescriptionCompat description);
1255aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        CharSequence getQueueTitle();
1256aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        Bundle getExtras();
125724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        int getRatingType();
1258e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        boolean isCaptioningEnabled();
125921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        int getRepeatMode();
126021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        boolean isShuffleModeEnabled();
126174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        int getShuffleMode();
1262aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        long getFlags();
1263312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        PlaybackInfo getPlaybackInfo();
1264aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        PendingIntent getSessionActivity();
1265aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1266aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        void setVolumeTo(int value, int flags);
1267aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        void adjustVolume(int direction, int flags);
1268b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        void sendCommand(String command, Bundle params, ResultReceiver cb);
1269aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1270aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        String getPackageName();
127124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        Object getMediaController();
127224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
127324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
127424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    static class MediaControllerImplBase implements MediaControllerImpl {
1275e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private IMediaSession mBinder;
1276e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private TransportControls mTransportControls;
1277e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1278e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public MediaControllerImplBase(MediaSessionCompat.Token token) {
1279e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mBinder = IMediaSession.Stub.asInterface((IBinder) token.getToken());
1280e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1281e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
128224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
128316ac83bebda2a19930b9d692789f3b507c49951bRoboErik        public void registerCallback(Callback callback, Handler handler) {
1284e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (callback == null) {
1285e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                throw new IllegalArgumentException("callback may not be null.");
1286e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1287e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1288e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.asBinder().linkToDeath(callback, 0);
1289e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.registerCallbackListener((IMediaControllerCallback) callback.mCallbackObj);
1290e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.setHandler(handler);
1291e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.mRegistered = true;
1292e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1293e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in registerCallback.", e);
1294e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.onSessionDestroyed();
1295e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
129624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
129724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
129824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
129916ac83bebda2a19930b9d692789f3b507c49951bRoboErik        public void unregisterCallback(Callback callback) {
1300e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (callback == null) {
1301e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                throw new IllegalArgumentException("callback may not be null.");
1302e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1303e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1304e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.unregisterCallbackListener(
1305e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        (IMediaControllerCallback) callback.mCallbackObj);
1306e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.asBinder().unlinkToDeath(callback, 0);
1307e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.mRegistered = false;
1308e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1309e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in unregisterCallback.", e);
1310e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
131124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
131224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
131324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
131424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public boolean dispatchMediaButtonEvent(KeyEvent event) {
1315e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (event == null) {
1316e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                throw new IllegalArgumentException("event may not be null.");
1317e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1318e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1319e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.sendMediaButton(event);
1320e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1321e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in dispatchMediaButtonEvent.", e);
1322e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
132324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return false;
132424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
132524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
132624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
132724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public TransportControls getTransportControls() {
1328e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (mTransportControls == null) {
1329e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mTransportControls = new TransportControlsBase(mBinder);
1330e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1331e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1332e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            return mTransportControls;
133324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
133424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
133524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
133624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public PlaybackStateCompat getPlaybackState() {
1337e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1338e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getPlaybackState();
1339e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1340e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getPlaybackState.", e);
1341e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
134224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
134324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
134424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
134524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
134624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaMetadataCompat getMetadata() {
1347e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1348e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getMetadata();
1349e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1350e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getMetadata.", e);
1351e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
135224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
135324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
135424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
135524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
135665cde2c4554985493a2e7560b5e71c5f24969287Sungsoo        public List<QueueItem> getQueue() {
1357e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1358e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getQueue();
1359e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1360e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getQueue.", e);
1361e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1362aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1363aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1364aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1365aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1366db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        public void addQueueItem(MediaDescriptionCompat description) {
1367db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            try {
1368db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                long flags = mBinder.getFlags();
1369db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1370db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                    throw new UnsupportedOperationException(
1371db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                            "This session doesn't support queue management operations");
1372db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                }
1373db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                mBinder.addQueueItem(description);
1374db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            } catch (RemoteException e) {
1375e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in addQueueItem.", e);
1376db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            }
1377db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        }
1378db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
1379db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        @Override
1380db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        public void addQueueItem(MediaDescriptionCompat description, int index) {
1381db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            try {
1382db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                long flags = mBinder.getFlags();
1383db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1384db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                    throw new UnsupportedOperationException(
1385db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                            "This session doesn't support queue management operations");
1386db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                }
1387db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                mBinder.addQueueItemAt(description, index);
1388db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            } catch (RemoteException e) {
1389e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in addQueueItemAt.", e);
1390db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            }
1391db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        }
1392db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
1393db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        @Override
1394db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        public void removeQueueItem(MediaDescriptionCompat description) {
1395db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            try {
1396db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                long flags = mBinder.getFlags();
1397db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1398db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                    throw new UnsupportedOperationException(
1399db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                            "This session doesn't support queue management operations");
1400db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                }
1401db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon                mBinder.removeQueueItem(description);
1402db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            } catch (RemoteException e) {
1403e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in removeQueueItem.", e);
1404db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            }
1405db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        }
1406db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
1407db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        @Override
1408aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public CharSequence getQueueTitle() {
1409e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1410e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getQueueTitle();
1411e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1412e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getQueueTitle.", e);
1413e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1414aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1415aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1416aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1417aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1418aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public Bundle getExtras() {
1419e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1420e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getExtras();
1421e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1422e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getExtras.", e);
1423e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1424aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1425aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1426aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1427aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
142824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getRatingType() {
1429e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1430e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getRatingType();
1431e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1432e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getRatingType.", e);
1433e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
143424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return 0;
143524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
143624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
143724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1438e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        public boolean isCaptioningEnabled() {
1439e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            try {
1440e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                return mBinder.isCaptioningEnabled();
1441e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            } catch (RemoteException e) {
1442e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                Log.e(TAG, "Dead object in isCaptioningEnabled.", e);
1443e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            }
1444e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            return false;
1445e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        }
1446e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
1447e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        @Override
144821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public int getRepeatMode() {
14498955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            try {
14508955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                return mBinder.getRepeatMode();
14518955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            } catch (RemoteException e) {
1452e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getRepeatMode.", e);
14538955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            }
145421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return 0;
145521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
145621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
145721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
145821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public boolean isShuffleModeEnabled() {
14598955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            try {
146074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                return mBinder.isShuffleModeEnabledDeprecated();
14618955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            } catch (RemoteException e) {
1462e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in isShuffleModeEnabled.", e);
14638955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            }
146421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return false;
146521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
146621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
146721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
146874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        public int getShuffleMode() {
146974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            try {
147074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                return mBinder.getShuffleMode();
147174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            } catch (RemoteException e) {
147274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                Log.e(TAG, "Dead object in getShuffleMode.", e);
147374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            }
147474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            return 0;
147574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        }
147674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
147774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        @Override
1478aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public long getFlags() {
1479e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1480e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getFlags();
1481e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1482e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getFlags.", e);
1483e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1484aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return 0;
1485aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1486aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1487aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1488312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public PlaybackInfo getPlaybackInfo() {
1489e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1490e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                ParcelableVolumeInfo info = mBinder.getVolumeAttributes();
1491e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                PlaybackInfo pi = new PlaybackInfo(info.volumeType, info.audioStream,
1492e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        info.controlType, info.maxVolume, info.currentVolume);
1493e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return pi;
1494e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1495e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getPlaybackInfo.", e);
1496e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
149724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
149824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
149924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
150024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1501aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public PendingIntent getSessionActivity() {
1502e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1503e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getLaunchPendingIntent();
1504e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1505e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getSessionActivity.", e);
1506e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1507aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1508aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1509aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1510aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1511aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void setVolumeTo(int value, int flags) {
1512e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1513e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.setVolumeTo(value, flags, null);
1514e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1515e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in setVolumeTo.", e);
1516e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1517aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1518aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1519aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1520aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void adjustVolume(int direction, int flags) {
1521e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1522e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.adjustVolume(direction, flags, null);
1523e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1524e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in adjustVolume.", e);
1525e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1526aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1527aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1528aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1529b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        public void sendCommand(String command, Bundle params, ResultReceiver cb) {
1530e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1531e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.sendCommand(command, params,
1532e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        new MediaSessionCompat.ResultReceiverWrapper(cb));
1533e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1534e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in sendCommand.", e);
1535e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
153624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
153724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
153824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1539aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public String getPackageName() {
1540e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1541e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getPackageName();
1542e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1543e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in getPackageName.", e);
1544e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1545aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1546aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1547aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1548aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
154924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public Object getMediaController() {
155024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
155124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
155224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
155324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
1554e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    static class TransportControlsBase extends TransportControls {
1555e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private IMediaSession mBinder;
1556e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1557e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public TransportControlsBase(IMediaSession binder) {
1558e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mBinder = binder;
1559e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1560e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1561e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1562bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepare() {
15635491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
15645491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepare();
15655491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
1566e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in prepare.", e);
15675491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1568bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1569bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1570bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1571bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromMediaId(String mediaId, Bundle extras) {
15725491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
15735491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepareFromMediaId(mediaId, extras);
15745491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
1575e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in prepareFromMediaId.", e);
15765491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1577bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1578bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1579bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1580bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromSearch(String query, Bundle extras) {
15815491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
15825491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepareFromSearch(query, extras);
15835491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
1584e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in prepareFromSearch.", e);
15855491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1586bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1587bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1588bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1589bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromUri(Uri uri, Bundle extras) {
15905491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
15915491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepareFromUri(uri, extras);
15925491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
1593e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in prepareFromUri.", e);
15945491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1595bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1596bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1597bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1598e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void play() {
1599e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1600e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.play();
1601e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1602e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in play.", e);
1603e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1604e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1605e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1606e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1607e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void playFromMediaId(String mediaId, Bundle extras) {
1608e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1609e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.playFromMediaId(mediaId, extras);
1610e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1611e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in playFromMediaId.", e);
1612e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1613e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1614e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1615e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1616e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void playFromSearch(String query, Bundle extras) {
1617e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1618e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.playFromSearch(query, extras);
1619e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1620e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in playFromSearch.", e);
1621e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1622e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1623e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1624e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1625b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public void playFromUri(Uri uri, Bundle extras) {
1626b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            try {
1627b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake                mBinder.playFromUri(uri, extras);
1628b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            } catch (RemoteException e) {
1629e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in playFromUri.", e);
1630b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            }
1631b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1632b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1633b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
1634e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void skipToQueueItem(long id) {
1635e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1636e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.skipToQueueItem(id);
1637e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1638e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in skipToQueueItem.", e);
1639e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1640e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1641e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1642e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1643e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void pause() {
1644e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1645e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.pause();
1646e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1647e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in pause.", e);
1648e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1649e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1650e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1651e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1652e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void stop() {
1653e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1654e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.stop();
1655e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1656e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in stop.", e);
1657e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1658e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1659e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1660e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1661e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void seekTo(long pos) {
1662e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1663e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.seekTo(pos);
1664e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1665e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in seekTo.", e);
1666e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1667e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1668e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1669e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1670e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void fastForward() {
1671e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1672e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.fastForward();
1673e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1674e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in fastForward.", e);
1675e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1676e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1677e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1678e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1679e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void skipToNext() {
1680e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1681e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.next();
1682e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1683e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in skipToNext.", e);
1684e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1685e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1686e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1687e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1688e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void rewind() {
1689e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1690e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.rewind();
1691e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1692e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in rewind.", e);
1693e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1694e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1695e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1696e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1697e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void skipToPrevious() {
1698e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1699e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.previous();
1700e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1701e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in skipToPrevious.", e);
1702e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1703e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1704e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1705e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1706e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void setRating(RatingCompat rating) {
1707e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1708e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.rate(rating);
1709e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1710e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in setRating.", e);
1711e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1712e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1713e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1714e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1715e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        public void setCaptioningEnabled(boolean enabled) {
1716e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            try {
1717e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                mBinder.setCaptioningEnabled(enabled);
1718e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            } catch (RemoteException e) {
1719e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                Log.e(TAG, "Dead object in setCaptioningEnabled.", e);
1720e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            }
1721e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        }
1722e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
1723e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        @Override
172421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode) {
17258955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            try {
17268955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon                mBinder.setRepeatMode(repeatMode);
17278955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            } catch (RemoteException e) {
1728e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in setRepeatMode.", e);
17298955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            }
173021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
173121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
173221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
173321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setShuffleModeEnabled(boolean enabled) {
17348955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            try {
173574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                mBinder.setShuffleModeEnabledDeprecated(enabled);
17368955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            } catch (RemoteException e) {
1737e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in setShuffleModeEnabled.", e);
17388955729d97dd15a512f5396b299784a96f2a44e4Hyundo Moon            }
173921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
174021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
174121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
174274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        public void setShuffleMode(@PlaybackStateCompat.ShuffleMode int shuffleMode) {
174374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            try {
174474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                mBinder.setShuffleMode(shuffleMode);
174574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            } catch (RemoteException e) {
174674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                Log.e(TAG, "Dead object in setShuffleMode.", e);
174774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            }
174874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        }
174974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
175074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        @Override
1751e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void sendCustomAction(CustomAction customAction, Bundle args) {
1752e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            sendCustomAction(customAction.getAction(), args);
1753e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1754e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1755e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1756e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void sendCustomAction(String action, Bundle args) {
1757fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho            validateCustomAction(action, args);
1758e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1759e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.sendCustomAction(action, args);
1760e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1761e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                Log.e(TAG, "Dead object in sendCustomAction.", e);
1762e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1763e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1764e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    }
1765e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1766c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(21)
176724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    static class MediaControllerImplApi21 implements MediaControllerImpl {
1768b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        protected final Object mControllerObj;
176924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
177026444949f9bec919a5fd09772a22d6d9a63ee8edHyundo Moon        private final List<Callback> mPendingCallbacks = new ArrayList<>();
177126444949f9bec919a5fd09772a22d6d9a63ee8edHyundo Moon
177224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        // Extra binder is used for applying the framework change of new APIs and bug fixes
177324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        // after API 21.
177424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        private IMediaSession mExtraBinder;
177524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        private HashMap<Callback, ExtraCallback> mCallbackMap = new HashMap<>();
177624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
177724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaControllerImplApi21(Context context, MediaSessionCompat session) {
17785c41750574ba65da432b69f89cd32dc356281005RoboErik            mControllerObj = MediaControllerCompatApi21.fromToken(context,
177924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                    session.getSessionToken().getToken());
1780b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo            mExtraBinder = session.getSessionToken().getExtraBinder();
1781b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo            if (mExtraBinder == null) {
1782b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo                requestExtraBinder();
1783b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo            }
178424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
178524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
178624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaControllerImplApi21(Context context, MediaSessionCompat.Token sessionToken)
178724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                throws RemoteException {
17885c41750574ba65da432b69f89cd32dc356281005RoboErik            mControllerObj = MediaControllerCompatApi21.fromToken(context,
178924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                    sessionToken.getToken());
179024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            if (mControllerObj == null) throw new RemoteException();
1791b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo            mExtraBinder = sessionToken.getExtraBinder();
1792b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo            if (mExtraBinder == null) {
1793b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo                requestExtraBinder();
1794b8adc9a8c558abc70c3ec0694c88c7e7ab4a9d86Sungsoo            }
179524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
179624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
179724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
179824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        public final void registerCallback(Callback callback, Handler handler) {
179924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            MediaControllerCompatApi21.registerCallback(
180024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    mControllerObj, callback.mCallbackObj, handler);
180124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            if (mExtraBinder != null) {
180224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                callback.setHandler(handler);
180324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                ExtraCallback extraCallback = new ExtraCallback(callback);
180424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                mCallbackMap.put(callback, extraCallback);
180524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                callback.mHasExtraCallback = true;
180624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                try {
180724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    mExtraBinder.registerCallbackListener(extraCallback);
180824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                } catch (RemoteException e) {
1809e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                    Log.e(TAG, "Dead object in registerCallback.", e);
181024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
1811447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho            } else {
181224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                callback.setHandler(handler);
1813447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                synchronized (mPendingCallbacks) {
1814447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    mPendingCallbacks.add(callback);
1815447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                }
181624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
181724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
181824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
181924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
182024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        public final void unregisterCallback(Callback callback) {
182116ac83bebda2a19930b9d692789f3b507c49951bRoboErik            MediaControllerCompatApi21.unregisterCallback(mControllerObj, callback.mCallbackObj);
182224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            if (mExtraBinder != null) {
182324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                try {
182424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    ExtraCallback extraCallback = mCallbackMap.remove(callback);
182524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    if (extraCallback != null) {
182624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                        mExtraBinder.unregisterCallbackListener(extraCallback);
182724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    }
182824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                } catch (RemoteException e) {
1829e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                    Log.e(TAG, "Dead object in unregisterCallback.", e);
183024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
1831447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho            } else {
1832447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                synchronized (mPendingCallbacks) {
1833447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    mPendingCallbacks.remove(callback);
183424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
183524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
183624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
183724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
183824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
183924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public boolean dispatchMediaButtonEvent(KeyEvent event) {
184024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return MediaControllerCompatApi21.dispatchMediaButtonEvent(mControllerObj, event);
184124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
184224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
184324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
184424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public TransportControls getTransportControls() {
18451435afe32073dee10e721dfb6122ce6a194a6412RoboErik            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
184624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return controlsObj != null ? new TransportControlsApi21(controlsObj) : null;
184724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
184824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
184924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
185024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public PlaybackStateCompat getPlaybackState() {
1851a627c31cf8b6e99db03842dfc6864133bedd0f88Donghyun Cho            if (mExtraBinder != null) {
185224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                try {
185324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    return mExtraBinder.getPlaybackState();
185424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                } catch (RemoteException e) {
1855e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                    Log.e(TAG, "Dead object in getPlaybackState.", e);
185624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
185724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
185824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            Object stateObj = MediaControllerCompatApi21.getPlaybackState(mControllerObj);
185924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return stateObj != null ? PlaybackStateCompat.fromPlaybackState(stateObj) : null;
186024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
186124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
186224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
186324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaMetadataCompat getMetadata() {
186424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            Object metadataObj = MediaControllerCompatApi21.getMetadata(mControllerObj);
186524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return metadataObj != null ? MediaMetadataCompat.fromMediaMetadata(metadataObj) : null;
186624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
186724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
186824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
186965cde2c4554985493a2e7560b5e71c5f24969287Sungsoo        public List<QueueItem> getQueue() {
1870aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            List<Object> queueObjs = MediaControllerCompatApi21.getQueue(mControllerObj);
187165cde2c4554985493a2e7560b5e71c5f24969287Sungsoo            return queueObjs != null ? QueueItem.fromQueueItemList(queueObjs) : null;
1872aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1873aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1874aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1875db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        public void addQueueItem(MediaDescriptionCompat description) {
1876c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            long flags = getFlags();
1877c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1878c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon                throw new UnsupportedOperationException(
1879c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon                        "This session doesn't support queue management operations");
1880c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            }
1881db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            Bundle params = new Bundle();
1882db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
1883db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            sendCommand(COMMAND_ADD_QUEUE_ITEM, params, null);
1884db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        }
1885db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
1886db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        @Override
1887db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        public void addQueueItem(MediaDescriptionCompat description, int index) {
1888c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            long flags = getFlags();
1889c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1890c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon                throw new UnsupportedOperationException(
1891c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon                        "This session doesn't support queue management operations");
1892c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            }
1893db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            Bundle params = new Bundle();
1894db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
1895db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            params.putInt(COMMAND_ARGUMENT_INDEX, index);
1896db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            sendCommand(COMMAND_ADD_QUEUE_ITEM_AT, params, null);
1897db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        }
1898db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
1899db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        @Override
1900db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        public void removeQueueItem(MediaDescriptionCompat description) {
1901c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            long flags = getFlags();
1902c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
1903c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon                throw new UnsupportedOperationException(
1904c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon                        "This session doesn't support queue management operations");
1905c10aca3fa402839d997db961d88d34b0d82ee7d7Hyundo Moon            }
1906db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            Bundle params = new Bundle();
1907db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
1908db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon            sendCommand(COMMAND_REMOVE_QUEUE_ITEM, params, null);
1909db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        }
1910db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon
1911db6b58731980f2972bfec455abbf2b82ad773a8dHyundo Moon        @Override
1912aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public CharSequence getQueueTitle() {
1913aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getQueueTitle(mControllerObj);
1914aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1915aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1916aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1917aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public Bundle getExtras() {
1918aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getExtras(mControllerObj);
1919aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1920aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1921aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
192224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getRatingType() {
192324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            if (android.os.Build.VERSION.SDK_INT < 22 && mExtraBinder != null) {
192424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                try {
192524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    return mExtraBinder.getRatingType();
192624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                } catch (RemoteException e) {
1927e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                    Log.e(TAG, "Dead object in getRatingType.", e);
192824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
192924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
193024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return MediaControllerCompatApi21.getRatingType(mControllerObj);
193124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
193224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
193324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1934e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        public boolean isCaptioningEnabled() {
1935e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            if (mExtraBinder != null) {
1936e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                try {
1937e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                    return mExtraBinder.isCaptioningEnabled();
1938e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                } catch (RemoteException e) {
1939e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                    Log.e(TAG, "Dead object in isCaptioningEnabled.", e);
1940e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                }
1941e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            }
1942e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            return false;
1943e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        }
1944e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
1945e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        @Override
194621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public int getRepeatMode() {
19477598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            if (mExtraBinder != null) {
19487598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                try {
19497598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                    return mExtraBinder.getRepeatMode();
19507598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                } catch (RemoteException e) {
1951e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                    Log.e(TAG, "Dead object in getRepeatMode.", e);
19527598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                }
19537598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            }
19547598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            return PlaybackStateCompat.REPEAT_MODE_NONE;
195521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
195621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
195721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
195821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public boolean isShuffleModeEnabled() {
19597598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            if (mExtraBinder != null) {
19607598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                try {
196174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    return mExtraBinder.isShuffleModeEnabledDeprecated();
19627598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                } catch (RemoteException e) {
1963e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                    Log.e(TAG, "Dead object in isShuffleModeEnabled.", e);
19647598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                }
19657598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            }
196621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return false;
196721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
196821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
196921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
197074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        public int getShuffleMode() {
197174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            if (mExtraBinder != null) {
197274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                try {
197374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    return mExtraBinder.getShuffleMode();
197474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                } catch (RemoteException e) {
197574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    Log.e(TAG, "Dead object in getShuffleMode.", e);
197674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                }
197774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            }
197874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            return PlaybackStateCompat.SHUFFLE_MODE_NONE;
197974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        }
198074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
198174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        @Override
1982aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public long getFlags() {
1983aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getFlags(mControllerObj);
1984aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1985aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1986aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1987312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public PlaybackInfo getPlaybackInfo() {
1988312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            Object volumeInfoObj = MediaControllerCompatApi21.getPlaybackInfo(mControllerObj);
1989312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            return volumeInfoObj != null ? new PlaybackInfo(
1990312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getPlaybackType(volumeInfoObj),
1991312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getLegacyAudioStream(volumeInfoObj),
1992312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getVolumeControl(volumeInfoObj),
1993312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getMaxVolume(volumeInfoObj),
1994312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getCurrentVolume(volumeInfoObj)) : null;
199524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
199624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
199724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1998aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public PendingIntent getSessionActivity() {
1999aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getSessionActivity(mControllerObj);
2000aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2001aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2002aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2003aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void setVolumeTo(int value, int flags) {
2004aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.setVolumeTo(mControllerObj, value, flags);
2005aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2006aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2007aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2008aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void adjustVolume(int direction, int flags) {
2009aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.adjustVolume(mControllerObj, direction, flags);
2010aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2011aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2012aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2013b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        public void sendCommand(String command, Bundle params, ResultReceiver cb) {
2014b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal            MediaControllerCompatApi21.sendCommand(mControllerObj, command, params, cb);
201524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
201624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
201724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
2018aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public String getPackageName() {
2019aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getPackageName(mControllerObj);
2020aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2021aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2022aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
202324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public Object getMediaController() {
202424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mControllerObj;
202524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
202624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
202724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        private void requestExtraBinder() {
2028208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            sendCommand(COMMAND_GET_EXTRA_BINDER, null,
2029208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                    new ExtraBinderRequestResultReceiver(this, new Handler()));
2030208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho        }
2031208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho
2032208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho        private void processPendingCallbacks() {
2033447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho            if (mExtraBinder == null) {
2034208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                return;
2035208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            }
2036447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho            synchronized (mPendingCallbacks) {
2037447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                for (Callback callback : mPendingCallbacks) {
2038447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    ExtraCallback extraCallback = new ExtraCallback(callback);
2039447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    mCallbackMap.put(callback, extraCallback);
2040447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    callback.mHasExtraCallback = true;
2041447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    try {
2042447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                        mExtraBinder.registerCallbackListener(extraCallback);
2043447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    } catch (RemoteException e) {
2044e6e4fd277b5d364067cbd67865bf91e3e0cd5cb6Chulwoo Lee                        Log.e(TAG, "Dead object in registerCallback.", e);
2045447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                        break;
2046447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                    }
204724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                }
2048447e08a8c75f6eeb9b499bb0b65025e4f1432a74Donghyun Cho                mPendingCallbacks.clear();
2049208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            }
2050208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho        }
2051208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho
2052208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho        private static class ExtraBinderRequestResultReceiver extends ResultReceiver {
2053208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            private WeakReference<MediaControllerImplApi21> mMediaControllerImpl;
2054208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho
2055208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            public ExtraBinderRequestResultReceiver(MediaControllerImplApi21 mediaControllerImpl,
2056208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                    Handler handler) {
2057208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                super(handler);
2058208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                mMediaControllerImpl = new WeakReference<>(mediaControllerImpl);
2059208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            }
2060208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho
2061208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            @Override
2062208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            protected void onReceiveResult(int resultCode, Bundle resultData) {
2063208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                MediaControllerImplApi21 mediaControllerImpl = mMediaControllerImpl.get();
2064208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                if (mediaControllerImpl == null || resultData == null) {
2065208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                    return;
2066208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                }
2067208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                mediaControllerImpl.mExtraBinder = IMediaSession.Stub.asInterface(
2068208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                        BundleCompat.getBinder(resultData, MediaSessionCompat.EXTRA_BINDER));
2069208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho                mediaControllerImpl.processPendingCallbacks();
2070208f5a7ab7c9a101bc88ab131b0815173132c78aDonghyun Cho            }
207124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        }
207224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
207326444949f9bec919a5fd09772a22d6d9a63ee8edHyundo Moon        private static class ExtraCallback extends IMediaControllerCallback.Stub {
207424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            private Callback mCallback;
207524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
207624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            ExtraCallback(Callback callback) {
207724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                mCallback = callback;
207824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
207924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
208024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
208124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onEvent(final String event, final Bundle extras) throws RemoteException {
208224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                mCallback.mHandler.post(new Runnable() {
208324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    @Override
208424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    public void run() {
208524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                        mCallback.onSessionEvent(event, extras);
208624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    }
208724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                });
208824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
208924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
209024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
209124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onSessionDestroyed() throws RemoteException {
209224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                // Will not be called.
209324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                throw new AssertionError();
209424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
209524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
209624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
209724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onPlaybackStateChanged(final PlaybackStateCompat state)
209824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    throws RemoteException {
209924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                mCallback.mHandler.post(new Runnable() {
210024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    @Override
210124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    public void run() {
210224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                        mCallback.onPlaybackStateChanged(state);
210324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                    }
210424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                });
210524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
210624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
210724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
210824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onMetadataChanged(MediaMetadataCompat metadata) throws RemoteException {
210924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                // Will not be called.
211024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                throw new AssertionError();
211124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
211224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
211324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
211424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onQueueChanged(List<QueueItem> queue) throws RemoteException {
211524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                // Will not be called.
211624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                throw new AssertionError();
211724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
211824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
211924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
212024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onQueueTitleChanged(CharSequence title) throws RemoteException {
212124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                // Will not be called.
212224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                throw new AssertionError();
212324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
212424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
212524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
2126e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            public void onCaptioningEnabledChanged(final boolean enabled) throws RemoteException {
2127e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                mCallback.mHandler.post(new Runnable() {
2128e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                    @Override
2129e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                    public void run() {
2130e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                        mCallback.onCaptioningEnabledChanged(enabled);
2131e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                    }
2132e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho                });
2133e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            }
2134e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
2135e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            @Override
21367598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            public void onRepeatModeChanged(final int repeatMode) throws RemoteException {
21377598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                mCallback.mHandler.post(new Runnable() {
21387598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                    @Override
21397598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                    public void run() {
21407598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                        mCallback.onRepeatModeChanged(repeatMode);
21417598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                    }
21427598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                });
214324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
214424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
214524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
214674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            public void onShuffleModeChangedDeprecated(final boolean enabled)
214774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    throws RemoteException {
21487598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                mCallback.mHandler.post(new Runnable() {
21497598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                    @Override
21507598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                    public void run() {
21517598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                        mCallback.onShuffleModeChanged(enabled);
21527598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                    }
21537598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon                });
215424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
215524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
215624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
215774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            public void onShuffleModeChanged(final int shuffleMode) throws RemoteException {
215874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                mCallback.mHandler.post(new Runnable() {
215974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    @Override
216074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    public void run() {
216174198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                        mCallback.onShuffleModeChanged(shuffleMode);
216274198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                    }
216374198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon                });
216474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            }
216574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
216674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            @Override
216724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onExtrasChanged(Bundle extras) throws RemoteException {
216824b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                // Will not be called.
216924b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                throw new AssertionError();
217024b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
217124b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo
217224b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            @Override
217324b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException {
217424b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                // Will not be called.
217524b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo                throw new AssertionError();
217624b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo            }
217724b728a673504b26d9c46f0a24d184a5d9e726b6Sungsoo        }
217824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
217924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
218024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    static class TransportControlsApi21 extends TransportControls {
2181b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        protected final Object mControlsObj;
218224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
218324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public TransportControlsApi21(Object controlsObj) {
218424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mControlsObj = controlsObj;
218524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
218624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
218724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
2188bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepare() {
2189993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE, null);
2190bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2191bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2192bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2193bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromMediaId(String mediaId, Bundle extras) {
2194993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            Bundle bundle = new Bundle();
2195993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putString(MediaSessionCompat.ACTION_ARGUMENT_MEDIA_ID, mediaId);
2196993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
2197993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_MEDIA_ID, bundle);
2198bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2199bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2200bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2201bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromSearch(String query, Bundle extras) {
2202993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            Bundle bundle = new Bundle();
2203993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putString(MediaSessionCompat.ACTION_ARGUMENT_QUERY, query);
2204993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
2205993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_SEARCH, bundle);
2206bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2207bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2208bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2209bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromUri(Uri uri, Bundle extras) {
2210993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            Bundle bundle = new Bundle();
2211993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_URI, uri);
2212993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
2213993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_URI, bundle);
2214bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2215bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2216bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
221724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void play() {
221824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.play(mControlsObj);
221924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
222024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
222124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
222224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void pause() {
222324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.pause(mControlsObj);
222424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
222524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
222624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
222724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void stop() {
222824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.stop(mControlsObj);
222924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
223024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
223124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
223224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void seekTo(long pos) {
223324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.seekTo(mControlsObj, pos);
223424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
223524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
223624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
223724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void fastForward() {
223824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.fastForward(mControlsObj);
223924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
224024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
224124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
224224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void rewind() {
224324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.rewind(mControlsObj);
224424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
224524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
224624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
224724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void skipToNext() {
224824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.skipToNext(mControlsObj);
224924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
225024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
225124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
225224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void skipToPrevious() {
225324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.skipToPrevious(mControlsObj);
225424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
225524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
225624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
225724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void setRating(RatingCompat rating) {
225824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.setRating(mControlsObj,
225924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                    rating != null ? rating.getRating() : null);
226024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
2261aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2262aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2263e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        public void setCaptioningEnabled(boolean enabled) {
2264e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            Bundle bundle = new Bundle();
2265e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            bundle.putBoolean(MediaSessionCompat.ACTION_ARGUMENT_CAPTIONING_ENABLED, enabled);
2266e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_SET_CAPTIONING_ENABLED, bundle);
2267e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        }
2268e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho
2269e90c068c82ce62a0069c4e88f6b26e92468231d6Donghyun Cho        @Override
227021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode) {
22717598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            Bundle bundle = new Bundle();
22727598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            bundle.putInt(MediaSessionCompat.ACTION_ARGUMENT_REPEAT_MODE, repeatMode);
22737598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            sendCustomAction(MediaSessionCompat.ACTION_SET_REPEAT_MODE, bundle);
227421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
227521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
227621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
227721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setShuffleModeEnabled(boolean enabled) {
22787598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            Bundle bundle = new Bundle();
22797598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            bundle.putBoolean(MediaSessionCompat.ACTION_ARGUMENT_SHUFFLE_MODE_ENABLED, enabled);
22807598c3b9e75b61e7fe3853329032a3c7f8cef6f7Hyundo Moon            sendCustomAction(MediaSessionCompat.ACTION_SET_SHUFFLE_MODE_ENABLED, bundle);
228121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
228221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
228321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
228474198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        public void setShuffleMode(@PlaybackStateCompat.ShuffleMode int shuffleMode) {
228574198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            Bundle bundle = new Bundle();
228674198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            bundle.putInt(MediaSessionCompat.ACTION_ARGUMENT_SHUFFLE_MODE, shuffleMode);
228774198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon            sendCustomAction(MediaSessionCompat.ACTION_SET_SHUFFLE_MODE, bundle);
228874198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        }
228974198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon
229074198cdcc6e4f53c7c6586d99ff727886de2441aHyundo Moon        @Override
2291aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void playFromMediaId(String mediaId, Bundle extras) {
2292aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.playFromMediaId(mControlsObj, mediaId,
2293aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    extras);
2294aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2295aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2296aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2297aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void playFromSearch(String query, Bundle extras) {
2298aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.playFromSearch(mControlsObj, query,
2299aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    extras);
2300aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2301aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2302aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2303b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public void playFromUri(Uri uri, Bundle extras) {
23044b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            if (uri == null || Uri.EMPTY.equals(uri)) {
23054b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho                throw new IllegalArgumentException(
23064b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho                        "You must specify a non-empty Uri for playFromUri.");
23074b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            }
23084b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            Bundle bundle = new Bundle();
23094b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_URI, uri);
23104b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
23114b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PLAY_FROM_URI, bundle);
2312b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
2313b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2314b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
2315aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void skipToQueueItem(long id) {
2316aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.skipToQueueItem(mControlsObj, id);
2317aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2318aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2319aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2320aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void sendCustomAction(CustomAction customAction, Bundle args) {
2321fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho            validateCustomAction(customAction.getAction(), args);
2322aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj,
2323aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    customAction.getAction(), args);
2324aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
2325aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
2326aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
2327aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void sendCustomAction(String action, Bundle args) {
2328fe64c4572037c6464b0b77e06213750c0e92ace2Donghyun Cho            validateCustomAction(action, args);
2329aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj, action,
2330aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    args);
2331aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
233224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
2333b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2334c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(23)
2335b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    static class MediaControllerImplApi23 extends MediaControllerImplApi21 {
2336b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2337b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public MediaControllerImplApi23(Context context, MediaSessionCompat session) {
2338b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            super(context, session);
2339b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
2340b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2341b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public MediaControllerImplApi23(Context context, MediaSessionCompat.Token sessionToken)
2342b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake                throws RemoteException {
2343b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            super(context, sessionToken);
2344b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
2345b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2346b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
2347b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public TransportControls getTransportControls() {
2348b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
2349b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            return controlsObj != null ? new TransportControlsApi23(controlsObj) : null;
2350b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
2351b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    }
2352b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2353c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(23)
2354b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    static class TransportControlsApi23 extends TransportControlsApi21 {
2355b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2356b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public TransportControlsApi23(Object controlsObj) {
2357b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            super(controlsObj);
2358b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
2359b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
2360b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
2361b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public void playFromUri(Uri uri, Bundle extras) {
2362b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            MediaControllerCompatApi23.TransportControls.playFromUri(mControlsObj, uri,
2363b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake                    extras);
2364b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
2365b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    }
2366bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2367c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(24)
2368bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    static class MediaControllerImplApi24 extends MediaControllerImplApi23 {
2369bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2370bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public MediaControllerImplApi24(Context context, MediaSessionCompat session) {
2371bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            super(context, session);
2372bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2373bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2374bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public MediaControllerImplApi24(Context context, MediaSessionCompat.Token sessionToken)
2375bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho                throws RemoteException {
2376bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            super(context, sessionToken);
2377bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2378bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2379bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2380bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public TransportControls getTransportControls() {
2381bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
2382bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            return controlsObj != null ? new TransportControlsApi24(controlsObj) : null;
2383bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2384bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    }
2385bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2386c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(24)
2387bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    static class TransportControlsApi24 extends TransportControlsApi23 {
2388bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2389bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public TransportControlsApi24(Object controlsObj) {
2390bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            super(controlsObj);
2391bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2392bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2393bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2394bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepare() {
2395bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepare(mControlsObj);
2396bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2397bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2398bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2399bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromMediaId(String mediaId, Bundle extras) {
2400bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepareFromMediaId(
2401bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho                    mControlsObj, mediaId, extras);
2402bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2403bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2404bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2405bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromSearch(String query, Bundle extras) {
2406bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepareFromSearch(
2407bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho                    mControlsObj, query, extras);
2408bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2409bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
2410bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
2411bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromUri(Uri uri, Bundle extras) {
2412bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepareFromUri(mControlsObj, uri, extras);
2413bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
2414bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    }
241524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
2416