Merge "Audio focus enforcement: duck automatically apps for SDK O+" into oc-dev

This commit is contained in:
Jean-Michel Trivi
2017-04-26 15:26:59 +00:00
committed by Android (Google) Code Review
7 changed files with 60 additions and 14 deletions

View File

@@ -33,6 +33,7 @@ public final class AudioFocusInfo implements Parcelable {
private final int mClientUid;
private final String mClientId;
private final String mPackageName;
private final int mSdkTarget;
private int mGainRequest;
private int mLossReceived;
private int mFlags;
@@ -49,7 +50,7 @@ public final class AudioFocusInfo implements Parcelable {
* @hide
*/
public AudioFocusInfo(AudioAttributes aa, int clientUid, String clientId, String packageName,
int gainRequest, int lossReceived, int flags) {
int gainRequest, int lossReceived, int flags, int sdk) {
mAttributes = aa == null ? new AudioAttributes.Builder().build() : aa;
mClientUid = clientUid;
mClientId = clientId == null ? "" : clientId;
@@ -57,6 +58,7 @@ public final class AudioFocusInfo implements Parcelable {
mGainRequest = gainRequest;
mLossReceived = lossReceived;
mFlags = flags;
mSdkTarget = sdk;
}
@@ -96,6 +98,9 @@ public final class AudioFocusInfo implements Parcelable {
@SystemApi
public int getLossReceived() { return mLossReceived; }
/** @hide */
public int getSdkTarget() { return mSdkTarget; }
/** @hide */
public void clearLossReceived() { mLossReceived = 0; }
@@ -122,6 +127,7 @@ public final class AudioFocusInfo implements Parcelable {
dest.writeInt(mGainRequest);
dest.writeInt(mLossReceived);
dest.writeInt(mFlags);
dest.writeInt(mSdkTarget);
}
@SystemApi
@@ -161,6 +167,9 @@ public final class AudioFocusInfo implements Parcelable {
if (mFlags != other.mFlags) {
return false;
}
if (mSdkTarget != other.mSdkTarget) {
return false;
}
return true;
}
@@ -175,7 +184,8 @@ public final class AudioFocusInfo implements Parcelable {
in.readString(), //String packageName
in.readInt(), //int gainRequest
in.readInt(), //int lossReceived
in.readInt() //int flags
in.readInt(), //int flags
in.readInt() //int sdkTarget
);
}

View File

@@ -34,6 +34,7 @@ import android.media.session.MediaSession;
import android.media.session.MediaSessionLegacyHelper;
import android.media.session.MediaSessionManager;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -2483,13 +2484,21 @@ public class AudioManager {
registerAudioFocusRequest(afr);
final IAudioService service = getService();
final int status;
int sdk;
try {
sdk = getContext().getApplicationInfo().targetSdkVersion;
} catch (NullPointerException e) {
// some tests don't have a Context
sdk = Build.VERSION.SDK_INT;
}
try {
status = service.requestAudioFocus(afr.getAudioAttributes(),
afr.getFocusGain(), mICallBack,
mAudioFocusDispatcher,
getIdForAudioFocusListener(afr.getOnAudioFocusChangeListener()),
getContext().getOpPackageName() /* package name */, afr.getFlags(),
ap != null ? ap.cb() : null);
ap != null ? ap.cb() : null,
sdk);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2515,7 +2524,7 @@ public class AudioManager {
AudioSystem.IN_VOICE_COMM_FOCUS_ID,
getContext().getOpPackageName(),
AUDIOFOCUS_FLAG_LOCK,
null /* policy token */);
null /* policy token */, 0 /* sdk n/a here*/);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -121,7 +121,7 @@ interface IAudioService {
int requestAudioFocus(in AudioAttributes aa, int durationHint, IBinder cb,
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
IAudioPolicyCallback pcb);
IAudioPolicyCallback pcb, int sdk);
int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, in AudioAttributes aa,
in String callingPackageName);

View File

@@ -5669,7 +5669,7 @@ public class AudioService extends IAudioService.Stub
//==========================================================================================
public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
IAudioPolicyCallback pcb) {
IAudioPolicyCallback pcb, int sdk) {
// permission checks
if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
@@ -5690,7 +5690,7 @@ public class AudioService extends IAudioService.Stub
}
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
clientId, callingPackageName, flags);
clientId, callingPackageName, flags, sdk);
}
public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,

View File

