From b3658569e9a87afe1b3168837cc282235fd4d1f8 Mon Sep 17 00:00:00 2001 From: Sungsoo Date: Mon, 22 May 2017 17:10:44 +0900 Subject: [PATCH] Restore the selected route when an app starts to make sound Limitation: When two apps make sound simultaneously while one uses a BT route and the other uses the default route, switching activities between the two different apps will not change the BT A2DP status until one of the apps changes its playback status to inactive. Bug: 32958908, Bug: 35567695, Bug: 33186346 Test: Passed MediaRouter/MediaSession test, and manually varified that the b/33186346 is fixed. Change-Id: I1da97dcb74fa2095425b311ad62cdd00f8118cea --- .../android/media/IMediaRouterClient.aidl | 1 + .../android/media/IMediaRouterService.aidl | 1 + media/java/android/media/MediaRouter.java | 75 ++++++++--- .../server/media/AudioPlaybackMonitor.java | 124 +++++++++++++++--- .../server/media/MediaRouterService.java | 118 ++++++++++++++++- .../server/media/MediaSessionService.java | 23 ++-- 6 files changed, 288 insertions(+), 54 deletions(-) diff --git a/media/java/android/media/IMediaRouterClient.aidl b/media/java/android/media/IMediaRouterClient.aidl index 9640dcbd6518a..08344f188098f 100644 --- a/media/java/android/media/IMediaRouterClient.aidl +++ b/media/java/android/media/IMediaRouterClient.aidl @@ -21,4 +21,5 @@ package android.media; */ oneway interface IMediaRouterClient { void onStateChanged(); + void onRestoreRoute(); } diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index f8f5fdfd2d62f..3308fc929b035 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -27,6 +27,7 @@ interface IMediaRouterService { void unregisterClient(IMediaRouterClient client); MediaRouterClientState getState(IMediaRouterClient client); + boolean isPlaybackActive(IMediaRouterClient client); void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan); void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit); diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index d5509c14e09b4..cff7043f0fa26 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -88,6 +88,7 @@ public class MediaRouter { RouteInfo mBluetoothA2dpRoute; RouteInfo mSelectedRoute; + RouteInfo mSystemAudioRoute; final boolean mCanConfigureWifiDisplays; boolean mActivelyScanningWifiDisplays; @@ -149,6 +150,7 @@ public class MediaRouter { } addRouteStatic(mDefaultAudioVideo); + mSystemAudioRoute = mDefaultAudioVideo; // This will select the active wifi display route if there is one. updateWifiDisplayStatus(mDisplayService.getWifiDisplayStatus()); @@ -197,8 +199,8 @@ public class MediaRouter { } else { name = com.android.internal.R.string.default_audio_route_name; } - sStatic.mDefaultAudioVideo.mNameResId = name; - dispatchRouteChanged(sStatic.mDefaultAudioVideo); + mDefaultAudioVideo.mNameResId = name; + dispatchRouteChanged(mDefaultAudioVideo); updated = true; } @@ -207,22 +209,28 @@ public class MediaRouter { if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) { mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName; if (mCurAudioRoutesInfo.bluetoothName != null) { - if (sStatic.mBluetoothA2dpRoute == null) { - final RouteInfo info = new RouteInfo(sStatic.mSystemCategory); + if (mBluetoothA2dpRoute == null) { + // BT connected + final RouteInfo info = new RouteInfo(mSystemCategory); info.mName = mCurAudioRoutesInfo.bluetoothName; - info.mDescription = sStatic.mResources.getText( + info.mDescription = mResources.getText( com.android.internal.R.string.bluetooth_a2dp_audio_route_name); info.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO; info.mDeviceType = RouteInfo.DEVICE_TYPE_BLUETOOTH; - sStatic.mBluetoothA2dpRoute = info; - addRouteStatic(sStatic.mBluetoothA2dpRoute); + mBluetoothA2dpRoute = info; + addRouteStatic(mBluetoothA2dpRoute); + mSystemAudioRoute = mBluetoothA2dpRoute; + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false); } else { - sStatic.mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.bluetoothName; - dispatchRouteChanged(sStatic.mBluetoothA2dpRoute); + mBluetoothA2dpRoute.mName = mCurAudioRoutesInfo.bluetoothName; + dispatchRouteChanged(mBluetoothA2dpRoute); } - } else if (sStatic.mBluetoothA2dpRoute != null) { - removeRouteStatic(sStatic.mBluetoothA2dpRoute); - sStatic.mBluetoothA2dpRoute = null; + } else if (mBluetoothA2dpRoute != null) { + // BT disconnected + removeRouteStatic(mBluetoothA2dpRoute); + mBluetoothA2dpRoute = null; + mSystemAudioRoute = mDefaultAudioVideo; + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mSystemAudioRoute, false); } updated = true; } @@ -230,11 +238,13 @@ public class MediaRouter { if (mBluetoothA2dpRoute != null) { final boolean a2dpEnabled = isBluetoothA2dpOn(); if (mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false); + // A2DP off + mSystemAudioRoute = mDefaultAudioVideo; updated = true; } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) && a2dpEnabled) { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute, false); + // A2DP on or BT connected + mSystemAudioRoute = mBluetoothA2dpRoute; updated = true; } } @@ -471,7 +481,7 @@ public class MediaRouter { } RouteInfo makeGlobalRoute(MediaRouterClientState.RouteInfo globalRoute) { - RouteInfo route = new RouteInfo(sStatic.mSystemCategory); + RouteInfo route = new RouteInfo(mSystemCategory); route.mGlobalRouteId = globalRoute.id; route.mName = globalRoute.name; route.mDescription = globalRoute.description; @@ -567,6 +577,17 @@ public class MediaRouter { return null; } + boolean isPlaybackActive() { + if (mClient != null) { + try { + return mMediaRouterService.isPlaybackActive(mClient); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to retrieve playback active state.", ex); + } + } + return false; + } + final class Client extends IMediaRouterClient.Stub { @Override public void onStateChanged() { @@ -579,6 +600,19 @@ public class MediaRouter { } }); } + + @Override + public void onRestoreRoute() { + if ((mSelectedRoute != mDefaultAudioVideo && mSelectedRoute != mBluetoothA2dpRoute) + || mSelectedRoute == mSystemAudioRoute) { + return; + } + try { + sStatic.mAudioService.setBluetoothA2dpOn(mSelectedRoute == mBluetoothA2dpRoute); + } catch (RemoteException e) { + Log.e(TAG, "Error changing Bluetooth A2DP state", e); + } + } } } @@ -900,7 +934,12 @@ public class MediaRouter { Log.v(TAG, "Selecting route: " + route); assert(route != null); final RouteInfo oldRoute = sStatic.mSelectedRoute; - if (oldRoute == route) return; + boolean wasDefaultOrBluetoothRoute = (oldRoute == sStatic.mDefaultAudioVideo + || oldRoute == sStatic.mBluetoothA2dpRoute); + if (oldRoute == route + && (!wasDefaultOrBluetoothRoute || oldRoute == sStatic.mSystemAudioRoute)) { + return; + } if (!route.matchesTypes(types)) { Log.w(TAG, "selectRoute ignored; cannot select route with supported types " + typesToString(route.getSupportedTypes()) + " into route types " + @@ -909,8 +948,8 @@ public class MediaRouter { } final RouteInfo btRoute = sStatic.mBluetoothA2dpRoute; - if (btRoute != null && (types & ROUTE_TYPE_LIVE_AUDIO) != 0 && - (route == btRoute || route == sStatic.mDefaultAudioVideo)) { + if (sStatic.isPlaybackActive() && btRoute != null && (types & ROUTE_TYPE_LIVE_AUDIO) != 0 + && (route == btRoute || route == sStatic.mDefaultAudioVideo)) { try { sStatic.mAudioService.setBluetoothA2dpOn(route == btRoute); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/media/AudioPlaybackMonitor.java b/services/core/java/com/android/server/media/AudioPlaybackMonitor.java index c6dc11c53393f..f6f767653c832 100644 --- a/services/core/java/com/android/server/media/AudioPlaybackMonitor.java +++ b/services/core/java/com/android/server/media/AudioPlaybackMonitor.java @@ -31,17 +31,22 @@ import android.util.SparseArray; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; /** - * Monitors changes in audio playback and notify the newly started audio playback through the - * {@link OnAudioPlaybackStartedListener}. + * Monitors changes in audio playback, and notify the newly started audio playback through the + * {@link OnAudioPlaybackStartedListener} and the activeness change through the + * {@link OnAudioPlaybackActiveStateListener}. */ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub { private static boolean DEBUG = MediaSessionService.DEBUG; private static String TAG = "AudioPlaybackMonitor"; + private static AudioPlaybackMonitor sInstance; + /** * Called when audio playback is started for a given UID. */ @@ -49,22 +54,36 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub { void onAudioPlaybackStarted(int uid); } + /** + * Called when audio player state is changed. + */ + interface OnAudioPlayerActiveStateChangedListener { + void onAudioPlayerActiveStateChanged(int uid, boolean active); + } + private final Object mLock = new Object(); private final Context mContext; - private final OnAudioPlaybackStartedListener mListener; - - private Set mActiveAudioPlaybackPlayerInterfaceIds = new HashSet<>(); - private Set mActiveAudioPlaybackClientUids = new HashSet<>(); + private final List mAudioPlaybackStartedListeners + = new ArrayList<>(); + private final List + mAudioPlayerActiveStateChangedListeners = new ArrayList<>(); + private final Map mAudioPlaybackStates = new HashMap<>(); + private final Set mActiveAudioPlaybackClientUids = new HashSet<>(); // Sorted array of UIDs that had active audio playback. (i.e. playing an audio/video) // The UID whose audio playback becomes active at the last comes first. // TODO(b/35278867): Find and use unique identifier for apps because apps may share the UID. private final IntArray mSortedAudioPlaybackClientUids = new IntArray(); - AudioPlaybackMonitor(Context context, IAudioService audioService, - OnAudioPlaybackStartedListener listener) { + static AudioPlaybackMonitor getInstance(Context context, IAudioService audioService) { + if (sInstance == null) { + sInstance = new AudioPlaybackMonitor(context, audioService); + } + return sInstance; + } + + private AudioPlaybackMonitor(Context context, IAudioService audioService) { mContext = context; - mListener = listener; try { audioService.registerPlaybackCallback(this); } catch (RemoteException e) { @@ -84,9 +103,12 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub { public void dispatchPlaybackConfigChange(List configs) { final long token = Binder.clearCallingIdentity(); try { - Set newActiveAudioPlaybackPlayerInterfaceIds = new HashSet<>(); List newActiveAudioPlaybackClientUids = new ArrayList<>(); + List audioPlayerActiveStateChangedListeners; + List audioPlaybackStartedListeners; synchronized (mLock) { + // Update mActiveAudioPlaybackClientUids and mSortedAudioPlaybackClientUids, + // and find newly activated audio playbacks. mActiveAudioPlaybackClientUids.clear(); for (AudioPlaybackConfiguration config : configs) { // Ignore inactive (i.e. not playing) or PLAYER_TYPE_JAM_SOUNDPOOL @@ -94,16 +116,14 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub { // playback. // Note that we shouldn't ignore PLAYER_TYPE_UNKNOWN because it might be OEM // specific audio/video players. - if (!config.isActive() - || config.getPlayerType() + if (!config.isActive() || config.getPlayerType() == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) { continue; } - mActiveAudioPlaybackClientUids.add(config.getClientUid()); - newActiveAudioPlaybackPlayerInterfaceIds.add(config.getPlayerInterfaceId()); - if (!mActiveAudioPlaybackPlayerInterfaceIds.contains( - config.getPlayerInterfaceId())) { + mActiveAudioPlaybackClientUids.add(config.getClientUid()); + Integer oldState = mAudioPlaybackStates.get(config.getPlayerInterfaceId()); + if (!isActiveState(oldState)) { if (DEBUG) { Log.d(TAG, "Found a new active media playback. " + AudioPlaybackConfiguration.toLogFriendlyString(config)); @@ -120,17 +140,76 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub { mSortedAudioPlaybackClientUids.add(0, config.getClientUid()); } } - mActiveAudioPlaybackPlayerInterfaceIds.clear(); - mActiveAudioPlaybackPlayerInterfaceIds = newActiveAudioPlaybackPlayerInterfaceIds; + audioPlayerActiveStateChangedListeners = new ArrayList<>( + mAudioPlayerActiveStateChangedListeners); + audioPlaybackStartedListeners = new ArrayList<>(mAudioPlaybackStartedListeners); } + // Notify the change of audio playback states. + for (AudioPlaybackConfiguration config : configs) { + boolean wasActive = isActiveState( + mAudioPlaybackStates.get(config.getPlayerInterfaceId())); + boolean isActive = config.isActive(); + if (wasActive != isActive) { + for (OnAudioPlayerActiveStateChangedListener listener + : audioPlayerActiveStateChangedListeners) { + listener.onAudioPlayerActiveStateChanged(config.getClientUid(), + isActive); + } + } + } + // Notify the start of audio playback for (int uid : newActiveAudioPlaybackClientUids) { - mListener.onAudioPlaybackStarted(uid); + for (OnAudioPlaybackStartedListener listener : audioPlaybackStartedListeners) { + listener.onAudioPlaybackStarted(uid); + } + } + mAudioPlaybackStates.clear(); + for (AudioPlaybackConfiguration config : configs) { + mAudioPlaybackStates.put(config.getPlayerInterfaceId(), config.getPlayerState()); } } finally { Binder.restoreCallingIdentity(token); } } + /** + * Registers OnAudioPlaybackStartedListener. + */ + public void registerOnAudioPlaybackStartedListener(OnAudioPlaybackStartedListener listener) { + synchronized (mLock) { + mAudioPlaybackStartedListeners.add(listener); + } + } + + /** + * Unregisters OnAudioPlaybackStartedListener. + */ + public void unregisterOnAudioPlaybackStartedListener(OnAudioPlaybackStartedListener listener) { + synchronized (mLock) { + mAudioPlaybackStartedListeners.remove(listener); + } + } + + /** + * Registers OnAudioPlayerActiveStateChangedListener. + */ + public void registerOnAudioPlayerActiveStateChangedListener( + OnAudioPlayerActiveStateChangedListener listener) { + synchronized (mLock) { + mAudioPlayerActiveStateChangedListeners.add(listener); + } + } + + /** + * Unregisters OnAudioPlayerActiveStateChangedListener. + */ + public void unregisterOnAudioPlayerActiveStateChangedListener( + OnAudioPlayerActiveStateChangedListener listener) { + synchronized (mLock) { + mAudioPlayerActiveStateChangedListeners.remove(listener); + } + } + /** * Returns the sorted list of UIDs that have had active audio playback. (i.e. playing an * audio/video) The UID whose audio playback becomes active at the last comes first. @@ -167,7 +246,8 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub { if (mSortedAudioPlaybackClientUids.get(i) == mediaButtonSessionUid) { break; } - if (userId == UserHandle.getUserId(mSortedAudioPlaybackClientUids.get(i))) { + int uid = mSortedAudioPlaybackClientUids.get(i); + if (userId == UserHandle.getUserId(uid) && !isPlaybackActive(uid)) { // Clean up unnecessary UIDs. // It doesn't need to be managed profile aware because it's just to prevent // the list from increasing indefinitely. The media button session updating @@ -198,4 +278,8 @@ class AudioPlaybackMonitor extends IPlaybackConfigDispatcher.Stub { } } } + + private boolean isActiveState(Integer state) { + return state != null && state.equals(AudioPlaybackConfiguration.PLAYER_STATE_STARTED); + } } diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index d1fa5efe4dc1f..5ba8f4853407c 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -18,6 +18,7 @@ package com.android.server.media; import com.android.internal.util.DumpUtils; import com.android.server.Watchdog; +import com.android.server.media.AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener; import android.Manifest; import android.app.ActivityManager; @@ -26,7 +27,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.media.AudioRoutesInfo; import android.media.AudioSystem; +import android.media.IAudioRoutesObserver; +import android.media.IAudioService; import android.media.IMediaRouterClient; import android.media.IMediaRouterService; import android.media.MediaRouter; @@ -39,9 +43,12 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; +import android.os.UserHandle; import android.text.TextUtils; import android.util.ArrayMap; +import android.util.IntArray; import android.util.Log; import android.util.Slog; import android.util.SparseArray; @@ -89,10 +96,54 @@ public final class MediaRouterService extends IMediaRouterService.Stub private final ArrayMap mAllClientRecords = new ArrayMap(); private int mCurrentUserId = -1; + private boolean mHasBluetoothRoute = false; + private final IAudioService mAudioService; + private final AudioPlaybackMonitor mAudioPlaybackMonitor; public MediaRouterService(Context context) { mContext = context; Watchdog.getInstance().addMonitor(this); + + mAudioService = IAudioService.Stub.asInterface( + ServiceManager.getService(Context.AUDIO_SERVICE)); + + mAudioPlaybackMonitor = AudioPlaybackMonitor.getInstance(context, mAudioService); + mAudioPlaybackMonitor.registerOnAudioPlayerActiveStateChangedListener( + new AudioPlaybackMonitor.OnAudioPlayerActiveStateChangedListener() { + @Override + public void onAudioPlayerActiveStateChanged(int uid, boolean active) { + if (active) { + restoreRoute(uid); + } else { + IntArray sortedAudioPlaybackClientUids = + mAudioPlaybackMonitor.getSortedAudioPlaybackClientUids(); + boolean restored = false; + for (int i = 0; i < sortedAudioPlaybackClientUids.size(); i++) { + if (mAudioPlaybackMonitor.isPlaybackActive( + sortedAudioPlaybackClientUids.get(i))) { + restoreRoute(sortedAudioPlaybackClientUids.get(i)); + restored = true; + break; + } + } + if (!restored) { + restoreBluetoothA2dp(); + } + } + } + }); + AudioRoutesInfo audioRoutes = null; + try { + audioRoutes = mAudioService.startWatchingRoutes(new IAudioRoutesObserver.Stub() { + @Override + public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) { + mHasBluetoothRoute = newRoutes.bluetoothName != null; + } + }); + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException in the audio service."); + } + mHasBluetoothRoute = (audioRoutes != null && audioRoutes.bluetoothName != null); } public void systemRunning() { @@ -135,7 +186,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { - registerClientLocked(client, pid, packageName, resolvedUserId, trusted); + registerClientLocked(client, uid, pid, packageName, resolvedUserId, trusted); } } finally { Binder.restoreCallingIdentity(token); @@ -176,6 +227,23 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } + // Binder call + @Override + public boolean isPlaybackActive(IMediaRouterClient client) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + return isPlaybackActiveLocked(client); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + // Binder call @Override public void setDiscoveryRequest(IMediaRouterClient client, @@ -276,6 +344,36 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } + void restoreBluetoothA2dp() { + try { + mAudioService.setBluetoothA2dpOn(mHasBluetoothRoute); + } catch (RemoteException e) { + Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn."); + } + } + + void restoreRoute(int uid) { + ClientRecord clientRecord = null; + UserRecord userRecord = mUserRecords.get(UserHandle.getUserId(uid)); + if (userRecord.mClientRecords != null) { + for (ClientRecord cr : userRecord.mClientRecords) { + if (validatePackageName(uid, cr.mPackageName)) { + clientRecord = cr; + break; + } + } + } + if (clientRecord != null) { + try { + clientRecord.mClient.onRestoreRoute(); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onRestoreRoute. Client probably died."); + } + } else { + restoreBluetoothA2dp(); + } + } + void switchUser() { synchronized (mLock) { int userId = ActivityManager.getCurrentUser(); @@ -304,7 +402,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub } private void registerClientLocked(IMediaRouterClient client, - int pid, String packageName, int userId, boolean trusted) { + int uid, int pid, String packageName, int userId, boolean trusted) { final IBinder binder = client.asBinder(); ClientRecord clientRecord = mAllClientRecords.get(binder); if (clientRecord == null) { @@ -314,7 +412,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub userRecord = new UserRecord(userId); newUser = true; } - clientRecord = new ClientRecord(userRecord, client, pid, packageName, trusted); + clientRecord = new ClientRecord(userRecord, client, uid, pid, packageName, trusted); try { binder.linkToDeath(clientRecord, 0); } catch (RemoteException ex) { @@ -350,6 +448,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub return null; } + private boolean isPlaybackActiveLocked(IMediaRouterClient client) { + ClientRecord clientRecord = mAllClientRecords.get(client.asBinder()); + if (clientRecord != null) { + return mAudioPlaybackMonitor.isPlaybackActive(clientRecord.mUid); + } + return false; + } + private void setDiscoveryRequestLocked(IMediaRouterClient client, int routeTypes, boolean activeScan) { final IBinder binder = client.asBinder(); @@ -489,6 +595,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub final class ClientRecord implements DeathRecipient { public final UserRecord mUserRecord; public final IMediaRouterClient mClient; + public final int mUid; public final int mPid; public final String mPackageName; public final boolean mTrusted; @@ -498,9 +605,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub public String mSelectedRouteId; public ClientRecord(UserRecord userRecord, IMediaRouterClient client, - int pid, String packageName, boolean trusted) { + int uid, int pid, String packageName, boolean trusted) { mUserRecord = userRecord; mClient = client; + mUid = uid; mPid = pid; mPackageName = packageName; mTrusted = trusted; @@ -997,7 +1105,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub try { mTempClients.get(i).onStateChanged(); } catch (RemoteException ex) { - // ignore errors, client probably died + Slog.w(TAG, "Failed to call onStateChanged. Client probably died."); } } } finally { diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 38c615791d9f0..adb50f0f16099 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -138,19 +138,20 @@ public class MediaSessionService extends SystemService implements Monitor { mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE); mAudioService = getAudioService(); - mAudioPlaybackMonitor = new AudioPlaybackMonitor(getContext(), mAudioService, + mAudioPlaybackMonitor = AudioPlaybackMonitor.getInstance(getContext(), mAudioService); + mAudioPlaybackMonitor.registerOnAudioPlaybackStartedListener( new AudioPlaybackMonitor.OnAudioPlaybackStartedListener() { - @Override - public void onAudioPlaybackStarted(int uid) { - synchronized (mLock) { - FullUserRecord user = - getFullUserRecordLocked(UserHandle.getUserId(uid)); - if (user != null) { - user.mPriorityStack.updateMediaButtonSessionIfNeeded(); - } - } + @Override + public void onAudioPlaybackStarted(int uid) { + synchronized (mLock) { + FullUserRecord user = + getFullUserRecordLocked(UserHandle.getUserId(uid)); + if (user != null) { + user.mPriorityStack.updateMediaButtonSessionIfNeeded(); } - }); + } + } + }); mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mContentResolver = getContext().getContentResolver(); mSettingsObserver = new SettingsObserver();