MediaControllerCompat.java revision 21ecb1a40992b5e478a6a7fe115da40d060b198a
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
19aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.app.PendingIntent;
2024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.content.Context;
21aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.media.AudioManager;
22aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.net.Uri;
2324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Bundle;
2424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Handler;
25e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.IBinder;
26e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.Looper;
27e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.Message;
2824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.RemoteException;
2924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.ResultReceiver;
3024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.MediaMetadataCompat;
3124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.RatingCompat;
3224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.VolumeProviderCompat;
33e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.support.v4.media.session.MediaSessionCompat.QueueItem;
34aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport android.support.v4.media.session.PlaybackStateCompat.CustomAction;
3524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.text.TextUtils;
36e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.util.Log;
3724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.view.KeyEvent;
3824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
39aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErikimport java.util.List;
40aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
4124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown/**
4224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Allows an app to interact with an ongoing media session. Media buttons and
4324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * other commands can be sent to the session. A callback may be registered to
4424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * receive updates from the session, such as metadata and play state changes.
4524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p>
4624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * A MediaController can be created if you have a {@link MediaSessionCompat.Token}
4724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * from the session owner.
4824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p>
4924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * MediaController objects are thread-safe.
5024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p>
5124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * This is a helper for accessing features in {@link android.media.session.MediaSession}
5224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * introduced after API level 4 in a backwards compatible fashion.
5324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */
5424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownpublic final class MediaControllerCompat {
55b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas    static final String TAG = "MediaControllerCompat";
56e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
5724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    private final MediaControllerImpl mImpl;
5894be6100218126ce6a08bf1f56209578500b361fRoboErik    private final MediaSessionCompat.Token mToken;
5924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
6024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
6124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Creates a media controller from a session.
6224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
6324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param session The session to be controlled.
6424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
6524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public MediaControllerCompat(Context context, MediaSessionCompat session) {
6624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (session == null) {
6724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("session must not be null");
6824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
6994be6100218126ce6a08bf1f56209578500b361fRoboErik        mToken = session.getSessionToken();
7024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
7121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        if (android.os.Build.VERSION.SDK_INT >= 25) {
7221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            mImpl = new MediaControllerImplApi25(context, session);
7321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        } else if (android.os.Build.VERSION.SDK_INT >= 24) {
74bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            mImpl = new MediaControllerImplApi24(context, session);
75bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        } else if (android.os.Build.VERSION.SDK_INT >= 23) {
76b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            mImpl = new MediaControllerImplApi23(context, session);
77b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
7824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mImpl = new MediaControllerImplApi21(context, session);
7924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        } else {
80e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mImpl = new MediaControllerImplBase(mToken);
8124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
8224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
8324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
8424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
8524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Creates a media controller from a session token which may have
8624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * been obtained from another process.
8724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
8824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param sessionToken The token of the session to be controlled.
8924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @throws RemoteException if the session is not accessible.
9024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
9124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public MediaControllerCompat(Context context, MediaSessionCompat.Token sessionToken)
9224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throws RemoteException {
9324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (sessionToken == null) {
9424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("sessionToken must not be null");
9524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
9694be6100218126ce6a08bf1f56209578500b361fRoboErik        mToken = sessionToken;
9724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
9821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        if (android.os.Build.VERSION.SDK_INT >= 25) {
9921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            mImpl = new MediaControllerImplApi25(context, sessionToken);
10021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        } else if (android.os.Build.VERSION.SDK_INT >= 24) {
101bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            mImpl = new MediaControllerImplApi24(context, sessionToken);
102bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        } else if (android.os.Build.VERSION.SDK_INT >= 23) {
103bbc4b0e06a9e5868cf0c44b2b3ec24fb6ca00b2cDonghyun Cho            mImpl = new MediaControllerImplApi23(context, sessionToken);
104bbc4b0e06a9e5868cf0c44b2b3ec24fb6ca00b2cDonghyun Cho        } else if (android.os.Build.VERSION.SDK_INT >= 21) {
10524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mImpl = new MediaControllerImplApi21(context, sessionToken);
10624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        } else {
107e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mImpl = new MediaControllerImplBase(mToken);
10824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
10924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
11024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
11124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
11224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get a {@link TransportControls} instance for this session.
11324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
11424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return A controls instance
11524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
11624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public TransportControls getTransportControls() {
11724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getTransportControls();
11824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
11924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
12024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
12124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Send the specified media button event to the session. Only media keys can
12224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * be sent by this method, other keys will be ignored.
12324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
12424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param keyEvent The media button event to dispatch.
12524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return true if the event was sent to the session, false otherwise.
12624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
12724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public boolean dispatchMediaButtonEvent(KeyEvent keyEvent) {
12824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (keyEvent == null) {
12924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("KeyEvent may not be null");
13024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
13124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.dispatchMediaButtonEvent(keyEvent);
13224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
13324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
13424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
13524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get the current playback state for this session.
13624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
13724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return The current PlaybackState or null
13824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
13924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public PlaybackStateCompat getPlaybackState() {
14024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getPlaybackState();
14124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
14224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
14324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
14424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get the current metadata for this session.
14524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
14624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return The current MediaMetadata or null.
14724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
14824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public MediaMetadataCompat getMetadata() {
14924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getMetadata();
15024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
15124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
15224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
153aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the current play queue for this session if one is set. If you only
154aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * care about the current item {@link #getMetadata()} should be used.
155aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
156aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The current play queue or null.
157aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
158aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public List<MediaSessionCompat.QueueItem> getQueue() {
159aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getQueue();
160aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
161aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
162aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
163aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the queue title for this session.
164aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
165aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public CharSequence getQueueTitle() {
166aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getQueueTitle();
167aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
168aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
169aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
170aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the extras for this session.
171aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
172aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public Bundle getExtras() {
173aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getExtras();
174aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
175aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
176aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
17724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Get the rating type supported by the session. One of:
17824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <ul>
17924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_NONE}</li>
18024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_HEART}</li>
18124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_THUMB_UP_DOWN}</li>
18224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_3_STARS}</li>
18324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_4_STARS}</li>
18424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_5_STARS}</li>
18524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <li>{@link RatingCompat#RATING_PERCENTAGE}</li>
18624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * </ul>
18724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
18824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @return The supported rating type
18924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
19024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public int getRatingType() {
19124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getRatingType();
19224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
19324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
19424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
19521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * Get the repeat mode for this session.
19621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     *
19721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * @return The latest repeat mode set to the session, or
19821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     *         {@link PlaybackStateCompat#REPEAT_MODE_NONE} if not set.
19921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     */
20021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    public int getRepeatMode() {
20121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        return mImpl.getRepeatMode();
20221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    }
20321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
20421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    /**
20521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * Return whether the shuffle mode is enabled for this session.
20621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     *
20721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     * @return {@code true} if the shuffle mode is enabled, {@code false} if disabled or not set.
20821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon     */
20921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    public boolean isShuffleModeEnabled() {
21021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        return mImpl.isShuffleModeEnabled();
21121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    }
21221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
21321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    /**
214aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the flags for this session. Flags are defined in
215aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link MediaSessionCompat}.
216aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
217aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The current set of flags for the session.
218aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
219aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public long getFlags() {
220aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getFlags();
221aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
222aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
223aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
224312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik     * Get the current playback info for this session.
22524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
226312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik     * @return The current playback info or null.
22724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
228312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik    public PlaybackInfo getPlaybackInfo() {
229312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        return mImpl.getPlaybackInfo();
23024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
23124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
23224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
233aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get an intent for launching UI associated with this session if one
234aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * exists.
235aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
236aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return A {@link PendingIntent} to launch UI or null.
237aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
238aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public PendingIntent getSessionActivity() {
239aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getSessionActivity();
240aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
241aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
242aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
24394be6100218126ce6a08bf1f56209578500b361fRoboErik     * Get the token for the session this controller is connected to.
24494be6100218126ce6a08bf1f56209578500b361fRoboErik     *
24594be6100218126ce6a08bf1f56209578500b361fRoboErik     * @return The session's token.
24694be6100218126ce6a08bf1f56209578500b361fRoboErik     */
24794be6100218126ce6a08bf1f56209578500b361fRoboErik    public MediaSessionCompat.Token getSessionToken() {
24894be6100218126ce6a08bf1f56209578500b361fRoboErik        return mToken;
24994be6100218126ce6a08bf1f56209578500b361fRoboErik    }
25094be6100218126ce6a08bf1f56209578500b361fRoboErik
25194be6100218126ce6a08bf1f56209578500b361fRoboErik    /**
252aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Set the volume of the output this session is playing on. The command will
253aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * be ignored if it does not support
254aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in
255aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link AudioManager} may be used to affect the handling.
256aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
257aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @see #getPlaybackInfo()
258aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param value The value to set it to, between 0 and the reported max.
259aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param flags Flags from {@link AudioManager} to include with the volume
260aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *            request.
261aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
262aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public void setVolumeTo(int value, int flags) {
263aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        mImpl.setVolumeTo(value, flags);
264aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
265aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
266aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
267aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Adjust the volume of the output this session is playing on. The direction
268aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * must be one of {@link AudioManager#ADJUST_LOWER},
269aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}.
270aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * The command will be ignored if the session does not support
271aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE} or
272aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}. The flags in
273aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link AudioManager} may be used to affect the handling.
274aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
275aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @see #getPlaybackInfo()
276aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param direction The direction to adjust the volume in.
277aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @param flags Any flags to pass with the command.
278aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
279aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public void adjustVolume(int direction, int flags) {
280aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        mImpl.adjustVolume(direction, flags);
281aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
282aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
283aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
28424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Adds a callback to receive updates from the Session. Updates will be
28524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * posted on the caller's thread.
28624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
28724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param callback The callback object, must not be null.
28824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
28916ac83bebda2a19930b9d692789f3b507c49951bRoboErik    public void registerCallback(Callback callback) {
29016ac83bebda2a19930b9d692789f3b507c49951bRoboErik        registerCallback(callback, null);
29124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
29224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
29324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
29424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Adds a callback to receive updates from the session. Updates will be
29524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * posted on the specified handler's thread.
29624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
29724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param callback The callback object, must not be null.
29824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param handler The handler to post updates on. If null the callers thread
29924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *            will be used.
30024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
30116ac83bebda2a19930b9d692789f3b507c49951bRoboErik    public void registerCallback(Callback callback, Handler handler) {
30224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (callback == null) {
30324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("callback cannot be null");
30424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
30524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (handler == null) {
30624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            handler = new Handler();
30724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
30816ac83bebda2a19930b9d692789f3b507c49951bRoboErik        mImpl.registerCallback(callback, handler);
30924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
31024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
31124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
31224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Stop receiving updates on the specified callback. If an update has
31324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * already been posted you may still receive it after calling this method.
31424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
31524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param callback The callback to remove
31624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
31716ac83bebda2a19930b9d692789f3b507c49951bRoboErik    public void unregisterCallback(Callback callback) {
31824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (callback == null) {
31924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("callback cannot be null");
32024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
32116ac83bebda2a19930b9d692789f3b507c49951bRoboErik        mImpl.unregisterCallback(callback);
32224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
32324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
32424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
32524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Sends a generic command to the session. It is up to the session creator
32624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * to decide what commands and parameters they will support. As such,
32724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * commands should only be sent to sessions that the controller owns.
32824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
32924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param command The command to send
33024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param params Any parameters to include with the command
33124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * @param cb The callback to receive the result on
33224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
333b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal    public void sendCommand(String command, Bundle params, ResultReceiver cb) {
33424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        if (TextUtils.isEmpty(command)) {
33524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            throw new IllegalArgumentException("command cannot be null or empty");
33624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
337b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        mImpl.sendCommand(command, params, cb);
33824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
33924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
34024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
341aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Get the session owner's package name.
342aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *
343aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The package name of of the session owner.
344aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     */
345aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    public String getPackageName() {
346aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        return mImpl.getPackageName();
347aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    }
348aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
349aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik    /**
350aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * Gets the underlying framework
351aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * {@link android.media.session.MediaController} object.
35224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * <p>
35324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * This method is only supported on API 21+.
35424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * </p>
35524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     *
356aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     * @return The underlying {@link android.media.session.MediaController}
357aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik     *         object, or null if none.
35824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
35924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public Object getMediaController() {
36024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return mImpl.getMediaController();
36124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
36224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
36324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
36424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Callback for receiving updates on from the session. A Callback can be
36516ac83bebda2a19930b9d692789f3b507c49951bRoboErik     * registered using {@link #registerCallback}
36624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
367e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    public static abstract class Callback implements IBinder.DeathRecipient {
368e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private final Object mCallbackObj;
369b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas        MessageHandler mHandler;
370e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
371b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas        boolean mRegistered = false;
37224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
37324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public Callback() {
37421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            if (android.os.Build.VERSION.SDK_INT >= 25) {
37521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon                mCallbackObj = MediaControllerCompatApi25.createCallback(new StubApi25());
37621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            } else if (android.os.Build.VERSION.SDK_INT >= 21) {
37724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                mCallbackObj = MediaControllerCompatApi21.createCallback(new StubApi21());
37824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            } else {
379e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mCallbackObj = new StubCompat();
38024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            }
38124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
38224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
38324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
38423138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik         * Override to handle the session being destroyed. The session is no
38523138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik         * longer valid after this call and calls to it will be ignored.
38623138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik         */
38723138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik        public void onSessionDestroyed() {
38823138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik        }
38923138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik
39023138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik        /**
39124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Override to handle custom events sent by the session owner without a
39224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * specified interface. Controllers should only handle these for
39324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * sessions they own.
39424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
39524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param event The event from the session.
39624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param extras Optional parameters for the event.
39724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
39824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onSessionEvent(String event, Bundle extras) {
39924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
40024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
40124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
40224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Override to handle changes in playback state.
40324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
40424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param state The new playback state of the session
40524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
40624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onPlaybackStateChanged(PlaybackStateCompat state) {
40724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
40824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
40924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
41024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Override to handle changes to the current metadata.
41124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
41224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param metadata The current metadata for the session or null if none.
4139d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim         * @see MediaMetadataCompat
41424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
41524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onMetadataChanged(MediaMetadataCompat metadata) {
41624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
41724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
418aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
419aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle changes to items in the queue.
420aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
421aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @see MediaSessionCompat.QueueItem
422aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param queue A list of items in the current play queue. It should
423aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            include the currently playing item as well as previous and
424aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            upcoming items if applicable.
425aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
426aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
427aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
428aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
429aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
430aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle changes to the queue title.
431aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
432aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param title The title that should be displayed along with the play
433aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            queue such as "Now Playing". May be null if there is no
434aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            such title.
435aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
436aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void onQueueTitleChanged(CharSequence title) {
437aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
438aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
439aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
440aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle chagnes to the {@link MediaSessionCompat} extras.
441aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
442aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param extras The extras that can include other information
443aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            associated with the {@link MediaSessionCompat}.
444aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
445aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void onExtrasChanged(Bundle extras) {
446aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
447aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
448aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
449aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Override to handle changes to the audio info.
450aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
451aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param info The current audio info for this session.
452aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
453aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void onAudioInfoChanged(PlaybackInfo info) {
454aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
455aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
45621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
45721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Override to handle changes to the repeat mode.
45821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
45921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param repeatMode The repeat mode. It should be one of followings:
46021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *            {@link PlaybackStateCompat#REPEAT_MODE_NONE},
46121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *            {@link PlaybackStateCompat#REPEAT_MODE_ONE},
46221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *            {@link PlaybackStateCompat#REPEAT_MODE_ALL}
46321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
46421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void onRepeatModeChanged(@PlaybackStateCompat.RepeatMode int repeatMode) {
46521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
46621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
46721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
46821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Override to handle changes to the shuffle mode.
46921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
47021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param enabled {@code true} if the shuffle mode is enabled, {@code false} otherwise.
47121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
47221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void onShuffleModeChanged(boolean enabled) {
47321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
47421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
475e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
476e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void binderDied() {
477e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            onSessionDestroyed();
478e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
479e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
480e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        /**
481e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik         * Set the handler to use for pre 21 callbacks.
482e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik         */
483e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private void setHandler(Handler handler) {
484e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mHandler = new MessageHandler(handler.getLooper());
485e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
486e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
48724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private class StubApi21 implements MediaControllerCompatApi21.Callback {
488b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            StubApi21() {
489b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            }
490b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas
49124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            @Override
49223138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik            public void onSessionDestroyed() {
49323138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik                Callback.this.onSessionDestroyed();
49423138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik            }
49523138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik
49623138c4b9be07abdab0cfdde2c62186359c9e7faRoboErik            @Override
49724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            public void onSessionEvent(String event, Bundle extras) {
49824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                Callback.this.onSessionEvent(event, extras);
49924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            }
50024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
50124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            @Override
50224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            public void onPlaybackStateChanged(Object stateObj) {
50324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                Callback.this.onPlaybackStateChanged(
50424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                        PlaybackStateCompat.fromPlaybackState(stateObj));
50524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            }
50624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
50724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            @Override
50824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            public void onMetadataChanged(Object metadataObj) {
5099d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onMetadataChanged(MediaMetadataCompat.fromMediaMetadata(metadataObj));
5109d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
5119d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
5129d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
513203a34227e8fa3bd16721fb7ff450fb6feba7c50Hyundo Moon            public void onQueueChanged(List<?> queue) {
514203a34227e8fa3bd16721fb7ff450fb6feba7c50Hyundo Moon                Callback.this.onQueueChanged(QueueItem.fromQueueItemList(queue));
5159d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
5169d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
5179d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
5189d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            public void onQueueTitleChanged(CharSequence title) {
5199d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onQueueTitleChanged(title);
5209d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
5219d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
5229d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
5239d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            public void onExtrasChanged(Bundle extras) {
5249d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onExtrasChanged(extras);
5259d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
5269d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim
5279d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            @Override
5289d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            public void onAudioInfoChanged(
5299d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                    int type, int stream, int control, int max, int current) {
5309d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                Callback.this.onAudioInfoChanged(
5319d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim                        new PlaybackInfo(type, stream, control, max, current));
5329d18baac7c99ec5c8ca88cfca10ad21e4106e2f1Sungsoo Lim            }
53324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
534e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
53521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        private class StubApi25 extends StubApi21 implements MediaControllerCompatApi25.Callback {
53621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            @Override
53721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            public void onRepeatModeChanged(@PlaybackStateCompat.RepeatMode int repeatMode) {
53821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon                Callback.this.onRepeatModeChanged(repeatMode);
53921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            }
54021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
54121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            @Override
54221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            public void onShuffleModeChanged(boolean enabled) {
54321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon                Callback.this.onShuffleModeChanged(enabled);
54421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            }
54521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
54621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
547e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private class StubCompat extends IMediaControllerCallback.Stub {
548e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
549b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            StubCompat() {
550b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas            }
551b768ed3824de2c109411654b3830feabe564ff0aAurimas Liutikas
552e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
553e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onEvent(String event, Bundle extras) throws RemoteException {
554e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_EVENT, event, extras);
555e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
556e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
557e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
558e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onSessionDestroyed() throws RemoteException {
559e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_DESTROYED, null, null);
560e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
561e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
562e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
563e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onPlaybackStateChanged(PlaybackStateCompat state) throws RemoteException {
564e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_PLAYBACK_STATE, state, null);
565e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
566e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
567e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
568e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onMetadataChanged(MediaMetadataCompat metadata) throws RemoteException {
569e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_METADATA, metadata, null);
570e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
571e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
572e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
573e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onQueueChanged(List<QueueItem> queue) throws RemoteException {
574e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_QUEUE, queue, null);
575e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
576e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
577e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
578e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onQueueTitleChanged(CharSequence title) throws RemoteException {
579e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_QUEUE_TITLE, title, null);
580e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
581e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
582e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
583e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onExtrasChanged(Bundle extras) throws RemoteException {
584e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_EXTRAS, extras, null);
585e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
586e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
587e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
588e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void onVolumeInfoChanged(ParcelableVolumeInfo info) throws RemoteException {
589e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                PlaybackInfo pi = null;
590e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                if (info != null) {
591e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    pi = new PlaybackInfo(info.volumeType, info.audioStream, info.controlType,
592e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                            info.maxVolume, info.currentVolume);
593e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                }
594e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mHandler.post(MessageHandler.MSG_UPDATE_VOLUME, pi, null);
595e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
596e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
597e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
598e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private class MessageHandler extends Handler {
599e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_EVENT = 1;
600e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
601e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_METADATA = 3;
602e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_VOLUME = 4;
603e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_QUEUE = 5;
604e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_QUEUE_TITLE = 6;
605e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_UPDATE_EXTRAS = 7;
606e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            private static final int MSG_DESTROYED = 8;
607e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
608e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public MessageHandler(Looper looper) {
609e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                super(looper);
610e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
611e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
612e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            @Override
613e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void handleMessage(Message msg) {
614e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                if (!mRegistered) {
615e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    return;
616e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                }
617e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                switch (msg.what) {
618e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_EVENT:
619e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onSessionEvent((String) msg.obj, msg.getData());
620e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
621e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_PLAYBACK_STATE:
622e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onPlaybackStateChanged((PlaybackStateCompat) msg.obj);
623e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
624e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_METADATA:
625e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onMetadataChanged((MediaMetadataCompat) msg.obj);
626e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
627e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_QUEUE:
628e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onQueueChanged((List<MediaSessionCompat.QueueItem>) msg.obj);
629e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
630e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_QUEUE_TITLE:
631e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onQueueTitleChanged((CharSequence) msg.obj);
632e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
633e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_EXTRAS:
634e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onExtrasChanged((Bundle) msg.obj);
635e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
636e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_UPDATE_VOLUME:
637e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onAudioInfoChanged((PlaybackInfo) msg.obj);
638e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
639e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                    case MSG_DESTROYED:
640e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        onSessionDestroyed();
641e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        break;
642e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                }
643e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
644e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
645e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            public void post(int what, Object obj, Bundle data) {
646ecc231b11c9e6c1813bf12232559ea372cf02ea7Sungsoo Lim                Message msg = obtainMessage(what, obj);
647ecc231b11c9e6c1813bf12232559ea372cf02ea7Sungsoo Lim                msg.setData(data);
648ecc231b11c9e6c1813bf12232559ea372cf02ea7Sungsoo Lim                msg.sendToTarget();
649e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
650e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
65124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
65224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
65324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
65424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Interface for controlling media playback on a session. This allows an app
65524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * to send media transport commands to the session.
65624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
65724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static abstract class TransportControls {
65824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        TransportControls() {
65924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
66024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
66124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
662bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare its playback without audio focus. In other words, other
663bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * session can continue to play during the preparation of this session. This method can be
664bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * used to speed up the start of the playback. Once the preparation is done, the session
665bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * will change its playback state to {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards,
666bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link #play} can be called to start playback. If the preparation is not needed,
667bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link #play} can be directly called without this method.
668bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
669bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepare();
670bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
671bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
672bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare playback for a specific media id. In other words, other
673bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * session can continue to play during the preparation of this session. This method can be
674bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * used to speed up the start of the playback. Once the preparation is
675bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * done, the session will change its playback state to
676bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
677bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * start playback. If the preparation is not needed, {@link #playFromMediaId} can
678bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * be directly called without this method.
679bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *
680bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param mediaId The id of the requested media.
681bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param extras Optional extras that can include extra information about the media item
682bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *               to be prepared.
683bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
684bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepareFromMediaId(String mediaId, Bundle extras);
685bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
686bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
687bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare playback for a specific search query.
688bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * An empty or null query should be treated as a request to prepare any
689bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * music. In other words, other session can continue to play during
690bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * the preparation of this session. This method can be used to speed up the start of the
691bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * playback. Once the preparation is done, the session will change its playback state to
692bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
693bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * start playback. If the preparation is not needed, {@link #playFromSearch} can be directly
694bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * called without this method.
695bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *
696bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param query The search query.
697bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param extras Optional extras that can include extra information
698bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *               about the query.
699bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
700bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepareFromSearch(String query, Bundle extras);
701bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
702bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
703bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Request that the player prepare playback for a specific {@link Uri}.
704bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * In other words, other session can continue to play during the preparation of this
705bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * session. This method can be used to speed up the start of the playback.
706bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * Once the preparation is done, the session will change its playback state to
707bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * {@link PlaybackStateCompat#STATE_PAUSED}. Afterwards, {@link #play} can be called to
708bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * start playback. If the preparation is not needed, {@link #playFromUri} can be directly
709bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * called without this method.
710bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *
711bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param uri The URI of the requested media.
712bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         * @param extras Optional extras that can include extra information about the media item
713bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         *               to be prepared.
714bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho         */
715bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public abstract void prepareFromUri(Uri uri, Bundle extras);
716bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
717bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        /**
71824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Request that the player start its playback at its current position.
71924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
72024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void play();
72124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
72224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
723aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Request that the player start playback for a specific {@link Uri}.
724aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
725aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param mediaId The uri of the requested media.
726aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param extras Optional extras that can include extra information
727aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            about the media item to be played.
728aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
729aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void playFromMediaId(String mediaId, Bundle extras);
730aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
731aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
732aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Request that the player start playback for a specific search query.
733aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * An empty or null query should be treated as a request to play any
734aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * music.
735aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
736aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param query The search query.
737aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param extras Optional extras that can include extra information
738aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            about the query.
739aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
740aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void playFromSearch(String query, Bundle extras);
741aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
742aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
743b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         * Request that the player start playback for a specific {@link Uri}.
744b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         *
745b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         * @param uri  The URI of the requested media.
746b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         * @param extras Optional extras that can include extra information about the media item
747b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         *               to be played.
748b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake         */
749b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public abstract void playFromUri(Uri uri, Bundle extras);
750b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
751b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        /**
752aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Play an item with a specific id in the play queue. If you specify an
753aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * id that is not in the play queue, the behavior is undefined.
754aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
755aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void skipToQueueItem(long id);
756aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
757aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
75824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Request that the player pause its playback and stay at its current
75924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * position.
76024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
76124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void pause();
76224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
76324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
76424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Request that the player stop its playback; it may clear its state in
76524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * whatever way is appropriate.
76624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
76724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void stop();
76824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
76924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
77024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Move to a new location in the media stream.
77124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
77224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param pos Position to move to, in milliseconds.
77324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
77424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void seekTo(long pos);
77524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
77624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
77724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Start fast forwarding. If playback is already fast forwarding this
77824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * may increase the rate.
77924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
78024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void fastForward();
78124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
78224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
78324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Skip to the next item.
78424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
78524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void skipToNext();
78624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
78724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
78824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Start rewinding. If playback is already rewinding this may increase
78924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * the rate.
79024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
79124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void rewind();
79224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
79324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
79424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Skip to the previous item.
79524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
79624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void skipToPrevious();
79724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
79824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
79924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Rate the current content. This will cause the rating to be set for
80024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * the current user. The Rating type must match the type returned by
80124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * {@link #getRatingType()}.
80224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
80324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @param rating The rating to set for the current content
80424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
80524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public abstract void setRating(RatingCompat rating);
806aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
807aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
80821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Set the repeat mode for this session.
80921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
81021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param repeatMode The repeat mode. Must be one of the followings:
81121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *            {@link PlaybackStateCompat#REPEAT_MODE_NONE},
81221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *            {@link PlaybackStateCompat#REPEAT_MODE_ONE},
81321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *            {@link PlaybackStateCompat#REPEAT_MODE_ALL}
81421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
81521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public abstract void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode);
81621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
81721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
81821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * Set the shuffle mode for this session.
81921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         *
82021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         * @param enabled {@code true} to enable the shuffle mode, {@code false} to disable.
82121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon         */
82221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public abstract void setShuffleModeEnabled(boolean enabled);
82321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
82421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        /**
825aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Send a custom action for the {@link MediaSessionCompat} to perform.
826aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
827aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param customAction The action to perform.
828aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param args Optional arguments to supply to the
829aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            {@link MediaSessionCompat} for this custom action.
830aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
831aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void sendCustomAction(PlaybackStateCompat.CustomAction customAction,
832aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                Bundle args);
833aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
834aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        /**
835aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * Send the id and args from a custom action for the
836aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * {@link MediaSessionCompat} to perform.
837aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *
838aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @see #sendCustomAction(PlaybackStateCompat.CustomAction action,
839aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *      Bundle args)
840aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param action The action identifier of the
841aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            {@link PlaybackStateCompat.CustomAction} as specified by
842aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            the {@link MediaSessionCompat}.
843aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         * @param args Optional arguments to supply to the
844aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         *            {@link MediaSessionCompat} for this custom action.
845aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik         */
846aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public abstract void sendCustomAction(String action, Bundle args);
84724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
84824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
84924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    /**
85024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     * Holds information about the way volume is handled for this session.
85124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown     */
852312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik    public static final class PlaybackInfo {
853312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        /**
854312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * The session uses local playback.
855312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         */
856312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public static final int PLAYBACK_TYPE_LOCAL = 1;
857312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        /**
858312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * The session uses remote playback.
859312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         */
860312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public static final int PLAYBACK_TYPE_REMOTE = 2;
861312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik
862312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        private final int mPlaybackType;
8631435afe32073dee10e721dfb6122ce6a194a6412RoboErik        // TODO update audio stream with AudioAttributes support version
86424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mAudioStream;
86524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mVolumeControl;
86624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mMaxVolume;
86724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        private final int mCurrentVolume;
86824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
869312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        PlaybackInfo(int type, int stream, int control, int max, int current) {
870312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            mPlaybackType = type;
87124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mAudioStream = stream;
87224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mVolumeControl = control;
87324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mMaxVolume = max;
87424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCurrentVolume = current;
87524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
87624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
87724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
87824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the type of volume handling, either local or remote. One of:
87924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <ul>
880312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * <li>{@link PlaybackInfo#PLAYBACK_TYPE_LOCAL}</li>
881312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * <li>{@link PlaybackInfo#PLAYBACK_TYPE_REMOTE}</li>
88224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * </ul>
88324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
88424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The type of volume handling this session is using.
88524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
886312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public int getPlaybackType() {
887312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            return mPlaybackType;
88824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
88924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
89024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
89124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the stream this is currently controlling volume on. When the volume
892312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik         * type is {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} this value does not
89324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * have meaning and should be ignored.
89424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
89524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The stream this session is playing on.
89624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
89724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getAudioStream() {
898aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            // TODO switch to AudioAttributesCompat when it is added.
89924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mAudioStream;
90024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
90124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
90224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
90324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the type of volume control that can be used. One of:
90424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <ul>
90524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE}</li>
90624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_RELATIVE}</li>
90724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * <li>{@link VolumeProviderCompat#VOLUME_CONTROL_FIXED}</li>
90824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * </ul>
90924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
91024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The type of volume control that may be used with this
91124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *         session.
91224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
91324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getVolumeControl() {
91424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mVolumeControl;
91524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
91624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
91724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
91824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the maximum volume that may be set for this session.
91924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
92024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The maximum allowed volume where this session is playing.
92124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
92224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getMaxVolume() {
92324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mMaxVolume;
92424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
92524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
92624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        /**
92724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * Get the current volume for this session.
92824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         *
92924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         * @return The current volume where this session is playing.
93024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown         */
93124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getCurrentVolume() {
93224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mCurrentVolume;
93324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
93424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
93524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
93624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    interface MediaControllerImpl {
93716ac83bebda2a19930b9d692789f3b507c49951bRoboErik        void registerCallback(Callback callback, Handler handler);
93816ac83bebda2a19930b9d692789f3b507c49951bRoboErik
93916ac83bebda2a19930b9d692789f3b507c49951bRoboErik        void unregisterCallback(Callback callback);
94024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        boolean dispatchMediaButtonEvent(KeyEvent keyEvent);
94124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        TransportControls getTransportControls();
94224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        PlaybackStateCompat getPlaybackState();
94324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        MediaMetadataCompat getMetadata();
944aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
945aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        List<MediaSessionCompat.QueueItem> getQueue();
946aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        CharSequence getQueueTitle();
947aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        Bundle getExtras();
94824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        int getRatingType();
94921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        int getRepeatMode();
95021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        boolean isShuffleModeEnabled();
951aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        long getFlags();
952312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        PlaybackInfo getPlaybackInfo();
953aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        PendingIntent getSessionActivity();
954aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
955aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        void setVolumeTo(int value, int flags);
956aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        void adjustVolume(int direction, int flags);
957b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        void sendCommand(String command, Bundle params, ResultReceiver cb);
958aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
959aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        String getPackageName();
96024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        Object getMediaController();
96124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
96224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
96324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    static class MediaControllerImplBase implements MediaControllerImpl {
964e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private MediaSessionCompat.Token mToken;
965e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private IMediaSession mBinder;
966e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private TransportControls mTransportControls;
967e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
968e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public MediaControllerImplBase(MediaSessionCompat.Token token) {
969e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mToken = token;
970e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mBinder = IMediaSession.Stub.asInterface((IBinder) token.getToken());
971e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
972e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
97324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
97416ac83bebda2a19930b9d692789f3b507c49951bRoboErik        public void registerCallback(Callback callback, Handler handler) {
975e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (callback == null) {
976e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                throw new IllegalArgumentException("callback may not be null.");
977e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
978e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
979e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.asBinder().linkToDeath(callback, 0);
980e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.registerCallbackListener((IMediaControllerCallback) callback.mCallbackObj);
981e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.setHandler(handler);
982e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.mRegistered = true;
983e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
984e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in registerCallback. " + e);
985e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.onSessionDestroyed();
986e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
98724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
98824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
98924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
99016ac83bebda2a19930b9d692789f3b507c49951bRoboErik        public void unregisterCallback(Callback callback) {
991e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (callback == null) {
992e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                throw new IllegalArgumentException("callback may not be null.");
993e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
994e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
995e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.unregisterCallbackListener(
996e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        (IMediaControllerCallback) callback.mCallbackObj);
997e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.asBinder().unlinkToDeath(callback, 0);
998e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                callback.mRegistered = false;
999e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1000e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in unregisterCallback. " + e);
1001e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
100224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
100324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
100424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
100524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public boolean dispatchMediaButtonEvent(KeyEvent event) {
1006e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (event == null) {
1007e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                throw new IllegalArgumentException("event may not be null.");
1008e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1009e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1010e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.sendMediaButton(event);
1011e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1012e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in dispatchMediaButtonEvent. " + e);
1013e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
101424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return false;
101524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
101624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
101724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
101824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public TransportControls getTransportControls() {
1019e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            if (mTransportControls == null) {
1020e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mTransportControls = new TransportControlsBase(mBinder);
1021e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1022e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1023e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            return mTransportControls;
102424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
102524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
102624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
102724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public PlaybackStateCompat getPlaybackState() {
1028e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1029e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getPlaybackState();
1030e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1031e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getPlaybackState. " + e);
1032e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
103324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
103424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
103524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
103624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
103724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaMetadataCompat getMetadata() {
1038e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1039e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getMetadata();
1040e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1041e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getMetadata. " + e);
1042e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
104324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
104424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
104524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
104624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1047aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public List<MediaSessionCompat.QueueItem> getQueue() {
1048e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1049e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getQueue();
1050e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1051e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getQueue. " + e);
1052e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1053aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1054aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1055aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1056aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1057aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public CharSequence getQueueTitle() {
1058e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1059e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getQueueTitle();
1060e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1061e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getQueueTitle. " + e);
1062e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1063aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1064aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1065aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1066aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1067aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public Bundle getExtras() {
1068e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1069e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getExtras();
1070e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1071e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getExtras. " + e);
1072e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1073aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1074aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1075aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1076aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
107724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getRatingType() {
1078e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1079e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getRatingType();
1080e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1081e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getRatingType. " + e);
1082e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
108324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return 0;
108424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
108524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
108624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
108721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public int getRepeatMode() {
108821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: implement this
108921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return 0;
109021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
109121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
109221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
109321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public boolean isShuffleModeEnabled() {
109421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: implement this
109521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return false;
109621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
109721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
109821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
1099aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public long getFlags() {
1100e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1101e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getFlags();
1102e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1103e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getFlags. " + e);
1104e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1105aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return 0;
1106aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1107aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1108aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1109312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public PlaybackInfo getPlaybackInfo() {
1110e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1111e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                ParcelableVolumeInfo info = mBinder.getVolumeAttributes();
1112e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                PlaybackInfo pi = new PlaybackInfo(info.volumeType, info.audioStream,
1113e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        info.controlType, info.maxVolume, info.currentVolume);
1114e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return pi;
1115e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1116e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getPlaybackInfo. " + e);
1117e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
111824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
111924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
112024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
112124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1122aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public PendingIntent getSessionActivity() {
1123e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1124e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getLaunchPendingIntent();
1125e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1126e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getSessionActivity. " + e);
1127e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1128aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1129aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1130aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1131aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1132aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void setVolumeTo(int value, int flags) {
1133e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1134e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.setVolumeTo(value, flags, null);
1135e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1136e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in setVolumeTo. " + e);
1137e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1138aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1139aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1140aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1141aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void adjustVolume(int direction, int flags) {
1142e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1143e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.adjustVolume(direction, flags, null);
1144e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1145e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in adjustVolume. " + e);
1146e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1147aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1148aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1149aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1150b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        public void sendCommand(String command, Bundle params, ResultReceiver cb) {
1151e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1152e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.sendCommand(command, params,
1153e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                        new MediaSessionCompat.ResultReceiverWrapper(cb));
1154e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1155e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in sendCommand. " + e);
1156e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
115724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
115824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
115924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1160aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public String getPackageName() {
1161e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1162e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                return mBinder.getPackageName();
1163e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1164e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in getPackageName. " + e);
1165e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1166aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return null;
1167aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1168aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1169aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
117024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public Object getMediaController() {
117124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return null;
117224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
117324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
117424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
1175e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    static class TransportControlsBase extends TransportControls {
1176e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        private IMediaSession mBinder;
1177e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1178e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public TransportControlsBase(IMediaSession binder) {
1179e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            mBinder = binder;
1180e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1181e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1182e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1183bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepare() {
11845491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
11855491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepare();
11865491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
11875491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                Log.e(TAG, "Dead object in prepare. " + e);
11885491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1189bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1190bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1191bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1192bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromMediaId(String mediaId, Bundle extras) {
11935491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
11945491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepareFromMediaId(mediaId, extras);
11955491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
11965491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                Log.e(TAG, "Dead object in prepareFromMediaId. " + e);
11975491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1198bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1199bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1200bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1201bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromSearch(String query, Bundle extras) {
12025491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
12035491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepareFromSearch(query, extras);
12045491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
12055491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                Log.e(TAG, "Dead object in prepareFromSearch. " + e);
12065491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1207bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1208bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1209bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1210bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromUri(Uri uri, Bundle extras) {
12115491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            try {
12125491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                mBinder.prepareFromUri(uri, extras);
12135491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            } catch (RemoteException e) {
12145491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho                Log.e(TAG, "Dead object in prepareFromUri. " + e);
12155491f533f2781b1693efb6e44df0fb5928bec70dDonghyun Cho            }
1216bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1217bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1218bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1219e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void play() {
1220e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1221e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.play();
1222e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1223e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in play. " + e);
1224e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1225e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1226e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1227e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1228e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void playFromMediaId(String mediaId, Bundle extras) {
1229e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1230e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.playFromMediaId(mediaId, extras);
1231e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1232e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in playFromMediaId. " + e);
1233e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1234e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1235e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1236e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1237e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void playFromSearch(String query, Bundle extras) {
1238e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1239e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.playFromSearch(query, extras);
1240e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1241e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in playFromSearch. " + e);
1242e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1243e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1244e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1245e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1246b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public void playFromUri(Uri uri, Bundle extras) {
1247b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            try {
1248b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake                mBinder.playFromUri(uri, extras);
1249b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            } catch (RemoteException e) {
1250b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake                Log.e(TAG, "Dead object in playFromUri. " + e);
1251b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            }
1252b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1253b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1254b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
1255e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void skipToQueueItem(long id) {
1256e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1257e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.skipToQueueItem(id);
1258e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1259e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in skipToQueueItem. " + e);
1260e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1261e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1262e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1263e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1264e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void pause() {
1265e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1266e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.pause();
1267e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1268e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in pause. " + e);
1269e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1270e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1271e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1272e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1273e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void stop() {
1274e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1275e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.stop();
1276e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1277e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in stop. " + e);
1278e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1279e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1280e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1281e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1282e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void seekTo(long pos) {
1283e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1284e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.seekTo(pos);
1285e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1286e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in seekTo. " + e);
1287e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1288e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1289e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1290e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1291e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void fastForward() {
1292e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1293e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.fastForward();
1294e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1295e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in fastForward. " + e);
1296e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1297e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1298e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1299e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1300e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void skipToNext() {
1301e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1302e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.next();
1303e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1304e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in skipToNext. " + e);
1305e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1306e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1307e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1308e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1309e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void rewind() {
1310e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1311e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.rewind();
1312e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1313e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in rewind. " + e);
1314e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1315e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1316e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1317e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1318e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void skipToPrevious() {
1319e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1320e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.previous();
1321e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1322e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in skipToPrevious. " + e);
1323e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1324e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1325e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1326e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1327e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void setRating(RatingCompat rating) {
1328e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1329e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.rate(rating);
1330e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1331e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in setRating. " + e);
1332e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1333e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1334e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1335e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
133621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode) {
133721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: impletment this
133821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
133921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
134021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
134121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setShuffleModeEnabled(boolean enabled) {
134221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: impletment this
134321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
134421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
134521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
1346e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void sendCustomAction(CustomAction customAction, Bundle args) {
1347e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            sendCustomAction(customAction.getAction(), args);
1348e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1349e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
1350e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        @Override
1351e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        public void sendCustomAction(String action, Bundle args) {
1352e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            try {
1353e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                mBinder.sendCustomAction(action, args);
1354e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            } catch (RemoteException e) {
1355e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik                Log.e(TAG, "Dead object in sendCustomAction. " + e);
1356e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            }
1357e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
1358e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    }
1359e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik
136024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    static class MediaControllerImplApi21 implements MediaControllerImpl {
1361b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        protected final Object mControllerObj;
136224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
136324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaControllerImplApi21(Context context, MediaSessionCompat session) {
13645c41750574ba65da432b69f89cd32dc356281005RoboErik            mControllerObj = MediaControllerCompatApi21.fromToken(context,
136524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                    session.getSessionToken().getToken());
136624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
136724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
136824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaControllerImplApi21(Context context, MediaSessionCompat.Token sessionToken)
136924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                throws RemoteException {
13705c41750574ba65da432b69f89cd32dc356281005RoboErik            mControllerObj = MediaControllerCompatApi21.fromToken(context,
137124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                    sessionToken.getToken());
137224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            if (mControllerObj == null) throw new RemoteException();
137324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
137424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
137524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
137616ac83bebda2a19930b9d692789f3b507c49951bRoboErik        public void registerCallback(Callback callback, Handler handler) {
137716ac83bebda2a19930b9d692789f3b507c49951bRoboErik            MediaControllerCompatApi21.registerCallback(mControllerObj, callback.mCallbackObj, handler);
137824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
137924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
138024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
138116ac83bebda2a19930b9d692789f3b507c49951bRoboErik        public void unregisterCallback(Callback callback) {
138216ac83bebda2a19930b9d692789f3b507c49951bRoboErik            MediaControllerCompatApi21.unregisterCallback(mControllerObj, callback.mCallbackObj);
138324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
138424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
138524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
138624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public boolean dispatchMediaButtonEvent(KeyEvent event) {
138724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return MediaControllerCompatApi21.dispatchMediaButtonEvent(mControllerObj, event);
138824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
138924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
139024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
139124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public TransportControls getTransportControls() {
13921435afe32073dee10e721dfb6122ce6a194a6412RoboErik            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
139324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return controlsObj != null ? new TransportControlsApi21(controlsObj) : null;
139424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
139524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
139624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
139724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public PlaybackStateCompat getPlaybackState() {
139824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            Object stateObj = MediaControllerCompatApi21.getPlaybackState(mControllerObj);
139924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return stateObj != null ? PlaybackStateCompat.fromPlaybackState(stateObj) : null;
140024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
140124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
140224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
140324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public MediaMetadataCompat getMetadata() {
140424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            Object metadataObj = MediaControllerCompatApi21.getMetadata(mControllerObj);
140524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return metadataObj != null ? MediaMetadataCompat.fromMediaMetadata(metadataObj) : null;
140624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
140724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
140824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1409aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public List<MediaSessionCompat.QueueItem> getQueue() {
1410aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            List<Object> queueObjs = MediaControllerCompatApi21.getQueue(mControllerObj);
1411203a34227e8fa3bd16721fb7ff450fb6feba7c50Hyundo Moon            return queueObjs != null ? MediaSessionCompat.QueueItem.fromQueueItemList(queueObjs)
1412203a34227e8fa3bd16721fb7ff450fb6feba7c50Hyundo Moon                    : null;
1413aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1414aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1415aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1416aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public CharSequence getQueueTitle() {
1417aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getQueueTitle(mControllerObj);
1418aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1419aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1420aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1421aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public Bundle getExtras() {
1422aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getExtras(mControllerObj);
1423aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1424aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1425aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
142624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public int getRatingType() {
142724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return MediaControllerCompatApi21.getRatingType(mControllerObj);
142824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
142924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
143024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
143121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public int getRepeatMode() {
143221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: implement this
143321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return 0;
143421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
143521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
143621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
143721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public boolean isShuffleModeEnabled() {
143821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: implement this
143921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return false;
144021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
144121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
144221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
1443aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public long getFlags() {
1444aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getFlags(mControllerObj);
1445aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1446aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1447aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1448312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik        public PlaybackInfo getPlaybackInfo() {
1449312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            Object volumeInfoObj = MediaControllerCompatApi21.getPlaybackInfo(mControllerObj);
1450312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik            return volumeInfoObj != null ? new PlaybackInfo(
1451312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getPlaybackType(volumeInfoObj),
1452312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getLegacyAudioStream(volumeInfoObj),
1453312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getVolumeControl(volumeInfoObj),
1454312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getMaxVolume(volumeInfoObj),
1455312f13dea7b4a9229dff784c6e94b0ec0c722b74RoboErik                    MediaControllerCompatApi21.PlaybackInfo.getCurrentVolume(volumeInfoObj)) : null;
145624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
145724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
145824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1459aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public PendingIntent getSessionActivity() {
1460aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getSessionActivity(mControllerObj);
1461aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1462aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1463aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1464aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void setVolumeTo(int value, int flags) {
1465aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.setVolumeTo(mControllerObj, value, flags);
1466aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1467aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1468aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1469aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void adjustVolume(int direction, int flags) {
1470aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.adjustVolume(mControllerObj, direction, flags);
1471aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1472aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1473aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1474b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        public void sendCommand(String command, Bundle params, ResultReceiver cb) {
1475b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal            MediaControllerCompatApi21.sendCommand(mControllerObj, command, params, cb);
147624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
147724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
147824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1479aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public String getPackageName() {
1480aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            return MediaControllerCompatApi21.getPackageName(mControllerObj);
1481aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1482aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1483aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
148424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public Object getMediaController() {
148524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            return mControllerObj;
148624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
148724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
148824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
148924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    static class TransportControlsApi21 extends TransportControls {
1490b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        protected final Object mControlsObj;
149124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
149224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public TransportControlsApi21(Object controlsObj) {
149324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mControlsObj = controlsObj;
149424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
149524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
149624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
1497bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepare() {
1498993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE, null);
1499bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1500bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1501bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1502bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromMediaId(String mediaId, Bundle extras) {
1503993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            Bundle bundle = new Bundle();
1504993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putString(MediaSessionCompat.ACTION_ARGUMENT_MEDIA_ID, mediaId);
1505993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
1506993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_MEDIA_ID, bundle);
1507bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1508bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1509bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1510bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromSearch(String query, Bundle extras) {
1511993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            Bundle bundle = new Bundle();
1512993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putString(MediaSessionCompat.ACTION_ARGUMENT_QUERY, query);
1513993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
1514993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_SEARCH, bundle);
1515bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1516bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1517bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1518bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromUri(Uri uri, Bundle extras) {
1519993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            Bundle bundle = new Bundle();
1520993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_URI, uri);
1521993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            bundle.putBundle(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
1522993cf322bbe36230e231e955c98274d679b1dabbDonghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PREPARE_FROM_URI, bundle);
1523bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1524bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1525bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
152624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void play() {
152724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.play(mControlsObj);
152824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
152924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
153024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
153124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void pause() {
153224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.pause(mControlsObj);
153324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
153424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
153524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
153624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void stop() {
153724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.stop(mControlsObj);
153824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
153924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
154024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
154124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void seekTo(long pos) {
154224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.seekTo(mControlsObj, pos);
154324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
154424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
154524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
154624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void fastForward() {
154724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.fastForward(mControlsObj);
154824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
154924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
155024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
155124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void rewind() {
155224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.rewind(mControlsObj);
155324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
155424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
155524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
155624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void skipToNext() {
155724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.skipToNext(mControlsObj);
155824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
155924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
156024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
156124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void skipToPrevious() {
156224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.skipToPrevious(mControlsObj);
156324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
156424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
156524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
156624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void setRating(RatingCompat rating) {
156724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            MediaControllerCompatApi21.TransportControls.setRating(mControlsObj,
156824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown                    rating != null ? rating.getRating() : null);
156924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
1570aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1571aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
157221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode) {
157321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: implement this
157421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
157521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
157621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
157721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setShuffleModeEnabled(boolean enabled) {
157821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            // TODO: implement this
157921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
158021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
158121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
1582aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void playFromMediaId(String mediaId, Bundle extras) {
1583aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.playFromMediaId(mControlsObj, mediaId,
1584aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    extras);
1585aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1586aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1587aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1588aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void playFromSearch(String query, Bundle extras) {
1589aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.playFromSearch(mControlsObj, query,
1590aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    extras);
1591aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1592aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1593aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1594b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public void playFromUri(Uri uri, Bundle extras) {
15954b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            if (uri == null || Uri.EMPTY.equals(uri)) {
15964b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho                throw new IllegalArgumentException(
15974b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho                        "You must specify a non-empty Uri for playFromUri.");
15984b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            }
15994b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            Bundle bundle = new Bundle();
16004b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_URI, uri);
16014b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            bundle.putParcelable(MediaSessionCompat.ACTION_ARGUMENT_EXTRAS, extras);
16024b2318177dddccb9e996d0128daa674b2c6d3fc2Donghyun Cho            sendCustomAction(MediaSessionCompat.ACTION_PLAY_FROM_URI, bundle);
1603b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1604b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1605b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
1606aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void skipToQueueItem(long id) {
1607aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.skipToQueueItem(mControlsObj, id);
1608aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1609aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1610aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1611aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void sendCustomAction(CustomAction customAction, Bundle args) {
1612aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj,
1613aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    customAction.getAction(), args);
1614aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
1615aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik
1616aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        @Override
1617aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        public void sendCustomAction(String action, Bundle args) {
1618aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik            MediaControllerCompatApi21.TransportControls.sendCustomAction(mControlsObj, action,
1619aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik                    args);
1620aeb95a772d4365008145407ed52dfbaa61d3c4acRoboErik        }
162124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
1622b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1623b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    static class MediaControllerImplApi23 extends MediaControllerImplApi21 {
1624b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1625b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public MediaControllerImplApi23(Context context, MediaSessionCompat session) {
1626b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            super(context, session);
1627b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1628b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1629b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public MediaControllerImplApi23(Context context, MediaSessionCompat.Token sessionToken)
1630b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake                throws RemoteException {
1631b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            super(context, sessionToken);
1632b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1633b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1634b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
1635b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public TransportControls getTransportControls() {
1636b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
1637b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            return controlsObj != null ? new TransportControlsApi23(controlsObj) : null;
1638b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1639b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    }
1640b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1641b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    static class TransportControlsApi23 extends TransportControlsApi21 {
1642b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1643b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public TransportControlsApi23(Object controlsObj) {
1644b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            super(controlsObj);
1645b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1646b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake
1647b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        @Override
1648b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        public void playFromUri(Uri uri, Bundle extras) {
1649b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake            MediaControllerCompatApi23.TransportControls.playFromUri(mControlsObj, uri,
1650b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake                    extras);
1651b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake        }
1652b51f456b92aeb62d5aa9d67e1fb2725b2035fdddIan Lake    }
1653bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1654bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    static class MediaControllerImplApi24 extends MediaControllerImplApi23 {
1655bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1656bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public MediaControllerImplApi24(Context context, MediaSessionCompat session) {
1657bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            super(context, session);
1658bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1659bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1660bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public MediaControllerImplApi24(Context context, MediaSessionCompat.Token sessionToken)
1661bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho                throws RemoteException {
1662bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            super(context, sessionToken);
1663bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1664bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1665bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1666bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public TransportControls getTransportControls() {
1667bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
1668bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            return controlsObj != null ? new TransportControlsApi24(controlsObj) : null;
1669bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1670bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    }
1671bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1672bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    static class TransportControlsApi24 extends TransportControlsApi23 {
1673bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1674bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public TransportControlsApi24(Object controlsObj) {
1675bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            super(controlsObj);
1676bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1677bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1678bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1679bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepare() {
1680bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepare(mControlsObj);
1681bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1682bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1683bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1684bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromMediaId(String mediaId, Bundle extras) {
1685bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepareFromMediaId(
1686bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho                    mControlsObj, mediaId, extras);
1687bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1688bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1689bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1690bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromSearch(String query, Bundle extras) {
1691bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepareFromSearch(
1692bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho                    mControlsObj, query, extras);
1693bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1694bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
1695bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        @Override
1696bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        public void prepareFromUri(Uri uri, Bundle extras) {
1697bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho            MediaControllerCompatApi24.TransportControls.prepareFromUri(mControlsObj, uri, extras);
1698bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho        }
1699bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho    }
1700bee5a864724f8aebaa7308a21c862e646c0e6aa3Donghyun Cho
170121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    static class MediaControllerImplApi25 extends MediaControllerImplApi24 {
170221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
170321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        MediaControllerImplApi25(Context context, MediaSessionCompat session) {
170421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            super(context, session);
170521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
170621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
170721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        MediaControllerImplApi25(Context context, MediaSessionCompat.Token sessionToken)
170821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon                throws RemoteException {
170921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            super(context, sessionToken);
171021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
171121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
171221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
171321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public TransportControls getTransportControls() {
171421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            Object controlsObj = MediaControllerCompatApi21.getTransportControls(mControllerObj);
171521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return controlsObj != null ? new TransportControlsApi25(controlsObj) : null;
171621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
171721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
171821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
171921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public int getRepeatMode() {
172021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return MediaControllerCompatApi25.getRepeatMode(mControllerObj);
172121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
172221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
172321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
172421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public boolean isShuffleModeEnabled() {
172521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            return MediaControllerCompatApi25.isShuffleModeEnabled(mControllerObj);
172621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
172721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    }
172821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
172921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    static class TransportControlsApi25 extends TransportControlsApi24 {
173021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
173121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        TransportControlsApi25(Object controlsObj) {
173221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            super(controlsObj);
173321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
173421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
173521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
173621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setRepeatMode(@PlaybackStateCompat.RepeatMode int repeatMode) {
173721ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            MediaControllerCompatApi25.TransportControls.setRepeatMode(mControlsObj, repeatMode);
173821ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
173921ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
174021ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        @Override
174121ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        public void setShuffleModeEnabled(boolean enabled) {
174221ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon            MediaControllerCompatApi25.TransportControls.setShuffleModeEnabled(mControlsObj,
174321ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon                    enabled);
174421ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon        }
174521ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon    }
174621ecb1a40992b5e478a6a7fe115da40d060b198aHyundo Moon
174724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
1748