Loading services/core/java/com/android/server/media/AudioPlayerStateMonitor.java +74 −99 Original line number Diff line number Diff line Loading @@ -18,14 +18,11 @@ package com.android.server.media; import android.annotation.NonNull; import android.content.Context; import android.media.AudioManager; import android.media.AudioPlaybackConfiguration; import android.media.IAudioService; import android.media.IPlaybackConfigDispatcher; import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; Loading @@ -42,11 +39,11 @@ import java.util.Set; /** * Monitors the state changes of audio players. */ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { class AudioPlayerStateMonitor { private static boolean DEBUG = MediaSessionService.DEBUG; private static String TAG = "AudioPlayerStateMonitor"; private static AudioPlayerStateMonitor sInstance = new AudioPlayerStateMonitor(); private static AudioPlayerStateMonitor sInstance; /** * Listener for handling the active state changes of audio players. Loading Loading @@ -96,94 +93,31 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { private final Map<OnAudioPlayerActiveStateChangedListener, MessageHandler> mListenerMap = new ArrayMap<>(); @GuardedBy("mLock") private final Set<Integer> mActiveAudioUids = new ArraySet<>(); @SuppressWarnings("WeakerAccess") /* synthetic access */ final Set<Integer> mActiveAudioUids = new ArraySet<>(); @GuardedBy("mLock") private ArrayMap<Integer, AudioPlaybackConfiguration> mPrevActiveAudioPlaybackConfigs = @SuppressWarnings("WeakerAccess") /* synthetic access */ ArrayMap<Integer, AudioPlaybackConfiguration> mPrevActiveAudioPlaybackConfigs = new ArrayMap<>(); // 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. @GuardedBy("mLock") private final IntArray mSortedAudioPlaybackClientUids = new IntArray(); @SuppressWarnings("WeakerAccess") /* synthetic access */ final IntArray mSortedAudioPlaybackClientUids = new IntArray(); @GuardedBy("mLock") private boolean mRegisteredToAudioService; static AudioPlayerStateMonitor getInstance() { return sInstance; } private AudioPlayerStateMonitor() { } /** * Called when the {@link AudioPlaybackConfiguration} is updated. * <p>If an app starts audio playback, the app's local media session will be the media button * session. If the app has multiple media sessions, the playback active local session will be * picked. * * @param configs List of the current audio playback configuration */ @Override public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs, boolean flush) { if (flush) { Binder.flushPendingCommands(); } final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { // Update mActiveAudioUids mActiveAudioUids.clear(); ArrayMap<Integer, AudioPlaybackConfiguration> activeAudioPlaybackConfigs = new ArrayMap<>(); for (AudioPlaybackConfiguration config : configs) { if (config.isActive()) { mActiveAudioUids.add(config.getClientUid()); activeAudioPlaybackConfigs.put(config.getPlayerInterfaceId(), config); } } // Update mSortedAuioPlaybackClientUids. for (int i = 0; i < activeAudioPlaybackConfigs.size(); ++i) { AudioPlaybackConfiguration config = activeAudioPlaybackConfigs.valueAt(i); final int uid = config.getClientUid(); if (!mPrevActiveAudioPlaybackConfigs.containsKey( config.getPlayerInterfaceId())) { if (DEBUG) { Log.d(TAG, "Found a new active media playback. " + AudioPlaybackConfiguration.toLogFriendlyString(config)); } // New active audio playback. int index = mSortedAudioPlaybackClientUids.indexOf(uid); if (index == 0) { // It's the lastly played music app already. Skip updating. continue; } else if (index > 0) { mSortedAudioPlaybackClientUids.remove(index); } mSortedAudioPlaybackClientUids.add(0, uid); } } // Notify the active state change of audio players. for (AudioPlaybackConfiguration config : configs) { final int pii = config.getPlayerInterfaceId(); boolean wasActive = mPrevActiveAudioPlaybackConfigs.remove(pii) != null; if (wasActive != config.isActive()) { sendAudioPlayerActiveStateChangedMessageLocked( config, /* isRemoved */ false); static AudioPlayerStateMonitor getInstance(Context context) { synchronized (AudioPlayerStateMonitor.class) { if (sInstance == null) { sInstance = new AudioPlayerStateMonitor(context); } return sInstance; } for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) { sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true); } // Update mPrevActiveAudioPlaybackConfigs mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs; } } finally { Binder.restoreCallingIdentity(token); } private AudioPlayerStateMonitor(Context context) { AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); am.registerAudioPlaybackCallback(new AudioManagerPlaybackListener(), null); } /** Loading Loading @@ -275,25 +209,66 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { } } public void registerSelfIntoAudioServiceIfNeeded(IAudioService audioService) { @GuardedBy("mLock") private void sendAudioPlayerActiveStateChangedMessageLocked( final AudioPlaybackConfiguration config, final boolean isRemoved) { for (MessageHandler messageHandler : mListenerMap.values()) { messageHandler.sendAudioPlayerActiveStateChangedMessage(config, isRemoved); } } private class AudioManagerPlaybackListener extends AudioManager.AudioPlaybackCallback { @Override public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) { synchronized (mLock) { try { if (!mRegisteredToAudioService) { audioService.registerPlaybackCallback(this); mRegisteredToAudioService = true; // Update mActiveAudioUids mActiveAudioUids.clear(); ArrayMap<Integer, AudioPlaybackConfiguration> activeAudioPlaybackConfigs = new ArrayMap<>(); for (AudioPlaybackConfiguration config : configs) { if (config.isActive()) { mActiveAudioUids.add(config.getClientUid()); activeAudioPlaybackConfigs.put(config.getPlayerInterfaceId(), config); } } // Update mSortedAuioPlaybackClientUids. for (int i = 0; i < activeAudioPlaybackConfigs.size(); ++i) { AudioPlaybackConfiguration config = activeAudioPlaybackConfigs.valueAt(i); final int uid = config.getClientUid(); if (!mPrevActiveAudioPlaybackConfigs.containsKey( config.getPlayerInterfaceId())) { if (DEBUG) { Log.d(TAG, "Found a new active media playback. " + AudioPlaybackConfiguration.toLogFriendlyString(config)); } } catch (RemoteException e) { Log.wtf(TAG, "Failed to register playback callback", e); mRegisteredToAudioService = false; // New active audio playback. int index = mSortedAudioPlaybackClientUids.indexOf(uid); if (index == 0) { // It's the lastly played music app already. Skip updating. continue; } else if (index > 0) { mSortedAudioPlaybackClientUids.remove(index); } mSortedAudioPlaybackClientUids.add(0, uid); } } // Notify the active state change of audio players. for (AudioPlaybackConfiguration config : configs) { final int pii = config.getPlayerInterfaceId(); boolean wasActive = mPrevActiveAudioPlaybackConfigs.remove(pii) != null; if (wasActive != config.isActive()) { sendAudioPlayerActiveStateChangedMessageLocked( config, /* isRemoved */ false); } } for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) { sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true); } @GuardedBy("mLock") private void sendAudioPlayerActiveStateChangedMessageLocked( final AudioPlaybackConfiguration config, final boolean isRemoved) { for (MessageHandler messageHandler : mListenerMap.values()) { messageHandler.sendAudioPlayerActiveStateChangedMessage(config, isRemoved); // Update mPrevActiveAudioPlaybackConfigs mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs; } } } } services/core/java/com/android/server/media/MediaRouterService.java +1 −2 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub mAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context); mAudioPlayerStateMonitor.registerListener( new AudioPlayerStateMonitor.OnAudioPlayerActiveStateChangedListener() { static final long WAIT_MS = 500; Loading Loading @@ -168,7 +168,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } }, mHandler); mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService); AudioRoutesInfo audioRoutes = null; try { Loading services/core/java/com/android/server/media/MediaSessionServiceImpl.java +1 −2 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(mContext); mAudioPlayerStateMonitor.registerListener( (config, isRemoved) -> { if (isRemoved || !config.isActive() || config.getPlayerType() Loading @@ -183,7 +183,6 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { } } }, null /* handler */); mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService); mContentResolver = mContext.getContentResolver(); mSettingsObserver = new SettingsObserver(); mSettingsObserver.observe(); Loading Loading
services/core/java/com/android/server/media/AudioPlayerStateMonitor.java +74 −99 Original line number Diff line number Diff line Loading @@ -18,14 +18,11 @@ package com.android.server.media; import android.annotation.NonNull; import android.content.Context; import android.media.AudioManager; import android.media.AudioPlaybackConfiguration; import android.media.IAudioService; import android.media.IPlaybackConfigDispatcher; import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; Loading @@ -42,11 +39,11 @@ import java.util.Set; /** * Monitors the state changes of audio players. */ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { class AudioPlayerStateMonitor { private static boolean DEBUG = MediaSessionService.DEBUG; private static String TAG = "AudioPlayerStateMonitor"; private static AudioPlayerStateMonitor sInstance = new AudioPlayerStateMonitor(); private static AudioPlayerStateMonitor sInstance; /** * Listener for handling the active state changes of audio players. Loading Loading @@ -96,94 +93,31 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { private final Map<OnAudioPlayerActiveStateChangedListener, MessageHandler> mListenerMap = new ArrayMap<>(); @GuardedBy("mLock") private final Set<Integer> mActiveAudioUids = new ArraySet<>(); @SuppressWarnings("WeakerAccess") /* synthetic access */ final Set<Integer> mActiveAudioUids = new ArraySet<>(); @GuardedBy("mLock") private ArrayMap<Integer, AudioPlaybackConfiguration> mPrevActiveAudioPlaybackConfigs = @SuppressWarnings("WeakerAccess") /* synthetic access */ ArrayMap<Integer, AudioPlaybackConfiguration> mPrevActiveAudioPlaybackConfigs = new ArrayMap<>(); // 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. @GuardedBy("mLock") private final IntArray mSortedAudioPlaybackClientUids = new IntArray(); @SuppressWarnings("WeakerAccess") /* synthetic access */ final IntArray mSortedAudioPlaybackClientUids = new IntArray(); @GuardedBy("mLock") private boolean mRegisteredToAudioService; static AudioPlayerStateMonitor getInstance() { return sInstance; } private AudioPlayerStateMonitor() { } /** * Called when the {@link AudioPlaybackConfiguration} is updated. * <p>If an app starts audio playback, the app's local media session will be the media button * session. If the app has multiple media sessions, the playback active local session will be * picked. * * @param configs List of the current audio playback configuration */ @Override public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs, boolean flush) { if (flush) { Binder.flushPendingCommands(); } final long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { // Update mActiveAudioUids mActiveAudioUids.clear(); ArrayMap<Integer, AudioPlaybackConfiguration> activeAudioPlaybackConfigs = new ArrayMap<>(); for (AudioPlaybackConfiguration config : configs) { if (config.isActive()) { mActiveAudioUids.add(config.getClientUid()); activeAudioPlaybackConfigs.put(config.getPlayerInterfaceId(), config); } } // Update mSortedAuioPlaybackClientUids. for (int i = 0; i < activeAudioPlaybackConfigs.size(); ++i) { AudioPlaybackConfiguration config = activeAudioPlaybackConfigs.valueAt(i); final int uid = config.getClientUid(); if (!mPrevActiveAudioPlaybackConfigs.containsKey( config.getPlayerInterfaceId())) { if (DEBUG) { Log.d(TAG, "Found a new active media playback. " + AudioPlaybackConfiguration.toLogFriendlyString(config)); } // New active audio playback. int index = mSortedAudioPlaybackClientUids.indexOf(uid); if (index == 0) { // It's the lastly played music app already. Skip updating. continue; } else if (index > 0) { mSortedAudioPlaybackClientUids.remove(index); } mSortedAudioPlaybackClientUids.add(0, uid); } } // Notify the active state change of audio players. for (AudioPlaybackConfiguration config : configs) { final int pii = config.getPlayerInterfaceId(); boolean wasActive = mPrevActiveAudioPlaybackConfigs.remove(pii) != null; if (wasActive != config.isActive()) { sendAudioPlayerActiveStateChangedMessageLocked( config, /* isRemoved */ false); static AudioPlayerStateMonitor getInstance(Context context) { synchronized (AudioPlayerStateMonitor.class) { if (sInstance == null) { sInstance = new AudioPlayerStateMonitor(context); } return sInstance; } for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) { sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true); } // Update mPrevActiveAudioPlaybackConfigs mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs; } } finally { Binder.restoreCallingIdentity(token); } private AudioPlayerStateMonitor(Context context) { AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); am.registerAudioPlaybackCallback(new AudioManagerPlaybackListener(), null); } /** Loading Loading @@ -275,25 +209,66 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { } } public void registerSelfIntoAudioServiceIfNeeded(IAudioService audioService) { @GuardedBy("mLock") private void sendAudioPlayerActiveStateChangedMessageLocked( final AudioPlaybackConfiguration config, final boolean isRemoved) { for (MessageHandler messageHandler : mListenerMap.values()) { messageHandler.sendAudioPlayerActiveStateChangedMessage(config, isRemoved); } } private class AudioManagerPlaybackListener extends AudioManager.AudioPlaybackCallback { @Override public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) { synchronized (mLock) { try { if (!mRegisteredToAudioService) { audioService.registerPlaybackCallback(this); mRegisteredToAudioService = true; // Update mActiveAudioUids mActiveAudioUids.clear(); ArrayMap<Integer, AudioPlaybackConfiguration> activeAudioPlaybackConfigs = new ArrayMap<>(); for (AudioPlaybackConfiguration config : configs) { if (config.isActive()) { mActiveAudioUids.add(config.getClientUid()); activeAudioPlaybackConfigs.put(config.getPlayerInterfaceId(), config); } } // Update mSortedAuioPlaybackClientUids. for (int i = 0; i < activeAudioPlaybackConfigs.size(); ++i) { AudioPlaybackConfiguration config = activeAudioPlaybackConfigs.valueAt(i); final int uid = config.getClientUid(); if (!mPrevActiveAudioPlaybackConfigs.containsKey( config.getPlayerInterfaceId())) { if (DEBUG) { Log.d(TAG, "Found a new active media playback. " + AudioPlaybackConfiguration.toLogFriendlyString(config)); } } catch (RemoteException e) { Log.wtf(TAG, "Failed to register playback callback", e); mRegisteredToAudioService = false; // New active audio playback. int index = mSortedAudioPlaybackClientUids.indexOf(uid); if (index == 0) { // It's the lastly played music app already. Skip updating. continue; } else if (index > 0) { mSortedAudioPlaybackClientUids.remove(index); } mSortedAudioPlaybackClientUids.add(0, uid); } } // Notify the active state change of audio players. for (AudioPlaybackConfiguration config : configs) { final int pii = config.getPlayerInterfaceId(); boolean wasActive = mPrevActiveAudioPlaybackConfigs.remove(pii) != null; if (wasActive != config.isActive()) { sendAudioPlayerActiveStateChangedMessageLocked( config, /* isRemoved */ false); } } for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) { sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true); } @GuardedBy("mLock") private void sendAudioPlayerActiveStateChangedMessageLocked( final AudioPlaybackConfiguration config, final boolean isRemoved) { for (MessageHandler messageHandler : mListenerMap.values()) { messageHandler.sendAudioPlayerActiveStateChangedMessage(config, isRemoved); // Update mPrevActiveAudioPlaybackConfigs mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs; } } } }
services/core/java/com/android/server/media/MediaRouterService.java +1 −2 Original line number Diff line number Diff line Loading @@ -117,7 +117,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub mAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context); mAudioPlayerStateMonitor.registerListener( new AudioPlayerStateMonitor.OnAudioPlayerActiveStateChangedListener() { static final long WAIT_MS = 500; Loading Loading @@ -168,7 +168,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } }, mHandler); mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService); AudioRoutesInfo audioRoutes = null; try { Loading
services/core/java/com/android/server/media/MediaSessionServiceImpl.java +1 −2 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(mContext); mAudioPlayerStateMonitor.registerListener( (config, isRemoved) -> { if (isRemoved || !config.isActive() || config.getPlayerType() Loading @@ -183,7 +183,6 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl { } } }, null /* handler */); mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService); mContentResolver = mContext.getContentResolver(); mSettingsObserver = new SettingsObserver(); mSettingsObserver.observe(); Loading