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

Commit 064cd7b3 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by android-build-merger
Browse files

Merge "Source of deadlock between PlayerBase.mLock and PlaybackActivityMonitor.mPlayerLock:"

am: d53bd6b8

Change-Id: I1408348aa98c9442de544b22cd9cddb9a1eac907
parents cca80fbe d53bd6b8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ public final class AudioPlaybackConfiguration implements Parcelable {
    /** @hide */
    public static final int PLAYER_PIID_INVALID = -1;
    /** @hide */
    public static final int PLAYER_PIID_UNASSIGNED = 0;
    /** @hide */
    public static final int PLAYER_UPID_INVALID = -1;

    // information about the implementation
+44 −36
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;

@@ -58,20 +59,29 @@ public abstract class PlayerBase {
    protected float mRightVolume = 1.0f;
    protected float mAuxEffectSendLevel = 0.0f;

    // NEVER call into AudioService (see getService()) with mLock held: PlayerBase can run in
    // the same process as AudioService, which can synchronously call back into this class,
    // causing deadlocks between the two
    private final Object mLock = new Object();

    // for AppOps
    private IAppOpsService mAppOps; // may be null
    private @Nullable IAppOpsService mAppOps;
    private IAppOpsCallback mAppOpsCallback;
    private boolean mHasAppOpsPlayAudio = true; // sync'd on mLock
    private final Object mLock = new Object();
    @GuardedBy("mLock")
    private boolean mHasAppOpsPlayAudio = true;

    private final int mImplType;
    // uniquely identifies the Player Interface throughout the system (P I Id)
    private int mPlayerIId;
    private int mPlayerIId = AudioPlaybackConfiguration.PLAYER_PIID_UNASSIGNED;

    private int mState; // sync'd on mLock
    private int mStartDelayMs = 0; // sync'd on mLock
    private float mPanMultiplierL = 1.0f; // sync'd on mLock
    private float mPanMultiplierR = 1.0f; // sync'd on mLock
    @GuardedBy("mLock")
    private int mState;
    @GuardedBy("mLock")
    private int mStartDelayMs = 0;
    @GuardedBy("mLock")
    private float mPanMultiplierL = 1.0f;
    @GuardedBy("mLock")
    private float mPanMultiplierR = 1.0f;

    /**
     * Constructor. Must be given audio attributes, as they are required for AppOps.
@@ -133,16 +143,24 @@ public abstract class PlayerBase {
        }
    }

    void baseStart() {
        if (DEBUG) { Log.v(TAG, "baseStart() piid=" + mPlayerIId); }
        try {
    private void updateState(int state) {
        final int piid;
        synchronized (mLock) {
                mState = AudioPlaybackConfiguration.PLAYER_STATE_STARTED;
                getService().playerEvent(mPlayerIId, mState);
            mState = state;
            piid = mPlayerIId;
        }
        try {
            getService().playerEvent(piid, state);
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to audio service, STARTED state will not be tracked", e);
            Log.e(TAG, "Error talking to audio service, "
                    + AudioPlaybackConfiguration.toLogFriendlyPlayerState(state)
                    + " state will not be tracked for piid=" + piid, e);
        }
    }

    void baseStart() {
        if (DEBUG) { Log.v(TAG, "baseStart() piid=" + mPlayerIId); }
        updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED);
        synchronized (mLock) {
            if (isRestricted_sync()) {
                playerSetVolume(true/*muting*/,0, 0);
@@ -164,26 +182,12 @@ public abstract class PlayerBase {

    void basePause() {
        if (DEBUG) { Log.v(TAG, "basePause() piid=" + mPlayerIId); }
        try {
            synchronized (mLock) {
                mState = AudioPlaybackConfiguration.PLAYER_STATE_PAUSED;
                getService().playerEvent(mPlayerIId, mState);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to audio service, PAUSED state will not be tracked", e);
        }
        updateState(AudioPlaybackConfiguration.PLAYER_STATE_PAUSED);
    }

    void baseStop() {
        if (DEBUG) { Log.v(TAG, "baseStop() piid=" + mPlayerIId); }
        try {
            synchronized (mLock) {
                mState = AudioPlaybackConfiguration.PLAYER_STATE_STOPPED;
                getService().playerEvent(mPlayerIId, mState);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to audio service, STOPPED state will not be tracked", e);
        }
        updateState(AudioPlaybackConfiguration.PLAYER_STATE_STOPPED);
    }

    void baseSetPan(float pan) {
@@ -227,13 +231,17 @@ public abstract class PlayerBase {
     */
    void baseRelease() {
        if (DEBUG) { Log.v(TAG, "baseRelease() piid=" + mPlayerIId + " state=" + mState); }
        try {
        boolean releasePlayer = false;
        synchronized (mLock) {
            if (mState != AudioPlaybackConfiguration.PLAYER_STATE_RELEASED) {
                    getService().releasePlayer(mPlayerIId);
                releasePlayer = true;
                mState = AudioPlaybackConfiguration.PLAYER_STATE_RELEASED;
            }
        }
        try {
            if (releasePlayer) {
                getService().releasePlayer(mPlayerIId);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Error talking to audio service, the player will still be tracked", e);
        }