Merge "PlayerBase: fix deadlock" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-04-12 01:46:52 +00:00
committed by Android (Google) Code Review
2 changed files with 48 additions and 38 deletions

View File

@@ -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

View File

@@ -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;
// for AppOps
private IAppOpsService mAppOps; // may be null
private IAppOpsCallback mAppOpsCallback;
private boolean mHasAppOpsPlayAudio = true; // sync'd on mLock
// 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 @Nullable IAppOpsService mAppOps;
private IAppOpsCallback mAppOpsCallback;
@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.
@@ -134,16 +144,24 @@ public abstract class PlayerBase {
}
}
private void updateState(int state) {
final int piid;
synchronized (mLock) {
mState = state;
piid = mPlayerIId;
}
try {
getService().playerEvent(piid, state);
} catch (RemoteException 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); }
try {
synchronized (mLock) {
mState = AudioPlaybackConfiguration.PLAYER_STATE_STARTED;
getService().playerEvent(mPlayerIId, mState);
}
} catch (RemoteException e) {
Log.e(TAG, "Error talking to audio service, STARTED state will not be tracked", e);
}
updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED);
synchronized (mLock) {
if (isRestricted_sync()) {
playerSetVolume(true/*muting*/,0, 0);
@@ -165,26 +183,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) {
@@ -228,12 +232,16 @@ public abstract class PlayerBase {
*/
void baseRelease() {
if (DEBUG) { Log.v(TAG, "baseRelease() piid=" + mPlayerIId + " state=" + mState); }
boolean releasePlayer = false;
synchronized (mLock) {
if (mState != AudioPlaybackConfiguration.PLAYER_STATE_RELEASED) {
releasePlayer = true;
mState = AudioPlaybackConfiguration.PLAYER_STATE_RELEASED;
}
}
try {
synchronized (mLock) {
if (mState != AudioPlaybackConfiguration.PLAYER_STATE_RELEASED) {
getService().releasePlayer(mPlayerIId);
mState = AudioPlaybackConfiguration.PLAYER_STATE_RELEASED;
}
if (releasePlayer) {
getService().releasePlayer(mPlayerIId);
}
} catch (RemoteException e) {
Log.e(TAG, "Error talking to audio service, the player will still be tracked", e);