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
1985d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErikimport android.app.PendingIntent;
2024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.content.Context;
2124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.content.Intent;
221435afe32073dee10e721dfb6122ce6a194a6412RoboErikimport android.media.AudioAttributes;
23ceb8bf5e5cce7a37736981e626c4be416378767bRoboErikimport android.media.MediaDescription;
2424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.media.MediaMetadata;
2524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.media.Rating;
2624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.media.VolumeProvider;
2724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.media.session.MediaSession;
2824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.media.session.PlaybackState;
2924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Bundle;
3024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Handler;
3124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Parcelable;
3224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.ResultReceiver;
338f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viveretteimport android.support.annotation.RequiresApi;
34be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsooimport android.util.Log;
3524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
36be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsooimport java.lang.reflect.Field;
37ceb8bf5e5cce7a37736981e626c4be416378767bRoboErikimport java.util.ArrayList;
38ceb8bf5e5cce7a37736981e626c4be416378767bRoboErikimport java.util.List;
39ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
408f886fe8c7e23fe6ccb8734167c960c2ed3429c3Alan Viverette@RequiresApi(21)
4124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownclass MediaSessionCompatApi21 {
42be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo    static final String TAG = "MediaSessionCompatApi21";
43be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo
4424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static Object createSession(Context context, String tag) {
45f87e8513ce55303168acd9c698acd5bbd33b9badRoboErik        return new MediaSession(context, tag);
4624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
4724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
48bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik    public static Object verifySession(Object mediaSession) {
49bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik        if (mediaSession instanceof MediaSession) {
50bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik            return mediaSession;
51bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik        }
52bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik        throw new IllegalArgumentException("mediaSession is not a valid MediaSession object");
53bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik    }
54bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik
55ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik    public static Object verifyToken(Object token) {
56ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik        if (token instanceof MediaSession.Token) {
57ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik            return token;
58ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik        }
59ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik        throw new IllegalArgumentException("token is not a valid MediaSession.Token object");
60ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik    }
61ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik
6224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static Object createCallback(Callback callback) {
6324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return new CallbackProxy<Callback>(callback);
6424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
6524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
668af0092e2d7409e79779af396d63ca4146f1fb21RoboErik    public static void setCallback(Object sessionObj, Object callbackObj, Handler handler) {
678af0092e2d7409e79779af396d63ca4146f1fb21RoboErik        ((MediaSession) sessionObj).setCallback((MediaSession.Callback) callbackObj, handler);
6824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
6924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
7024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void setFlags(Object sessionObj, int flags) {
7124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        ((MediaSession)sessionObj).setFlags(flags);
7224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
7324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
7424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void setPlaybackToLocal(Object sessionObj, int stream) {
751435afe32073dee10e721dfb6122ce6a194a6412RoboErik        // TODO update APIs to use support version of AudioAttributes
761435afe32073dee10e721dfb6122ce6a194a6412RoboErik        AudioAttributes.Builder bob = new AudioAttributes.Builder();
771435afe32073dee10e721dfb6122ce6a194a6412RoboErik        bob.setLegacyStreamType(stream);
781435afe32073dee10e721dfb6122ce6a194a6412RoboErik        ((MediaSession) sessionObj).setPlaybackToLocal(bob.build());
7924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
8024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
8124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void setPlaybackToRemote(Object sessionObj, Object volumeProviderObj) {
8224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        ((MediaSession)sessionObj).setPlaybackToRemote((VolumeProvider)volumeProviderObj);
8324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
8424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
8524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void setActive(Object sessionObj, boolean active) {
8624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        ((MediaSession)sessionObj).setActive(active);
8724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
8824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
8924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static boolean isActive(Object sessionObj) {
9024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return ((MediaSession)sessionObj).isActive();
9124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
9224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
9324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void sendSessionEvent(Object sessionObj, String event, Bundle extras) {
9424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        ((MediaSession)sessionObj).sendSessionEvent(event, extras);
9524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
9624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
9724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void release(Object sessionObj) {
9824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        ((MediaSession)sessionObj).release();
9924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
10024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
10124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static Parcelable getSessionToken(Object sessionObj) {
10224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        return ((MediaSession)sessionObj).getSessionToken();
10324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
10424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
10524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void setPlaybackState(Object sessionObj, Object stateObj) {
10624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        ((MediaSession)sessionObj).setPlaybackState((PlaybackState)stateObj);
10724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
10824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
10924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    public static void setMetadata(Object sessionObj, Object metadataObj) {
11024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        ((MediaSession)sessionObj).setMetadata((MediaMetadata)metadataObj);
11124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
11224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
11385d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik    public static void setSessionActivity(Object sessionObj, PendingIntent pi) {
11485d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik        ((MediaSession) sessionObj).setSessionActivity(pi);
11585d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik    }
11685d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik
117ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    public static void setMediaButtonReceiver(Object sessionObj, PendingIntent pi) {
118ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        ((MediaSession) sessionObj).setMediaButtonReceiver(pi);
119ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    }
120ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
121ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    public static void setQueue(Object sessionObj, List<Object> queueObjs) {
122ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        if (queueObjs == null) {
123ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik            ((MediaSession) sessionObj).setQueue(null);
124ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik            return;
125ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        }
126ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        ArrayList<MediaSession.QueueItem> queue = new ArrayList<MediaSession.QueueItem>();
127ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        for (Object itemObj : queueObjs) {
128ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik            queue.add((MediaSession.QueueItem) itemObj);
129ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        }
130ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        ((MediaSession) sessionObj).setQueue(queue);
131ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    }
132ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
133ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    public static void setQueueTitle(Object sessionObj, CharSequence title) {
134ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        ((MediaSession) sessionObj).setQueueTitle(title);
135ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    }
136ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
137ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    public static void setExtras(Object sessionObj, Bundle extras) {
138ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        ((MediaSession) sessionObj).setExtras(extras);
139ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    }
140ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
141be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo    public static boolean hasCallback(Object sessionObj) {
142be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo        Field callbackField = null;
143be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo        try {
144be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo            callbackField = sessionObj.getClass().getDeclaredField("mCallback");
145be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo            if (callbackField != null) {
146be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo                callbackField.setAccessible(true);
147be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo                return callbackField.get(sessionObj) != null;
148be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo            }
149be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo        } catch (NoSuchFieldException | IllegalAccessException e) {
150be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo            Log.w(TAG, "Failed to get mCallback object.");
151be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo        }
152be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo        return false;
153be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo    }
154be3bec76ad7ad0248c35549a89e2a3cf27348f65Sungsoo
155bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake    interface Callback {
156bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onCommand(String command, Bundle extras, ResultReceiver cb);
157bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        boolean onMediaButtonEvent(Intent mediaButtonIntent);
158bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onPlay();
159bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onPlayFromMediaId(String mediaId, Bundle extras);
160bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onPlayFromSearch(String search, Bundle extras);
161bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onSkipToQueueItem(long id);
162bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onPause();
163bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onSkipToNext();
164bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onSkipToPrevious();
165bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onFastForward();
166bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onRewind();
167bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onStop();
168bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onSeekTo(long position);
169bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onSetRating(Object ratingObject);
170bd51c368d8bf32d652ae370c2723080d82b2834dIan Lake        void onCustomAction(String action, Bundle extras);
17124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
17224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
17324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    static class CallbackProxy<T extends Callback> extends MediaSession.Callback {
17424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        protected final T mCallback;
17524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
17624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public CallbackProxy(T callback) {
17724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback = callback;
17824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
17924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
18024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
181b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal        public void onCommand(String command, Bundle args, ResultReceiver cb) {
182b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal            mCallback.onCommand(command, args, cb);
18324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
18424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
1858af0092e2d7409e79779af396d63ca4146f1fb21RoboErik        @Override
1868af0092e2d7409e79779af396d63ca4146f1fb21RoboErik        public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
187944a4e92d6d9619fa1a2172a4ec9dc683eb65b40Ian Lake            return mCallback.onMediaButtonEvent(mediaButtonIntent)
188944a4e92d6d9619fa1a2172a4ec9dc683eb65b40Ian Lake                    || super.onMediaButtonEvent(mediaButtonIntent);
18924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
19024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
19124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
19224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onPlay() {
19324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onPlay();
19424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
19524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
19624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
19726d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        public void onPlayFromMediaId(String mediaId, Bundle extras) {
19826d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake            mCallback.onPlayFromMediaId(mediaId, extras);
19926d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        }
20026d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake
20126d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        @Override
20226d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        public void onPlayFromSearch(String search, Bundle extras) {
20326d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake            mCallback.onPlayFromSearch(search, extras);
20426d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        }
20526d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake
20626d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        @Override
20726d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        public void onSkipToQueueItem(long id) {
20826d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake            mCallback.onSkipToQueueItem(id);
20926d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        }
21026d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake
21126d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        @Override
21224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onPause() {
21324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onPause();
21424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
21524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
21624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
21724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onSkipToNext() {
21824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onSkipToNext();
21924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
22024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
22124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
22224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onSkipToPrevious() {
22324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onSkipToPrevious();
22424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
22524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
22624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
22724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onFastForward() {
22824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onFastForward();
22924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
23024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
23124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
23224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onRewind() {
23324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onRewind();
23424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
23524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
23624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
23724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onStop() {
23824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onStop();
23924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
24024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
24124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
24224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onSeekTo(long pos) {
24324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onSeekTo(pos);
24424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
24524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown
24624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        @Override
24724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        public void onSetRating(Rating rating) {
24824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown            mCallback.onSetRating(rating);
24924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown        }
25026d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake
25126d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        @Override
25226d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        public void onCustomAction(String action, Bundle extras) {
25326d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake            mCallback.onCustomAction(action, extras);
25426d994357fa4dbcd813f1c066ce09d5fdaa301a9Ian Lake        }
25524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown    }
256ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
257ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    static class QueueItem {
258ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
259ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        public static Object createItem(Object mediaDescription, long id) {
260ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik            return new MediaSession.QueueItem((MediaDescription) mediaDescription, id);
261ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        }
262ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
263ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        public static Object getDescription(Object queueItem) {
264ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik            return ((MediaSession.QueueItem) queueItem).getDescription();
265ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        }
266ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik
267ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        public static long getQueueId(Object queueItem) {
268ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik            return ((MediaSession.QueueItem) queueItem).getQueueId();
269ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik        }
270ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik    }
27124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown}
272