diff options
4 files changed, 82 insertions, 31 deletions
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java index db55138e446d..bd129f70ee29 100644 --- a/services/core/java/com/android/server/audio/FocusRequester.java +++ b/services/core/java/com/android/server/audio/FocusRequester.java @@ -364,28 +364,8 @@ public class FocusRequester { // check enforcement by the framework boolean handled = false; - if (focusLoss == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK - && MediaFocusControl.ENFORCE_DUCKING - && frWinner != null) { - // candidate for enforcement by the framework - if (frWinner.mCallingUid != this.mCallingUid) { - if (!forceDuck && ((mGrantFlags - & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0)) { - // the focus loser declared it would pause instead of duck, let it - // handle it (the framework doesn't pause for apps) - handled = false; - Log.v(TAG, "not ducking uid " + this.mCallingUid + " - flags"); - } else if (!forceDuck && (MediaFocusControl.ENFORCE_DUCKING_FOR_NEW && - this.getSdkTarget() <= MediaFocusControl.DUCKING_IN_APP_SDK_LEVEL)) - { - // legacy behavior, apps used to be notified when they should be ducking - handled = false; - Log.v(TAG, "not ducking uid " + this.mCallingUid + " - old SDK"); - } else { - handled = mFocusController.duckPlayers(frWinner, this, forceDuck); - } - } // else: the focus change is within the same app, so let the dispatching - // happen as if the framework was not involved. + if (frWinner != null) { + handled = frameworkHandleFocusLoss(focusLoss, frWinner, forceDuck); } if (handled) { @@ -415,6 +395,47 @@ public class FocusRequester { } } + /** + * Let the framework handle the focus loss if possible + * @param focusLoss + * @param frWinner + * @param forceDuck + * @return true if the framework handled the focus loss + */ + @GuardedBy("MediaFocusControl.mAudioFocusLock") + private boolean frameworkHandleFocusLoss(int focusLoss, @NonNull final FocusRequester frWinner, + boolean forceDuck) { + if (frWinner.mCallingUid == this.mCallingUid) { + // the focus change is within the same app, so let the dispatching + // happen as if the framework was not involved. + return false; + } + + if (focusLoss == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { + if (!MediaFocusControl.ENFORCE_DUCKING) { + return false; + } + + // candidate for enforcement by the framework + if (!forceDuck && ((mGrantFlags + & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0)) { + // the focus loser declared it would pause instead of duck, let it + // handle it (the framework doesn't pause for apps) + Log.v(TAG, "not ducking uid " + this.mCallingUid + " - flags"); + return false; + } + if (!forceDuck && (MediaFocusControl.ENFORCE_DUCKING_FOR_NEW + && this.getSdkTarget() <= MediaFocusControl.DUCKING_IN_APP_SDK_LEVEL)) { + // legacy behavior, apps used to be notified when they should be ducking + Log.v(TAG, "not ducking uid " + this.mCallingUid + " - old SDK"); + return false; + } + + return mFocusController.duckPlayers(frWinner, this, forceDuck); + } + return false; + } + int dispatchFocusChange(int focusChange) { if (mFocusDispatcher == null) { if (MediaFocusControl.DEBUG) { Log.e(TAG, "dispatchFocusChange: no focus dispatcher"); } diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index 5c93071fd551..c845981fea7e 100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -105,12 +105,13 @@ public class MediaFocusControl implements PlayerFocusEnforcer { //================================================================= // PlayerFocusEnforcer implementation @Override - public boolean duckPlayers(FocusRequester winner, FocusRequester loser, boolean forceDuck) { + public boolean duckPlayers(@NonNull FocusRequester winner, @NonNull FocusRequester loser, + boolean forceDuck) { return mFocusEnforcer.duckPlayers(winner, loser, forceDuck); } @Override - public void unduckPlayers(FocusRequester winner) { + public void unduckPlayers(@NonNull FocusRequester winner) { mFocusEnforcer.unduckPlayers(winner); } @@ -742,7 +743,20 @@ public class MediaFocusControl implements PlayerFocusEnforcer { } } - /** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */ + /** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) + * @param aa + * @param focusChangeHint + * @param cb + * @param fd + * @param clientId + * @param callingPackageName + * @param flags + * @param sdk + * @param forceDuck only true if + * {@link android.media.AudioFocusRequest.Builder#setFocusGain(int)} was set to true for + * accessibility. + * @return + */ protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb, IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName, int flags, int sdk, boolean forceDuck) { diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index 3a25d980e97a..f8ba55bcd092 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -425,7 +425,8 @@ public final class PlaybackActivityMonitor private final DuckingManager mDuckingManager = new DuckingManager(); @Override - public boolean duckPlayers(FocusRequester winner, FocusRequester loser, boolean forceDuck) { + public boolean duckPlayers(@NonNull FocusRequester winner, @NonNull FocusRequester loser, + boolean forceDuck) { if (DEBUG) { Log.v(TAG, String.format("duckPlayers: uids winner=%d loser=%d", winner.getClientUid(), loser.getClientUid())); @@ -473,7 +474,7 @@ public final class PlaybackActivityMonitor } @Override - public void unduckPlayers(FocusRequester winner) { + public void unduckPlayers(@NonNull FocusRequester winner) { if (DEBUG) { Log.v(TAG, "unduckPlayers: uids winner=" + winner.getClientUid()); } synchronized (mPlayerLock) { mDuckingManager.unduckUid(winner.getClientUid(), mPlayers); diff --git a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java index 3c834daf3c8a..89e7b7828b15 100644 --- a/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java +++ b/services/core/java/com/android/server/audio/PlayerFocusEnforcer.java @@ -16,6 +16,8 @@ package com.android.server.audio; +import android.annotation.NonNull; + public interface PlayerFocusEnforcer { /** @@ -25,11 +27,24 @@ public interface PlayerFocusEnforcer { * @param loser * @return */ - public boolean duckPlayers(FocusRequester winner, FocusRequester loser, boolean forceDuck); + boolean duckPlayers(@NonNull FocusRequester winner, @NonNull FocusRequester loser, + boolean forceDuck); - public void unduckPlayers(FocusRequester winner); + /** + * Unduck the players that had been ducked with + * {@link #duckPlayers(FocusRequester, FocusRequester, boolean)} + * @param winner + */ + void unduckPlayers(@NonNull FocusRequester winner); - public void mutePlayersForCall(int[] usagesToMute); + /** + * Mute players at the beginning of a call + * @param usagesToMute array of {@link android.media.AudioAttributes} usages to mute + */ + void mutePlayersForCall(int[] usagesToMute); - public void unmutePlayersForCall(); + /** + * Unmute players at the end of a call + */ + void unmutePlayersForCall(); }
\ No newline at end of file |