@@ -48,6 +48,7 @@ public class FocusRequester {
private final String mPackageName;
private final int mCallingUid;
private final MediaFocusControl mFocusController; // never null
private final int mSdkTarget;
/**
* the audio focus gain request that caused the addition of this object in the focus stack.
@@ -87,7 +88,7 @@ public class FocusRequester {
*/
FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags,
IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr,
String pn, int uid, @NonNull MediaFocusControl ctlr) {
String pn, int uid, @NonNull MediaFocusControl ctlr, int sdk) {
mAttributes = aa;
mFocusDispatcher = afl;
mSourceRef = source;
@@ -99,6 +100,7 @@ public class FocusRequester {
mGrantFlags = grantFlags;
mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
mFocusController = ctlr;
mSdkTarget = sdk;
}
FocusRequester(AudioFocusInfo afi, IAudioFocusDispatcher afl,
@@ -110,6 +112,7 @@ public class FocusRequester {
mFocusGainRequest = afi.getGainRequest();
mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
mGrantFlags = afi.getFlags();
mSdkTarget = afi.getSdkTarget();
mFocusDispatcher = afl;
mSourceRef = source;
@@ -169,6 +172,9 @@ public class FocusRequester {
return mAttributes;
}
int getSdkTarget() {
return mSdkTarget;
}
private static String focusChangeToString(int focus) {
switch(focus) {
@@ -226,7 +232,8 @@ public class FocusRequester {
+ " -- loss: " + focusLossToString()
+ " -- notified: " + mFocusLossWasNotified
+ " -- uid: " + mCallingUid
+ " -- attr: " + mAttributes);
+ " -- attr: " + mAttributes
+ " -- sdk:" + mSdkTarget);
}
@@ -419,6 +426,6 @@ public class FocusRequester {
AudioFocusInfo toAudioFocusInfo() {
return new AudioFocusInfo(mAttributes, mCallingUid, mClientId, mPackageName,
mFocusGainRequest, mFocusLossReceived, mGrantFlags);
mFocusGainRequest, mFocusLossReceived, mGrantFlags, mSdkTarget);
}
}

View File

@@ -27,6 +27,7 @@ import android.media.IAudioFocusDispatcher;
import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -55,6 +56,17 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
* that they lost focus for most use cases.
*/
static final boolean ENFORCE_DUCKING = true;
/**
* set to true to the framework enforces ducking itself only with apps above a given SDK
* target level. Is ignored if ENFORCE_DUCKING is false.
*/
static final boolean ENFORCE_DUCKING_FOR_NEW = true;
/**
* the SDK level (included) up to which the framework doesn't enforce ducking itself. Is ignored
* if ENFORCE_DUCKING_FOR_NEW is false;
*/
// automatic ducking was introduced for Android O
static final int DUCKING_IN_APP_SDK_LEVEL = Build.VERSION_CODES.N_MR1;
/**
* set to true so the framework enforces muting media/game itself when the device is ringing
* or in a call.
@@ -629,7 +641,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
/** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */
protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb,
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags) {
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
int sdk) {
Log.i(TAG, " AudioFocus requestAudioFocus() from uid/pid " + Binder.getCallingUid()
+ "/" + Binder.getCallingPid()
+ " clientId=" + clientId
@@ -656,7 +669,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
// construct AudioFocusInfo as it will be communicated to audio focus policy
afiForExtPolicy = new AudioFocusInfo(aa, Binder.getCallingUid(),
clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/,
flags);
flags, sdk);
} else {
afiForExtPolicy = null;
}
@@ -722,7 +735,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
removeFocusStackEntry(clientId, false /* signal */, false /*notifyFocusFollowers*/);
final FocusRequester nfr = new FocusRequester(aa, focusChangeHint, flags, fd, cb,
clientId, afdh, callingPackageName, Binder.getCallingUid(), this);
clientId, afdh, callingPackageName, Binder.getCallingUid(), this, sdk);
if (focusGrantDelayed) {
// focusGrantDelayed being true implies we can't reassign focus right now
// which implies the focus stack is not empty.
@@ -767,7 +780,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
if (mFocusPolicy != null) {
final AudioFocusInfo afi = new AudioFocusInfo(aa, Binder.getCallingUid(),
clientId, callingPackageName, 0 /*gainRequest*/, 0 /*lossReceived*/,
0 /*flags*/);
0 /*flags*/, 0 /* sdk n/a here*/);
if (notifyExtFocusPolicyFocusAbandon_syncAf(afi)) {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}

View File

@@ -308,10 +308,17 @@ public final class PlaybackActivityMonitor
{
if (mDuckedPlayers.contains(new Integer(piid))) {
if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); }
} else if (MediaFocusControl.ENFORCE_DUCKING
&& MediaFocusControl.ENFORCE_DUCKING_FOR_NEW
&& loser.getSdkTarget() <= MediaFocusControl.DUCKING_IN_APP_SDK_LEVEL) {
// legacy behavior, apps used to be notified when they should be ducking
if (DEBUG) { Log.v(TAG, "not ducking player " + piid + ": old SDK"); }
return false;
} else if (apc.getAudioAttributes().getContentType() ==
AudioAttributes.CONTENT_TYPE_SPEECH) {
// the player is speaking, ducking will make the speech unintelligible
// so let the app handle it instead
if (DEBUG) { Log.v(TAG, "not ducking player " + piid + ": SPEECH"); }
return false;
} else if (apc.getPlayerType()
== AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {