Merge "DO NOT MERGE: Fix system_server watchdog timeout"

This commit is contained in:
Sungsoo Lim
2019-04-05 13:10:03 +00:00
committed by Gerrit Code Review
3 changed files with 80 additions and 108 deletions

View File

@@ -18,14 +18,11 @@ package com.android.server.media;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.Context; import android.content.Context;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration; import android.media.AudioPlaybackConfiguration;
import android.media.IAudioService;
import android.media.IPlaybackConfigDispatcher;
import android.os.Binder;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
@@ -42,11 +39,11 @@ import java.util.Set;
/** /**
* Monitors the state changes of audio players. * Monitors the state changes of audio players.
*/ */
class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub { class AudioPlayerStateMonitor {
private static boolean DEBUG = MediaSessionService.DEBUG; private static boolean DEBUG = MediaSessionService.DEBUG;
private static String TAG = "AudioPlayerStateMonitor"; 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. * Listener for handling the active state changes of audio players.
@@ -96,96 +93,33 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub {
private final Map<OnAudioPlayerActiveStateChangedListener, MessageHandler> mListenerMap = private final Map<OnAudioPlayerActiveStateChangedListener, MessageHandler> mListenerMap =
new ArrayMap<>(); new ArrayMap<>();
@GuardedBy("mLock") @GuardedBy("mLock")
private final Set<Integer> mActiveAudioUids = new ArraySet<>(); @SuppressWarnings("WeakerAccess") /* synthetic access */
final Set<Integer> mActiveAudioUids = new ArraySet<>();
@GuardedBy("mLock") @GuardedBy("mLock")
private ArrayMap<Integer, AudioPlaybackConfiguration> mPrevActiveAudioPlaybackConfigs = @SuppressWarnings("WeakerAccess") /* synthetic access */
ArrayMap<Integer, AudioPlaybackConfiguration> mPrevActiveAudioPlaybackConfigs =
new ArrayMap<>(); new ArrayMap<>();
// Sorted array of UIDs that had active audio playback. (i.e. playing an audio/video) // 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. // 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. // TODO(b/35278867): Find and use unique identifier for apps because apps may share the UID.
@GuardedBy("mLock") @GuardedBy("mLock")
private final IntArray mSortedAudioPlaybackClientUids = new IntArray(); @SuppressWarnings("WeakerAccess") /* synthetic access */
final IntArray mSortedAudioPlaybackClientUids = new IntArray();
@GuardedBy("mLock") static AudioPlayerStateMonitor getInstance(Context context) {
private boolean mRegisteredToAudioService; synchronized (AudioPlayerStateMonitor.class) {
if (sInstance == null) {
static AudioPlayerStateMonitor getInstance() { sInstance = new AudioPlayerStateMonitor(context);
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);
}
}
for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) {
sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true);
}
// Update mPrevActiveAudioPlaybackConfigs
mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs;
} }
} finally { return sInstance;
Binder.restoreCallingIdentity(token);
} }
} }
private AudioPlayerStateMonitor(Context context) {
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
am.registerAudioPlaybackCallback(new AudioManagerPlaybackListener(), null);
}
/** /**
* Registers OnAudioPlayerActiveStateChangedListener. * 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") @GuardedBy("mLock")
private void sendAudioPlayerActiveStateChangedMessageLocked( private void sendAudioPlayerActiveStateChangedMessageLocked(
final AudioPlaybackConfiguration config, final boolean isRemoved) { final AudioPlaybackConfiguration config, final boolean isRemoved) {
@@ -296,4 +216,59 @@ class AudioPlayerStateMonitor extends IPlaybackConfigDispatcher.Stub {
messageHandler.sendAudioPlayerActiveStateChangedMessage(config, isRemoved); messageHandler.sendAudioPlayerActiveStateChangedMessage(config, isRemoved);
} }
} }
private class AudioManagerPlaybackListener extends AudioManager.AudioPlaybackCallback {
@Override
public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
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);
}
}
for (AudioPlaybackConfiguration config : mPrevActiveAudioPlaybackConfigs.values()) {
sendAudioPlayerActiveStateChangedMessageLocked(config, /* isRemoved */ true);
}
// Update mPrevActiveAudioPlaybackConfigs
mPrevActiveAudioPlaybackConfigs = activeAudioPlaybackConfigs;
}
}
}
} }

View File

@@ -16,14 +16,10 @@
package com.android.server.media; package com.android.server.media;
import com.android.internal.util.DumpUtils;
import com.android.server.Watchdog;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -57,6 +53,9 @@ import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.TimeUtils; import android.util.TimeUtils;
import com.android.internal.util.DumpUtils;
import com.android.server.Watchdog;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
@@ -115,7 +114,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mAudioService = IAudioService.Stub.asInterface( mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE)); ServiceManager.getService(Context.AUDIO_SERVICE));
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context);
mAudioPlayerStateMonitor.registerListener( mAudioPlayerStateMonitor.registerListener(
new AudioPlayerStateMonitor.OnAudioPlayerActiveStateChangedListener() { new AudioPlayerStateMonitor.OnAudioPlayerActiveStateChangedListener() {
static final long WAIT_MS = 500; static final long WAIT_MS = 500;
@@ -166,7 +165,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub
} }
} }
}, mHandler); }, mHandler);
mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService);
AudioRoutesInfo audioRoutes = null; AudioRoutesInfo audioRoutes = null;
try { try {

View File

@@ -93,8 +93,8 @@ import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set;
/** /**
* System implementation of MediaSessionManager * System implementation of MediaSessionManager
@@ -164,7 +164,7 @@ public class MediaSessionService extends SystemService implements Monitor {
mKeyguardManager = mKeyguardManager =
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE); (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService(); mAudioService = getAudioService();
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(getContext());
mAudioPlayerStateMonitor.registerListener( mAudioPlayerStateMonitor.registerListener(
(config, isRemoved) -> { (config, isRemoved) -> {
if (isRemoved || !config.isActive() || config.getPlayerType() if (isRemoved || !config.isActive() || config.getPlayerType()
@@ -179,7 +179,6 @@ public class MediaSessionService extends SystemService implements Monitor {
} }
} }
}, null /* handler */); }, null /* handler */);
mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService);
mContentResolver = getContext().getContentResolver(); mContentResolver = getContext().getContentResolver();
mSettingsObserver = new SettingsObserver(); mSettingsObserver = new SettingsObserver();
mSettingsObserver.observe(); mSettingsObserver.observe();