1f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock/* 2f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Copyright (C) 2015 The Android Open Source Project 3f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * 4f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 5f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * you may not use this file except in compliance with the License. 6f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * You may obtain a copy of the License at 7f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * 8f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * http://www.apache.org/licenses/LICENSE-2.0 9f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * 10f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Unless required by applicable law or agreed to in writing, software 11f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 12f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * See the License for the specific language governing permissions and 14f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * limitations under the License. 15f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock */ 16f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 17f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockpackage com.android.systemui.volume; 18f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 19f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.app.PendingIntent; 20f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.Context; 21f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.Intent; 22f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.pm.ApplicationInfo; 23f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.pm.PackageManager; 24f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.pm.PackageManager.NameNotFoundException; 25f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.content.pm.ResolveInfo; 26f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.IRemoteVolumeController; 27f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.MediaMetadata; 28f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.ISessionController; 29f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaController; 30f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaController.PlaybackInfo; 31f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaSession.QueueItem; 32f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaSession.Token; 33f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaSessionManager; 34f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.MediaSessionManager.OnActiveSessionsChangedListener; 35f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.media.session.PlaybackState; 36f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Bundle; 37f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Handler; 38f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Looper; 39f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.Message; 40f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.os.RemoteException; 41f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport android.util.Log; 42f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 43f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.io.PrintWriter; 44f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.io.StringWriter; 45f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.HashMap; 46f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.HashSet; 47f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.List; 48f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.Map; 49f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.Objects; 50f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockimport java.util.Set; 51f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 52f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock/** 53f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * Convenience client for all media session updates. Provides a callback interface for events 54f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock * related to remote media sessions. 55f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock */ 56f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlockpublic class MediaSessions { 57f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private static final String TAG = Util.logTag(MediaSessions.class); 58f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 59f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private static final boolean USE_SERVICE_LABEL = false; 60f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 61f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final Context mContext; 62f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final H mHandler; 63f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final MediaSessionManager mMgr; 64f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final Map<Token, MediaControllerRecord> mRecords = new HashMap<>(); 65f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final Callbacks mCallbacks; 66f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 67f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private boolean mInit; 68f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 69f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public MediaSessions(Context context, Looper looper, Callbacks callbacks) { 70f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mContext = context; 71f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mHandler = new H(looper); 72f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mMgr = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE); 73f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mCallbacks = callbacks; 74f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 75f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 76f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void dump(PrintWriter writer) { 77f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(getClass().getSimpleName() + " state:"); 78f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.print(" mInit: "); writer.println(mInit); 79f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.print(" mRecords.size: "); writer.println(mRecords.size()); 80f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock int i = 0; 81f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock for (MediaControllerRecord r : mRecords.values()) { 82f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock dump(++i, writer, r.controller); 83f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 84f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 85f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 86f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void init() { 87f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, "init"); 88f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock // will throw if no permission 89f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mMgr.addOnActiveSessionsChangedListener(mSessionsListener, null, mHandler); 90f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mInit = true; 91f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock postUpdateSessions(); 92f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mMgr.setRemoteVolumeController(mRvc); 93f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 94f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 95f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock protected void postUpdateSessions() { 96f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (!mInit) return; 97f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mHandler.sendEmptyMessage(H.UPDATE_SESSIONS); 98f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 99f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 100f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void destroy() { 101f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, "destroy"); 102f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mInit = false; 103f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mMgr.removeOnActiveSessionsChangedListener(mSessionsListener); 104f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 105f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 106f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void setVolume(Token token, int level) { 107f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaControllerRecord r = mRecords.get(token); 108f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (r == null) { 109f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock Log.w(TAG, "setVolume: No record found for token " + token); 110f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock return; 111f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 112f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, "Setting level to " + level); 113f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock r.controller.setVolumeTo(level, 0); 114f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 115f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 116f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private void onRemoteVolumeChangedH(ISessionController session, int flags) { 117f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaController controller = new MediaController(mContext, session); 118f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, "remoteVolumeChangedH " + controller.getPackageName() + " " 119f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock + Util.audioManagerFlagsToString(flags)); 120f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final Token token = controller.getSessionToken(); 121f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mCallbacks.onRemoteVolumeChanged(token, flags); 122f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 123f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 124f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private void onUpdateRemoteControllerH(ISessionController session) { 125f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaController controller = session != null ? new MediaController(mContext, session) 126f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock : null; 127f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final String pkg = controller != null ? controller.getPackageName() : null; 128f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, "updateRemoteControllerH " + pkg); 129f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock // this may be our only indication that a remote session is changed, refresh 130f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock postUpdateSessions(); 131f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 132f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 133f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock protected void onActiveSessionsUpdatedH(List<MediaController> controllers) { 134f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, "onActiveSessionsUpdatedH n=" + controllers.size()); 135f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final Set<Token> toRemove = new HashSet<Token>(mRecords.keySet()); 136f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock for (MediaController controller : controllers) { 137f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final Token token = controller.getSessionToken(); 138f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final PlaybackInfo pi = controller.getPlaybackInfo(); 139f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock toRemove.remove(token); 140f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (!mRecords.containsKey(token)) { 141f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaControllerRecord r = new MediaControllerRecord(controller); 142f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock r.name = getControllerName(controller); 143f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mRecords.put(token, r); 144f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock controller.registerCallback(r, mHandler); 145f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 146f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaControllerRecord r = mRecords.get(token); 147f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final boolean remote = isRemote(pi); 148f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (remote) { 149f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock updateRemoteH(token, r.name, pi); 150f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock r.sentRemote = true; 151f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 152f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 153f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock for (Token t : toRemove) { 154f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaControllerRecord r = mRecords.get(t); 155f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock r.controller.unregisterCallback(r); 156f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mRecords.remove(t); 157f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, "Removing " + r.name + " sentRemote=" + r.sentRemote); 158f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (r.sentRemote) { 159f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mCallbacks.onRemoteRemoved(t); 160f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock r.sentRemote = false; 161f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 162f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 163f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 164f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 165f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private static boolean isRemote(PlaybackInfo pi) { 166f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock return pi != null && pi.getPlaybackType() == PlaybackInfo.PLAYBACK_TYPE_REMOTE; 167f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 168f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 169f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock protected String getControllerName(MediaController controller) { 170f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final PackageManager pm = mContext.getPackageManager(); 171f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final String pkg = controller.getPackageName(); 172f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock try { 173f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (USE_SERVICE_LABEL) { 174f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final List<ResolveInfo> ris = pm.queryIntentServices( 175f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock new Intent("android.media.MediaRouteProviderService").setPackage(pkg), 0); 176f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (ris != null) { 177f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock for (ResolveInfo ri : ris) { 178f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (ri.serviceInfo == null) continue; 179f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (pkg.equals(ri.serviceInfo.packageName)) { 180f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final String serviceLabel = 181f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock Objects.toString(ri.serviceInfo.loadLabel(pm), "").trim(); 182f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (serviceLabel.length() > 0) { 183f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock return serviceLabel; 184f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 185f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 186f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 187f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 188f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 189f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); 190f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final String appLabel = Objects.toString(ai.loadLabel(pm), "").trim(); 191f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (appLabel.length() > 0) { 192f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock return appLabel; 193f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 194f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } catch (NameNotFoundException e) { } 195f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock return pkg; 196f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 197f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 198f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private void updateRemoteH(Token token, String name, PlaybackInfo pi) { 199f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (mCallbacks != null) { 200f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mCallbacks.onRemoteUpdate(token, name, pi); 201f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 202f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 203f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 204f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private static void dump(int n, PrintWriter writer, MediaController c) { 205f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" Controller " + n + ": " + c.getPackageName()); 206f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final Bundle extras = c.getExtras(); 207f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final long flags = c.getFlags(); 208f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaMetadata mm = c.getMetadata(); 209f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final PlaybackInfo pi = c.getPlaybackInfo(); 210f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final PlaybackState playbackState = c.getPlaybackState(); 211f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final List<QueueItem> queue = c.getQueue(); 212f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final CharSequence queueTitle = c.getQueueTitle(); 213f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final int ratingType = c.getRatingType(); 214f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final PendingIntent sessionActivity = c.getSessionActivity(); 215f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 216f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" PlaybackState: " + Util.playbackStateToString(playbackState)); 217f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" PlaybackInfo: " + Util.playbackInfoToString(pi)); 218f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (mm != null) { 219f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" MediaMetadata.desc=" + mm.getDescription()); 220f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 221f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" RatingType: " + ratingType); 222f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" Flags: " + flags); 223f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (extras != null) { 224f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" Extras:"); 225f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock for (String key : extras.keySet()) { 226f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" " + key + "=" + extras.get(key)); 227f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 228f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 229f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (queueTitle != null) { 230f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" QueueTitle: " + queueTitle); 231f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 232f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (queue != null && !queue.isEmpty()) { 233f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" Queue:"); 234f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock for (QueueItem qi : queue) { 235f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" " + qi); 236f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 237f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 238f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (pi != null) { 239f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock writer.println(" sessionActivity: " + sessionActivity); 240f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 241f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 242f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 243f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public static void dumpMediaSessions(Context context) { 244f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final MediaSessionManager mgr = (MediaSessionManager) context 245f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock .getSystemService(Context.MEDIA_SESSION_SERVICE); 246f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock try { 247f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final List<MediaController> controllers = mgr.getActiveSessions(null); 248f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final int N = controllers.size(); 249f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, N + " controllers"); 250f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock for (int i = 0; i < N; i++) { 251f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final StringWriter sw = new StringWriter(); 252f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final PrintWriter pw = new PrintWriter(sw, true); 253f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock dump(i + 1, pw, controllers.get(i)); 254f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, sw.toString()); 255f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 256f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } catch (SecurityException e) { 257f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock Log.w(TAG, "Not allowed to get sessions", e); 258f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 259f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 260f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 261f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final class MediaControllerRecord extends MediaController.Callback { 262f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final MediaController controller; 263f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 264f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private boolean sentRemote; 265f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private String name; 266f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 267f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private MediaControllerRecord(MediaController controller) { 268f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock this.controller = controller; 269f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 270f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 271f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private String cb(String method) { 272f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock return method + " " + controller.getPackageName() + " "; 273f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 274f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 275f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 276f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onAudioInfoChanged(PlaybackInfo info) { 277f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onAudioInfoChanged") + Util.playbackInfoToString(info) 278f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock + " sentRemote=" + sentRemote); 279f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock final boolean remote = isRemote(info); 280f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (!remote && sentRemote) { 281f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mCallbacks.onRemoteRemoved(controller.getSessionToken()); 282f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock sentRemote = false; 283f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } else if (remote) { 284f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock updateRemoteH(controller.getSessionToken(), name, info); 285f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock sentRemote = true; 286f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 287f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 288f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 289f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 290f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onExtrasChanged(Bundle extras) { 291f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onExtrasChanged") + extras); 292f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 293f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 294f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 295f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onMetadataChanged(MediaMetadata metadata) { 296f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onMetadataChanged") + Util.mediaMetadataToString(metadata)); 297f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 298f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 299f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 300f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onPlaybackStateChanged(PlaybackState state) { 301f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onPlaybackStateChanged") + Util.playbackStateToString(state)); 302f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 303f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 304f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 305f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onQueueChanged(List<QueueItem> queue) { 306f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onQueueChanged") + queue); 307f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 308f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 309f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 310f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onQueueTitleChanged(CharSequence title) { 311f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onQueueTitleChanged") + title); 312f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 313f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 314f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 315f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onSessionDestroyed() { 316f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onSessionDestroyed")); 317f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 318f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 319f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 320f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onSessionEvent(String event, Bundle extras) { 321f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock if (D.BUG) Log.d(TAG, cb("onSessionEvent") + "event=" + event + " extras=" + extras); 322f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 323f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 324f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 325f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final OnActiveSessionsChangedListener mSessionsListener = 326f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock new OnActiveSessionsChangedListener() { 327f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 328f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void onActiveSessionsChanged(List<MediaController> controllers) { 329f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock onActiveSessionsUpdatedH(controllers); 330f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 331f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock }; 332f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 333f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final IRemoteVolumeController mRvc = new IRemoteVolumeController.Stub() { 334f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 335f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void remoteVolumeChanged(ISessionController session, int flags) 336f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock throws RemoteException { 337f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mHandler.obtainMessage(H.REMOTE_VOLUME_CHANGED, flags, 0, session).sendToTarget(); 338f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 339f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 340f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 341f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void updateRemoteController(final ISessionController session) 342f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock throws RemoteException { 343f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock mHandler.obtainMessage(H.UPDATE_REMOTE_CONTROLLER, session).sendToTarget(); 344f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 345f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock }; 346f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 347f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private final class H extends Handler { 348f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private static final int UPDATE_SESSIONS = 1; 349f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private static final int REMOTE_VOLUME_CHANGED = 2; 350f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private static final int UPDATE_REMOTE_CONTROLLER = 3; 351f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 352f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock private H(Looper looper) { 353f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock super(looper); 354f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 355f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 356f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock @Override 357f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public void handleMessage(Message msg) { 358f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock switch (msg.what) { 359f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock case UPDATE_SESSIONS: 360f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock onActiveSessionsUpdatedH(mMgr.getActiveSessions(null)); 361f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock break; 362f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock case REMOTE_VOLUME_CHANGED: 363f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock onRemoteVolumeChangedH((ISessionController) msg.obj, msg.arg1); 364f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock break; 365f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock case UPDATE_REMOTE_CONTROLLER: 366f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock onUpdateRemoteControllerH((ISessionController) msg.obj); 367f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock break; 368f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 369f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 370f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 371f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 372f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock public interface Callbacks { 373f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock void onRemoteUpdate(Token token, String name, PlaybackInfo pi); 374f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock void onRemoteRemoved(Token t); 375f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock void onRemoteVolumeChanged(Token token, int flags); 376f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock } 377f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock 378f88d8082a86bee00c604cbbcfb5261f5573936feJohn Spurlock} 379