Merge "DO NOT MERGE: Fix system_server watchdog timeout"
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user