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 1701fe661ae5da3739215d93922412df4b24c859a2RoboErikpackage com.android.server.media; 1801fe661ae5da3739215d93922412df4b24c859a2RoboErik 19e34c09daf89fb888fe2638e71758573462d85173RoboErikimport android.app.PendingIntent; 206f0e4ddd66fcdcc13944d8970d0b560e2626508bRoboErikimport android.content.ComponentName; 21ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErikimport android.content.Context; 2201fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.content.Intent; 23f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.content.pm.ParceledListSlice; 24f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.media.AudioManager; 250dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErikimport android.media.AudioManagerInternal; 26165809b33198cd3926cc11e8cbc96b671d4c87d3RoboErikimport android.media.AudioSystem; 273625bf72cb8bcf3c7f8f8cd8d708d7206824cc62RoboErikimport android.media.MediaDescription; 28f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.media.MediaMetadata; 29f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.media.Rating; 30f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.media.VolumeProvider; 3107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport android.media.session.ISession; 3207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport android.media.session.ISessionCallback; 33f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.media.session.ISessionController; 34f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.media.session.ISessionControllerCallback; 3542ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaController; 36d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErikimport android.media.session.MediaController.PlaybackInfo; 3742ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErikimport android.media.session.MediaSession; 387c82ced4fc5b66c09a19eed9a5499039530142fbRoboErikimport android.media.session.MediaSessionManager; 39ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErikimport android.media.session.ParcelableVolumeInfo; 40f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.media.session.PlaybackState; 419db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErikimport android.media.AudioAttributes; 42f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Pealimport android.net.Uri; 43f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErikimport android.os.Binder; 4401fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.Bundle; 45d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErikimport android.os.DeadObjectException; 468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.os.Handler; 4701fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.IBinder; 488ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.os.Looper; 498ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.os.Message; 5001fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.os.RemoteException; 518ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.os.ResultReceiver; 52f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErikimport android.os.SystemClock; 5301fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.util.Log; 548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErikimport android.util.Slog; 5501fe661ae5da3739215d93922412df4b24c859a2RoboErikimport android.view.KeyEvent; 5601fe661ae5da3739215d93922412df4b24c859a2RoboErik 570dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErikimport com.android.server.LocalServices; 580dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik 59a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErikimport java.io.PrintWriter; 6001fe661ae5da3739215d93922412df4b24c859a2RoboErikimport java.util.ArrayList; 6107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErikimport java.util.UUID; 6201fe661ae5da3739215d93922412df4b24c859a2RoboErik 6301fe661ae5da3739215d93922412df4b24c859a2RoboErik/** 6401fe661ae5da3739215d93922412df4b24c859a2RoboErik * This is the system implementation of a Session. Apps will interact with the 6501fe661ae5da3739215d93922412df4b24c859a2RoboErik * MediaSession wrapper class instead. 6601fe661ae5da3739215d93922412df4b24c859a2RoboErik */ 6701fe661ae5da3739215d93922412df4b24c859a2RoboErikpublic class MediaSessionRecord implements IBinder.DeathRecipient { 6807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik private static final String TAG = "MediaSessionRecord"; 69d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik private static final boolean DEBUG = false; 7001fe661ae5da3739215d93922412df4b24c859a2RoboErik 71a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 72a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * The length of time a session will still be considered active after 73a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * pausing in ms. 74a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 75a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private static final int ACTIVE_BUFFER = 30000; 76a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 7719c9518f6a817d53d5234de0020313cab6950b2fRoboErik /** 7819c9518f6a817d53d5234de0020313cab6950b2fRoboErik * The amount of time we'll send an assumed volume after the last volume 7919c9518f6a817d53d5234de0020313cab6950b2fRoboErik * command before reverting to the last reported volume. 8019c9518f6a817d53d5234de0020313cab6950b2fRoboErik */ 8119c9518f6a817d53d5234de0020313cab6950b2fRoboErik private static final int OPTIMISTIC_VOLUME_TIMEOUT = 1000; 8219c9518f6a817d53d5234de0020313cab6950b2fRoboErik 838ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private final MessageHandler mHandler; 848ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 85a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik private final int mOwnerPid; 86a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik private final int mOwnerUid; 87a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik private final int mUserId; 88aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik private final String mPackageName; 8901fe661ae5da3739215d93922412df4b24c859a2RoboErik private final String mTag; 9001fe661ae5da3739215d93922412df4b24c859a2RoboErik private final ControllerStub mController; 9101fe661ae5da3739215d93922412df4b24c859a2RoboErik private final SessionStub mSession; 9201fe661ae5da3739215d93922412df4b24c859a2RoboErik private final SessionCb mSessionCb; 9301fe661ae5da3739215d93922412df4b24c859a2RoboErik private final MediaSessionService mService; 94519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik private final boolean mUseMasterVolume; 9501fe661ae5da3739215d93922412df4b24c859a2RoboErik 9607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik private final Object mLock = new Object(); 9707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik private final ArrayList<ISessionControllerCallback> mControllerCallbacks = 9807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik new ArrayList<ISessionControllerCallback>(); 998ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 100e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik private long mFlags; 101b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik private PendingIntent mMediaButtonReceiver; 102e34c09daf89fb888fe2638e71758573462d85173RoboErik private PendingIntent mLaunchIntent; 1038ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 1048ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik // TransportPerformer fields 10501fe661ae5da3739215d93922412df4b24c859a2RoboErik 106f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private Bundle mExtras; 1078ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private MediaMetadata mMetadata; 1088ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private PlaybackState mPlaybackState; 109f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private ParceledListSlice mQueue; 110f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private CharSequence mQueueTitle; 1118ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private int mRatingType; 112a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private long mLastActiveTime; 1138ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik // End TransportPerformer fields 1148ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 115b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik // Volume handling fields 1169db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik private AudioAttributes mAudioAttrs; 117ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik private AudioManager mAudioManager; 1180dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik private AudioManagerInternal mAudioManagerInternal; 119d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik private int mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL; 120ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE; 121b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik private int mMaxVolume = 0; 122b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik private int mCurrentVolume = 0; 12319c9518f6a817d53d5234de0020313cab6950b2fRoboErik private int mOptimisticVolume = -1; 124b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik // End volume handling fields 125b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 126a8f951462791a16f47e8c07e552232f31dcefac5RoboErik private boolean mIsActive = false; 1274646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik private boolean mDestroyed = false; 12801fe661ae5da3739215d93922412df4b24c859a2RoboErik 129a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName, 130a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik ISessionCallback cb, String tag, MediaSessionService service, Handler handler) { 131a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik mOwnerPid = ownerPid; 132a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik mOwnerUid = ownerUid; 133a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik mUserId = userId; 134aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik mPackageName = ownerPackageName; 13501fe661ae5da3739215d93922412df4b24c859a2RoboErik mTag = tag; 13601fe661ae5da3739215d93922412df4b24c859a2RoboErik mController = new ControllerStub(); 13701fe661ae5da3739215d93922412df4b24c859a2RoboErik mSession = new SessionStub(); 13801fe661ae5da3739215d93922412df4b24c859a2RoboErik mSessionCb = new SessionCb(cb); 13901fe661ae5da3739215d93922412df4b24c859a2RoboErik mService = service; 1408ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mHandler = new MessageHandler(handler.getLooper()); 141ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE); 1420dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); 1439db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(); 144519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik mUseMasterVolume = service.getContext().getResources().getBoolean( 145519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik com.android.internal.R.bool.config_useMasterVolume); 14601fe661ae5da3739215d93922412df4b24c859a2RoboErik } 14701fe661ae5da3739215d93922412df4b24c859a2RoboErik 14807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik /** 14942ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik * Get the binder for the {@link MediaSession}. 15007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 15107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * @return The session binder apps talk to. 15207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik */ 15307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public ISession getSessionBinder() { 15401fe661ae5da3739215d93922412df4b24c859a2RoboErik return mSession; 15501fe661ae5da3739215d93922412df4b24c859a2RoboErik } 15601fe661ae5da3739215d93922412df4b24c859a2RoboErik 15707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik /** 15842ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik * Get the binder for the {@link MediaController}. 15907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 16007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * @return The controller binder apps talk to. 16107c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik */ 16207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public ISessionController getControllerBinder() { 16301fe661ae5da3739215d93922412df4b24c859a2RoboErik return mController; 16401fe661ae5da3739215d93922412df4b24c859a2RoboErik } 16501fe661ae5da3739215d93922412df4b24c859a2RoboErik 16607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik /** 16707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * Get the info for this session. 16807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 16907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * @return Info that identifies this session. 17007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik */ 171aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik public String getPackageName() { 172aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik return mPackageName; 173aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik } 174aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik 175aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik /** 176aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * Get the tag for the session. 177aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * 178aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik * @return The session's tag. 179aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik */ 180aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik public String getTag() { 181aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik return mTag; 18207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik } 18307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik 184b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik /** 185b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik * Get the intent the app set for their media button receiver. 186b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik * 187b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik * @return The pending intent set by the app or null. 188b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik */ 189b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik public PendingIntent getMediaButtonReceiver() { 1906f0e4ddd66fcdcc13944d8970d0b560e2626508bRoboErik return mMediaButtonReceiver; 1916f0e4ddd66fcdcc13944d8970d0b560e2626508bRoboErik } 1926f0e4ddd66fcdcc13944d8970d0b560e2626508bRoboErik 19307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik /** 194e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik * Get this session's flags. 195e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik * 196e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik * @return The flags for this session. 197e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik */ 198e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik public long getFlags() { 199e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik return mFlags; 200e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik } 201e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik 202e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik /** 203a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Check if this session has the specified flag. 204a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 205a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @param flag The flag to check. 206a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return True if this session has that flag set, false otherwise. 207a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 208a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public boolean hasFlag(int flag) { 209a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return (mFlags & flag) != 0; 210a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 211a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 212a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 213a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * Get the user id this session was created for. 214a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * 215a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik * @return The user id for this session. 216a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik */ 217a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik public int getUserId() { 218a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik return mUserId; 219a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik } 220a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik 221a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik /** 222e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik * Check if this session has system priorty and should receive media buttons 223e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik * before any other sessions. 224e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik * 225e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik * @return True if this is a system priority session, false otherwise 226e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik */ 227e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik public boolean isSystemPriority() { 22842ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik return (mFlags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0; 229e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik } 230e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik 231e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik /** 2321ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * Send a volume adjustment to the session owner. Direction must be one of 2331ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * {@link AudioManager#ADJUST_LOWER}, {@link AudioManager#ADJUST_RAISE}, 2341ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * {@link AudioManager#ADJUST_SAME}. 235b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * 2361ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik * @param direction The direction to adjust volume in. 237272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik * @param flags Any of the flags from {@link AudioManager}. 238272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik * @param packageName The package that made the original volume request. 239272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik * @param uid The uid that made the original volume request. 240272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik * @param useSuggested True to use adjustSuggestedStreamVolume instead of 241272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik * adjustStreamVolume. 242b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik */ 243272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik public void adjustVolume(int direction, int flags, String packageName, int uid, 244272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik boolean useSuggested) { 245165809b33198cd3926cc11e8cbc96b671d4c87d3RoboErik int previousFlagPlaySound = flags & AudioManager.FLAG_PLAY_SOUND; 2467a18cb5672127bf12c8edac8a327f9b706b79ff7RoboErik if (isPlaybackActive(false) || hasFlag(MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY)) { 247e9466805e55595ce72c070c73e2fcae46e857850RoboErik flags &= ~AudioManager.FLAG_PLAY_SOUND; 248e9466805e55595ce72c070c73e2fcae46e857850RoboErik } 2497c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik boolean isMute = direction == MediaSessionManager.DIRECTION_MUTE; 2501ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik if (direction > 1) { 2511ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik direction = 1; 2521ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik } else if (direction < -1) { 2531ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik direction = -1; 2541ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik } 255d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) { 256519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik if (mUseMasterVolume) { 257519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik // If this device only uses master volume and playback is local 258519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik // just adjust the master volume and return. 2592b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent boolean isMasterMute = mAudioManager.isMasterMute(); 2607c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (isMute) { 2612b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManagerInternal.setMasterMuteForUid(!isMasterMute, 2622610d71251e3e376e2514f20986c81e5d55f1b55RoboErik flags, packageName, mService.mICallback, uid); 2637c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } else { 2647c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik mAudioManagerInternal.adjustMasterVolumeForUid(direction, flags, packageName, 2657c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik uid); 2662b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent if (isMasterMute) { 2672b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManagerInternal.setMasterMuteForUid(false, 2682610d71251e3e376e2514f20986c81e5d55f1b55RoboErik flags, packageName, mService.mICallback, uid); 2692b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent } 2707c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 271519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik return; 272519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik } 2739db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs); 2742b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent boolean isStreamMute = mAudioManager.isStreamMute(stream); 275272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik if (useSuggested) { 276165809b33198cd3926cc11e8cbc96b671d4c87d3RoboErik if (AudioSystem.isStreamActive(stream, 0)) { 2777c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (isMute) { 2782b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManager.setStreamMute(stream, !isStreamMute); 2797c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } else { 2807c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction, 2817c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik flags, packageName, uid); 2822610d71251e3e376e2514f20986c81e5d55f1b55RoboErik if (isStreamMute && direction != 0) { 2832b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManager.setStreamMute(stream, false); 2842b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent } 2857c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 286165809b33198cd3926cc11e8cbc96b671d4c87d3RoboErik } else { 287165809b33198cd3926cc11e8cbc96b671d4c87d3RoboErik flags |= previousFlagPlaySound; 2882b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent isStreamMute = 2892b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManager.isStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE); 2907c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (isMute) { 2917c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik mAudioManager.setStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE, 2922b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent !isStreamMute); 2937c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } else { 2947c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik mAudioManagerInternal.adjustSuggestedStreamVolumeForUid( 2957c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik AudioManager.USE_DEFAULT_STREAM_TYPE, direction, flags, packageName, 2967c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik uid); 2972610d71251e3e376e2514f20986c81e5d55f1b55RoboErik if (isStreamMute && direction != 0) { 2982b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManager.setStreamMute(AudioManager.USE_DEFAULT_STREAM_TYPE, 2992b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent false); 3002b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent } 3017c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 302165809b33198cd3926cc11e8cbc96b671d4c87d3RoboErik } 303272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik } else { 3047c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (isMute) { 3052b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManager.setStreamMute(stream, !isStreamMute); 3067c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } else { 3077c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, 3087c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik packageName, uid); 3092610d71251e3e376e2514f20986c81e5d55f1b55RoboErik if (isStreamMute && direction != 0) { 3102b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent mAudioManager.setStreamMute(stream, false); 3112b5208c3583b5fd82564523bfd9e85b4bf44afa0Eric Laurent } 3127c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 313272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik } 314ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } else { 315ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) { 316ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik // Nothing to do, the volume cannot be changed 317ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return; 318ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 3197c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (isMute) { 3207c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik Log.w(TAG, "Muting remote playback is not supported"); 3217c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik return; 3227c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 3231ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik mSessionCb.adjustVolume(direction); 32419c9518f6a817d53d5234de0020313cab6950b2fRoboErik 32519c9518f6a817d53d5234de0020313cab6950b2fRoboErik int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); 3261ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik mOptimisticVolume = volumeBefore + direction; 32719c9518f6a817d53d5234de0020313cab6950b2fRoboErik mOptimisticVolume = Math.max(0, Math.min(mOptimisticVolume, mMaxVolume)); 32819c9518f6a817d53d5234de0020313cab6950b2fRoboErik mHandler.removeCallbacks(mClearOptimisticVolumeRunnable); 32919c9518f6a817d53d5234de0020313cab6950b2fRoboErik mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT); 33019c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (volumeBefore != mOptimisticVolume) { 33119c9518f6a817d53d5234de0020313cab6950b2fRoboErik pushVolumeUpdate(); 33219c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 3339c5b7cb048699237b35dad7a2a634ed6efb997c7RoboErik mService.notifyRemoteVolumeChanged(flags, this); 33419c9518f6a817d53d5234de0020313cab6950b2fRoboErik 33519c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (DEBUG) { 33619c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.d(TAG, "Adjusted optimistic volume to " + mOptimisticVolume + " max is " 33719c9518f6a817d53d5234de0020313cab6950b2fRoboErik + mMaxVolume); 33819c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 339b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 340b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 341b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 3420dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik public void setVolumeTo(int value, int flags, String packageName, int uid) { 343d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) { 3449db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs); 3450dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid); 346ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } else { 347ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) { 348ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik // Nothing to do. The volume can't be set directly. 349ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return; 350ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 35119c9518f6a817d53d5234de0020313cab6950b2fRoboErik value = Math.max(0, Math.min(value, mMaxVolume)); 352ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik mSessionCb.setVolumeTo(value); 35319c9518f6a817d53d5234de0020313cab6950b2fRoboErik 35419c9518f6a817d53d5234de0020313cab6950b2fRoboErik int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume); 35519c9518f6a817d53d5234de0020313cab6950b2fRoboErik mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume)); 35619c9518f6a817d53d5234de0020313cab6950b2fRoboErik mHandler.removeCallbacks(mClearOptimisticVolumeRunnable); 35719c9518f6a817d53d5234de0020313cab6950b2fRoboErik mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT); 35819c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (volumeBefore != mOptimisticVolume) { 35919c9518f6a817d53d5234de0020313cab6950b2fRoboErik pushVolumeUpdate(); 36019c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 3619c5b7cb048699237b35dad7a2a634ed6efb997c7RoboErik mService.notifyRemoteVolumeChanged(flags, this); 36219c9518f6a817d53d5234de0020313cab6950b2fRoboErik 36319c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (DEBUG) { 36419c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.d(TAG, "Set optimistic volume to " + mOptimisticVolume + " max is " 36519c9518f6a817d53d5234de0020313cab6950b2fRoboErik + mMaxVolume); 36619c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 367b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 368b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 369b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 370b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik /** 371a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Check if this session has been set to active by the app. 372a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * 373a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return True if the session is active, false otherwise. 374a8f951462791a16f47e8c07e552232f31dcefac5RoboErik */ 375a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public boolean isActive() { 3764646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik return mIsActive && !mDestroyed; 377a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 378a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 379a8f951462791a16f47e8c07e552232f31dcefac5RoboErik /** 380a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * Check if the session is currently performing playback. This will also 381a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * return true if the session was recently paused. 38207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik * 383b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * @param includeRecentlyActive True if playback that was recently paused 384b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * should count, false if it shouldn't. 385a8f951462791a16f47e8c07e552232f31dcefac5RoboErik * @return True if the session is performing playback, false otherwise. 38607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik */ 387b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public boolean isPlaybackActive(boolean includeRecentlyActive) { 388a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int state = mPlaybackState == null ? 0 : mPlaybackState.getState(); 3893c45c29109d23981d8b707c809b3b43ce2e20fc3RoboErik if (MediaSession.isActiveState(state)) { 390a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 391a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 392b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik if (includeRecentlyActive && state == mPlaybackState.STATE_PAUSED) { 393a8f951462791a16f47e8c07e552232f31dcefac5RoboErik long inactiveTime = SystemClock.uptimeMillis() - mLastActiveTime; 394a8f951462791a16f47e8c07e552232f31dcefac5RoboErik if (inactiveTime < ACTIVE_BUFFER) { 395a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return true; 396a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 397a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 398a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return false; 399a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 400a8f951462791a16f47e8c07e552232f31dcefac5RoboErik 4014646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik /** 402b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * Get the type of playback, either local or remote. 403b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * 404b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * @return The current type of playback. 405b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik */ 406b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public int getPlaybackType() { 407ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik return mVolumeType; 408b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 409b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 410b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik /** 411b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * Get the local audio stream being used. Only valid if playback type is 412b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * local. 413b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * 414b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * @return The audio stream the session is using. 415b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik */ 4169db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik public AudioAttributes getAudioAttributes() { 4179db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik return mAudioAttrs; 418b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 419b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 420b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik /** 421b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * Get the type of volume control. Only valid if playback type is remote. 422b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * 423b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * @return The volume control type being used. 424b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik */ 425b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public int getVolumeControl() { 426b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik return mVolumeControlType; 427b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 428b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 429b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik /** 430b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * Get the max volume that can be set. Only valid if playback type is 431b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * remote. 432b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * 433b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * @return The max volume that can be set. 434b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik */ 435b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public int getMaxVolume() { 436b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik return mMaxVolume; 437b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 438b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 439b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik /** 440b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * Get the current volume for this session. Only valid if playback type is 441b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * remote. 442b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * 443b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik * @return The current volume of the remote playback. 444b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik */ 445b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public int getCurrentVolume() { 446b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik return mCurrentVolume; 447b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 448b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 449b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik /** 45019c9518f6a817d53d5234de0020313cab6950b2fRoboErik * Get the volume we'd like it to be set to. This is only valid for a short 45119c9518f6a817d53d5234de0020313cab6950b2fRoboErik * while after a call to adjust or set volume. 45219c9518f6a817d53d5234de0020313cab6950b2fRoboErik * 45319c9518f6a817d53d5234de0020313cab6950b2fRoboErik * @return The current optimistic volume or -1. 45419c9518f6a817d53d5234de0020313cab6950b2fRoboErik */ 45519c9518f6a817d53d5234de0020313cab6950b2fRoboErik public int getOptimisticVolume() { 45619c9518f6a817d53d5234de0020313cab6950b2fRoboErik return mOptimisticVolume; 45719c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 45819c9518f6a817d53d5234de0020313cab6950b2fRoboErik 459a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public boolean isTransportControlEnabled() { 46042ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik return hasFlag(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); 4618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 4628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 46307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik @Override 46407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public void binderDied() { 46507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik mService.sessionDied(this); 46607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik } 46707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik 4684646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik /** 4694646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik * Finish cleaning up this session, including disconnecting if connected and 4704646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik * removing the death observer from the callback binder. 4714646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik */ 4724646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik public void onDestroy() { 4734646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik synchronized (mLock) { 4744646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik if (mDestroyed) { 4754646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik return; 4764646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 4774646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik mDestroyed = true; 47824762bffc3358762666079cd802040a316b3260dRoboErik mHandler.post(MessageHandler.MSG_DESTROYED); 4794646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 4804646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 4814646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik 4824646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik public ISessionCallback getCallback() { 4834646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik return mSessionCb.mCb; 4844646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 4854646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik 486418c10ca9df1505509afeffd558cd92fc97bc635RoboErik public void sendMediaButton(KeyEvent ke, int sequenceId, ResultReceiver cb) { 487418c10ca9df1505509afeffd558cd92fc97bc635RoboErik mSessionCb.sendMediaButton(ke, sequenceId, cb); 4888a2cfc309ab9126e90022916967c65a793c034f0RoboErik } 4898a2cfc309ab9126e90022916967c65a793c034f0RoboErik 490a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik public void dump(PrintWriter pw, String prefix) { 491a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik pw.println(prefix + mTag + " " + this); 492a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik 493a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik final String indent = prefix + " "; 494a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik pw.println(indent + "ownerPid=" + mOwnerPid + ", ownerUid=" + mOwnerUid 495a5b02329209be355eafadbdf9ee685ffa58d3148RoboErik + ", userId=" + mUserId); 496aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik pw.println(indent + "package=" + mPackageName); 4977aef77bbf5b983b9f949936ed6cd174251697ca8RoboErik pw.println(indent + "launchIntent=" + mLaunchIntent); 4987aef77bbf5b983b9f949936ed6cd174251697ca8RoboErik pw.println(indent + "mediaButtonReceiver=" + mMediaButtonReceiver); 4994646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik pw.println(indent + "active=" + mIsActive); 500a8f951462791a16f47e8c07e552232f31dcefac5RoboErik pw.println(indent + "flags=" + mFlags); 501a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik pw.println(indent + "rating type=" + mRatingType); 502a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik pw.println(indent + "controllers: " + mControllerCallbacks.size()); 503a8f951462791a16f47e8c07e552232f31dcefac5RoboErik pw.println(indent + "state=" + (mPlaybackState == null ? null : mPlaybackState.toString())); 5047aef77bbf5b983b9f949936ed6cd174251697ca8RoboErik pw.println(indent + "audioAttrs=" + mAudioAttrs); 5057aef77bbf5b983b9f949936ed6cd174251697ca8RoboErik pw.println(indent + "volumeType=" + mVolumeType + ", controlType=" + mVolumeControlType 5067aef77bbf5b983b9f949936ed6cd174251697ca8RoboErik + ", max=" + mMaxVolume + ", current=" + mCurrentVolume); 50766dea73906f24226a6f699759e79040726bde8b5RoboErik pw.println(indent + "metadata:" + getShortMetadataString()); 5087aef77bbf5b983b9f949936ed6cd174251697ca8RoboErik pw.println(indent + "queueTitle=" + mQueueTitle + ", size=" 5097aef77bbf5b983b9f949936ed6cd174251697ca8RoboErik + (mQueue == null ? 0 : mQueue.getList().size())); 510a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik } 511a278ea7cecb59a73586e5dd74ec05e85caa370c5RoboErik 512aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik @Override 513aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik public String toString() { 514aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik return mPackageName + "/" + mTag; 515aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik } 516aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik 51766dea73906f24226a6f699759e79040726bde8b5RoboErik private String getShortMetadataString() { 51866dea73906f24226a6f699759e79040726bde8b5RoboErik int fields = mMetadata == null ? 0 : mMetadata.size(); 5193625bf72cb8bcf3c7f8f8cd8d708d7206824cc62RoboErik MediaDescription description = mMetadata == null ? null : mMetadata 52075847b98f39e521a57042c50e69be9e142788d32RoboErik .getDescription(); 52175847b98f39e521a57042c50e69be9e142788d32RoboErik return "size=" + fields + ", description=" + description; 52266dea73906f24226a6f699759e79040726bde8b5RoboErik } 52366dea73906f24226a6f699759e79040726bde8b5RoboErik 5248ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private void pushPlaybackStateUpdate() { 52507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik synchronized (mLock) { 5264646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik if (mDestroyed) { 5274646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik return; 5284646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 5298ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 53007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik ISessionControllerCallback cb = mControllerCallbacks.get(i); 5318ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 5328ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik cb.onPlaybackStateChanged(mPlaybackState); 533d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } catch (DeadObjectException e) { 5348ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mControllerCallbacks.remove(i); 53519c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.w(TAG, "Removed dead callback in pushPlaybackStateUpdate.", e); 536d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } catch (RemoteException e) { 537d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik Log.w(TAG, "unexpected exception in pushPlaybackStateUpdate.", e); 5388ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 5398ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 5408ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 5418ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 54201fe661ae5da3739215d93922412df4b24c859a2RoboErik 5438ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private void pushMetadataUpdate() { 54407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik synchronized (mLock) { 5454646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik if (mDestroyed) { 5464646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik return; 5474646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 5488ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 54907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik ISessionControllerCallback cb = mControllerCallbacks.get(i); 5508ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 5518ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik cb.onMetadataChanged(mMetadata); 552d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } catch (DeadObjectException e) { 55319c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.w(TAG, "Removing dead callback in pushMetadataUpdate. ", e); 5548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mControllerCallbacks.remove(i); 555d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } catch (RemoteException e) { 55619c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.w(TAG, "unexpected exception in pushMetadataUpdate. ", e); 55719c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 55819c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 55919c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 56019c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 56119c9518f6a817d53d5234de0020313cab6950b2fRoboErik 562f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private void pushQueueUpdate() { 563f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal synchronized (mLock) { 564f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (mDestroyed) { 565f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal return; 566f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 567f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 568f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal ISessionControllerCallback cb = mControllerCallbacks.get(i); 569f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 570f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal cb.onQueueChanged(mQueue); 571f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (DeadObjectException e) { 572f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mControllerCallbacks.remove(i); 573f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.w(TAG, "Removed dead callback in pushQueueUpdate.", e); 574f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 575f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.w(TAG, "unexpected exception in pushQueueUpdate.", e); 576f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 577f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 578f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 579f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 580f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 581f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private void pushQueueTitleUpdate() { 582f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal synchronized (mLock) { 583f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (mDestroyed) { 584f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal return; 585f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 586f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 587f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal ISessionControllerCallback cb = mControllerCallbacks.get(i); 588f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 589f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal cb.onQueueTitleChanged(mQueueTitle); 590f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (DeadObjectException e) { 591f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mControllerCallbacks.remove(i); 592f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.w(TAG, "Removed dead callback in pushQueueTitleUpdate.", e); 593f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 594f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.w(TAG, "unexpected exception in pushQueueTitleUpdate.", e); 595f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 596f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 597f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 598f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 599f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 600f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private void pushExtrasUpdate() { 601f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal synchronized (mLock) { 602f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal if (mDestroyed) { 603f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal return; 604f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 605f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 606f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal ISessionControllerCallback cb = mControllerCallbacks.get(i); 607f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 608f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal cb.onExtrasChanged(mExtras); 609f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (DeadObjectException e) { 610f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mControllerCallbacks.remove(i); 611f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.w(TAG, "Removed dead callback in pushExtrasUpdate.", e); 612f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 613f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Log.w(TAG, "unexpected exception in pushExtrasUpdate.", e); 614f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 615f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 616f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 617f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 618f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 61919c9518f6a817d53d5234de0020313cab6950b2fRoboErik private void pushVolumeUpdate() { 62019c9518f6a817d53d5234de0020313cab6950b2fRoboErik synchronized (mLock) { 62119c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (mDestroyed) { 62219c9518f6a817d53d5234de0020313cab6950b2fRoboErik return; 62319c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 62419c9518f6a817d53d5234de0020313cab6950b2fRoboErik ParcelableVolumeInfo info = mController.getVolumeAttributes(); 62519c9518f6a817d53d5234de0020313cab6950b2fRoboErik for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 62619c9518f6a817d53d5234de0020313cab6950b2fRoboErik ISessionControllerCallback cb = mControllerCallbacks.get(i); 62719c9518f6a817d53d5234de0020313cab6950b2fRoboErik try { 62819c9518f6a817d53d5234de0020313cab6950b2fRoboErik cb.onVolumeInfoChanged(info); 62919c9518f6a817d53d5234de0020313cab6950b2fRoboErik } catch (DeadObjectException e) { 63019c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.w(TAG, "Removing dead callback in pushVolumeUpdate. ", e); 63119c9518f6a817d53d5234de0020313cab6950b2fRoboErik } catch (RemoteException e) { 63219c9518f6a817d53d5234de0020313cab6950b2fRoboErik Log.w(TAG, "Unexpected exception in pushVolumeUpdate. ", e); 6338ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 6348ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 63501fe661ae5da3739215d93922412df4b24c859a2RoboErik } 6368ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 6378ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 6388ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private void pushEvent(String event, Bundle data) { 63907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik synchronized (mLock) { 6404646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik if (mDestroyed) { 6414646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik return; 6424646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik } 6438ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 64407c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik ISessionControllerCallback cb = mControllerCallbacks.get(i); 6458ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 6468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik cb.onEvent(event, data); 647d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } catch (DeadObjectException e) { 648d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik Log.w(TAG, "Removing dead callback in pushEvent.", e); 649d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik mControllerCallbacks.remove(i); 6508ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 651d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik Log.w(TAG, "unexpected exception in pushEvent.", e); 6528ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 6538ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 6548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 6558ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 6568ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 65724762bffc3358762666079cd802040a316b3260dRoboErik private void pushSessionDestroyed() { 65824762bffc3358762666079cd802040a316b3260dRoboErik synchronized (mLock) { 65924762bffc3358762666079cd802040a316b3260dRoboErik // This is the only method that may be (and can only be) called 66024762bffc3358762666079cd802040a316b3260dRoboErik // after the session is destroyed. 66124762bffc3358762666079cd802040a316b3260dRoboErik if (!mDestroyed) { 66224762bffc3358762666079cd802040a316b3260dRoboErik return; 66324762bffc3358762666079cd802040a316b3260dRoboErik } 66424762bffc3358762666079cd802040a316b3260dRoboErik for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 66524762bffc3358762666079cd802040a316b3260dRoboErik ISessionControllerCallback cb = mControllerCallbacks.get(i); 66624762bffc3358762666079cd802040a316b3260dRoboErik try { 66724762bffc3358762666079cd802040a316b3260dRoboErik cb.onSessionDestroyed(); 66824762bffc3358762666079cd802040a316b3260dRoboErik } catch (DeadObjectException e) { 66924762bffc3358762666079cd802040a316b3260dRoboErik Log.w(TAG, "Removing dead callback in pushEvent.", e); 67024762bffc3358762666079cd802040a316b3260dRoboErik mControllerCallbacks.remove(i); 67124762bffc3358762666079cd802040a316b3260dRoboErik } catch (RemoteException e) { 67224762bffc3358762666079cd802040a316b3260dRoboErik Log.w(TAG, "unexpected exception in pushEvent.", e); 67324762bffc3358762666079cd802040a316b3260dRoboErik } 67424762bffc3358762666079cd802040a316b3260dRoboErik } 67524762bffc3358762666079cd802040a316b3260dRoboErik // After notifying clear all listeners 67624762bffc3358762666079cd802040a316b3260dRoboErik mControllerCallbacks.clear(); 67724762bffc3358762666079cd802040a316b3260dRoboErik } 67824762bffc3358762666079cd802040a316b3260dRoboErik } 67924762bffc3358762666079cd802040a316b3260dRoboErik 680f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik private PlaybackState getStateWithUpdatedPosition() { 681df382cada180033e5bbde82998b73ef19e541ed2RoboErik PlaybackState state; 68282df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik long duration = -1; 683df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 684df382cada180033e5bbde82998b73ef19e541ed2RoboErik state = mPlaybackState; 68582df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik if (mMetadata != null && mMetadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) { 68682df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik duration = mMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION); 68782df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik } 688f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 689f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik PlaybackState result = null; 690f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (state != null) { 69179fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik if (state.getState() == PlaybackState.STATE_PLAYING 69279fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik || state.getState() == PlaybackState.STATE_FAST_FORWARDING 69379fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik || state.getState() == PlaybackState.STATE_REWINDING) { 694f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik long updateTime = state.getLastPositionUpdateTime(); 695c785a78fb483fe54012175c53d3758b2412de7b9RoboErik long currentTime = SystemClock.elapsedRealtime(); 696f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (updateTime > 0) { 697c785a78fb483fe54012175c53d3758b2412de7b9RoboErik long position = (long) (state.getPlaybackSpeed() 698c785a78fb483fe54012175c53d3758b2412de7b9RoboErik * (currentTime - updateTime)) + state.getPosition(); 699f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik if (duration >= 0 && position > duration) { 700f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik position = duration; 701f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } else if (position < 0) { 702f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik position = 0; 703f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 704c785a78fb483fe54012175c53d3758b2412de7b9RoboErik PlaybackState.Builder builder = new PlaybackState.Builder(state); 705c785a78fb483fe54012175c53d3758b2412de7b9RoboErik builder.setState(state.getState(), position, state.getPlaybackSpeed(), 706c785a78fb483fe54012175c53d3758b2412de7b9RoboErik currentTime); 707c785a78fb483fe54012175c53d3758b2412de7b9RoboErik result = builder.build(); 708f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 709f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 710f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 711f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik return result == null ? state : result; 712f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik } 713f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik 714d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik private int getControllerCbIndexForCb(ISessionControllerCallback cb) { 715d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik IBinder binder = cb.asBinder(); 716d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { 717d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik if (binder.equals(mControllerCallbacks.get(i).asBinder())) { 718d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik return i; 719d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 720d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 721d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik return -1; 722d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 723d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik 72419c9518f6a817d53d5234de0020313cab6950b2fRoboErik private final Runnable mClearOptimisticVolumeRunnable = new Runnable() { 72519c9518f6a817d53d5234de0020313cab6950b2fRoboErik @Override 72619c9518f6a817d53d5234de0020313cab6950b2fRoboErik public void run() { 72719c9518f6a817d53d5234de0020313cab6950b2fRoboErik boolean needUpdate = (mOptimisticVolume != mCurrentVolume); 72819c9518f6a817d53d5234de0020313cab6950b2fRoboErik mOptimisticVolume = -1; 72919c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (needUpdate) { 73019c9518f6a817d53d5234de0020313cab6950b2fRoboErik pushVolumeUpdate(); 73119c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 73219c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 73319c9518f6a817d53d5234de0020313cab6950b2fRoboErik }; 73419c9518f6a817d53d5234de0020313cab6950b2fRoboErik 73507c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik private final class SessionStub extends ISession.Stub { 73601fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 73707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public void destroy() { 7384646d288821d62fdfe481be67d8b7fed7d7eabd8RoboErik mService.destroySession(MediaSessionRecord.this); 73901fe661ae5da3739215d93922412df4b24c859a2RoboErik } 74001fe661ae5da3739215d93922412df4b24c859a2RoboErik 74101fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 74207c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public void sendEvent(String event, Bundle data) { 743df382cada180033e5bbde82998b73ef19e541ed2RoboErik mHandler.post(MessageHandler.MSG_SEND_EVENT, event, 744df382cada180033e5bbde82998b73ef19e541ed2RoboErik data == null ? null : new Bundle(data)); 7458ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 7468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 7478ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 74807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public ISessionController getController() { 74907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik return mController; 7508ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 7518ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 7528ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 753a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void setActive(boolean active) { 754a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mIsActive = active; 755a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mService.updateSession(MediaSessionRecord.this); 756a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE); 75701fe661ae5da3739215d93922412df4b24c859a2RoboErik } 75801fe661ae5da3739215d93922412df4b24c859a2RoboErik 75901fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 760a8f951462791a16f47e8c07e552232f31dcefac5RoboErik public void setFlags(int flags) { 76142ea7eecd149161ed192d3029f0d77d1d08a4aa5RoboErik if ((flags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) { 762e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik int pid = getCallingPid(); 763e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik int uid = getCallingUid(); 764e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik mService.enforcePhoneStatePermission(pid, uid); 765e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik } 766e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik mFlags = flags; 767a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE); 768e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik } 769e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik 770e7880d8eb1903d42e4e2a90c99b58e2240e01e82RoboErik @Override 771b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik public void setMediaButtonReceiver(PendingIntent pi) { 772b214efbb9170a9f6a4991684a63ca59680074cc7RoboErik mMediaButtonReceiver = pi; 7736f0e4ddd66fcdcc13944d8970d0b560e2626508bRoboErik } 7746f0e4ddd66fcdcc13944d8970d0b560e2626508bRoboErik 7756f0e4ddd66fcdcc13944d8970d0b560e2626508bRoboErik @Override 776e34c09daf89fb888fe2638e71758573462d85173RoboErik public void setLaunchPendingIntent(PendingIntent pi) { 777e34c09daf89fb888fe2638e71758573462d85173RoboErik mLaunchIntent = pi; 778e34c09daf89fb888fe2638e71758573462d85173RoboErik } 779e34c09daf89fb888fe2638e71758573462d85173RoboErik 780e34c09daf89fb888fe2638e71758573462d85173RoboErik @Override 7818ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void setMetadata(MediaMetadata metadata) { 782df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 78382df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata) 78482df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik .build(); 78582df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik // This is to guarantee that the underlying bundle is unparceled 78682df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik // before we set it to prevent concurrent reads from throwing an 78782df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik // exception 788421c9df7ff52f8c43fd5356a59702931f39dc029RoboErik if (temp != null) { 789421c9df7ff52f8c43fd5356a59702931f39dc029RoboErik temp.size(); 790421c9df7ff52f8c43fd5356a59702931f39dc029RoboErik } 79182df2c0839876d158889ea0e28e6f3adf0d4797dRoboErik mMetadata = temp; 792df382cada180033e5bbde82998b73ef19e541ed2RoboErik } 7938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mHandler.post(MessageHandler.MSG_UPDATE_METADATA); 79401fe661ae5da3739215d93922412df4b24c859a2RoboErik } 79501fe661ae5da3739215d93922412df4b24c859a2RoboErik 7968ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 7978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void setPlaybackState(PlaybackState state) { 798a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int oldState = mPlaybackState == null ? 0 : mPlaybackState.getState(); 799a8f951462791a16f47e8c07e552232f31dcefac5RoboErik int newState = state == null ? 0 : state.getState(); 8003c45c29109d23981d8b707c809b3b43ce2e20fc3RoboErik if (MediaSession.isActiveState(oldState) && newState == PlaybackState.STATE_PAUSED) { 801a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mLastActiveTime = SystemClock.elapsedRealtime(); 802a8f951462791a16f47e8c07e552232f31dcefac5RoboErik } 803df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 804df382cada180033e5bbde82998b73ef19e541ed2RoboErik mPlaybackState = state; 805df382cada180033e5bbde82998b73ef19e541ed2RoboErik } 806a8f951462791a16f47e8c07e552232f31dcefac5RoboErik mService.onSessionPlaystateChange(MediaSessionRecord.this, oldState, newState); 8078ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mHandler.post(MessageHandler.MSG_UPDATE_PLAYBACK_STATE); 8088ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 8098ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 8108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 811f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void setQueue(ParceledListSlice queue) { 812df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 813df382cada180033e5bbde82998b73ef19e541ed2RoboErik mQueue = queue; 814df382cada180033e5bbde82998b73ef19e541ed2RoboErik } 815f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mHandler.post(MessageHandler.MSG_UPDATE_QUEUE); 816f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 817f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 818f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 819f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void setQueueTitle(CharSequence title) { 820f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mQueueTitle = title; 821f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mHandler.post(MessageHandler.MSG_UPDATE_QUEUE_TITLE); 822f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 823f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 824f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 825f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void setExtras(Bundle extras) { 826df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 827df382cada180033e5bbde82998b73ef19e541ed2RoboErik mExtras = extras == null ? null : new Bundle(extras); 828df382cada180033e5bbde82998b73ef19e541ed2RoboErik } 829f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mHandler.post(MessageHandler.MSG_UPDATE_EXTRAS); 830f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 831f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 832f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 8338ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void setRatingType(int type) { 8348ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mRatingType = type; 8358ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 83607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik 83707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik @Override 838b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public void setCurrentVolume(int volume) { 839b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik mCurrentVolume = volume; 84019c9518f6a817d53d5234de0020313cab6950b2fRoboErik mHandler.post(MessageHandler.MSG_UPDATE_VOLUME); 841b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 842b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 843b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik @Override 8449db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik public void setPlaybackToLocal(AudioAttributes attributes) { 8459db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik boolean typeChanged; 8469db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik synchronized (mLock) { 847d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE; 848d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL; 8499db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik if (attributes != null) { 8509db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik mAudioAttrs = attributes; 8519db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik } else { 8529db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik Log.e(TAG, "Received null audio attributes, using existing attributes"); 8539db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik } 854b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 85519c9518f6a817d53d5234de0020313cab6950b2fRoboErik if (typeChanged) { 85619c9518f6a817d53d5234de0020313cab6950b2fRoboErik mService.onSessionPlaybackTypeChanged(MediaSessionRecord.this); 85719c9518f6a817d53d5234de0020313cab6950b2fRoboErik } 858b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 859b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 8609db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik @Override 8619db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik public void setPlaybackToRemote(int control, int max) { 8629db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik boolean typeChanged; 8639db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik synchronized (mLock) { 864d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik typeChanged = mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL; 865d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik mVolumeType = PlaybackInfo.PLAYBACK_TYPE_REMOTE; 8669db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik mVolumeControlType = control; 8679db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik mMaxVolume = max; 8689db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik } 8699db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik if (typeChanged) { 8709db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik mService.onSessionPlaybackTypeChanged(MediaSessionRecord.this); 8719db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik } 872b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 87301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 87401fe661ae5da3739215d93922412df4b24c859a2RoboErik 87501fe661ae5da3739215d93922412df4b24c859a2RoboErik class SessionCb { 87607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik private final ISessionCallback mCb; 87701fe661ae5da3739215d93922412df4b24c859a2RoboErik 87807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public SessionCb(ISessionCallback cb) { 87901fe661ae5da3739215d93922412df4b24c859a2RoboErik mCb = cb; 88001fe661ae5da3739215d93922412df4b24c859a2RoboErik } 88101fe661ae5da3739215d93922412df4b24c859a2RoboErik 88279fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik public boolean sendMediaButton(KeyEvent keyEvent, int sequenceId, ResultReceiver cb) { 88301fe661ae5da3739215d93922412df4b24c859a2RoboErik Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); 88401fe661ae5da3739215d93922412df4b24c859a2RoboErik mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); 88501fe661ae5da3739215d93922412df4b24c859a2RoboErik try { 886418c10ca9df1505509afeffd558cd92fc97bc635RoboErik mCb.onMediaButton(mediaButtonIntent, sequenceId, cb); 88779fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik return true; 88801fe661ae5da3739215d93922412df4b24c859a2RoboErik } catch (RemoteException e) { 8898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in sendMediaRequest.", e); 8908ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 89179fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik return false; 8928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 8938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 894f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal public void sendCommand(String command, Bundle args, ResultReceiver cb) { 8958ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 896f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal mCb.onCommand(command, args, cb); 8978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 8988ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in sendCommand.", e); 8998ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9008ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9018ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 902f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal public void sendCustomAction(String action, Bundle args) { 903f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal try { 904f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal mCb.onCustomAction(action, args); 905f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } catch (RemoteException e) { 906f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal Slog.e(TAG, "Remote failure in sendCustomAction.", e); 907f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 908f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 909f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal 9108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void play() { 9118ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 9128ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onPlay(); 9138ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 9148ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in play.", e); 91501fe661ae5da3739215d93922412df4b24c859a2RoboErik } 91601fe661ae5da3739215d93922412df4b24c859a2RoboErik } 91701fe661ae5da3739215d93922412df4b24c859a2RoboErik 9183625bf72cb8bcf3c7f8f8cd8d708d7206824cc62RoboErik public void playFromMediaId(String mediaId, Bundle extras) { 919f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 9203625bf72cb8bcf3c7f8f8cd8d708d7206824cc62RoboErik mCb.onPlayFromMediaId(mediaId, extras); 921f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 922f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Slog.e(TAG, "Remote failure in playUri.", e); 923f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 924f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 925f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 926f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void playFromSearch(String query, Bundle extras) { 927f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 928f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mCb.onPlayFromSearch(query, extras); 929f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 930f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Slog.e(TAG, "Remote failure in playFromSearch.", e); 931f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 932f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 933f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 934f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void skipToTrack(long id) { 935f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal try { 936f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mCb.onSkipToTrack(id); 937f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } catch (RemoteException e) { 938f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal Slog.e(TAG, "Remote failure in skipToTrack", e); 939f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 940f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 941f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 9428ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void pause() { 94301fe661ae5da3739215d93922412df4b24c859a2RoboErik try { 9448ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onPause(); 94501fe661ae5da3739215d93922412df4b24c859a2RoboErik } catch (RemoteException e) { 9468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in pause.", e); 94701fe661ae5da3739215d93922412df4b24c859a2RoboErik } 94801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 94901fe661ae5da3739215d93922412df4b24c859a2RoboErik 9508ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void stop() { 9518ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 9528ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onStop(); 9538ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 9548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in stop.", e); 9558ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9568ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 95701fe661ae5da3739215d93922412df4b24c859a2RoboErik 9588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void next() { 9598ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 9608ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onNext(); 9618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 9628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in next.", e); 9638ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 96401fe661ae5da3739215d93922412df4b24c859a2RoboErik } 96501fe661ae5da3739215d93922412df4b24c859a2RoboErik 9668ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void previous() { 9678ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 9688ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onPrevious(); 9698ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 9708ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in previous.", e); 9718ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9728ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9738ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 9748ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void fastForward() { 9758ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 9768ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onFastForward(); 9778ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 9788ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in fastForward.", e); 9798ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9808ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9818ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 9828ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void rewind() { 9838ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 9848ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onRewind(); 9858ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 9868ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in rewind.", e); 9878ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 9908ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void seekTo(long pos) { 9918ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 9928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onSeekTo(pos); 9938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 9948ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in seekTo.", e); 9958ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9968ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 9978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 9988ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void rate(Rating rating) { 9998ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik try { 10008ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mCb.onRate(rating); 10018ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } catch (RemoteException e) { 10028ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Slog.e(TAG, "Remote failure in rate.", e); 10038ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 10048ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 1005b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 10061ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik public void adjustVolume(int direction) { 1007b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik try { 10081ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik mCb.onAdjustVolume(direction); 1009b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } catch (RemoteException e) { 10101ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik Slog.e(TAG, "Remote failure in adjustVolume.", e); 1011b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 1012b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 1013b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik 1014b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik public void setVolumeTo(int value) { 1015b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik try { 1016b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik mCb.onSetVolumeTo(value); 1017b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } catch (RemoteException e) { 10181ff5b1648a051e9650614f0c0f1b3f449777db81RoboErik Slog.e(TAG, "Remote failure in setVolumeTo.", e); 1019b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 1020b69ffd4dc2c8fa85e0064151141ebeee90de471eRoboErik } 102101fe661ae5da3739215d93922412df4b24c859a2RoboErik } 102201fe661ae5da3739215d93922412df4b24c859a2RoboErik 102307c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik class ControllerStub extends ISessionController.Stub { 102401fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 1025f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal public void sendCommand(String command, Bundle args, ResultReceiver cb) 10268ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik throws RemoteException { 1027f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal mSessionCb.sendCommand(command, args, cb); 102801fe661ae5da3739215d93922412df4b24c859a2RoboErik } 102901fe661ae5da3739215d93922412df4b24c859a2RoboErik 103001fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 103179fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik public boolean sendMediaButton(KeyEvent mediaButtonIntent) { 103279fa4630bbca7c6c251eea99fe8997e4b45beceeRoboErik return mSessionCb.sendMediaButton(mediaButtonIntent, 0, null); 103301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 103401fe661ae5da3739215d93922412df4b24c859a2RoboErik 103501fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 103607c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public void registerCallbackListener(ISessionControllerCallback cb) { 103707c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik synchronized (mLock) { 103824762bffc3358762666079cd802040a316b3260dRoboErik // If this session is already destroyed tell the caller and 103924762bffc3358762666079cd802040a316b3260dRoboErik // don't add them. 104024762bffc3358762666079cd802040a316b3260dRoboErik if (mDestroyed) { 104124762bffc3358762666079cd802040a316b3260dRoboErik try { 104224762bffc3358762666079cd802040a316b3260dRoboErik cb.onSessionDestroyed(); 104324762bffc3358762666079cd802040a316b3260dRoboErik } catch (Exception e) { 104424762bffc3358762666079cd802040a316b3260dRoboErik // ignored 104524762bffc3358762666079cd802040a316b3260dRoboErik } 104624762bffc3358762666079cd802040a316b3260dRoboErik return; 104724762bffc3358762666079cd802040a316b3260dRoboErik } 1048d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik if (getControllerCbIndexForCb(cb) < 0) { 10498ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mControllerCallbacks.add(cb); 1050d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik if (DEBUG) { 1051d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik Log.d(TAG, "registering controller callback " + cb); 1052d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 10538ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 105401fe661ae5da3739215d93922412df4b24c859a2RoboErik } 105501fe661ae5da3739215d93922412df4b24c859a2RoboErik } 105601fe661ae5da3739215d93922412df4b24c859a2RoboErik 105701fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 105807c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public void unregisterCallbackListener(ISessionControllerCallback cb) 105901fe661ae5da3739215d93922412df4b24c859a2RoboErik throws RemoteException { 106007c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik synchronized (mLock) { 1061d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik int index = getControllerCbIndexForCb(cb); 1062d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik if (index != -1) { 1063d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik mControllerCallbacks.remove(index); 1064d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 1065d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik if (DEBUG) { 1066d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik Log.d(TAG, "unregistering callback " + cb + ". index=" + index); 1067d3c8642dae9a1f6db60e2f8e5c7b32cd1b3169dfRoboErik } 10688ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 106901fe661ae5da3739215d93922412df4b24c859a2RoboErik } 107001fe661ae5da3739215d93922412df4b24c859a2RoboErik 107101fe661ae5da3739215d93922412df4b24c859a2RoboErik @Override 1072aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik public String getPackageName() { 1073aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik return mPackageName; 1074aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik } 1075aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik 1076aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik @Override 1077aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik public String getTag() { 1078aa4e23bbb36994708ba72c5f4c83255025d99e07RoboErik return mTag; 1079fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik } 1080fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik 1081fb442b03840245c7e52cf2a540a77c5fc6c54587RoboErik @Override 1082e34c09daf89fb888fe2638e71758573462d85173RoboErik public PendingIntent getLaunchPendingIntent() { 1083e34c09daf89fb888fe2638e71758573462d85173RoboErik return mLaunchIntent; 1084e34c09daf89fb888fe2638e71758573462d85173RoboErik } 1085e34c09daf89fb888fe2638e71758573462d85173RoboErik 1086e34c09daf89fb888fe2638e71758573462d85173RoboErik @Override 108773e23e229dd1a2d25687b1c6a63c708665378e41RoboErik public long getFlags() { 108873e23e229dd1a2d25687b1c6a63c708665378e41RoboErik return mFlags; 108973e23e229dd1a2d25687b1c6a63c708665378e41RoboErik } 109073e23e229dd1a2d25687b1c6a63c708665378e41RoboErik 109173e23e229dd1a2d25687b1c6a63c708665378e41RoboErik @Override 1092ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik public ParcelableVolumeInfo getVolumeAttributes() { 1093ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik synchronized (mLock) { 1094ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik int type; 1095ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik int max; 1096ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik int current; 1097d2b8c947ddfc6349a3ae6c3968b422b9cf50d7edRoboErik if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_REMOTE) { 1098ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik type = mVolumeControlType; 1099ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik max = mMaxVolume; 110019c9518f6a817d53d5234de0020313cab6950b2fRoboErik current = mOptimisticVolume != -1 ? mOptimisticVolume 110119c9518f6a817d53d5234de0020313cab6950b2fRoboErik : mCurrentVolume; 1102ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } else { 11039db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs); 1104ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik type = VolumeProvider.VOLUME_CONTROL_ABSOLUTE; 11059db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik max = mAudioManager.getStreamMaxVolume(stream); 11069db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik current = mAudioManager.getStreamVolume(stream); 1107ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 11089db9bf7034d7dcdf596dc22d521b18975d0dd2b9RoboErik return new ParcelableVolumeInfo(mVolumeType, mAudioAttrs, type, max, current); 1109ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 1110ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 1111ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 1112ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik @Override 11130dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik public void adjustVolume(int direction, int flags, String packageName) { 11140dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik int uid = Binder.getCallingUid(); 1115f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik final long token = Binder.clearCallingIdentity(); 1116f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik try { 1117272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik MediaSessionRecord.this.adjustVolume(direction, flags, packageName, uid, false); 1118f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik } finally { 1119f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik Binder.restoreCallingIdentity(token); 1120f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik } 1121ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 1122ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 1123ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik @Override 11240dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik public void setVolumeTo(int value, int flags, String packageName) { 11250dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik int uid = Binder.getCallingUid(); 1126f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik final long token = Binder.clearCallingIdentity(); 1127f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik try { 11280dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik MediaSessionRecord.this.setVolumeTo(value, flags, packageName, uid); 1129f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik } finally { 1130f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik Binder.restoreCallingIdentity(token); 1131f77b99f08afed6f6b8d8f5bc72978f2ff7b8db55RoboErik } 1132ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik } 1133ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik 1134ef3c9e9b057a5aac2d0d012e8e6385660478e203RoboErik @Override 11358ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void play() throws RemoteException { 11368ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.play(); 11378ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11388ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11398ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11403625bf72cb8bcf3c7f8f8cd8d708d7206824cc62RoboErik public void playFromMediaId(String mediaId, Bundle extras) throws RemoteException { 11413625bf72cb8bcf3c7f8f8cd8d708d7206824cc62RoboErik mSessionCb.playFromMediaId(mediaId, extras); 1142f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 1143f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 1144f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 1145f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public void playFromSearch(String query, Bundle extras) throws RemoteException { 1146f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mSessionCb.playFromSearch(query, extras); 1147f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 1148f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 1149f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 11503625bf72cb8bcf3c7f8f8cd8d708d7206824cc62RoboErik public void skipToQueueItem(long id) { 1151f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal mSessionCb.skipToTrack(id); 1152f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 1153f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 1154f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 1155f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 11568ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void pause() throws RemoteException { 11578ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.pause(); 11588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11598ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11608ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void stop() throws RemoteException { 11628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.stop(); 11638ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11648ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11658ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11668ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void next() throws RemoteException { 11678ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.next(); 11688ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11698ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11708ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11718ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void previous() throws RemoteException { 11728ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.previous(); 11738ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11748ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11758ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11768ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void fastForward() throws RemoteException { 11778ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.fastForward(); 11788ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11798ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11808ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11818ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void rewind() throws RemoteException { 11828ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.rewind(); 11838ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11848ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11858ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11868ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void seekTo(long pos) throws RemoteException { 11878ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.seekTo(pos); 11888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 11908ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 11918ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void rate(Rating rating) throws RemoteException { 11928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik mSessionCb.rate(rating); 11938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 11948ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 1195f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal @Override 1196f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal public void sendCustomAction(String action, Bundle args) 1197f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal throws RemoteException { 1198f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal mSessionCb.sendCustomAction(action, args); 1199f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal } 1200f364f944962c4ec66f5e5b33dafe8480f38f6db6Gabriel Peal 12018ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12028ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 12038ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public MediaMetadata getMetadata() { 1204df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 1205df382cada180033e5bbde82998b73ef19e541ed2RoboErik return mMetadata; 1206df382cada180033e5bbde82998b73ef19e541ed2RoboErik } 12078ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12088ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12098ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 12108ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public PlaybackState getPlaybackState() { 1211f1372428f2df781c71c71caa2f6a4db6f847cf10RoboErik return getStateWithUpdatedPosition(); 121201fe661ae5da3739215d93922412df4b24c859a2RoboErik } 12138ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12148ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 1215f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public ParceledListSlice getQueue() { 1216df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 1217df382cada180033e5bbde82998b73ef19e541ed2RoboErik return mQueue; 1218df382cada180033e5bbde82998b73ef19e541ed2RoboErik } 1219f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 1220f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 1221f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 1222f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public CharSequence getQueueTitle() { 1223f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal return mQueueTitle; 1224f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 1225f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 1226f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 1227f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal public Bundle getExtras() { 1228df382cada180033e5bbde82998b73ef19e541ed2RoboErik synchronized (mLock) { 1229df382cada180033e5bbde82998b73ef19e541ed2RoboErik return mExtras; 1230df382cada180033e5bbde82998b73ef19e541ed2RoboErik } 1231f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal } 1232f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal 1233f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal @Override 12348ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public int getRatingType() { 12358ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik return mRatingType; 12368ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12378ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12388ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 123907c7077c54717dbbf2c401ea32d00fa6df6d77c6RoboErik public boolean isTransportControlEnabled() { 1240a8f951462791a16f47e8c07e552232f31dcefac5RoboErik return MediaSessionRecord.this.isTransportControlEnabled(); 12418ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12428ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12438ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12448ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private class MessageHandler extends Handler { 12458ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private static final int MSG_UPDATE_METADATA = 1; 12468ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik private static final int MSG_UPDATE_PLAYBACK_STATE = 2; 1247f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_QUEUE = 3; 1248f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_QUEUE_TITLE = 4; 1249f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_EXTRAS = 5; 1250f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_SEND_EVENT = 6; 1251f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_SESSION_STATE = 7; 1252f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal private static final int MSG_UPDATE_VOLUME = 8; 125324762bffc3358762666079cd802040a316b3260dRoboErik private static final int MSG_DESTROYED = 9; 12548ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12558ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public MessageHandler(Looper looper) { 12568ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik super(looper); 12578ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12588ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik @Override 12598ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void handleMessage(Message msg) { 12608ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik switch (msg.what) { 12618ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik case MSG_UPDATE_METADATA: 12628ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik pushMetadataUpdate(); 12638ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik break; 12648ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik case MSG_UPDATE_PLAYBACK_STATE: 12658ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik pushPlaybackStateUpdate(); 12668ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik break; 1267f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal case MSG_UPDATE_QUEUE: 1268f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal pushQueueUpdate(); 1269f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal break; 1270f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal case MSG_UPDATE_QUEUE_TITLE: 1271f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal pushQueueTitleUpdate(); 1272f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal break; 1273f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal case MSG_UPDATE_EXTRAS: 1274f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal pushExtrasUpdate(); 1275f0593bc17b61c872ae2d7705fb598c5e5056e679Gabriel Peal break; 12768ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik case MSG_SEND_EVENT: 12778ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik pushEvent((String) msg.obj, msg.getData()); 12788ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik break; 1279a8f951462791a16f47e8c07e552232f31dcefac5RoboErik case MSG_UPDATE_SESSION_STATE: 1280a8f951462791a16f47e8c07e552232f31dcefac5RoboErik // TODO add session state 1281a8f951462791a16f47e8c07e552232f31dcefac5RoboErik break; 128219c9518f6a817d53d5234de0020313cab6950b2fRoboErik case MSG_UPDATE_VOLUME: 128319c9518f6a817d53d5234de0020313cab6950b2fRoboErik pushVolumeUpdate(); 128419c9518f6a817d53d5234de0020313cab6950b2fRoboErik break; 128524762bffc3358762666079cd802040a316b3260dRoboErik case MSG_DESTROYED: 128624762bffc3358762666079cd802040a316b3260dRoboErik pushSessionDestroyed(); 12878ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12888ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12898ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12908ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void post(int what) { 12918ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik post(what, null); 12928ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12938ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12948ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void post(int what, Object obj) { 12958ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik obtainMessage(what, obj).sendToTarget(); 12968ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 12978ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik 12988ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik public void post(int what, Object obj, Bundle data) { 12998ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik Message msg = obtainMessage(what, obj); 13008ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik msg.setData(data); 13018ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik msg.sendToTarget(); 13028ae0f34db936a649ddaf9cdd086c224f6514efebRoboErik } 130301fe661ae5da3739215d93922412df4b24c859a2RoboErik } 130401fe661ae5da3739215d93922412df4b24c859a2RoboErik 130501fe661ae5da3739215d93922412df4b24c859a2RoboErik} 1306