diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java index 648c782a7d1eb..603d7cfb45250 100644 --- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java +++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java @@ -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; @@ -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. @@ -96,96 +93,33 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { private final Map mListenerMap = new ArrayMap<>(); @GuardedBy("mLock") - private final Set mActiveAudioUids = new ArraySet<>(); + @SuppressWarnings("WeakerAccess") /* synthetic access */ + final Set mActiveAudioUids = new ArraySet<>(); @GuardedBy("mLock") - private ArrayMap mPrevActiveAudioPlaybackConfigs = + @SuppressWarnings("WeakerAccess") /* synthetic access */ + ArrayMap 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. - *

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 configs, - boolean flush) { - if (flush) { - Binder.flushPendingCommands(); - } - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - // Update mActiveAudioUids - mActiveAudioUids.clear(); - ArrayMap 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); - } - } - for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) { - sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true); - } - - // Update mPrevActiveAudioPlaybackConfigs - mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs; + static AudioPlayerStateMonitor getInstance(Context context) { + synchronized (AudioPlayerStateMonitor.class) { + if (sInstance == null) { + sInstance = new AudioPlayerStateMonitor(context); } - } finally { - Binder.restoreCallingIdentity(token); + return sInstance; } } + private AudioPlayerStateMonitor(Context context) { + AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + am.registerAudioPlaybackCallback(new AudioManagerPlaybackListener(), null); + } + /** * Registers OnAudioPlayerActiveStateChangedListener. */ @@ -275,20 +209,6 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { } } - public void registerSelfIntoAudioServiceIfNeeded(IAudioService audioService) { - synchronized (mLock) { - try { - if (!mRegisteredToAudioService) { - audioService.registerPlaybackCallback(this); - mRegisteredToAudioService = true; - } - } catch (RemoteException e) { - Log.wtf(TAG, "Failed to register playback callback", e); - mRegisteredToAudioService = false; - } - } - } - @GuardedBy("mLock") private void sendAudioPlayerActiveStateChangedMessageLocked( final AudioPlaybackConfiguration config, final boolean isRemoved) { @@ -296,4 +216,59 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { messageHandler.sendAudioPlayerActiveStateChangedMessage(config, isRemoved); } } + + private class AudioManagerPlaybackListener extends AudioManager.AudioPlaybackCallback { + @Override + public void onPlaybackConfigChanged(List configs) { + synchronized (mLock) { + // Update mActiveAudioUids + mActiveAudioUids.clear(); + ArrayMap 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); + } + } + for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) { + sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true); + } + + // Update mPrevActiveAudioPlaybackConfigs + mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs; + } + } + } } diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index a7df0e23f63b1..47f22702cc02d 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -16,14 +16,10 @@ package com.android.server.media; -import com.android.internal.util.DumpUtils; -import com.android.server.Watchdog; - import android.annotation.NonNull; import android.app.ActivityManager; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -57,6 +53,9 @@ import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; +import com.android.internal.util.DumpUtils; +import com.android.server.Watchdog; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; @@ -115,7 +114,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; @@ -166,7 +165,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub } } }, mHandler); - mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService); AudioRoutesInfo audioRoutes = null; try { diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 68b2a583e020d..67f605ccecfb1 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -93,8 +93,8 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.NoSuchElementException; +import java.util.Set; /** * System implementation of MediaSessionManager @@ -164,7 +164,7 @@ public class MediaSessionService extends SystemService implements Monitor { mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE); mAudioService = getAudioService(); - mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); + mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(getContext()); mAudioPlayerStateMonitor.registerListener( (config, isRemoved) -> { if (isRemoved || !config.isActive() || config.getPlayerType() @@ -179,7 +179,6 @@ public class MediaSessionService extends SystemService implements Monitor { } } }, null /* handler */); - mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService); mContentResolver = getContext().getContentResolver(); mSettingsObserver = new SettingsObserver(); mSettingsObserver.observe();