diff options
4 files changed, 46 insertions, 13 deletions
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index d721291ad78f..0722417c0d18 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -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(); } diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index afcbc5769cf0..147e73599cad 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -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); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index aa33644357be..6238198e9488 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -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); } diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index bf49ac85d1dc..66f62355c7f0 100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -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); } |