Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4bb49a7b authored by Sungsoo Lim's avatar Sungsoo Lim Committed by Android (Google) Code Review
Browse files

Merge "Fix system_server watchdog timeout" into qt-dev

parents 841dc62b d4d1187e
Loading
Loading
Loading
Loading
+74 −99
Original line number Diff line number Diff line
@@ -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,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);
    }

    /**
@@ -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;
            }
        }
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -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;
@@ -168,7 +168,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub
                }
            }
        }, mHandler);
        mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService);

        AudioRoutesInfo audioRoutes = null;
        try {
+1 −2
Original line number Diff line number Diff line
@@ -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()
@@ -183,7 +183,6 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
                        }
                    }
                }, null /* handler */);
        mAudioPlayerStateMonitor.registerSelfIntoAudioServiceIfNeeded(mAudioService);
        mContentResolver = mContext.getContentResolver();
        mSettingsObserver = new SettingsObserver();
        mSettingsObserver.observe();