MediaController.java revision d2b8c947ddfc6349a3ae6c3968b422b9cf50d7ed
101fe661ae5da3739215d93922412df4b24c859a2RoboErik/* 201fe661ae5da3739215d93922412df4b24c859a2RoboErik * Copyright (C) 2014 The Android Open Source Project 301fe661ae5da3739215d93922412df4b24c859a2RoboErik * 401fe661ae5da3739215d93922412df4b24c859a2RoboErik * Licensed under the Apache License, Version 2.0 (the "License"); 501fe661ae5da3739215d93922412df4b24c859a2RoboErik * you may not use this file except in compliance with the License. 601fe661ae5da3739215d93922412df4b24c859a2RoboErik * You may obtain a copy of the License at 701fe661ae5da3739215d93922412df4b24c859a2RoboErik * 801fe661ae5da3739215d93922412df4b24c859a2RoboErik * http://www.apache.org/licenses/LICENSE-2.0 901fe661ae5da3739215d93922412df4b24c859a2RoboErik * 1001fe661ae5da3739215d93922412df4b24c859a2RoboErik * Unless required by applicable law or agreed to in writing, software 1101fe661ae5da3739215d93922412df4b24c859a2RoboErik * distributed under the License is distributed on an "AS IS" BASIS, 1201fe661ae5da3739215d93922412df4b24c859a2RoboErik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1301fe661ae5da3739215d93922412df4b24c859a2RoboErik * See the License for the specific language governing permissions and 1401fe661ae5da3739215d93922412df4b24c859a2RoboErik * limitations under the License. 1501fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 1601fe661ae5da3739215d93922412df4b24c859a2RoboErik 172f5b057da7d05d5d699a272aa24fd7c97cdda820RoboErikpackage android.media.session; 1801fe661ae5da3739215d93922412df4b24c859a2RoboErik 19bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brownimport android.annotation.NonNull; 20bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brownimport android.annotation.Nullable; 21e34c09daf89fb888fe2638e71758573462d85173RoboErikimport android.app.PendingIntent; 22031149cd5f22bd858142633c7a763450f42793f7RoboErikimport android.content.Context; 23f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.content.pm.ParceledListSlice; 249db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErikimport android.media.AudioAttributes; 2519c9518f6a817d53d5234de0020313cab6950b2fRoboErikimport android.media.AudioManager; 2642ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.MediaMetadata; 27c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErikimport android.media.Rating; 28ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErikimport android.media.VolumeProvider; 29f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.net.Uri; 3001fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.Bundle; 3101fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.Handler; 3201fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.Looper; 3301fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.Message; 3401fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.RemoteException; 358ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.os.ResultReceiver; 3601fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.text.TextUtils; 3701fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.util.Log; 3801fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.view.KeyEvent; 3901fe661ae5da3739215d93922412df4b24c859a2RoboErik 408ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport java.lang.ref.WeakReference; 4101fe661ae5da3739215d93922412df4b24c859a2RoboErikimport java.util.ArrayList; 42f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport java.util.List; 4301fe661ae5da3739215d93922412df4b24c859a2RoboErik 4401fe661ae5da3739215d93922412df4b24c859a2RoboErik/** 4501fe661ae5da3739215d93922412df4b24c859a2RoboErik * Allows an app to interact with an ongoing media session. Media buttons and 4601fe661ae5da3739215d93922412df4b24c859a2RoboErik * other commands can be sent to the session. A callback may be registered to 4701fe661ae5da3739215d93922412df4b24c859a2RoboErik * receive updates from the session, such as metadata and play state changes. 4801fe661ae5da3739215d93922412df4b24c859a2RoboErik * <p> 4942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik * A MediaController can be created through {@link MediaSessionManager} if you 5001fe661ae5da3739215d93922412df4b24c859a2RoboErik * hold the "android.permission.MEDIA_CONTENT_CONTROL" permission or directly if 51dba34ba35cd2042d9a8fecfda56e2abe7a680badJeff Brown * you have a {@link MediaSession.Token} from the session owner. 5201fe661ae5da3739215d93922412df4b24c859a2RoboErik * <p> 5301fe661ae5da3739215d93922412df4b24c859a2RoboErik * MediaController objects are thread-safe. 5401fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 5542ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikpublic final class MediaController { 56bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown private static final String TAG = "MediaController"; 5701fe661ae5da3739215d93922412df4b24c859a2RoboErik 588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private static final int MSG_EVENT = 1; 59c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik private static final int MSG_UPDATE_PLAYBACK_STATE = 2; 60c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik private static final int MSG_UPDATE_METADATA = 3; 6101a500ed1c6ae3fff66678144ae637aa8cad0eccJeff Brown private static final int MSG_UPDATE_VOLUME = 4; 62f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_QUEUE = 5; 63f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_QUEUE_TITLE = 6; 64f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_EXTRAS = 7; 6524762bffc3358762666079cd802040a316b3260dRoboErik private static final int MSG_DESTROYED = 8; 6601fe661ae5da3739215d93922412df4b24c859a2RoboErik 6707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik private final ISessionController mSessionBinder; 6801fe661ae5da3739215d93922412df4b24c859a2RoboErik 6976fca4e177e18b591439fdff64b8f5242a5122d0RoboErik private final MediaSession.Token mToken; 70031149cd5f22bd858142633c7a763450f42793f7RoboErik private final Context mContext; 718ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private final CallbackStub mCbStub = new CallbackStub(this); 728ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private final ArrayList<MessageHandler> mCallbacks = new ArrayList<MessageHandler>(); 7301fe661ae5da3739215d93922412df4b24c859a2RoboErik private final Object mLock = new Object(); 7401fe661ae5da3739215d93922412df4b24c859a2RoboErik 7501fe661ae5da3739215d93922412df4b24c859a2RoboErik private boolean mCbRegistered = false; 76aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik private String mPackageName; 77aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik private String mTag; 7801fe661ae5da3739215d93922412df4b24c859a2RoboErik 791a937b04e63539cb1fab1bde601031d415c7156fJeff Brown private final TransportControls mTransportControls; 808ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 8101fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 828b4bffcac996b4083e720310a09d315ca1c4a000RoboErik * Call for creating a MediaController directly from a binder. Should only 838b4bffcac996b4083e720310a09d315ca1c4a000RoboErik * be used by framework code. 848b4bffcac996b4083e720310a09d315ca1c4a000RoboErik * 858ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * @hide 8601fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 87031149cd5f22bd858142633c7a763450f42793f7RoboErik public MediaController(Context context, ISessionController sessionBinder) { 888b4bffcac996b4083e720310a09d315ca1c4a000RoboErik if (sessionBinder == null) { 898b4bffcac996b4083e720310a09d315ca1c4a000RoboErik throw new IllegalArgumentException("Session token cannot be null"); 908b4bffcac996b4083e720310a09d315ca1c4a000RoboErik } 91031149cd5f22bd858142633c7a763450f42793f7RoboErik if (context == null) { 92031149cd5f22bd858142633c7a763450f42793f7RoboErik throw new IllegalArgumentException("Context cannot be null"); 93031149cd5f22bd858142633c7a763450f42793f7RoboErik } 948b4bffcac996b4083e720310a09d315ca1c4a000RoboErik mSessionBinder = sessionBinder; 958b4bffcac996b4083e720310a09d315ca1c4a000RoboErik mTransportControls = new TransportControls(); 9676fca4e177e18b591439fdff64b8f5242a5122d0RoboErik mToken = new MediaSession.Token(sessionBinder); 97031149cd5f22bd858142633c7a763450f42793f7RoboErik mContext = context; 9801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 9901fe661ae5da3739215d93922412df4b24c859a2RoboErik 10001fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 1018b4bffcac996b4083e720310a09d315ca1c4a000RoboErik * Create a new MediaController from a session's token. 1028ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * 103031149cd5f22bd858142633c7a763450f42793f7RoboErik * @param context The caller's context. 1048b4bffcac996b4083e720310a09d315ca1c4a000RoboErik * @param token The token for the session. 10501fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 106031149cd5f22bd858142633c7a763450f42793f7RoboErik public MediaController(@NonNull Context context, @NonNull MediaSession.Token token) { 107031149cd5f22bd858142633c7a763450f42793f7RoboErik this(context, token.getBinder()); 10801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 10901fe661ae5da3739215d93922412df4b24c859a2RoboErik 11001fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 1111a937b04e63539cb1fab1bde601031d415c7156fJeff Brown * Get a {@link TransportControls} instance to send transport actions to 1121a937b04e63539cb1fab1bde601031d415c7156fJeff Brown * the associated session. 11301fe661ae5da3739215d93922412df4b24c859a2RoboErik * 1141a937b04e63539cb1fab1bde601031d415c7156fJeff Brown * @return A transport controls instance. 11501fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 116bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public @NonNull TransportControls getTransportControls() { 1171a937b04e63539cb1fab1bde601031d415c7156fJeff Brown return mTransportControls; 1181a937b04e63539cb1fab1bde601031d415c7156fJeff Brown } 1191a937b04e63539cb1fab1bde601031d415c7156fJeff Brown 1201a937b04e63539cb1fab1bde601031d415c7156fJeff Brown /** 12179fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik * Send the specified media button event to the session. Only media keys can 12279fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik * be sent by this method, other keys will be ignored. 12301fe661ae5da3739215d93922412df4b24c859a2RoboErik * 12479fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik * @param keyEvent The media button event to dispatch. 12579fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik * @return true if the event was sent to the session, false otherwise. 12601fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 127bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) { 12879fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik if (keyEvent == null) { 12979fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik throw new IllegalArgumentException("KeyEvent may not be null"); 13079fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik } 13179fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik if (!KeyEvent.isMediaKey(keyEvent.getKeyCode())) { 13279fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik return false; 13301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 13401fe661ae5da3739215d93922412df4b24c859a2RoboErik try { 13579fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik return mSessionBinder.sendMediaButton(keyEvent); 13601fe661ae5da3739215d93922412df4b24c859a2RoboErik } catch (RemoteException e) { 137c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik // System is dead. =( 13801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 13979fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik return false; 14001fe661ae5da3739215d93922412df4b24c859a2RoboErik } 14101fe661ae5da3739215d93922412df4b24c859a2RoboErik 14201fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 143c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Get the current playback state for this session. 144c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * 145c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * @return The current PlaybackState or null 146c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 147bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public @Nullable PlaybackState getPlaybackState() { 148c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 149c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik return mSessionBinder.getPlaybackState(); 150c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 151c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling getPlaybackState.", e); 152c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik return null; 153c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 154c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 155c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 156c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 157c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Get the current metadata for this session. 158c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * 159c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * @return The current MediaMetadata or null. 160c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 161bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public @Nullable MediaMetadata getMetadata() { 162c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 163c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik return mSessionBinder.getMetadata(); 164c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 165c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling getMetadata.", e); 166c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik return null; 167c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 168c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 169c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 170c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 171477d1197c3c25c01ace7ea4494437c23720a2eb3RoboErik * Get the current play queue for this session if one is set. If you only 172477d1197c3c25c01ace7ea4494437c23720a2eb3RoboErik * care about the current item {@link #getMetadata()} should be used. 173f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * 174f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * @return The current play queue or null. 175f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal */ 176a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik public @Nullable List<MediaSession.Item> getQueue() { 177f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 178f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal ParceledListSlice queue = mSessionBinder.getQueue(); 179f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (queue != null) { 180f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal return queue.getList(); 181f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 182f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 183f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.wtf(TAG, "Error calling getQueue.", e); 184f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 185f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal return null; 186f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 187f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 188f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal /** 18951fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen * Get the queue title for this session. 19051fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen */ 19151fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen public @Nullable CharSequence getQueueTitle() { 19251fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen try { 19351fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen return mSessionBinder.getQueueTitle(); 19451fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen } catch (RemoteException e) { 19551fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen Log.wtf(TAG, "Error calling getQueueTitle", e); 19651fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen } 19751fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen return null; 19851fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen } 19951fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen 20051fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen /** 20151fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen * Get the extras for this session. 20251fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen */ 20351fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen public @Nullable Bundle getExtras() { 20451fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen try { 20551fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen return mSessionBinder.getExtras(); 20651fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen } catch (RemoteException e) { 20751fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen Log.wtf(TAG, "Error calling getExtras", e); 20851fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen } 20951fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen return null; 21051fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen } 21151fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen 21251fdfa273e036d0e4f5e5c624988b33873fa3ec7Yao Chen /** 213c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Get the rating type supported by the session. One of: 214c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <ul> 215c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <li>{@link Rating#RATING_NONE}</li> 216c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <li>{@link Rating#RATING_HEART}</li> 217c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <li>{@link Rating#RATING_THUMB_UP_DOWN}</li> 218c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <li>{@link Rating#RATING_3_STARS}</li> 219c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <li>{@link Rating#RATING_4_STARS}</li> 220c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <li>{@link Rating#RATING_5_STARS}</li> 221c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * <li>{@link Rating#RATING_PERCENTAGE}</li> 222c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * </ul> 223c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * 224c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * @return The supported rating type 225c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 226c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public int getRatingType() { 227c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 228c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik return mSessionBinder.getRatingType(); 229c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 230c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling getRatingType.", e); 231c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik return Rating.RATING_NONE; 232c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 233c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 234c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 235c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 23676fca4e177e18b591439fdff64b8f5242a5122d0RoboErik * Get the flags for this session. Flags are defined in {@link MediaSession}. 23773e23e229dd1a2d25687b1c6a63c708665378e41RoboErik * 23873e23e229dd1a2d25687b1c6a63c708665378e41RoboErik * @return The current set of flags for the session. 23973e23e229dd1a2d25687b1c6a63c708665378e41RoboErik */ 24076fca4e177e18b591439fdff64b8f5242a5122d0RoboErik public @MediaSession.SessionFlags long getFlags() { 24173e23e229dd1a2d25687b1c6a63c708665378e41RoboErik try { 24273e23e229dd1a2d25687b1c6a63c708665378e41RoboErik return mSessionBinder.getFlags(); 24373e23e229dd1a2d25687b1c6a63c708665378e41RoboErik } catch (RemoteException e) { 24473e23e229dd1a2d25687b1c6a63c708665378e41RoboErik Log.wtf(TAG, "Error calling getFlags.", e); 24573e23e229dd1a2d25687b1c6a63c708665378e41RoboErik } 24673e23e229dd1a2d25687b1c6a63c708665378e41RoboErik return 0; 24773e23e229dd1a2d25687b1c6a63c708665378e41RoboErik } 24873e23e229dd1a2d25687b1c6a63c708665378e41RoboErik 24973e23e229dd1a2d25687b1c6a63c708665378e41RoboErik /** 250d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * Get the current playback info for this session. 251ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * 252d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * @return The current playback info or null. 253ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 254d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public @Nullable PlaybackInfo getPlaybackInfo() { 255ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik try { 256ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik ParcelableVolumeInfo result = mSessionBinder.getVolumeAttributes(); 257d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik return new PlaybackInfo(result.volumeType, result.audioAttrs, result.controlType, 258ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik result.maxVolume, result.currentVolume); 259ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 260ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } catch (RemoteException e) { 261a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik Log.wtf(TAG, "Error calling getAudioInfo.", e); 262ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 263ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return null; 264ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 265ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 266ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 267e34c09daf89fb888fe2638e71758573462d85173RoboErik * Get an intent for launching UI associated with this session if one 268e34c09daf89fb888fe2638e71758573462d85173RoboErik * exists. 269e34c09daf89fb888fe2638e71758573462d85173RoboErik * 270e34c09daf89fb888fe2638e71758573462d85173RoboErik * @return A {@link PendingIntent} to launch UI or null. 271e34c09daf89fb888fe2638e71758573462d85173RoboErik */ 272d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public @Nullable PendingIntent getSessionActivity() { 273e34c09daf89fb888fe2638e71758573462d85173RoboErik try { 274e34c09daf89fb888fe2638e71758573462d85173RoboErik return mSessionBinder.getLaunchPendingIntent(); 275e34c09daf89fb888fe2638e71758573462d85173RoboErik } catch (RemoteException e) { 276e34c09daf89fb888fe2638e71758573462d85173RoboErik Log.wtf(TAG, "Error calling getPendingIntent.", e); 277e34c09daf89fb888fe2638e71758573462d85173RoboErik } 278e34c09daf89fb888fe2638e71758573462d85173RoboErik return null; 279e34c09daf89fb888fe2638e71758573462d85173RoboErik } 280e34c09daf89fb888fe2638e71758573462d85173RoboErik 281e34c09daf89fb888fe2638e71758573462d85173RoboErik /** 28276fca4e177e18b591439fdff64b8f5242a5122d0RoboErik * Get the token for the session this is connected to. 28376fca4e177e18b591439fdff64b8f5242a5122d0RoboErik * 28476fca4e177e18b591439fdff64b8f5242a5122d0RoboErik * @return The token for the connected session. 28576fca4e177e18b591439fdff64b8f5242a5122d0RoboErik */ 28676fca4e177e18b591439fdff64b8f5242a5122d0RoboErik public @NonNull MediaSession.Token getSessionToken() { 28776fca4e177e18b591439fdff64b8f5242a5122d0RoboErik return mToken; 28876fca4e177e18b591439fdff64b8f5242a5122d0RoboErik } 28976fca4e177e18b591439fdff64b8f5242a5122d0RoboErik 29076fca4e177e18b591439fdff64b8f5242a5122d0RoboErik /** 2919db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * Set the volume of the output this session is playing on. The command will 2929db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * be ignored if it does not support 29319c9518f6a817d53d5234de0020313cab6950b2fRoboErik * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in 29419c9518f6a817d53d5234de0020313cab6950b2fRoboErik * {@link AudioManager} may be used to affect the handling. 29519c9518f6a817d53d5234de0020313cab6950b2fRoboErik * 296d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * @see #getPlaybackInfo() 29719c9518f6a817d53d5234de0020313cab6950b2fRoboErik * @param value The value to set it to, between 0 and the reported max. 298d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * @param flags Flags from {@link AudioManager} to include with the volume 299d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * request. 30019c9518f6a817d53d5234de0020313cab6950b2fRoboErik */ 30119c9518f6a817d53d5234de0020313cab6950b2fRoboErik public void setVolumeTo(int value, int flags) { 30219c9518f6a817d53d5234de0020313cab6950b2fRoboErik try { 3030dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName()); 30419c9518f6a817d53d5234de0020313cab6950b2fRoboErik } catch (RemoteException e) { 30519c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.wtf(TAG, "Error calling setVolumeTo.", e); 30619c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 30719c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 30819c9518f6a817d53d5234de0020313cab6950b2fRoboErik 30919c9518f6a817d53d5234de0020313cab6950b2fRoboErik /** 3109db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * Adjust the volume of the output this session is playing on. The direction 3119db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * must be one of {@link AudioManager#ADJUST_LOWER}, 3121ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}. 3131ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * The command will be ignored if the session does not support 3141ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * {@link VolumeProvider#VOLUME_CONTROL_RELATIVE} or 31519c9518f6a817d53d5234de0020313cab6950b2fRoboErik * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in 31619c9518f6a817d53d5234de0020313cab6950b2fRoboErik * {@link AudioManager} may be used to affect the handling. 31719c9518f6a817d53d5234de0020313cab6950b2fRoboErik * 318d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * @see #getPlaybackInfo() 3191ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * @param direction The direction to adjust the volume in. 32019c9518f6a817d53d5234de0020313cab6950b2fRoboErik * @param flags Any flags to pass with the command. 32119c9518f6a817d53d5234de0020313cab6950b2fRoboErik */ 3221ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik public void adjustVolume(int direction, int flags) { 32319c9518f6a817d53d5234de0020313cab6950b2fRoboErik try { 3240dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName()); 32519c9518f6a817d53d5234de0020313cab6950b2fRoboErik } catch (RemoteException e) { 32619c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.wtf(TAG, "Error calling adjustVolumeBy.", e); 32719c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 32819c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 32919c9518f6a817d53d5234de0020313cab6950b2fRoboErik 33019c9518f6a817d53d5234de0020313cab6950b2fRoboErik /** 33101fe661ae5da3739215d93922412df4b24c859a2RoboErik * Adds a callback to receive updates from the Session. Updates will be 33201fe661ae5da3739215d93922412df4b24c859a2RoboErik * posted on the caller's thread. 33301fe661ae5da3739215d93922412df4b24c859a2RoboErik * 334bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown * @param callback The callback object, must not be null. 33501fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 336bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public void addCallback(@NonNull Callback callback) { 337bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown addCallback(callback, null); 33801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 33901fe661ae5da3739215d93922412df4b24c859a2RoboErik 34001fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 34101fe661ae5da3739215d93922412df4b24c859a2RoboErik * Adds a callback to receive updates from the session. Updates will be 3428ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * posted on the specified handler's thread. 34301fe661ae5da3739215d93922412df4b24c859a2RoboErik * 344bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown * @param callback The callback object, must not be null. 3458ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * @param handler The handler to post updates on. If null the callers thread 346bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown * will be used. 34701fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 348bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public void addCallback(@NonNull Callback callback, @Nullable Handler handler) { 349bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown if (callback == null) { 350bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown throw new IllegalArgumentException("callback must not be null"); 351bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown } 35201fe661ae5da3739215d93922412df4b24c859a2RoboErik if (handler == null) { 35301fe661ae5da3739215d93922412df4b24c859a2RoboErik handler = new Handler(); 35401fe661ae5da3739215d93922412df4b24c859a2RoboErik } 35501fe661ae5da3739215d93922412df4b24c859a2RoboErik synchronized (mLock) { 356bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown addCallbackLocked(callback, handler); 35701fe661ae5da3739215d93922412df4b24c859a2RoboErik } 35801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 35901fe661ae5da3739215d93922412df4b24c859a2RoboErik 36001fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 36101fe661ae5da3739215d93922412df4b24c859a2RoboErik * Stop receiving updates on the specified callback. If an update has 36201fe661ae5da3739215d93922412df4b24c859a2RoboErik * already been posted you may still receive it after calling this method. 36301fe661ae5da3739215d93922412df4b24c859a2RoboErik * 364bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown * @param callback The callback to remove. 36501fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 366bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public void removeCallback(@NonNull Callback callback) { 367bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown if (callback == null) { 368bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown throw new IllegalArgumentException("callback must not be null"); 369bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown } 37001fe661ae5da3739215d93922412df4b24c859a2RoboErik synchronized (mLock) { 371bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown removeCallbackLocked(callback); 37201fe661ae5da3739215d93922412df4b24c859a2RoboErik } 37301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 37401fe661ae5da3739215d93922412df4b24c859a2RoboErik 3758ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik /** 3768ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Sends a generic command to the session. It is up to the session creator 3778ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * to decide what commands and parameters they will support. As such, 3788ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * commands should only be sent to sessions that the controller owns. 3798ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * 3808ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * @param command The command to send 381f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * @param args Any parameters to include with the command 3828ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * @param cb The callback to receive the result on 3838ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik */ 384f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal public void sendCommand(@NonNull String command, @Nullable Bundle args, 385bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown @Nullable ResultReceiver cb) { 3868ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (TextUtils.isEmpty(command)) { 3878ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik throw new IllegalArgumentException("command cannot be null or empty"); 3888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 3898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 390f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal mSessionBinder.sendCommand(command, args, cb); 3918ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 3928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Log.d(TAG, "Dead object in sendCommand.", e); 3938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 3948ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 3958ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 39607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik /** 397aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * Get the session owner's package name. 398fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik * 399aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * @return The package name of of the session owner. 400aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik */ 401aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik public String getPackageName() { 402aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik if (mPackageName == null) { 403aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik try { 404aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik mPackageName = mSessionBinder.getPackageName(); 405aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik } catch (RemoteException e) { 406aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik Log.d(TAG, "Dead object in getPackageName.", e); 407aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik } 408aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik } 409aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik return mPackageName; 410aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik } 411aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik 412aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik /** 413aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * Get the session's tag for debugging purposes. 414aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * 415aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * @return The session's tag. 416fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik * @hide 417fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik */ 418aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik public String getTag() { 419aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik if (mTag == null) { 42073e23e229dd1a2d25687b1c6a63c708665378e41RoboErik try { 421aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik mTag = mSessionBinder.getTag(); 42273e23e229dd1a2d25687b1c6a63c708665378e41RoboErik } catch (RemoteException e) { 423aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik Log.d(TAG, "Dead object in getTag.", e); 42473e23e229dd1a2d25687b1c6a63c708665378e41RoboErik } 425fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik } 426aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik return mTag; 427fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik } 428fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik 42901fe661ae5da3739215d93922412df4b24c859a2RoboErik /* 43001fe661ae5da3739215d93922412df4b24c859a2RoboErik * @hide 43101fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 43207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik ISessionController getSessionBinder() { 43301fe661ae5da3739215d93922412df4b24c859a2RoboErik return mSessionBinder; 43401fe661ae5da3739215d93922412df4b24c859a2RoboErik } 43501fe661ae5da3739215d93922412df4b24c859a2RoboErik 43601fe661ae5da3739215d93922412df4b24c859a2RoboErik private void addCallbackLocked(Callback cb, Handler handler) { 4378ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (getHandlerForCallbackLocked(cb) != null) { 43801fe661ae5da3739215d93922412df4b24c859a2RoboErik Log.w(TAG, "Callback is already added, ignoring"); 43901fe661ae5da3739215d93922412df4b24c859a2RoboErik return; 44001fe661ae5da3739215d93922412df4b24c859a2RoboErik } 4418ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik MessageHandler holder = new MessageHandler(handler.getLooper(), cb); 4428ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCallbacks.add(holder); 44301fe661ae5da3739215d93922412df4b24c859a2RoboErik 44401fe661ae5da3739215d93922412df4b24c859a2RoboErik if (!mCbRegistered) { 44501fe661ae5da3739215d93922412df4b24c859a2RoboErik try { 44601fe661ae5da3739215d93922412df4b24c859a2RoboErik mSessionBinder.registerCallbackListener(mCbStub); 44701fe661ae5da3739215d93922412df4b24c859a2RoboErik mCbRegistered = true; 44801fe661ae5da3739215d93922412df4b24c859a2RoboErik } catch (RemoteException e) { 449d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik Log.e(TAG, "Dead object in registerCallback", e); 45001fe661ae5da3739215d93922412df4b24c859a2RoboErik } 45101fe661ae5da3739215d93922412df4b24c859a2RoboErik } 45201fe661ae5da3739215d93922412df4b24c859a2RoboErik } 45301fe661ae5da3739215d93922412df4b24c859a2RoboErik 4548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private boolean removeCallbackLocked(Callback cb) { 455d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik boolean success = false; 4568ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik for (int i = mCallbacks.size() - 1; i >= 0; i--) { 4578ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik MessageHandler handler = mCallbacks.get(i); 4588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (cb == handler.mCallback) { 4598ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCallbacks.remove(i); 460d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik success = true; 46101fe661ae5da3739215d93922412df4b24c859a2RoboErik } 46201fe661ae5da3739215d93922412df4b24c859a2RoboErik } 463d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik if (mCbRegistered && mCallbacks.size() == 0) { 464d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik try { 465d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik mSessionBinder.unregisterCallbackListener(mCbStub); 466d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } catch (RemoteException e) { 467d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik Log.e(TAG, "Dead object in removeCallbackLocked"); 468d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 469d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik mCbRegistered = false; 470d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 471d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik return success; 47201fe661ae5da3739215d93922412df4b24c859a2RoboErik } 47301fe661ae5da3739215d93922412df4b24c859a2RoboErik 4748ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private MessageHandler getHandlerForCallbackLocked(Callback cb) { 4758ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (cb == null) { 4768ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik throw new IllegalArgumentException("Callback cannot be null"); 47701fe661ae5da3739215d93922412df4b24c859a2RoboErik } 4788ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik for (int i = mCallbacks.size() - 1; i >= 0; i--) { 4798ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik MessageHandler handler = mCallbacks.get(i); 4808ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (cb == handler.mCallback) { 4818ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik return handler; 4828ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 48301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 4848ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik return null; 48501fe661ae5da3739215d93922412df4b24c859a2RoboErik } 48601fe661ae5da3739215d93922412df4b24c859a2RoboErik 487c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik private final void postMessage(int what, Object obj, Bundle data) { 4888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik synchronized (mLock) { 4898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik for (int i = mCallbacks.size() - 1; i >= 0; i--) { 490c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mCallbacks.get(i).post(what, obj, data); 4918ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 49201fe661ae5da3739215d93922412df4b24c859a2RoboErik } 49301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 49401fe661ae5da3739215d93922412df4b24c859a2RoboErik 49501fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 4968ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Callback for receiving updates on from the session. A Callback can be 4978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * registered using {@link #addCallback} 49801fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 49901fe661ae5da3739215d93922412df4b24c859a2RoboErik public static abstract class Callback { 50001fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 50124762bffc3358762666079cd802040a316b3260dRoboErik * Override to handle the session being destroyed. The session is no 50224762bffc3358762666079cd802040a316b3260dRoboErik * longer valid after this call and calls to it will be ignored. 50324762bffc3358762666079cd802040a316b3260dRoboErik */ 50424762bffc3358762666079cd802040a316b3260dRoboErik public void onSessionDestroyed() { 50524762bffc3358762666079cd802040a316b3260dRoboErik } 50624762bffc3358762666079cd802040a316b3260dRoboErik 50724762bffc3358762666079cd802040a316b3260dRoboErik /** 5088ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * Override to handle custom events sent by the session owner without a 5098ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * specified interface. Controllers should only handle these for 5108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik * sessions they own. 51101fe661ae5da3739215d93922412df4b24c859a2RoboErik * 512bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown * @param event The event from the session. 513bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown * @param extras Optional parameters for the event, may be null. 51401fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 515bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public void onSessionEvent(@NonNull String event, @Nullable Bundle extras) { 51601fe661ae5da3739215d93922412df4b24c859a2RoboErik } 51701fe661ae5da3739215d93922412df4b24c859a2RoboErik 51801fe661ae5da3739215d93922412df4b24c859a2RoboErik /** 519c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Override to handle changes in playback state. 520c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * 521c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * @param state The new playback state of the session 522c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 523bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public void onPlaybackStateChanged(@NonNull PlaybackState state) { 524c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 525c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 526c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 527c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Override to handle changes to the current metadata. 528c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * 529bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown * @param metadata The current metadata for the session or null if none. 530c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * @see MediaMetadata 531c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 532bf58d9b727f1007c7c620f622ac1d8003b1b211bJeff Brown public void onMetadataChanged(@Nullable MediaMetadata metadata) { 533c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 53419c9518f6a817d53d5234de0020313cab6950b2fRoboErik 53519c9518f6a817d53d5234de0020313cab6950b2fRoboErik /** 536a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * Override to handle changes to items in the queue. 537f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * 538a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * @param queue A list of items in the current play queue. It should 539a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * include the currently playing item as well as previous and 540a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * upcoming items if applicable. 541a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * @see MediaSession.Item 542f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal */ 543a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik public void onQueueChanged(@Nullable List<MediaSession.Item> queue) { 544f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 545f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 546f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal /** 547f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * Override to handle changes to the queue title. 548f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * 549f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * @param title The title that should be displayed along with the play queue such as 550f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * "Now Playing". May be null if there is no such title. 551f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal */ 552f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void onQueueTitleChanged(@Nullable CharSequence title) { 553f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 554f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 555f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal /** 556f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * Override to handle changes to the {@link MediaSession} extras. 557f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * 558f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * @param extras The extras that can include other information associated with the 559f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * {@link MediaSession}. 560f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal */ 561f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void onExtrasChanged(@Nullable Bundle extras) { 562f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 563f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 564f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal /** 565a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * Override to handle changes to the audio info. 56619c9518f6a817d53d5234de0020313cab6950b2fRoboErik * 567a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * @param info The current audio info for this session. 56819c9518f6a817d53d5234de0020313cab6950b2fRoboErik */ 569d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public void onAudioInfoChanged(PlaybackInfo info) { 57019c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 571c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 572c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 573c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 574c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Interface for controlling media playback on a session. This allows an app 575c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * to send media transport commands to the session. 576c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 577c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public final class TransportControls { 578c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik private static final String TAG = "TransportController"; 579c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 580c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik private TransportControls() { 581c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 582c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 583c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 584c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Request that the player start its playback at its current position. 585c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 586c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void play() { 587c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 588c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.play(); 589c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 590c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling play.", e); 591c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 592c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 593c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 594c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 595f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * Request that the player start playback for a specific {@link Uri}. 596f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * 597f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * @param uri The uri of the requested media. 598f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * @param extras Optional extras that can include extra information about the media item 599f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * to be played. 600f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal */ 601f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void playUri(Uri uri, Bundle extras) { 602f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (uri == null) { 603f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal throw new IllegalArgumentException("You must specify a non-null Uri for playUri."); 604f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 605f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 606f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mSessionBinder.playUri(uri, extras); 607f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 608f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.wtf(TAG, "Error calling play(" + uri + ").", e); 609f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 610f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 611f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 612f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal /** 613f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * Request that the player start playback for a specific search query. 614f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * 615f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * @param query The search query. 616f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal * @param extras Optional extras that can include extra information about the query. 617f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal */ 618f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void playFromSearch(String query, Bundle extras) { 619f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (TextUtils.isEmpty(query)) { 620f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal throw new IllegalArgumentException( 621f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal "You must specify a non-empty search query for playFromSearch."); 622f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 623f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 624f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mSessionBinder.playFromSearch(query, extras); 625f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 626f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.wtf(TAG, "Error calling play(" + query + ").", e); 627f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 628f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 629f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 630f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal /** 631a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * Play an item with a specific id in the play queue. If you specify an 632a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik * id that is not in the play queue, the behavior is undefined. 633f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal */ 634a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik public void skipToItem(long id) { 635f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 636f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mSessionBinder.skipToTrack(id); 637f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 638a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik Log.wtf(TAG, "Error calling skipToItem(" + id + ").", e); 639f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 640f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 641f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 642f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal /** 643c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Request that the player pause its playback and stay at its current 644c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * position. 645c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 646c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void pause() { 647c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 648c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.pause(); 649c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 650c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling pause.", e); 651c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 652c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 653c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 654c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 655c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Request that the player stop its playback; it may clear its state in 656c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * whatever way is appropriate. 657c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 658c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void stop() { 659c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 660c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.stop(); 661c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 662c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling stop.", e); 663c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 664c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 665c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 666c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 667c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Move to a new location in the media stream. 668c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * 669c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * @param pos Position to move to, in milliseconds. 670c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 671c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void seekTo(long pos) { 672c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 673c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.seekTo(pos); 674c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 675c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling seekTo.", e); 676c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 677c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 678c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 679c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 680c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Start fast forwarding. If playback is already fast forwarding this 681c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * may increase the rate. 682c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 683c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void fastForward() { 684c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 685c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.fastForward(); 686c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 687c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling fastForward.", e); 688c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 689c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 690c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 691c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 692c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Skip to the next item. 693c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 694c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void skipToNext() { 695c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 696c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.next(); 697c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 698c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling next.", e); 699c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 700c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 701c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 702c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 703c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Start rewinding. If playback is already rewinding this may increase 704c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * the rate. 705c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 706c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void rewind() { 707c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 708c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.rewind(); 709c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 710c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling rewind.", e); 711c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 712c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 713c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 714c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 715c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Skip to the previous item. 716c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 717c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void skipToPrevious() { 718c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 719c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.previous(); 720c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 721c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling previous.", e); 722c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 723c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 724c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik 725c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik /** 726c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * Rate the current content. This will cause the rating to be set for 727c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * the current user. The Rating type must match the type returned by 728c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * {@link #getRatingType()}. 729c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * 730c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik * @param rating The rating to set for the current content 731c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik */ 732c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik public void setRating(Rating rating) { 733c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik try { 734c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mSessionBinder.rate(rating); 735c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } catch (RemoteException e) { 736c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik Log.wtf(TAG, "Error calling rate.", e); 737c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 738c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik } 739f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal 740f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal /** 741f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * Send a custom action back for the {@link MediaSession} to perform. 742f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * 743f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * @param customAction The action to perform. 744f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * @param args Optional arguments to supply to the {@link MediaSession} for this 745f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * custom action. 746f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal */ 747f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal public void sendCustomAction(@NonNull PlaybackState.CustomAction customAction, 748f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal @Nullable Bundle args) { 749f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal if (customAction == null) { 750f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal throw new IllegalArgumentException("CustomAction cannot be null."); 751f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 752f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal sendCustomAction(customAction.getAction(), args); 753f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 754f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal 755f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal /** 756f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * Send the id and args from a custom action back for the {@link MediaSession} to perform. 757f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * 758f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * @see #sendCustomAction(PlaybackState.CustomAction action, Bundle args) 759f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * @param action The action identifier of the {@link PlaybackState.CustomAction} as 760f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * specified by the {@link MediaSession}. 761f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * @param args Optional arguments to supply to the {@link MediaSession} for this 762f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal * custom action. 763f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal */ 764f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal public void sendCustomAction(@NonNull String action, @Nullable Bundle args) { 765f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal if (TextUtils.isEmpty(action)) { 766f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal throw new IllegalArgumentException("CustomAction cannot be null."); 767f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 768f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal try { 769f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal mSessionBinder.sendCustomAction(action, args); 770f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } catch (RemoteException e) { 771f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal Log.d(TAG, "Dead object in sendCustomAction.", e); 772f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 773f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 7748ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 77501fe661ae5da3739215d93922412df4b24c859a2RoboErik 776ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 777d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * Holds information about the current playback and how audio is handled for 778d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * this session. 779ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 780d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public static final class PlaybackInfo { 781d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik /** 782d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * The session uses remote playback. 783d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik */ 784d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public static final int PLAYBACK_TYPE_REMOTE = 2; 785d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik /** 786d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * The session uses local playback. 787d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik */ 788d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public static final int PLAYBACK_TYPE_LOCAL = 1; 789d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik 790ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik private final int mVolumeType; 791ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik private final int mVolumeControl; 792ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik private final int mMaxVolume; 793ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik private final int mCurrentVolume; 7949db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik private final AudioAttributes mAudioAttrs; 795ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 796ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 797ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * @hide 798ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 799d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public PlaybackInfo(int type, AudioAttributes attrs, int control, int max, int current) { 800ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik mVolumeType = type; 8019db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik mAudioAttrs = attrs; 802ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik mVolumeControl = control; 803ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik mMaxVolume = max; 804ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik mCurrentVolume = current; 805ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 806ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 807ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 808d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * Get the type of playback which affects volume handling. One of: 809ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * <ul> 810d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * <li>{@link #PLAYBACK_TYPE_LOCAL}</li> 811d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * <li>{@link #PLAYBACK_TYPE_REMOTE}</li> 812ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * </ul> 813ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * 814d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * @return The type of playback this session is using. 815ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 816d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik public int getPlaybackType() { 817ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return mVolumeType; 818ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 819ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 820ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 8219db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * Get the audio attributes for this session. The attributes will affect 8229db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * volume handling for the session. When the volume type is 823d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik * {@link PlaybackInfo#PLAYBACK_TYPE_REMOTE} these may be ignored by the 8249db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * remote volume handler. 825ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * 8269db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik * @return The attributes for this session. 827ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 8289db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik public AudioAttributes getAudioAttributes() { 8299db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik return mAudioAttrs; 830ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 831ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 832ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 833ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * Get the type of volume control that can be used. One of: 834ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * <ul> 835ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * <li>{@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}</li> 836ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * <li>{@link VolumeProvider#VOLUME_CONTROL_RELATIVE}</li> 837ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * <li>{@link VolumeProvider#VOLUME_CONTROL_FIXED}</li> 838ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * </ul> 839ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * 840ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * @return The type of volume control that may be used with this 841ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * session. 842ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 843ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik public int getVolumeControl() { 844ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return mVolumeControl; 845ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 846ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 847ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 848ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * Get the maximum volume that may be set for this session. 849ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * 850ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * @return The maximum allowed volume where this session is playing. 851ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 852ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik public int getMaxVolume() { 853ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return mMaxVolume; 854ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 855ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 856ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik /** 857ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * Get the current volume for this session. 858ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * 859ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik * @return The current volume where this session is playing. 860ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik */ 861ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik public int getCurrentVolume() { 862ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return mCurrentVolume; 863ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 864ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 865ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 86607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik private final static class CallbackStub extends ISessionControllerCallback.Stub { 86742ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik private final WeakReference<MediaController> mController; 86801fe661ae5da3739215d93922412df4b24c859a2RoboErik 86942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik public CallbackStub(MediaController controller) { 87042ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik mController = new WeakReference<MediaController>(controller); 87101fe661ae5da3739215d93922412df4b24c859a2RoboErik } 87201fe661ae5da3739215d93922412df4b24c859a2RoboErik 87301fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 87424762bffc3358762666079cd802040a316b3260dRoboErik public void onSessionDestroyed() { 87524762bffc3358762666079cd802040a316b3260dRoboErik MediaController controller = mController.get(); 87624762bffc3358762666079cd802040a316b3260dRoboErik if (controller != null) { 87724762bffc3358762666079cd802040a316b3260dRoboErik controller.postMessage(MSG_DESTROYED, null, null); 87824762bffc3358762666079cd802040a316b3260dRoboErik } 87924762bffc3358762666079cd802040a316b3260dRoboErik } 88024762bffc3358762666079cd802040a316b3260dRoboErik 88124762bffc3358762666079cd802040a316b3260dRoboErik @Override 8828ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void onEvent(String event, Bundle extras) { 88342ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik MediaController controller = mController.get(); 8848ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (controller != null) { 885c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik controller.postMessage(MSG_EVENT, event, extras); 88601fe661ae5da3739215d93922412df4b24c859a2RoboErik } 88701fe661ae5da3739215d93922412df4b24c859a2RoboErik } 88801fe661ae5da3739215d93922412df4b24c859a2RoboErik 88901fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 8908ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void onPlaybackStateChanged(PlaybackState state) { 89142ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik MediaController controller = mController.get(); 8928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (controller != null) { 893c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik controller.postMessage(MSG_UPDATE_PLAYBACK_STATE, state, null); 89401fe661ae5da3739215d93922412df4b24c859a2RoboErik } 89501fe661ae5da3739215d93922412df4b24c859a2RoboErik } 89601fe661ae5da3739215d93922412df4b24c859a2RoboErik 89701fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 8988ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void onMetadataChanged(MediaMetadata metadata) { 89942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik MediaController controller = mController.get(); 9008ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik if (controller != null) { 901c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik controller.postMessage(MSG_UPDATE_METADATA, metadata, null); 90201fe661ae5da3739215d93922412df4b24c859a2RoboErik } 90301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 90401fe661ae5da3739215d93922412df4b24c859a2RoboErik 90519c9518f6a817d53d5234de0020313cab6950b2fRoboErik @Override 906f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void onQueueChanged(ParceledListSlice parceledQueue) { 907a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik List<MediaSession.Item> queue = parceledQueue.getList(); 908f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal MediaController controller = mController.get(); 909f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (controller != null) { 910f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal controller.postMessage(MSG_UPDATE_QUEUE, queue, null); 911f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 912f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 913f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 914f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 915f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void onQueueTitleChanged(CharSequence title) { 916f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal MediaController controller = mController.get(); 917f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (controller != null) { 918f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal controller.postMessage(MSG_UPDATE_QUEUE_TITLE, title, null); 919f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 920f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 921f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 922f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 923f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void onExtrasChanged(Bundle extras) { 924f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal MediaController controller = mController.get(); 925f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (controller != null) { 926f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal controller.postMessage(MSG_UPDATE_EXTRAS, extras, null); 927f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 928f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 929f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 930f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 93119c9518f6a817d53d5234de0020313cab6950b2fRoboErik public void onVolumeInfoChanged(ParcelableVolumeInfo pvi) { 93219c9518f6a817d53d5234de0020313cab6950b2fRoboErik MediaController controller = mController.get(); 93319c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (controller != null) { 934d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik PlaybackInfo info = new PlaybackInfo(pvi.volumeType, pvi.audioAttrs, pvi.controlType, 93519c9518f6a817d53d5234de0020313cab6950b2fRoboErik pvi.maxVolume, pvi.currentVolume); 93619c9518f6a817d53d5234de0020313cab6950b2fRoboErik controller.postMessage(MSG_UPDATE_VOLUME, info, null); 93719c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 93819c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 93919c9518f6a817d53d5234de0020313cab6950b2fRoboErik 94001fe661ae5da3739215d93922412df4b24c859a2RoboErik } 94101fe661ae5da3739215d93922412df4b24c859a2RoboErik 94201fe661ae5da3739215d93922412df4b24c859a2RoboErik private final static class MessageHandler extends Handler { 94342ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik private final MediaController.Callback mCallback; 94401fe661ae5da3739215d93922412df4b24c859a2RoboErik 94542ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik public MessageHandler(Looper looper, MediaController.Callback cb) { 9468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik super(looper, null, true); 9478ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCallback = cb; 94801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 94901fe661ae5da3739215d93922412df4b24c859a2RoboErik 95001fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 95101fe661ae5da3739215d93922412df4b24c859a2RoboErik public void handleMessage(Message msg) { 95201fe661ae5da3739215d93922412df4b24c859a2RoboErik switch (msg.what) { 9538ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik case MSG_EVENT: 95479fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik mCallback.onSessionEvent((String) msg.obj, msg.getData()); 95501fe661ae5da3739215d93922412df4b24c859a2RoboErik break; 956c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik case MSG_UPDATE_PLAYBACK_STATE: 957c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mCallback.onPlaybackStateChanged((PlaybackState) msg.obj); 958c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik break; 959c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik case MSG_UPDATE_METADATA: 960c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik mCallback.onMetadataChanged((MediaMetadata) msg.obj); 961c47fa84b0a6bda48c38ba8822481ce613bafd019RoboErik break; 962f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal case MSG_UPDATE_QUEUE: 963a66c40bf6e0fb79ead6d8a9fc29c5671fa7b1206RoboErik mCallback.onQueueChanged((List<MediaSession.Item>) msg.obj); 964f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal break; 965f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal case MSG_UPDATE_QUEUE_TITLE: 966f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mCallback.onQueueTitleChanged((CharSequence) msg.obj); 967f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal break; 968f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal case MSG_UPDATE_EXTRAS: 969f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mCallback.onExtrasChanged((Bundle) msg.obj); 970f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal break; 97119c9518f6a817d53d5234de0020313cab6950b2fRoboErik case MSG_UPDATE_VOLUME: 972d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik mCallback.onAudioInfoChanged((PlaybackInfo) msg.obj); 97319c9518f6a817d53d5234de0020313cab6950b2fRoboErik break; 97424762bffc3358762666079cd802040a316b3260dRoboErik case MSG_DESTROYED: 97524762bffc3358762666079cd802040a316b3260dRoboErik mCallback.onSessionDestroyed(); 97624762bffc3358762666079cd802040a316b3260dRoboErik break; 97701fe661ae5da3739215d93922412df4b24c859a2RoboErik } 97801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 9798ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 9808ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void post(int what, Object obj, Bundle data) { 9818ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik obtainMessage(what, obj).sendToTarget(); 9828ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 98301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 98401fe661ae5da3739215d93922412df4b24c859a2RoboErik 98501fe661ae5da3739215d93922412df4b24c859a2RoboErik} 986