Merge "Audio focus enforcement: duck automatically apps for SDK O+" into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c4a169cfb4
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user