Merge "Audio focus: fix delayed focus request during locked focus behavior"

This commit is contained in:
Jean-Michel Trivi
2021-12-09 22:55:33 +00:00
committed by Android (Google) Code Review
4 changed files with 46 additions and 13 deletions

View File

@@ -4003,8 +4003,7 @@ public class AudioManager {
* @hide
* flag set on test API calls,
* see {@link #requestAudioFocusForTest(AudioFocusRequest, String, int, int)},
* note that it isn't used in conjunction with other flags, it is passed as the single
* value for flags */
*/
public static final int AUDIOFOCUS_FLAG_TEST = 0x1 << 3;
/** @hide */
public static final int AUDIOFOCUS_FLAGS_APPS = AUDIOFOCUS_FLAG_DELAY_OK
@@ -4187,7 +4186,9 @@ public class AudioManager {
afr.getFocusGain(),
mICallBack,
mAudioFocusDispatcher,
clientFakeId, "com.android.test.fakeclient", clientFakeUid, clientTargetSdk);
clientFakeId, "com.android.test.fakeclient",
afr.getFlags() | AudioManager.AUDIOFOCUS_FLAG_TEST,
clientFakeUid, clientTargetSdk);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -384,7 +384,7 @@ interface IAudioService {
int requestAudioFocusForTest(in AudioAttributes aa, int durationHint, IBinder cb,
in IAudioFocusDispatcher fd, in String clientId, in String callingPackageName,
int uid, int sdk);
int flags, int uid, int sdk);
int abandonAudioFocusForTest(in IAudioFocusDispatcher fd, in String clientId,
in AudioAttributes aa, in String callingPackageName);

View File

@@ -8252,6 +8252,9 @@ public class AudioService extends IAudioService.Stub
public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
IAudioFocusDispatcher fd, String clientId, String callingPackageName,
String attributionTag, int flags, IAudioPolicyCallback pcb, int sdk) {
if ((flags & AudioManager.AUDIOFOCUS_FLAG_TEST) != 0) {
throw new IllegalArgumentException("Invalid test flag");
}
final int uid = Binder.getCallingUid();
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId + "focus")
.setUid(uid)
@@ -8310,7 +8313,7 @@ public class AudioService extends IAudioService.Stub
/** see {@link AudioManager#requestAudioFocusForTest(AudioFocusRequest, String, int, int)} */
public int requestAudioFocusForTest(AudioAttributes aa, int durationHint, IBinder cb,
IAudioFocusDispatcher fd, String clientId, String callingPackageName,
int fakeUid, int sdk) {
int flags, int fakeUid, int sdk) {
if (!enforceQueryAudioStateForTest("focus request")) {
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
@@ -8320,7 +8323,7 @@ public class AudioService extends IAudioService.Stub
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
clientId, callingPackageName, null, AudioManager.AUDIOFOCUS_FLAG_TEST,
clientId, callingPackageName, null, flags,
sdk, false /*forceDuck*/, fakeUid);
}

View File

@@ -461,13 +461,19 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
* at the top of the focus stack
* Push the focus requester onto the audio focus stack at the first position immediately
* following the locked focus owners.
* Propagate through the stack the changes that the new (future) focus owner causes.
* @param nfr the future focus owner that will gain focus when the locked focus owners are
* removed from the stack
* @return {@link AudioManager#AUDIOFOCUS_REQUEST_GRANTED} or
* {@link AudioManager#AUDIOFOCUS_REQUEST_DELAYED}
*/
@GuardedBy("mAudioFocusLock")
private int pushBelowLockedFocusOwners(FocusRequester nfr) {
private int pushBelowLockedFocusOwnersAndPropagate(FocusRequester nfr) {
if (DEBUG) {
Log.v(TAG, "pushBelowLockedFocusOwnersAndPropagate client=" + nfr.getClientId());
}
int lastLockedFocusOwnerIndex = mFocusStack.size();
for (int index = mFocusStack.size()-1; index >= 0; index--) {
for (int index = mFocusStack.size() - 1; index >= 0; index--) {
if (isLockedFocusOwner(mFocusStack.elementAt(index))) {
lastLockedFocusOwnerIndex = index;
}
@@ -480,10 +486,33 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
propagateFocusLossFromGain_syncAf(nfr.getGainRequest(), nfr, false /*forceDuck*/);
mFocusStack.push(nfr);
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
} else {
mFocusStack.insertElementAt(nfr, lastLockedFocusOwnerIndex);
return AudioManager.AUDIOFOCUS_REQUEST_DELAYED;
}
if (DEBUG) {
Log.v(TAG, "> lastLockedFocusOwnerIndex=" + lastLockedFocusOwnerIndex);
}
mFocusStack.insertElementAt(nfr, lastLockedFocusOwnerIndex);
// propagate potential focus loss (and removal from stack) after the newly
// inserted FocusRequester (at index lastLockedFocusOwnerIndex-1)
final List<String> clientsToRemove = new LinkedList<String>();
for (int index = lastLockedFocusOwnerIndex - 1; index >= 0; index--) {
final boolean isDefinitiveLoss =
mFocusStack.elementAt(index).handleFocusLossFromGain(
nfr.getGainRequest(), nfr, false /*forceDuck*/);
if (isDefinitiveLoss) {
clientsToRemove.add(mFocusStack.elementAt(index).getClientId());
}
}
for (String clientToRemove : clientsToRemove) {
if (DEBUG) {
Log.v(TAG, "> removing focus client " + clientToRemove);
}
removeFocusStackEntry(clientToRemove, false /*signal*/,
true /*notifyFocusFollowers*/);
}
return AudioManager.AUDIOFOCUS_REQUEST_DELAYED;
}
/**
@@ -868,7 +897,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
* @param forceDuck only true if
* {@link android.media.AudioFocusRequest.Builder#setFocusGain(int)} was set to true for
* accessibility.
* @param testUid ignored if flags is not AudioManager.AUDIOFOCUS_FLAG_TEST (strictly equals to)
* @param testUid ignored if flags doesn't contain AudioManager.AUDIOFOCUS_FLAG_TEST
* otherwise the UID being injected for testing
* @return
*/
@@ -1029,7 +1058,7 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
if (focusGrantDelayed) {
// focusGrantDelayed being true implies we can't reassign focus right now
// which implies the focus stack is not empty.
final int requestResult = pushBelowLockedFocusOwners(nfr);
final int requestResult = pushBelowLockedFocusOwnersAndPropagate(nfr);
if (requestResult != AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(), requestResult);
}