124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown/* 324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Copyright (C) 2014 The Android Open Source Project 424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * you may not use this file except in compliance with the License. 724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * You may obtain a copy of the License at 824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 1024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 1124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Unless required by applicable law or agreed to in writing, software 1224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 1324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * See the License for the specific language governing permissions and 1524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * limitations under the License. 1624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 1724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 1824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownpackage android.support.v4.media.session; 1924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 2085d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErikimport android.app.Activity; 2185d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErikimport android.app.PendingIntent; 225c9469e010106467791b47b0fa83efda84491a21RoboErikimport android.content.ComponentName; 2324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.content.Context; 2424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.content.Intent; 2524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.media.AudioManager; 2624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Bundle; 2724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Handler; 28e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.IBinder; 29e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.Looper; 30e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.Message; 3124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Parcel; 3224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.Parcelable; 33e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.RemoteCallbackList; 34e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.RemoteException; 3524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.os.ResultReceiver; 36e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.os.SystemClock; 37ceb8bf5e5cce7a37736981e626c4be416378767bRoboErikimport android.support.v4.media.MediaDescriptionCompat; 3824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.MediaMetadataCompat; 3924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.RatingCompat; 4024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.support.v4.media.VolumeProviderCompat; 4124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownimport android.text.TextUtils; 42e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.util.Log; 43e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport android.view.KeyEvent; 4424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 45e49860b0f76d8336c1d41831ed370b0ff94278efRoboErikimport java.lang.ref.WeakReference; 46ceb8bf5e5cce7a37736981e626c4be416378767bRoboErikimport java.util.ArrayList; 47ceb8bf5e5cce7a37736981e626c4be416378767bRoboErikimport java.util.List; 48ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 4924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown/** 5024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Allows interaction with media controllers, volume keys, media buttons, and 5124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * transport controls. 5224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 5324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * A MediaSession should be created when an app wants to publish media playback 5424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * information or handle media keys. In general an app only needs one session 5524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * for all playback, though multiple sessions can be created to provide finer 5624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * grain controls of media. 5724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 5824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Once a session is created the owner of the session may pass its 5924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * {@link #getSessionToken() session token} to other processes to allow them to 6024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * create a {@link MediaControllerCompat} to interact with the session. 6124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 6224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * To receive commands, media keys, and other events a {@link Callback} must be 638af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * set with {@link #setCallback(Callback)}. 6424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 6524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * When an app is finished performing playback it must call {@link #release()} 6624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * to clean up the session and notify any controllers. 6724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 685c9469e010106467791b47b0fa83efda84491a21RoboErik * MediaSessionCompat objects are not thread safe and all calls should be made 695c9469e010106467791b47b0fa83efda84491a21RoboErik * from the same thread. 7024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 718af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * This is a helper for accessing features in 728af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * {@link android.media.session.MediaSession} introduced after API level 4 in a 738af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * backwards compatible fashion. 7424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 7524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brownpublic class MediaSessionCompat { 7624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown private final MediaSessionImpl mImpl; 77ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private final MediaControllerCompat mController; 785c9469e010106467791b47b0fa83efda84491a21RoboErik private final ArrayList<OnActiveChangeListener> 795c9469e010106467791b47b0fa83efda84491a21RoboErik mActiveListeners = new ArrayList<OnActiveChangeListener>(); 8024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 8124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 8224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Set this flag on the session to indicate that it can handle media button 8324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * events. 8424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 8524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1 << 0; 8624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 8724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 8824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Set this flag on the session to indicate that it handles transport 898af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * control commands through its {@link Callback}. 9024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 9124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1; 9224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 9324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 9424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Creates a new session. 9524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 9624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param context The context. 9724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param tag A short name for debugging purposes. 985c9469e010106467791b47b0fa83efda84491a21RoboErik * @param mediaButtonEventReceiver The component name for your receiver. 995c9469e010106467791b47b0fa83efda84491a21RoboErik * This must be non-null to support platform versions earlier 1005c9469e010106467791b47b0fa83efda84491a21RoboErik * than {@link android.os.Build.VERSION_CODES#LOLLIPOP}. 1015c9469e010106467791b47b0fa83efda84491a21RoboErik * @param mbrIntent The PendingIntent for your receiver component that 1025c9469e010106467791b47b0fa83efda84491a21RoboErik * handles media button events. This is optional and will be used 1035c9469e010106467791b47b0fa83efda84491a21RoboErik * on {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} and 1045c9469e010106467791b47b0fa83efda84491a21RoboErik * later instead of the component name. 10524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 1065c9469e010106467791b47b0fa83efda84491a21RoboErik public MediaSessionCompat(Context context, String tag, ComponentName mediaButtonEventReceiver, 1075c9469e010106467791b47b0fa83efda84491a21RoboErik PendingIntent mbrIntent) { 10824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown if (context == null) { 10924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown throw new IllegalArgumentException("context must not be null"); 11024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 11124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown if (TextUtils.isEmpty(tag)) { 11224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown throw new IllegalArgumentException("tag must not be null or empty"); 11324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 11424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 11524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown if (android.os.Build.VERSION.SDK_INT >= 21) { 11624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl = new MediaSessionImplApi21(context, tag); 1175c9469e010106467791b47b0fa83efda84491a21RoboErik mImpl.setMediaButtonReceiver(mbrIntent); 11824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } else { 119e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mImpl = new MediaSessionImplBase(context, tag, mediaButtonEventReceiver, mbrIntent); 12024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 121ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mController = new MediaControllerCompat(context, this); 12224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 12324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 124ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private MediaSessionCompat(Context context, MediaSessionImpl impl) { 125bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik mImpl = impl; 126ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mController = new MediaControllerCompat(context, this); 127bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik } 128bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik 12924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 13024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Add a callback to receive updates on for the MediaSession. This includes 13124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * media button and volume events. The caller's thread will be used to post 13224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * events. 13324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 13424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param callback The callback object 13524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 1368af0092e2d7409e79779af396d63ca4146f1fb21RoboErik public void setCallback(Callback callback) { 1378af0092e2d7409e79779af396d63ca4146f1fb21RoboErik setCallback(callback, null); 13824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 13924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 14024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 1418af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * Set the callback to receive updates for the MediaSession. This includes 1428af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * media button and volume events. Set the callback to null to stop 1438af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * receiving events. 14424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 14524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param callback The callback to receive updates on. 14624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param handler The handler that events should be posted on. 14724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 1488af0092e2d7409e79779af396d63ca4146f1fb21RoboErik public void setCallback(Callback callback, Handler handler) { 1498af0092e2d7409e79779af396d63ca4146f1fb21RoboErik mImpl.setCallback(callback, handler != null ? handler : new Handler()); 15024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 15124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 15224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 153ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Set an intent for launching UI for this Session. This can be used as a 154ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * quick link to an ongoing media screen. The intent should be for an 155ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * activity that may be started using 156ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * {@link Activity#startActivity(Intent)}. 157ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 158ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @param pi The intent to launch to show UI for this Session. 159ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 160ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setSessionActivity(PendingIntent pi) { 161ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mImpl.setSessionActivity(pi); 162ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 163ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 164ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 165ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Set a pending intent for your media button receiver to allow restarting 166ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * playback after the session has been stopped. If your app is started in 167ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * this way an {@link Intent#ACTION_MEDIA_BUTTON} intent will be sent via 168ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * the pending intent. 169ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <p> 1705c9469e010106467791b47b0fa83efda84491a21RoboErik * This method will only work on 1715c9469e010106467791b47b0fa83efda84491a21RoboErik * {@link android.os.Build.VERSION_CODES#LOLLIPOP} and later. Earlier 1725c9469e010106467791b47b0fa83efda84491a21RoboErik * platform versions must include the media button receiver in the 1735c9469e010106467791b47b0fa83efda84491a21RoboErik * constructor. 174ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 175ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @param mbr The {@link PendingIntent} to send the media button event to. 176ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 177ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setMediaButtonReceiver(PendingIntent mbr) { 178ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mImpl.setMediaButtonReceiver(mbr); 179ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 180ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 181ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 18224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Set any flags for the session. 18324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 18424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param flags The flags to set for this session. 18524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 18624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setFlags(int flags) { 18724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.setFlags(flags); 18824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 18924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 19024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 19124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Set the stream this session is playing on. This will affect the system's 19224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * volume handling for this session. If {@link #setPlaybackToRemote} was 19324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * previously called it will stop receiving volume commands and the system 19424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * will begin sending volume changes to the appropriate stream. 19524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 19624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * By default sessions are on {@link AudioManager#STREAM_MUSIC}. 19724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 19824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param stream The {@link AudioManager} stream this session is playing on. 19924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 20024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackToLocal(int stream) { 20124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.setPlaybackToLocal(stream); 20224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 20324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 20424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 20524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Configure this session to use remote volume handling. This must be called 20624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * to receive volume button events, otherwise the system will adjust the 20724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * current stream volume for this session. If {@link #setPlaybackToLocal} 20824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * was previously called that stream will stop receiving volume changes for 20924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * this session. 210e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * <p> 211e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * On platforms earlier than {@link android.os.Build.VERSION_CODES#LOLLIPOP} 212e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * this will only allow an app to handle volume commands sent directly to 213e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * the session by a {@link MediaControllerCompat}. System routing of volume 214e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * keys will not use the volume provider. 21524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 21624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param volumeProvider The provider that will handle volume changes. May 21724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * not be null. 21824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 21924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackToRemote(VolumeProviderCompat volumeProvider) { 22024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown if (volumeProvider == null) { 22124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown throw new IllegalArgumentException("volumeProvider may not be null!"); 22224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 22324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.setPlaybackToRemote(volumeProvider); 22424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 22524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 22624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 22724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Set if this session is currently active and ready to receive commands. If 22824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * set to false your session's controller may not be discoverable. You must 22924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * set the session to active before it can start receiving media button 23024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * events or transport commands. 231ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <p> 232ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * On platforms earlier than 233ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * {@link android.os.Build.VERSION_CODES#LOLLIPOP}, 234ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * {@link #setMediaButtonReceiver(PendingIntent)} must be called before 235ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * setting this to true. 23624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 23724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param active Whether this session is active or not. 23824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 23924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setActive(boolean active) { 24024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.setActive(active); 2415c9469e010106467791b47b0fa83efda84491a21RoboErik for (OnActiveChangeListener listener : mActiveListeners) { 2425c9469e010106467791b47b0fa83efda84491a21RoboErik listener.onActiveChanged(); 2435c9469e010106467791b47b0fa83efda84491a21RoboErik } 24424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 24524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 24624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 24724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Get the current active state of this session. 24824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 24924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @return True if the session is active, false otherwise. 25024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 25124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public boolean isActive() { 25224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return mImpl.isActive(); 25324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 25424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 25524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 25624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Send a proprietary event to all MediaControllers listening to this 25724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Session. It's up to the Controller/Session owner to determine the meaning 25824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * of any events. 25924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 26024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param event The name of the event to send 26124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param extras Any extras included with the event 26224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 26324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void sendSessionEvent(String event, Bundle extras) { 26424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown if (TextUtils.isEmpty(event)) { 26524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown throw new IllegalArgumentException("event cannot be null or empty"); 26624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 26724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.sendSessionEvent(event, extras); 26824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 26924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 27024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 27124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * This must be called when an app has finished performing playback. If 27224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * playback is expected to start again shortly the session can be left open, 27324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * but it must be released if your activity or service is being destroyed. 27424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 27524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void release() { 27624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.release(); 27724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 27824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 27924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 28024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Retrieve a token object that can be used by apps to create a 281e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * {@link MediaControllerCompat} for interacting with this session. The 282e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * owner of the session is responsible for deciding how to distribute these 283e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * tokens. 284e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * <p> 285e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * On platform versions before 286e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * {@link android.os.Build.VERSION_CODES#LOLLIPOP} this token may only be 287e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * used within your app as there is no way to guarantee other apps are using 288e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * the same version of the support library. 28924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 290e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * @return A token that can be used to create a media controller for this 29124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * session. 29224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 29324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Token getSessionToken() { 29424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return mImpl.getSessionToken(); 29524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 29624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 29724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 298ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Get a controller for this session. This is a convenience method to avoid 299ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * having to cache your own controller in process. 300ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 301ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @return A controller for this session. 302ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 303ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public MediaControllerCompat getController() { 304ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return mController; 305ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 306ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 307ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 30824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Update the current playback state. 30924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 31024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param state The current state of playback 31124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 31224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackState(PlaybackStateCompat state) { 31324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.setPlaybackState(state); 31424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 31524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 31624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 31724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Update the current metadata. New metadata can be created using 31824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * {@link android.media.MediaMetadata.Builder}. 31924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 32024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param metadata The new metadata 32124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 32224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setMetadata(MediaMetadataCompat metadata) { 32324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mImpl.setMetadata(metadata); 32424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 32524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 32624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 327ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Update the list of items in the play queue. It is an ordered list and 328ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * should contain the current item, and previous or upcoming items if they 329ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * exist. Specify null if there is no current play queue. 330ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <p> 331ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * The queue should be of reasonable size. If the play queue is unbounded 332ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * within your app, it is better to send a reasonable amount in a sliding 333ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * window instead. 33485d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik * 335ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @param queue A list of items in the play queue. 33685d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik */ 337ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setQueue(List<QueueItem> queue) { 338ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mImpl.setQueue(queue); 339ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 340ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 341ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 342ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Set the title of the play queue. The UI should display this title along 343ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * with the play queue itself. e.g. "Play Queue", "Now Playing", or an album 344ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * name. 345ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 346ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @param title The title of the play queue. 347ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 348ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setQueueTitle(CharSequence title) { 349ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mImpl.setQueueTitle(title); 350ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 351ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 352ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 353ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Set the style of rating used by this session. Apps trying to set the 354ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * rating should use this style. Must be one of the following: 355ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <ul> 356ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <li>{@link RatingCompat#RATING_NONE}</li> 357ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <li>{@link RatingCompat#RATING_3_STARS}</li> 358ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <li>{@link RatingCompat#RATING_4_STARS}</li> 359ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <li>{@link RatingCompat#RATING_5_STARS}</li> 360ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <li>{@link RatingCompat#RATING_HEART}</li> 361ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <li>{@link RatingCompat#RATING_PERCENTAGE}</li> 362ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <li>{@link RatingCompat#RATING_THUMB_UP_DOWN}</li> 363ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * </ul> 364ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 365ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setRatingType(int type) { 366ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mImpl.setRatingType(type); 367ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 368ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 369ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 370ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Set some extras that can be associated with the 371ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * {@link MediaSessionCompat}. No assumptions should be made as to how a 372ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * {@link MediaControllerCompat} will handle these extras. Keys should be 373ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * fully qualified (e.g. com.example.MY_EXTRA) to avoid conflicts. 374ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 375ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @param extras The extras associated with the session. 376ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 377ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setExtras(Bundle extras) { 378ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mImpl.setExtras(extras); 37985d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik } 38085d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik 38185d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik /** 38285d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik * Gets the underlying framework {@link android.media.session.MediaSession} 38385d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik * object. 38424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 38524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * This method is only supported on API 21+. 38624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * </p> 38724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 38824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @return The underlying {@link android.media.session.MediaSession} object, 38985d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik * or null if none. 39024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 39124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Object getMediaSession() { 39224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return mImpl.getMediaSession(); 39324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 39424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 39524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 3965c9469e010106467791b47b0fa83efda84491a21RoboErik * Gets the underlying framework {@link android.media.RemoteControlClient} 3975c9469e010106467791b47b0fa83efda84491a21RoboErik * object. 3985c9469e010106467791b47b0fa83efda84491a21RoboErik * <p> 3995c9469e010106467791b47b0fa83efda84491a21RoboErik * This method is only supported on APIs 14-20. On API 21+ 4005c9469e010106467791b47b0fa83efda84491a21RoboErik * {@link #getMediaSession()} should be used instead. 4015c9469e010106467791b47b0fa83efda84491a21RoboErik * 4025c9469e010106467791b47b0fa83efda84491a21RoboErik * @return The underlying {@link android.media.RemoteControlClient} object, 4035c9469e010106467791b47b0fa83efda84491a21RoboErik * or null if none. 4045c9469e010106467791b47b0fa83efda84491a21RoboErik */ 4055c9469e010106467791b47b0fa83efda84491a21RoboErik public Object getRemoteControlClient() { 4065c9469e010106467791b47b0fa83efda84491a21RoboErik return mImpl.getRemoteControlClient(); 4075c9469e010106467791b47b0fa83efda84491a21RoboErik } 4085c9469e010106467791b47b0fa83efda84491a21RoboErik 4095c9469e010106467791b47b0fa83efda84491a21RoboErik /** 4105c9469e010106467791b47b0fa83efda84491a21RoboErik * Adds a listener to be notified when the active status of this session 4115c9469e010106467791b47b0fa83efda84491a21RoboErik * changes. This is primarily used by the support library and should not be 4125c9469e010106467791b47b0fa83efda84491a21RoboErik * needed by apps. 4135c9469e010106467791b47b0fa83efda84491a21RoboErik * 4145c9469e010106467791b47b0fa83efda84491a21RoboErik * @param listener The listener to add. 4155c9469e010106467791b47b0fa83efda84491a21RoboErik */ 4165c9469e010106467791b47b0fa83efda84491a21RoboErik public void addOnActiveChangeListener(OnActiveChangeListener listener) { 4175c9469e010106467791b47b0fa83efda84491a21RoboErik if (listener == null) { 4185c9469e010106467791b47b0fa83efda84491a21RoboErik throw new IllegalArgumentException("Listener may not be null"); 4195c9469e010106467791b47b0fa83efda84491a21RoboErik } 4205c9469e010106467791b47b0fa83efda84491a21RoboErik mActiveListeners.add(listener); 4215c9469e010106467791b47b0fa83efda84491a21RoboErik } 4225c9469e010106467791b47b0fa83efda84491a21RoboErik 4235c9469e010106467791b47b0fa83efda84491a21RoboErik /** 4245c9469e010106467791b47b0fa83efda84491a21RoboErik * Stops the listener from being notified when the active status of this 4255c9469e010106467791b47b0fa83efda84491a21RoboErik * session changes. 4265c9469e010106467791b47b0fa83efda84491a21RoboErik * 4275c9469e010106467791b47b0fa83efda84491a21RoboErik * @param listener The listener to remove. 4285c9469e010106467791b47b0fa83efda84491a21RoboErik */ 4295c9469e010106467791b47b0fa83efda84491a21RoboErik public void removeOnActiveChangeListener(OnActiveChangeListener listener) { 4305c9469e010106467791b47b0fa83efda84491a21RoboErik if (listener == null) { 4315c9469e010106467791b47b0fa83efda84491a21RoboErik throw new IllegalArgumentException("Listener may not be null"); 4325c9469e010106467791b47b0fa83efda84491a21RoboErik } 4335c9469e010106467791b47b0fa83efda84491a21RoboErik mActiveListeners.remove(listener); 4345c9469e010106467791b47b0fa83efda84491a21RoboErik } 4355c9469e010106467791b47b0fa83efda84491a21RoboErik 4365c9469e010106467791b47b0fa83efda84491a21RoboErik /** 437bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik * Obtain a compat wrapper for an existing MediaSession. 438bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik * 439bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik * @param mediaSession The {@link android.media.session.MediaSession} to 440bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik * wrap. 441bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik * @return A compat wrapper for the provided session. 442bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik */ 443ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public static MediaSessionCompat obtain(Context context, Object mediaSession) { 444ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return new MediaSessionCompat(context, new MediaSessionImplApi21(mediaSession)); 445bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik } 446bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik 447bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik /** 4488af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * Receives transport controls, media buttons, and commands from controllers 4498af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * and the system. The callback may be set using {@link #setCallback}. 45024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 45124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public abstract static class Callback { 45224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown final Object mCallbackObj; 45324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 45424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Callback() { 45524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown if (android.os.Build.VERSION.SDK_INT >= 21) { 45624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mCallbackObj = MediaSessionCompatApi21.createCallback(new StubApi21()); 45724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } else { 45824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mCallbackObj = null; 45924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 46024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 46124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 46224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 46324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Called when a controller has sent a custom command to this session. 46424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * The owner of the session may handle custom commands but is not 46524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * required to. 46624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 46724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param command The command name. 46824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param extras Optional parameters for the command, may be null. 46924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param cb A result receiver to which a result may be sent by the command, may be null. 47024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 471b530c89bba371d2d575f10480b2e90914b0d3f3fGabriel Peal public void onCommand(String command, Bundle extras, ResultReceiver cb) { 47224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 47324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 4748af0092e2d7409e79779af396d63ca4146f1fb21RoboErik /** 4758af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * Override to handle media button events. 4768af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * 4778af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * @param mediaButtonEvent The media button event intent. 4788af0092e2d7409e79779af396d63ca4146f1fb21RoboErik * @return True if the event was handled, false otherwise. 4798af0092e2d7409e79779af396d63ca4146f1fb21RoboErik */ 4808af0092e2d7409e79779af396d63ca4146f1fb21RoboErik public boolean onMediaButtonEvent(Intent mediaButtonEvent) { 4818af0092e2d7409e79779af396d63ca4146f1fb21RoboErik return false; 48224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 48324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 48424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 48524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to begin playback. 48624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 48724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onPlay() { 48824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 48924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 49024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 491e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * Override to handle requests to play a specific mediaId that was 492e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * provided by your app. 493e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik */ 494e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onPlayFromMediaId(String mediaId, Bundle extras) { 495e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 496e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 497e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik /** 498e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * Override to handle requests to begin playback from a search query. An 499e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * empty query indicates that the app may play any music. The 500e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * implementation should attempt to make a smart choice about what to 501e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * play. 502e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik */ 503e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onPlayFromSearch(String query, Bundle extras) { 504e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 505e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 506e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik /** 507e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * Override to handle requests to play an item with a given id from the 508e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * play queue. 509e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik */ 510e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onSkipToQueueItem(long id) { 511e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 512e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 513e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik /** 51424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to pause playback. 51524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 51624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onPause() { 51724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 51824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 51924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 52024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to skip to the next media item. 52124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 52224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSkipToNext() { 52324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 52424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 52524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 52624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to skip to the previous media item. 52724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 52824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSkipToPrevious() { 52924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 53024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 53124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 53224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to fast forward. 53324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 53424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onFastForward() { 53524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 53624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 53724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 53824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to rewind. 53924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 54024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onRewind() { 54124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 54224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 54324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 54424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to stop playback. 54524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 54624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onStop() { 54724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 54824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 54924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 55024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle requests to seek to a specific position in ms. 55124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 55224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param pos New position to move to, in milliseconds. 55324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 55424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSeekTo(long pos) { 55524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 55624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 55724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 55824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Override to handle the item being rated. 55924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 56024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * @param rating 56124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 56224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSetRating(RatingCompat rating) { 56324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 56424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 565e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik /** 566e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * Called when a {@link MediaControllerCompat} wants a 567e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * {@link PlaybackStateCompat.CustomAction} to be performed. 568e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * 569e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * @param action The action that was originally sent in the 570e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * {@link PlaybackStateCompat.CustomAction}. 571e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * @param extras Optional extras specified by the 572e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * {@link MediaControllerCompat}. 573e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik */ 574e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onCustomAction(String action, Bundle extras) { 575e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 576e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 5778af0092e2d7409e79779af396d63ca4146f1fb21RoboErik private class StubApi21 implements MediaSessionCompatApi21.Callback { 5788af0092e2d7409e79779af396d63ca4146f1fb21RoboErik 5798af0092e2d7409e79779af396d63ca4146f1fb21RoboErik @Override 5808af0092e2d7409e79779af396d63ca4146f1fb21RoboErik public void onCommand(String command, Bundle extras, ResultReceiver cb) { 5818af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onCommand(command, extras, cb); 5828af0092e2d7409e79779af396d63ca4146f1fb21RoboErik } 5838af0092e2d7409e79779af396d63ca4146f1fb21RoboErik 5848af0092e2d7409e79779af396d63ca4146f1fb21RoboErik @Override 5858af0092e2d7409e79779af396d63ca4146f1fb21RoboErik public boolean onMediaButtonEvent(Intent mediaButtonIntent) { 5868af0092e2d7409e79779af396d63ca4146f1fb21RoboErik return Callback.this.onMediaButtonEvent(mediaButtonIntent); 5878af0092e2d7409e79779af396d63ca4146f1fb21RoboErik } 5888af0092e2d7409e79779af396d63ca4146f1fb21RoboErik 58924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 59024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onPlay() { 5918af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onPlay(); 59224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 59324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 59424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 595e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onPlayFromMediaId(String mediaId, Bundle extras) { 596e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Callback.this.onPlayFromMediaId(mediaId, extras); 597e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 598e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 599e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 600e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onPlayFromSearch(String search, Bundle extras) { 601e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Callback.this.onPlayFromSearch(search, extras); 602e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 603e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 604e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 605e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onSkipToQueueItem(long id) { 606e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Callback.this.onSkipToQueueItem(id); 607e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 608e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 609e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 61024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onPause() { 6118af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onPause(); 61224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 61324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 61424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 61524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSkipToNext() { 6168af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onSkipToNext(); 61724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 61824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 61924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 62024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSkipToPrevious() { 6218af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onSkipToPrevious(); 62224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 62324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 62424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 62524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onFastForward() { 6268af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onFastForward(); 62724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 62824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 62924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 63024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onRewind() { 6318af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onRewind(); 63224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 63324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 63424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 63524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onStop() { 6368af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onStop(); 63724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 63824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 63924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 64024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSeekTo(long pos) { 6418af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onSeekTo(pos); 64224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 64324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 64424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 64524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void onSetRating(Object ratingObj) { 6468af0092e2d7409e79779af396d63ca4146f1fb21RoboErik Callback.this.onSetRating(RatingCompat.fromRating(ratingObj)); 64724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 648e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 649e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 650e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void onCustomAction(String action, Bundle extras) { 651e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Callback.this.onCustomAction(action, extras); 652e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 65324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 65424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 65524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 65624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 65724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * Represents an ongoing session. This may be passed to apps by the session 65824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * owner to allow them to create a {@link MediaControllerCompat} to communicate with 65924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * the session. 66024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 66124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public static final class Token implements Parcelable { 662e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final Object mInner; 66324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 664e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Token(Object inner) { 66524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mInner = inner; 66624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 66724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 668ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik /** 669ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * Creates a compat Token from a framework 670ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * {@link android.media.session.MediaSession.Token} object. 671ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * <p> 672ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * This method is only supported on 673ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * {@link android.os.Build.VERSION_CODES#LOLLIPOP} and later. 674ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * </p> 675ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * 676ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * @param token The framework token object. 677ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik * @return A compat Token for use with {@link MediaControllerCompat}. 678ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik */ 6794e3b8470fa30cba04e2fb6b95516cff8f3e1e499RoboErik public static Token fromToken(Object token) { 680ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik if (token == null || android.os.Build.VERSION.SDK_INT < 21) { 681ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik return null; 682ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik } 683e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return new Token(MediaSessionCompatApi21.verifyToken(token)); 684ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik } 685ae70d8d953ef632acb9f176609a1f75bd948d101RoboErik 68624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 68724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public int describeContents() { 688e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return 0; 68924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 69024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 69124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 69224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void writeToParcel(Parcel dest, int flags) { 693e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (android.os.Build.VERSION.SDK_INT >= 21) { 694e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik dest.writeParcelable((Parcelable) mInner, flags); 695e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } else { 696e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik dest.writeStrongBinder((IBinder) mInner); 697e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 69824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 69924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 70024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown /** 7018ea3b7e9bae080d5ab65a150e952c87db70cc3a3Jeff Brown * Gets the underlying framework {@link android.media.session.MediaSession.Token} object. 70224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * <p> 70324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * This method is only supported on API 21+. 70424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * </p> 70524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * 7068ea3b7e9bae080d5ab65a150e952c87db70cc3a3Jeff Brown * @return The underlying {@link android.media.session.MediaSession.Token} object, 70724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown * or null if none. 70824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown */ 70924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Object getToken() { 71024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return mInner; 71124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 71224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 71324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public static final Parcelable.Creator<Token> CREATOR 71424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown = new Parcelable.Creator<Token>() { 71524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 71624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Token createFromParcel(Parcel in) { 717e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Object inner; 718e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (android.os.Build.VERSION.SDK_INT >= 21) { 719e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik inner = in.readParcelable(null); 720e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } else { 721e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik inner = in.readStrongBinder(); 722e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 723e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return new Token(inner); 72424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 72524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 72624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 72724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Token[] newArray(int size) { 72824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return new Token[size]; 72924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 73024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown }; 73124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 73224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 733ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 734ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * A single item that is part of the play queue. It contains a description 735ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * of the item and its id in the queue. 736ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 737ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public static final class QueueItem implements Parcelable { 738ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 739ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * This id is reserved. No items can be explicitly asigned this id. 740ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 741ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public static final int UNKNOWN_ID = -1; 742ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 743ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private final MediaDescriptionCompat mDescription; 744ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private final long mId; 745ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 746ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private Object mItem; 747ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 748ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 749ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Create a new {@link MediaSessionCompat.QueueItem}. 750ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 751ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @param description The {@link MediaDescriptionCompat} for this item. 752ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @param id An identifier for this item. It must be unique within the 753ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * play queue and cannot be {@link #UNKNOWN_ID}. 754ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 755ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public QueueItem(MediaDescriptionCompat description, long id) { 756ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik this(null, description, id); 757ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 758ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 759ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private QueueItem(Object queueItem, MediaDescriptionCompat description, long id) { 760ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik if (description == null) { 761ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik throw new IllegalArgumentException("Description cannot be null."); 762ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 763ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik if (id == UNKNOWN_ID) { 764ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik throw new IllegalArgumentException("Id cannot be QueueItem.UNKNOWN_ID"); 765ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 766ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mDescription = description; 767ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mId = id; 768ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mItem = queueItem; 769ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 770ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 771ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private QueueItem(Parcel in) { 772ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mDescription = MediaDescriptionCompat.CREATOR.createFromParcel(in); 773ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mId = in.readLong(); 774ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 775ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 776ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 777ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Get the description for this item. 778ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 779ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public MediaDescriptionCompat getDescription() { 780ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return mDescription; 781ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 782ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 783ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 784ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Get the queue id for this item. 785ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 786ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public long getQueueId() { 787ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return mId; 788ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 789ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 790ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 791ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void writeToParcel(Parcel dest, int flags) { 792ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mDescription.writeToParcel(dest, flags); 793ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik dest.writeLong(mId); 794ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 795ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 796ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 797ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public int describeContents() { 798ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return 0; 799ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 800ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 801ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 802ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Get the underlying 803ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * {@link android.media.session.MediaSession.QueueItem}. 804ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * <p> 805ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * On builds before {@link android.os.Build.VERSION_CODES#LOLLIPOP} null 806ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * is returned. 807ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 808ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @return The underlying 809ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * {@link android.media.session.MediaSession.QueueItem} or null. 810ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 811ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public Object getQueueItem() { 812ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik if (mItem != null || android.os.Build.VERSION.SDK_INT < 21) { 813ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return mItem; 814ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 815ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mItem = MediaSessionCompatApi21.QueueItem.createItem(mDescription.getMediaDescription(), 816ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mId); 817ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return mItem; 818ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 819ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 820ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik /** 821ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * Obtain a compat wrapper for an existing QueueItem. 822ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * 823b6362d072f329a3207aa709ac6b79a4aa3c4d522Ying Wang * @param queueItem The {@link android.media.session.MediaSession.QueueItem} to 824ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * wrap. 825ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik * @return A compat wrapper for the provided item. 826ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik */ 827ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public static QueueItem obtain(Object queueItem) { 828ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik Object descriptionObj = MediaSessionCompatApi21.QueueItem.getDescription(queueItem); 829ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik MediaDescriptionCompat description = MediaDescriptionCompat.fromMediaDescription( 830ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik descriptionObj); 831ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik long id = MediaSessionCompatApi21.QueueItem.getQueueId(queueItem); 832ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return new QueueItem(queueItem, description, id); 833ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 834ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 835ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public static final Creator<MediaSessionCompat.QueueItem> 836ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik CREATOR = new Creator<MediaSessionCompat.QueueItem>() { 837ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 838ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 839ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public MediaSessionCompat.QueueItem createFromParcel(Parcel p) { 840ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return new MediaSessionCompat.QueueItem(p); 841ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 842ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 843ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 844ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public MediaSessionCompat.QueueItem[] newArray(int size) { 845ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return new MediaSessionCompat.QueueItem[size]; 846ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 847ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik }; 848ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 849ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 850ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public String toString() { 851ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik return "MediaSession.QueueItem {" + 852ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik "Description=" + mDescription + 853ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik ", Id=" + mId + " }"; 854ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 855ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 856ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 857e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik /** 858e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * This is a wrapper for {@link ResultReceiver} for sending over aidl 859e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * interfaces. The framework version was not exposed to aidls until 860e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * {@link android.os.Build.VERSION_CODES#LOLLIPOP}. 861e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik */ 862e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik static final class ResultReceiverWrapper implements Parcelable { 863e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private ResultReceiver mResultReceiver; 864e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 865e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public ResultReceiverWrapper(ResultReceiver resultReceiver) { 866e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mResultReceiver = resultReceiver; 867e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 868e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 869e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik ResultReceiverWrapper(Parcel in) { 870e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mResultReceiver = ResultReceiver.CREATOR.createFromParcel(in); 871e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 872e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 873e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public static final Creator<ResultReceiverWrapper> 874e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik CREATOR = new Creator<ResultReceiverWrapper>() { 875e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 876e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public ResultReceiverWrapper createFromParcel(Parcel p) { 877e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return new ResultReceiverWrapper(p); 878e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 879e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 880e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 881e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public ResultReceiverWrapper[] newArray(int size) { 882e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return new ResultReceiverWrapper[size]; 883e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 884e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik }; 885e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 886e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 887e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public int describeContents() { 888e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return 0; 889e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 890e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 891e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 892e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void writeToParcel(Parcel dest, int flags) { 893e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mResultReceiver.writeToParcel(dest, flags); 894e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 895e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 896e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 8975c9469e010106467791b47b0fa83efda84491a21RoboErik public interface OnActiveChangeListener { 8985c9469e010106467791b47b0fa83efda84491a21RoboErik void onActiveChanged(); 8995c9469e010106467791b47b0fa83efda84491a21RoboErik } 9005c9469e010106467791b47b0fa83efda84491a21RoboErik 90124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown interface MediaSessionImpl { 9028af0092e2d7409e79779af396d63ca4146f1fb21RoboErik void setCallback(Callback callback, Handler handler); 90324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void setFlags(int flags); 90424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void setPlaybackToLocal(int stream); 90524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void setPlaybackToRemote(VolumeProviderCompat volumeProvider); 90624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void setActive(boolean active); 90724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown boolean isActive(); 90824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void sendSessionEvent(String event, Bundle extras); 90924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void release(); 91024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown Token getSessionToken(); 91124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void setPlaybackState(PlaybackStateCompat state); 91224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown void setMetadata(MediaMetadataCompat metadata); 91385d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik 91485d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik void setSessionActivity(PendingIntent pi); 915ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 916ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik void setMediaButtonReceiver(PendingIntent mbr); 917ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik void setQueue(List<QueueItem> queue); 918ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik void setQueueTitle(CharSequence title); 919ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 920ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik void setRatingType(int type); 921ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik void setExtras(Bundle extras); 922ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 92324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown Object getMediaSession(); 9245c9469e010106467791b47b0fa83efda84491a21RoboErik 9255c9469e010106467791b47b0fa83efda84491a21RoboErik Object getRemoteControlClient(); 92624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 92724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 92824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown // TODO: compatibility implementation 92924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown static class MediaSessionImplBase implements MediaSessionImpl { 9305c9469e010106467791b47b0fa83efda84491a21RoboErik private final Context mContext; 9315c9469e010106467791b47b0fa83efda84491a21RoboErik private final ComponentName mComponentName; 9325c9469e010106467791b47b0fa83efda84491a21RoboErik private final PendingIntent mMediaButtonEventReceiver; 9335c9469e010106467791b47b0fa83efda84491a21RoboErik private final Object mRccObj; 934e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final MediaSessionStub mStub; 935e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final Token mToken; 936e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final MessageHandler mHandler; 937e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final String mPackageName; 938e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final String mTag; 939e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final AudioManager mAudioManager; 9405c9469e010106467791b47b0fa83efda84491a21RoboErik 941e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final Object mLock = new Object(); 942e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private final RemoteCallbackList<IMediaControllerCallback> mControllerCallbacks 943e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik = new RemoteCallbackList<IMediaControllerCallback>(); 944e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 945e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private boolean mDestroyed = false; 9465c9469e010106467791b47b0fa83efda84491a21RoboErik private boolean mIsActive = false; 9475c9469e010106467791b47b0fa83efda84491a21RoboErik private boolean mIsRccRegistered = false; 9485c9469e010106467791b47b0fa83efda84491a21RoboErik private boolean mIsMbrRegistered = false; 9495c9469e010106467791b47b0fa83efda84491a21RoboErik private Callback mCallback; 9505c9469e010106467791b47b0fa83efda84491a21RoboErik 9515c9469e010106467791b47b0fa83efda84491a21RoboErik private int mFlags; 9525c9469e010106467791b47b0fa83efda84491a21RoboErik 9535c9469e010106467791b47b0fa83efda84491a21RoboErik private MediaMetadataCompat mMetadata; 9545c9469e010106467791b47b0fa83efda84491a21RoboErik private PlaybackStateCompat mState; 955e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private PendingIntent mSessionActivity; 956e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private List<QueueItem> mQueue; 957e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private CharSequence mQueueTitle; 958e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private int mRatingType; 959e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private Bundle mExtras; 960e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 961e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private int mVolumeType; 962e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private int mLocalStream; 963e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private VolumeProviderCompat mVolumeProvider; 9645c9469e010106467791b47b0fa83efda84491a21RoboErik 9651c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik private VolumeProviderCompat.Callback mVolumeCallback 9661c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik = new VolumeProviderCompat.Callback() { 9671c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik @Override 9681c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik public void onVolumeChanged(VolumeProviderCompat volumeProvider) { 9691c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik if (mVolumeProvider != volumeProvider) { 9701c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik return; 9711c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik } 9721c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik ParcelableVolumeInfo info = new ParcelableVolumeInfo(mVolumeType, mLocalStream, 9731c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik volumeProvider.getVolumeControl(), volumeProvider.getMaxVolume(), 9741c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik volumeProvider.getCurrentVolume()); 9751c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik sendVolumeInfoChanged(info); 9761c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik } 9771c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik }; 9781c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik 979e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public MediaSessionImplBase(Context context, String tag, ComponentName mbrComponent, 9805c9469e010106467791b47b0fa83efda84491a21RoboErik PendingIntent mbr) { 9815c9469e010106467791b47b0fa83efda84491a21RoboErik if (mbrComponent == null) { 9825c9469e010106467791b47b0fa83efda84491a21RoboErik throw new IllegalArgumentException( 9835c9469e010106467791b47b0fa83efda84491a21RoboErik "MediaButtonReceiver component may not be null."); 9845c9469e010106467791b47b0fa83efda84491a21RoboErik } 9855c9469e010106467791b47b0fa83efda84491a21RoboErik if (mbr == null) { 9865c9469e010106467791b47b0fa83efda84491a21RoboErik // construct a PendingIntent for the media button 9875c9469e010106467791b47b0fa83efda84491a21RoboErik Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 9885c9469e010106467791b47b0fa83efda84491a21RoboErik // the associated intent will be handled by the component being 9895c9469e010106467791b47b0fa83efda84491a21RoboErik // registered 9905c9469e010106467791b47b0fa83efda84491a21RoboErik mediaButtonIntent.setComponent(mbrComponent); 9915c9469e010106467791b47b0fa83efda84491a21RoboErik mbr = PendingIntent.getBroadcast(context, 9925c9469e010106467791b47b0fa83efda84491a21RoboErik 0/* requestCode, ignored */, mediaButtonIntent, 0/* flags */); 9935c9469e010106467791b47b0fa83efda84491a21RoboErik } 9945c9469e010106467791b47b0fa83efda84491a21RoboErik mContext = context; 995e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mPackageName = context.getPackageName(); 996e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 997e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mTag = tag; 9985c9469e010106467791b47b0fa83efda84491a21RoboErik mComponentName = mbrComponent; 9995c9469e010106467791b47b0fa83efda84491a21RoboErik mMediaButtonEventReceiver = mbr; 1000e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mStub = new MediaSessionStub(); 1001e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mToken = new Token(mStub); 1002e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler = new MessageHandler(Looper.myLooper()); 1003e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1004e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mRatingType = RatingCompat.RATING_NONE; 1005e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL; 1006e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mLocalStream = AudioManager.STREAM_MUSIC; 10075c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 14) { 10085c9469e010106467791b47b0fa83efda84491a21RoboErik mRccObj = MediaSessionCompatApi14.createRemoteControlClient(mbr); 10095c9469e010106467791b47b0fa83efda84491a21RoboErik } else { 10105c9469e010106467791b47b0fa83efda84491a21RoboErik mRccObj = null; 10115c9469e010106467791b47b0fa83efda84491a21RoboErik } 10125c9469e010106467791b47b0fa83efda84491a21RoboErik } 10135c9469e010106467791b47b0fa83efda84491a21RoboErik 101424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 10155c9469e010106467791b47b0fa83efda84491a21RoboErik public void setCallback(final Callback callback, Handler handler) { 10165c9469e010106467791b47b0fa83efda84491a21RoboErik if (callback == mCallback) { 10175c9469e010106467791b47b0fa83efda84491a21RoboErik return; 10185c9469e010106467791b47b0fa83efda84491a21RoboErik } 10195c9469e010106467791b47b0fa83efda84491a21RoboErik if (callback == null || android.os.Build.VERSION.SDK_INT < 18) { 10205c9469e010106467791b47b0fa83efda84491a21RoboErik // There's nothing to register on API < 18 since media buttons 10215c9469e010106467791b47b0fa83efda84491a21RoboErik // all go through the media button receiver 10225c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 18) { 10235c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi18.setOnPlaybackPositionUpdateListener(mRccObj, null); 10245c9469e010106467791b47b0fa83efda84491a21RoboErik } 10255c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 19) { 10265c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi19.setOnMetadataUpdateListener(mRccObj, null); 10275c9469e010106467791b47b0fa83efda84491a21RoboErik } 10285c9469e010106467791b47b0fa83efda84491a21RoboErik } else { 10295c9469e010106467791b47b0fa83efda84491a21RoboErik if (handler == null) { 10305c9469e010106467791b47b0fa83efda84491a21RoboErik handler = new Handler(); 10315c9469e010106467791b47b0fa83efda84491a21RoboErik } 10325c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi14.Callback cb14 = new MediaSessionCompatApi14.Callback() { 10335c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10345c9469e010106467791b47b0fa83efda84491a21RoboErik public void onStop() { 10355c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onStop(); 10365c9469e010106467791b47b0fa83efda84491a21RoboErik } 10375c9469e010106467791b47b0fa83efda84491a21RoboErik 10385c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10395c9469e010106467791b47b0fa83efda84491a21RoboErik public void onSkipToPrevious() { 10405c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onSkipToPrevious(); 10415c9469e010106467791b47b0fa83efda84491a21RoboErik } 10425c9469e010106467791b47b0fa83efda84491a21RoboErik 10435c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10445c9469e010106467791b47b0fa83efda84491a21RoboErik public void onSkipToNext() { 10455c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onSkipToNext(); 10465c9469e010106467791b47b0fa83efda84491a21RoboErik } 10475c9469e010106467791b47b0fa83efda84491a21RoboErik 10485c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10495c9469e010106467791b47b0fa83efda84491a21RoboErik public void onSetRating(Object ratingObj) { 10505c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onSetRating(RatingCompat.fromRating(ratingObj)); 10515c9469e010106467791b47b0fa83efda84491a21RoboErik } 10525c9469e010106467791b47b0fa83efda84491a21RoboErik 10535c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10545c9469e010106467791b47b0fa83efda84491a21RoboErik public void onSeekTo(long pos) { 10555c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onSeekTo(pos); 10565c9469e010106467791b47b0fa83efda84491a21RoboErik } 10575c9469e010106467791b47b0fa83efda84491a21RoboErik 10585c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10595c9469e010106467791b47b0fa83efda84491a21RoboErik public void onRewind() { 10605c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onRewind(); 10615c9469e010106467791b47b0fa83efda84491a21RoboErik } 10625c9469e010106467791b47b0fa83efda84491a21RoboErik 10635c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10645c9469e010106467791b47b0fa83efda84491a21RoboErik public void onPlay() { 10655c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onPlay(); 10665c9469e010106467791b47b0fa83efda84491a21RoboErik } 10675c9469e010106467791b47b0fa83efda84491a21RoboErik 10685c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10695c9469e010106467791b47b0fa83efda84491a21RoboErik public void onPause() { 10705c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onPause(); 10715c9469e010106467791b47b0fa83efda84491a21RoboErik } 10725c9469e010106467791b47b0fa83efda84491a21RoboErik 10735c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10745c9469e010106467791b47b0fa83efda84491a21RoboErik public boolean onMediaButtonEvent(Intent mediaButtonIntent) { 10755c9469e010106467791b47b0fa83efda84491a21RoboErik return callback.onMediaButtonEvent(mediaButtonIntent); 10765c9469e010106467791b47b0fa83efda84491a21RoboErik } 10775c9469e010106467791b47b0fa83efda84491a21RoboErik 10785c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10795c9469e010106467791b47b0fa83efda84491a21RoboErik public void onFastForward() { 10805c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onFastForward(); 10815c9469e010106467791b47b0fa83efda84491a21RoboErik } 10825c9469e010106467791b47b0fa83efda84491a21RoboErik 10835c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 10845c9469e010106467791b47b0fa83efda84491a21RoboErik public void onCommand(String command, Bundle extras, ResultReceiver cb) { 10855c9469e010106467791b47b0fa83efda84491a21RoboErik callback.onCommand(command, extras, cb); 10865c9469e010106467791b47b0fa83efda84491a21RoboErik } 10875c9469e010106467791b47b0fa83efda84491a21RoboErik }; 10885c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 18) { 10895c9469e010106467791b47b0fa83efda84491a21RoboErik Object onPositionUpdateObj = MediaSessionCompatApi18 10905c9469e010106467791b47b0fa83efda84491a21RoboErik .createPlaybackPositionUpdateListener(cb14); 10915c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi18.setOnPlaybackPositionUpdateListener(mRccObj, 10925c9469e010106467791b47b0fa83efda84491a21RoboErik onPositionUpdateObj); 10935c9469e010106467791b47b0fa83efda84491a21RoboErik } 10945c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 19) { 10955c9469e010106467791b47b0fa83efda84491a21RoboErik Object onMetadataUpdateObj = MediaSessionCompatApi19 10965c9469e010106467791b47b0fa83efda84491a21RoboErik .createMetadataUpdateListener(cb14); 10975c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi19.setOnMetadataUpdateListener(mRccObj, 10985c9469e010106467791b47b0fa83efda84491a21RoboErik onMetadataUpdateObj); 10995c9469e010106467791b47b0fa83efda84491a21RoboErik } 11005c9469e010106467791b47b0fa83efda84491a21RoboErik } 11015c9469e010106467791b47b0fa83efda84491a21RoboErik mCallback = callback; 110224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 110324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 110424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 110524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setFlags(int flags) { 1106e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1107e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mFlags = flags; 1108e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 11095c9469e010106467791b47b0fa83efda84491a21RoboErik update(); 111024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 111124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 111224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 111324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackToLocal(int stream) { 11141c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik if (mVolumeProvider != null) { 11151c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik mVolumeProvider.setCallback(null); 11161c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik } 1117e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_LOCAL; 1118e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik ParcelableVolumeInfo info = new ParcelableVolumeInfo(mVolumeType, mLocalStream, 1119e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE, 1120e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAudioManager.getStreamMaxVolume(mLocalStream), 1121e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAudioManager.getStreamVolume(mLocalStream)); 1122e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendVolumeInfoChanged(info); 112324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 112424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 112524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 112624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackToRemote(VolumeProviderCompat volumeProvider) { 1127e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (volumeProvider == null) { 1128e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik throw new IllegalArgumentException("volumeProvider may not be null"); 1129e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 11301c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik if (mVolumeProvider != null) { 11311c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik mVolumeProvider.setCallback(null); 11321c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik } 1133e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeType = MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE; 1134e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeProvider = volumeProvider; 1135e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik ParcelableVolumeInfo info = new ParcelableVolumeInfo(mVolumeType, mLocalStream, 1136e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeProvider.getVolumeControl(), mVolumeProvider.getMaxVolume(), 1137e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeProvider.getCurrentVolume()); 1138e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendVolumeInfoChanged(info); 11391c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik 11401c91ca160d4a8f4f3cf3cf2a8672e0ccd16d88d4RoboErik volumeProvider.setCallback(mVolumeCallback); 114124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 114224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 114324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 114424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setActive(boolean active) { 11455c9469e010106467791b47b0fa83efda84491a21RoboErik if (active == mIsActive) { 11465c9469e010106467791b47b0fa83efda84491a21RoboErik return; 11475c9469e010106467791b47b0fa83efda84491a21RoboErik } 11485c9469e010106467791b47b0fa83efda84491a21RoboErik mIsActive = active; 11495c9469e010106467791b47b0fa83efda84491a21RoboErik if (update()) { 11505c9469e010106467791b47b0fa83efda84491a21RoboErik setMetadata(mMetadata); 11515c9469e010106467791b47b0fa83efda84491a21RoboErik setPlaybackState(mState); 11525c9469e010106467791b47b0fa83efda84491a21RoboErik } 115324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 115424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 115524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 115624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public boolean isActive() { 11575c9469e010106467791b47b0fa83efda84491a21RoboErik return mIsActive; 115824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 115924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 116024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 116124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void sendSessionEvent(String event, Bundle extras) { 1162e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendEvent(event, extras); 116324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 116424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 116524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 116624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void release() { 11675c9469e010106467791b47b0fa83efda84491a21RoboErik mIsActive = false; 1168e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mDestroyed = true; 11695c9469e010106467791b47b0fa83efda84491a21RoboErik update(); 1170e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendSessionDestroyed(); 117124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 117224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 117324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 117424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Token getSessionToken() { 1175e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mToken; 117624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 117724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 117824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 117924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackState(PlaybackStateCompat state) { 1180e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1181e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mState = state; 1182e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1183e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendState(state); 11845c9469e010106467791b47b0fa83efda84491a21RoboErik if (!mIsActive) { 11855c9469e010106467791b47b0fa83efda84491a21RoboErik // Don't set the state until after the RCC is registered 11865c9469e010106467791b47b0fa83efda84491a21RoboErik return; 11875c9469e010106467791b47b0fa83efda84491a21RoboErik } 11885c9469e010106467791b47b0fa83efda84491a21RoboErik if (state == null) { 11895c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 14) { 11905c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi14.setState(mRccObj, PlaybackStateCompat.STATE_NONE); 11915c9469e010106467791b47b0fa83efda84491a21RoboErik } 11925c9469e010106467791b47b0fa83efda84491a21RoboErik } else { 11935c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 18) { 11945c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi18.setState(mRccObj, state.getState(), state.getPosition(), 11955c9469e010106467791b47b0fa83efda84491a21RoboErik state.getPlaybackSpeed(), state.getLastPositionUpdateTime()); 11965c9469e010106467791b47b0fa83efda84491a21RoboErik } else if (android.os.Build.VERSION.SDK_INT >= 14) { 11975c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi14.setState(mRccObj, state.getState()); 11985c9469e010106467791b47b0fa83efda84491a21RoboErik } 11995c9469e010106467791b47b0fa83efda84491a21RoboErik } 120024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 120124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 120224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 120324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setMetadata(MediaMetadataCompat metadata) { 1204e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1205e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mMetadata = metadata; 1206e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1207e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendMetadata(metadata); 12085c9469e010106467791b47b0fa83efda84491a21RoboErik if (!mIsActive) { 12095c9469e010106467791b47b0fa83efda84491a21RoboErik // Don't set metadata until after the rcc has been registered 12105c9469e010106467791b47b0fa83efda84491a21RoboErik return; 12115c9469e010106467791b47b0fa83efda84491a21RoboErik } 12125c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 19) { 12135c9469e010106467791b47b0fa83efda84491a21RoboErik boolean canRate = mState != null 12145c9469e010106467791b47b0fa83efda84491a21RoboErik && (mState.getActions() & PlaybackStateCompat.ACTION_SET_RATING) != 0; 12155c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi19.setMetadata(mRccObj, 12165c9469e010106467791b47b0fa83efda84491a21RoboErik metadata == null ? null : metadata.getBundle(), canRate); 12175c9469e010106467791b47b0fa83efda84491a21RoboErik } else if (android.os.Build.VERSION.SDK_INT >= 14) { 12185c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi14.setMetadata(mRccObj, 12195c9469e010106467791b47b0fa83efda84491a21RoboErik metadata == null ? null : metadata.getBundle()); 12205c9469e010106467791b47b0fa83efda84491a21RoboErik } 122124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 122224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 122324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 122485d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik public void setSessionActivity(PendingIntent pi) { 1225e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1226e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mSessionActivity = pi; 1227e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 122885d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik } 122985d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik 123085d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik @Override 1231ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setMediaButtonReceiver(PendingIntent mbr) { 12325c9469e010106467791b47b0fa83efda84491a21RoboErik // Do nothing, changing this is not supported before API 21. 1233ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1234ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1235ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 1236ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setQueue(List<QueueItem> queue) { 1237e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mQueue = queue; 1238e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendQueue(queue); 1239ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1240ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1241ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 1242ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setQueueTitle(CharSequence title) { 1243e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mQueueTitle = title; 1244e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik sendQueueTitle(title); 1245ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1246ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1247ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 124824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Object getMediaSession() { 124924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return null; 125024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 1251ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1252ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 12535c9469e010106467791b47b0fa83efda84491a21RoboErik public Object getRemoteControlClient() { 12545c9469e010106467791b47b0fa83efda84491a21RoboErik return mRccObj; 12555c9469e010106467791b47b0fa83efda84491a21RoboErik } 12565c9469e010106467791b47b0fa83efda84491a21RoboErik 12575c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 1258ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setRatingType(int type) { 1259e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mRatingType = type; 1260ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1261ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1262ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 1263ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setExtras(Bundle extras) { 1264e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mExtras = extras; 1265ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 12665c9469e010106467791b47b0fa83efda84491a21RoboErik 12675c9469e010106467791b47b0fa83efda84491a21RoboErik // Registers/unregisters the RCC and MediaButtonEventReceiver as needed. 12685c9469e010106467791b47b0fa83efda84491a21RoboErik private boolean update() { 12695c9469e010106467791b47b0fa83efda84491a21RoboErik boolean registeredRcc = false; 12705c9469e010106467791b47b0fa83efda84491a21RoboErik if (mIsActive) { 12715c9469e010106467791b47b0fa83efda84491a21RoboErik // On API 8+ register a MBR if it's supported, unregister it 12725c9469e010106467791b47b0fa83efda84491a21RoboErik // if support was removed. 12735c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 8) { 12745c9469e010106467791b47b0fa83efda84491a21RoboErik if (!mIsMbrRegistered && (mFlags & FLAG_HANDLES_MEDIA_BUTTONS) != 0) { 12755c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 18) { 12765c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi18.registerMediaButtonEventReceiver(mContext, 12775c9469e010106467791b47b0fa83efda84491a21RoboErik mMediaButtonEventReceiver); 12785c9469e010106467791b47b0fa83efda84491a21RoboErik } else { 12795c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi8.registerMediaButtonEventReceiver(mContext, 12805c9469e010106467791b47b0fa83efda84491a21RoboErik mComponentName); 12815c9469e010106467791b47b0fa83efda84491a21RoboErik } 12825c9469e010106467791b47b0fa83efda84491a21RoboErik mIsMbrRegistered = true; 12835c9469e010106467791b47b0fa83efda84491a21RoboErik } else if (mIsMbrRegistered && (mFlags & FLAG_HANDLES_MEDIA_BUTTONS) == 0) { 12845c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 18) { 12855c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi18.unregisterMediaButtonEventReceiver(mContext, 12865c9469e010106467791b47b0fa83efda84491a21RoboErik mMediaButtonEventReceiver); 12875c9469e010106467791b47b0fa83efda84491a21RoboErik } else { 12885c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi8.unregisterMediaButtonEventReceiver(mContext, 12895c9469e010106467791b47b0fa83efda84491a21RoboErik mComponentName); 12905c9469e010106467791b47b0fa83efda84491a21RoboErik } 12915c9469e010106467791b47b0fa83efda84491a21RoboErik mIsMbrRegistered = false; 12925c9469e010106467791b47b0fa83efda84491a21RoboErik } 12935c9469e010106467791b47b0fa83efda84491a21RoboErik } 12945c9469e010106467791b47b0fa83efda84491a21RoboErik // On API 14+ register a RCC if it's supported, unregister it if 12955c9469e010106467791b47b0fa83efda84491a21RoboErik // not. 12965c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 14) { 12975c9469e010106467791b47b0fa83efda84491a21RoboErik if (!mIsRccRegistered && (mFlags & FLAG_HANDLES_TRANSPORT_CONTROLS) != 0) { 12985c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi14.registerRemoteControlClient(mContext, mRccObj); 12995c9469e010106467791b47b0fa83efda84491a21RoboErik mIsRccRegistered = true; 13005c9469e010106467791b47b0fa83efda84491a21RoboErik registeredRcc = true; 13015c9469e010106467791b47b0fa83efda84491a21RoboErik } else if (mIsRccRegistered 13025c9469e010106467791b47b0fa83efda84491a21RoboErik && (mFlags & FLAG_HANDLES_TRANSPORT_CONTROLS) == 0) { 13035c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi14.unregisterRemoteControlClient(mContext, mRccObj); 13045c9469e010106467791b47b0fa83efda84491a21RoboErik mIsRccRegistered = false; 13055c9469e010106467791b47b0fa83efda84491a21RoboErik } 13065c9469e010106467791b47b0fa83efda84491a21RoboErik } 13075c9469e010106467791b47b0fa83efda84491a21RoboErik } else { 13085c9469e010106467791b47b0fa83efda84491a21RoboErik // When inactive remove any registered components. 13095c9469e010106467791b47b0fa83efda84491a21RoboErik if (mIsMbrRegistered) { 13105c9469e010106467791b47b0fa83efda84491a21RoboErik if (android.os.Build.VERSION.SDK_INT >= 18) { 13115c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi18.unregisterMediaButtonEventReceiver(mContext, 13125c9469e010106467791b47b0fa83efda84491a21RoboErik mMediaButtonEventReceiver); 13135c9469e010106467791b47b0fa83efda84491a21RoboErik } else { 13145c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi8.unregisterMediaButtonEventReceiver(mContext, 13155c9469e010106467791b47b0fa83efda84491a21RoboErik mComponentName); 13165c9469e010106467791b47b0fa83efda84491a21RoboErik } 13175c9469e010106467791b47b0fa83efda84491a21RoboErik mIsMbrRegistered = false; 13185c9469e010106467791b47b0fa83efda84491a21RoboErik } 13195c9469e010106467791b47b0fa83efda84491a21RoboErik if (mIsRccRegistered) { 13205c9469e010106467791b47b0fa83efda84491a21RoboErik MediaSessionCompatApi14.unregisterRemoteControlClient(mContext, mRccObj); 13215c9469e010106467791b47b0fa83efda84491a21RoboErik mIsRccRegistered = false; 13225c9469e010106467791b47b0fa83efda84491a21RoboErik } 13235c9469e010106467791b47b0fa83efda84491a21RoboErik } 13245c9469e010106467791b47b0fa83efda84491a21RoboErik return registeredRcc; 13255c9469e010106467791b47b0fa83efda84491a21RoboErik } 1326e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1327e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void adjustVolume(int direction, int flags) { 1328e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (mVolumeType == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) { 1329e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (mVolumeProvider != null) { 1330e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeProvider.onAdjustVolume(direction); 1331e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1332e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } else { 1333e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAudioManager.adjustStreamVolume(direction, mLocalStream, flags); 1334e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1335e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1336e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1337e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void setVolumeTo(int value, int flags) { 1338e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (mVolumeType == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) { 1339e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (mVolumeProvider != null) { 1340e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mVolumeProvider.onSetVolumeTo(value); 1341e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1342e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } else { 1343e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mAudioManager.setStreamVolume(mLocalStream, value, flags); 1344e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1345e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1346e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1347e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private PlaybackStateCompat getStateWithUpdatedPosition() { 1348e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik PlaybackStateCompat state; 1349e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik long duration = -1; 1350e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1351e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik state = mState; 1352e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (mMetadata != null 1353e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik && mMetadata.containsKey(MediaMetadataCompat.METADATA_KEY_DURATION)) { 1354e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik duration = mMetadata.getLong(MediaMetadataCompat.METADATA_KEY_DURATION); 1355e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1356e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1357e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1358e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik PlaybackStateCompat result = null; 1359e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (state != null) { 1360e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (state.getState() == PlaybackStateCompat.STATE_PLAYING 1361e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik || state.getState() == PlaybackStateCompat.STATE_FAST_FORWARDING 1362e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik || state.getState() == PlaybackStateCompat.STATE_REWINDING) { 1363e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik long updateTime = state.getLastPositionUpdateTime(); 1364e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik long currentTime = SystemClock.elapsedRealtime(); 1365e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (updateTime > 0) { 1366e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik long position = (long) (state.getPlaybackSpeed() 1367e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik * (currentTime - updateTime)) + state.getPosition(); 1368e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (duration >= 0 && position > duration) { 1369e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik position = duration; 1370e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } else if (position < 0) { 1371e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik position = 0; 1372e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1373e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder( 1374e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik state); 1375e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik builder.setState(state.getState(), position, state.getPlaybackSpeed(), 1376e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik currentTime); 1377e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik result = builder.build(); 1378e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1379e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1380e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1381e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return result == null ? state : result; 1382e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1383e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1384e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void sendVolumeInfoChanged(ParcelableVolumeInfo info) { 1385e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int size = mControllerCallbacks.beginBroadcast(); 1386e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik for (int i = size - 1; i >= 0; i--) { 1387e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); 1388e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1389e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onVolumeInfoChanged(info); 1390e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (RemoteException e) { 1391e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1392e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1393e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.finishBroadcast(); 1394e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1395e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1396e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void sendSessionDestroyed() { 1397e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int size = mControllerCallbacks.beginBroadcast(); 1398e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik for (int i = size - 1; i >= 0; i--) { 1399e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); 1400e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1401e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onSessionDestroyed();; 1402e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (RemoteException e) { 1403e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1404e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1405e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.finishBroadcast(); 1406e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.kill(); 1407e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1408e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1409e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void sendEvent(String event, Bundle extras) { 1410e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int size = mControllerCallbacks.beginBroadcast(); 1411e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik for (int i = size - 1; i >= 0; i--) { 1412e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); 1413e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1414e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onEvent(event, extras); 1415e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (RemoteException e) { 1416e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1417e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1418e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.finishBroadcast(); 1419e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1420e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1421e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void sendState(PlaybackStateCompat state) { 1422e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int size = mControllerCallbacks.beginBroadcast(); 1423e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik for (int i = size - 1; i >= 0; i--) { 1424e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); 1425e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1426e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onPlaybackStateChanged(state); 1427e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (RemoteException e) { 1428e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1429e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1430e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.finishBroadcast(); 1431e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1432e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1433e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void sendMetadata(MediaMetadataCompat metadata) { 1434e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int size = mControllerCallbacks.beginBroadcast(); 1435e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik for (int i = size - 1; i >= 0; i--) { 1436e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); 1437e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1438e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onMetadataChanged(metadata); 1439e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (RemoteException e) { 1440e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1441e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1442e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.finishBroadcast(); 1443e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1444e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1445e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void sendQueue(List<QueueItem> queue) { 1446e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int size = mControllerCallbacks.beginBroadcast(); 1447e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik for (int i = size - 1; i >= 0; i--) { 1448e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); 1449e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1450e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onQueueChanged(queue); 1451e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (RemoteException e) { 1452e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1453e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1454e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.finishBroadcast(); 1455e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1456e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1457e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private void sendQueueTitle(CharSequence queueTitle) { 1458e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int size = mControllerCallbacks.beginBroadcast(); 1459e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik for (int i = size - 1; i >= 0; i--) { 1460e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik IMediaControllerCallback cb = mControllerCallbacks.getBroadcastItem(i); 1461e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1462e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onQueueTitleChanged(queueTitle); 1463e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (RemoteException e) { 1464e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1465e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1466e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.finishBroadcast(); 1467e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1468e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1469e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik class MediaSessionStub extends IMediaSession.Stub { 1470e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1471e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void sendCommand(String command, Bundle args, ResultReceiverWrapper cb) { 1472e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_COMMAND, 1473e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik new Command(command, args, cb.mResultReceiver)); 1474e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1475e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1476e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1477e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public boolean sendMediaButton(KeyEvent mediaButton) { 1478e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik boolean handlesMediaButtons = 1479e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik (mFlags & MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS) != 0; 1480e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (handlesMediaButtons) { 1481e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_MEDIA_BUTTON, mediaButton); 1482e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1483e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return handlesMediaButtons; 1484e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1485e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1486e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1487e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void registerCallbackListener(IMediaControllerCallback cb) { 1488e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik // If this session is already destroyed tell the caller and 1489e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik // don't add them. 1490e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (mDestroyed) { 1491e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik try { 1492e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik cb.onSessionDestroyed(); 1493e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } catch (Exception e) { 1494e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik // ignored 1495e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1496e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return; 1497e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1498e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.register(cb); 1499e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1500e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1501e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1502e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void unregisterCallbackListener(IMediaControllerCallback cb) { 1503e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mControllerCallbacks.unregister(cb); 1504e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1505e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1506e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1507e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public String getPackageName() { 1508e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik // mPackageName is final so doesn't need synchronize block 1509e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mPackageName; 1510e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1511e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1512e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1513e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public String getTag() { 1514e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik // mTag is final so doesn't need synchronize block 1515e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mTag; 1516e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1517e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1518e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1519e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public PendingIntent getLaunchPendingIntent() { 1520e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1521e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mSessionActivity; 1522e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1523e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1524e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1525e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1526e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public long getFlags() { 1527e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1528e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mFlags; 1529e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1530e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1531e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1532e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1533e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public ParcelableVolumeInfo getVolumeAttributes() { 1534e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int controlType; 1535e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int max; 1536e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int current; 1537e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int stream; 1538e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik int volumeType; 1539e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1540e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik volumeType = mVolumeType; 1541e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik stream = mLocalStream; 1542e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik VolumeProviderCompat vp = mVolumeProvider; 1543e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (volumeType == MediaControllerCompat.PlaybackInfo.PLAYBACK_TYPE_REMOTE) { 1544e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik controlType = vp.getVolumeControl(); 1545e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik max = vp.getMaxVolume(); 1546e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik current = vp.getCurrentVolume(); 1547e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } else { 1548e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik controlType = VolumeProviderCompat.VOLUME_CONTROL_ABSOLUTE; 1549e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik max = mAudioManager.getStreamMaxVolume(stream); 1550e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik current = mAudioManager.getStreamVolume(stream); 1551e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1552e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1553e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return new ParcelableVolumeInfo(volumeType, stream, controlType, max, current); 1554e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1555e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1556e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1557e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void adjustVolume(int direction, int flags, String packageName) { 1558e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik MediaSessionImplBase.this.adjustVolume(direction, flags); 1559e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1560e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1561e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1562e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void setVolumeTo(int value, int flags, String packageName) { 1563e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik MediaSessionImplBase.this.setVolumeTo(value, flags); 1564e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1565e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1566e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1567e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void play() throws RemoteException { 1568e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_PLAY); 1569e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1570e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1571e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1572e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void playFromMediaId(String mediaId, Bundle extras) throws RemoteException { 1573e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_PLAY_MEDIA_ID, mediaId, extras); 1574e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1575e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1576e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1577e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void playFromSearch(String query, Bundle extras) throws RemoteException { 1578e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_PLAY_SEARCH, query, extras); 1579e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1580e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1581e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1582e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void skipToQueueItem(long id) { 1583e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_SKIP_TO_ITEM, id); 1584e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1585e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1586e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1587e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void pause() throws RemoteException { 1588e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_PAUSE); 1589e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1590e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1591e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1592e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void stop() throws RemoteException { 1593e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_STOP); 1594e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1595e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1596e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1597e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void next() throws RemoteException { 1598e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_NEXT); 1599e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1600e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1601e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1602e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void previous() throws RemoteException { 1603e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_PREVIOUS); 1604e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1605e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1606e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1607e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void fastForward() throws RemoteException { 1608e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_FAST_FORWARD); 1609e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1610e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1611e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1612e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void rewind() throws RemoteException { 1613e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_REWIND); 1614e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1615e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1616e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1617e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void seekTo(long pos) throws RemoteException { 1618e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_SEEK_TO, pos); 1619e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1620e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1621e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1622e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void rate(RatingCompat rating) throws RemoteException { 1623e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_RATE, rating); 1624e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1625e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1626e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1627e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void sendCustomAction(String action, Bundle args) 1628e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik throws RemoteException { 1629e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mHandler.post(MessageHandler.MSG_CUSTOM_ACTION, action, args); 1630e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1631e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1632e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1633e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public MediaMetadataCompat getMetadata() { 1634e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mMetadata; 1635e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1636e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1637e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1638e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public PlaybackStateCompat getPlaybackState() { 1639e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return getStateWithUpdatedPosition(); 1640e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1641e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1642e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1643e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public List<QueueItem> getQueue() { 1644e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1645e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mQueue; 1646e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1647e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1648e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1649e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1650e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public CharSequence getQueueTitle() { 1651e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mQueueTitle; 1652e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1653e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1654e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1655e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public Bundle getExtras() { 1656e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik synchronized (mLock) { 1657e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mExtras; 1658e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1659e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1660e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1661e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1662e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public int getRatingType() { 1663e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return mRatingType; 1664e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1665e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1666e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1667e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public boolean isTransportControlEnabled() { 1668e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return (mFlags & FLAG_HANDLES_TRANSPORT_CONTROLS) != 0; 1669e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1670e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1671e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1672e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final class Command { 1673e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public final String command; 1674e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public final Bundle extras; 1675e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public final ResultReceiver stub; 1676e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1677e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public Command(String command, Bundle extras, ResultReceiver stub) { 1678e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik this.command = command; 1679e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik this.extras = extras; 1680e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik this.stub = stub; 1681e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1682e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1683e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1684e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private class MessageHandler extends Handler { 1685e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1686e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_PLAY = 1; 1687e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_PLAY_MEDIA_ID = 2; 1688e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_PLAY_SEARCH = 3; 1689e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_SKIP_TO_ITEM = 4; 1690e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_PAUSE = 5; 1691e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_STOP = 6; 1692e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_NEXT = 7; 1693e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_PREVIOUS = 8; 1694e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_FAST_FORWARD = 9; 1695e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_REWIND = 10; 1696e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_SEEK_TO = 11; 1697e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_RATE = 12; 1698e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_CUSTOM_ACTION = 13; 1699e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_MEDIA_BUTTON = 14; 1700e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_COMMAND = 15; 1701e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_ADJUST_VOLUME = 16; 1702e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik private static final int MSG_SET_VOLUME = 17; 1703e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1704e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public MessageHandler(Looper looper) { 1705e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik super(looper); 1706e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1707e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1708e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void post(int what, Object obj, Bundle bundle) { 1709e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Message msg = obtainMessage(what, obj); 1710e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik msg.setData(bundle); 1711e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik msg.sendToTarget(); 1712e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1713e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1714e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void post(int what, Object obj) { 1715e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik obtainMessage(what, obj).sendToTarget(); 1716e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1717e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1718e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void post(int what) { 1719e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik post(what, null); 1720e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1721e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1722e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void post(int what, Object obj, int arg1) { 1723e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik obtainMessage(what, arg1, 0, obj).sendToTarget(); 1724e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1725e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik 1726e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik @Override 1727e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik public void handleMessage(Message msg) { 1728e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik if (mCallback == null) { 1729e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik return; 1730e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1731e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik switch (msg.what) { 1732e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_PLAY: 1733e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onPlay(); 1734e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1735e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_PLAY_MEDIA_ID: 1736e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onPlayFromMediaId((String) msg.obj, msg.getData()); 1737e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1738e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_PLAY_SEARCH: 1739e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onPlayFromSearch((String) msg.obj, msg.getData()); 1740e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1741e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_SKIP_TO_ITEM: 1742e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onSkipToQueueItem((Long) msg.obj); 1743e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1744e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_PAUSE: 1745e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onPause(); 1746e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1747e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_STOP: 1748e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onStop(); 1749e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1750e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_NEXT: 1751e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onSkipToNext(); 1752e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1753e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_PREVIOUS: 1754e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onSkipToPrevious(); 1755e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1756e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_FAST_FORWARD: 1757e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onFastForward(); 1758e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1759e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_REWIND: 1760e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onRewind(); 1761e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1762e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_SEEK_TO: 1763e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onSeekTo((Long) msg.obj); 1764e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1765e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_RATE: 1766e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onSetRating((RatingCompat) msg.obj); 1767e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1768e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_CUSTOM_ACTION: 1769e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onCustomAction((String) msg.obj, msg.getData()); 1770e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1771e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_MEDIA_BUTTON: 1772e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onMediaButtonEvent((Intent) msg.obj); 1773e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1774e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_COMMAND: 1775e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik Command cmd = (Command) msg.obj; 1776e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik mCallback.onCommand(cmd.command, cmd.extras, cmd.stub); 1777e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1778e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_ADJUST_VOLUME: 1779e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik adjustVolume((int) msg.obj, 0); 1780e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1781e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik case MSG_SET_VOLUME: 1782e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik setVolumeTo((int) msg.obj, 0); 1783e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik break; 1784e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1785e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 1786e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik } 178724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 178824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 178924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown static class MediaSessionImplApi21 implements MediaSessionImpl { 179024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown private final Object mSessionObj; 179124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown private final Token mToken; 179224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 1793ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik private PendingIntent mMediaButtonIntent; 1794ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 179524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public MediaSessionImplApi21(Context context, String tag) { 179624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mSessionObj = MediaSessionCompatApi21.createSession(context, tag); 179724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown mToken = new Token(MediaSessionCompatApi21.getSessionToken(mSessionObj)); 179824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 179924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 1800bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik public MediaSessionImplApi21(Object mediaSession) { 1801bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik mSessionObj = MediaSessionCompatApi21.verifySession(mediaSession); 1802bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik mToken = new Token(MediaSessionCompatApi21.getSessionToken(mSessionObj)); 1803bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik } 1804bbcdf78e350d58ecd6baa75e282d4908d3129fe2RoboErik 180524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 18068af0092e2d7409e79779af396d63ca4146f1fb21RoboErik public void setCallback(Callback callback, Handler handler) { 18078af0092e2d7409e79779af396d63ca4146f1fb21RoboErik MediaSessionCompatApi21.setCallback(mSessionObj, callback.mCallbackObj, handler); 180824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 180924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 181024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 181124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setFlags(int flags) { 181224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.setFlags(mSessionObj, flags); 181324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 181424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 181524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 181624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackToLocal(int stream) { 181724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.setPlaybackToLocal(mSessionObj, stream); 181824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 181924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 182024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 182124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackToRemote(VolumeProviderCompat volumeProvider) { 182224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.setPlaybackToRemote(mSessionObj, 182324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown volumeProvider.getVolumeProvider()); 182424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 182524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 182624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 182724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setActive(boolean active) { 182824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.setActive(mSessionObj, active); 182924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 183024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 183124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 183224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public boolean isActive() { 183324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return MediaSessionCompatApi21.isActive(mSessionObj); 183424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 183524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 183624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 183724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void sendSessionEvent(String event, Bundle extras) { 183824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.sendSessionEvent(mSessionObj, event, extras); 183924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 184024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 184124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 184224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void release() { 184324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.release(mSessionObj); 184424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 184524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 184624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 184724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Token getSessionToken() { 184824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return mToken; 184924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 185024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 185124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 185224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setPlaybackState(PlaybackStateCompat state) { 185324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.setPlaybackState(mSessionObj, state.getPlaybackState()); 185424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 185524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 185624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 185724fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public void setMetadata(MediaMetadataCompat metadata) { 185824fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown MediaSessionCompatApi21.setMetadata(mSessionObj, metadata.getMediaMetadata()); 185924fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 186024fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown 186124fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown @Override 186285d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik public void setSessionActivity(PendingIntent pi) { 186385d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik MediaSessionCompatApi21.setSessionActivity(mSessionObj, pi); 186485d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik } 186585d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik 186685d539daa11f9f7bd61ecb8ebb4d43536c02a736RoboErik @Override 1867ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setMediaButtonReceiver(PendingIntent mbr) { 1868ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik mMediaButtonIntent = mbr; 1869ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik MediaSessionCompatApi21.setMediaButtonReceiver(mSessionObj, mbr); 1870ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1871ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1872ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 1873ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setQueue(List<QueueItem> queue) { 1874ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik List<Object> queueObjs = null; 1875ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik if (queue != null) { 1876ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik queueObjs = new ArrayList<Object>(); 1877ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik for (QueueItem item : queue) { 1878ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik queueObjs.add(item.getQueueItem()); 1879ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1880ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1881ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik MediaSessionCompatApi21.setQueue(mSessionObj, queueObjs); 1882ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1883ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1884ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 1885ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setQueueTitle(CharSequence title) { 1886ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik MediaSessionCompatApi21.setQueueTitle(mSessionObj, title); 1887ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1888ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1889ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 1890ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setRatingType(int type) { 1891ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik if (android.os.Build.VERSION.SDK_INT < 22) { 1892ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik // TODO figure out 21 implementation 1893ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } else { 1894ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik MediaSessionCompatApi22.setRatingType(mSessionObj, type); 1895ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1896ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1897ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1898ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 1899ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik public void setExtras(Bundle extras) { 1900ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik MediaSessionCompatApi21.setExtras(mSessionObj, extras); 1901ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik } 1902ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik 1903ceb8bf5e5cce7a37736981e626c4be416378767bRoboErik @Override 190424fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown public Object getMediaSession() { 190524fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown return mSessionObj; 190624fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 19075c9469e010106467791b47b0fa83efda84491a21RoboErik 19085c9469e010106467791b47b0fa83efda84491a21RoboErik @Override 19095c9469e010106467791b47b0fa83efda84491a21RoboErik public Object getRemoteControlClient() { 19105c9469e010106467791b47b0fa83efda84491a21RoboErik return null; 19115c9469e010106467791b47b0fa83efda84491a21RoboErik } 191224fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown } 191324fa6c0dd42df057729e1a258388183f94da7f82Jeff Brown} 1914