Loading services/core/java/com/android/server/audio/FadeOutManager.java +14 −6 Original line number Diff line number Diff line Loading @@ -36,7 +36,16 @@ public final class FadeOutManager { public static final String TAG = "AudioService.FadeOutManager"; /** duration of the fade out curve */ /*package*/ static final long FADE_OUT_DURATION_MS = 2000; /** * delay after which a faded out player will be faded back in. This will be heard by the user * only in the case of unmuting players that didn't respect audio focus and didn't stop/pause * when their app lost focus. * This is the amount of time between the app being notified of * the focus loss (when its muted by the fade out), and the time fade in (to unmute) starts */ /*package*/ static final long DELAY_FADE_IN_OFFENDERS_MS = 2000; private static final boolean DEBUG = PlaybackActivityMonitor.DEBUG; Loading Loading @@ -148,6 +157,11 @@ public final class FadeOutManager { } } /** * Remove the app for the given UID from the list of faded out apps, unfade out its players * @param uid the uid for the app to unfade out * @param players map of current available players (so we can get an APC from piid) */ synchronized void unfadeOutUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) { Log.i(TAG, "unfadeOutUid() uid:" + uid); final FadedOutApp fa = mFadedApps.remove(uid); Loading @@ -157,12 +171,6 @@ public final class FadeOutManager { fa.removeUnfadeAll(players); } synchronized void forgetUid(int uid) { //Log.v(TAG, "forget() uid:" + uid); //mFadedApps.remove(uid); // TODO unfade all players later in case they are reused or the app continued to play } // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED // see {@link PlaybackActivityMonitor#playerEvent} synchronized void checkFade(@NonNull AudioPlaybackConfiguration apc) { Loading services/core/java/com/android/server/audio/MediaFocusControl.java +56 −1 Original line number Diff line number Diff line Loading @@ -131,6 +131,11 @@ public class MediaFocusControl implements PlayerFocusEnforcer { @Override public void restoreVShapedPlayers(@NonNull FocusRequester winner) { mFocusEnforcer.restoreVShapedPlayers(winner); // remove scheduled events to unfade out offending players (if any) corresponding to // this uid, as we're removing any effects of muting/ducking/fade out now mFocusHandler.removeEqualMessages(MSL_L_FORGET_UID, new ForgetFadeUidInfo(winner.getClientUid())); } @Override Loading Loading @@ -1182,6 +1187,13 @@ public class MediaFocusControl implements PlayerFocusEnforcer { mFocusHandler.obtainMessage(MSG_L_FOCUS_LOSS_AFTER_FADE, focusLoser), FadeOutManager.FADE_OUT_DURATION_MS); } private void postForgetUidLater(int uid) { mFocusHandler.sendMessageDelayed( mFocusHandler.obtainMessage(MSL_L_FORGET_UID, new ForgetFadeUidInfo(uid)), FadeOutManager.DELAY_FADE_IN_OFFENDERS_MS); } //================================================================= // Message handling private Handler mFocusHandler; Loading @@ -1196,6 +1208,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer { */ private static final int MSG_L_FOCUS_LOSS_AFTER_FADE = 1; private static final int MSL_L_FORGET_UID = 2; private void initFocusThreading() { mFocusThread = new HandlerThread(TAG); mFocusThread.start(); Loading @@ -1213,15 +1227,56 @@ public class MediaFocusControl implements PlayerFocusEnforcer { if (loser.isInFocusLossLimbo()) { loser.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS); loser.release(); mFocusEnforcer.forgetUid(loser.getClientUid()); postForgetUidLater(loser.getClientUid()); } } break; case MSL_L_FORGET_UID: final int uid = ((ForgetFadeUidInfo) msg.obj).mUid; if (DEBUG) { Log.d(TAG, "MSL_L_FORGET_UID uid=" + uid); } mFocusEnforcer.forgetUid(uid); break; default: break; } } }; } /** * Class to associate a UID with a scheduled event to "forget" a UID for the fade out behavior. * Having a class with an equals() override allows using Handler.removeEqualsMessage() to * unschedule events when needed. Here we need to unschedule the "unfading out" == "forget uid" * whenever a new, more recent, focus related event happens before this one is handled. */ private static final class ForgetFadeUidInfo { private final int mUid; ForgetFadeUidInfo(int uid) { mUid = uid; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final ForgetFadeUidInfo f = (ForgetFadeUidInfo) o; if (f.mUid != mUid) { return false; } return true; } @Override public int hashCode() { return mUid; } } } services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +5 −1 Original line number Diff line number Diff line Loading @@ -747,7 +747,11 @@ public final class PlaybackActivityMonitor @Override public void forgetUid(int uid) { mFadingManager.forgetUid(uid); final HashMap<Integer, AudioPlaybackConfiguration> players; synchronized (mPlayerLock) { players = (HashMap<Integer, AudioPlaybackConfiguration>) mPlayers.clone(); } mFadingManager.unfadeOutUid(uid, players); } //================================================================= Loading Loading
services/core/java/com/android/server/audio/FadeOutManager.java +14 −6 Original line number Diff line number Diff line Loading @@ -36,7 +36,16 @@ public final class FadeOutManager { public static final String TAG = "AudioService.FadeOutManager"; /** duration of the fade out curve */ /*package*/ static final long FADE_OUT_DURATION_MS = 2000; /** * delay after which a faded out player will be faded back in. This will be heard by the user * only in the case of unmuting players that didn't respect audio focus and didn't stop/pause * when their app lost focus. * This is the amount of time between the app being notified of * the focus loss (when its muted by the fade out), and the time fade in (to unmute) starts */ /*package*/ static final long DELAY_FADE_IN_OFFENDERS_MS = 2000; private static final boolean DEBUG = PlaybackActivityMonitor.DEBUG; Loading Loading @@ -148,6 +157,11 @@ public final class FadeOutManager { } } /** * Remove the app for the given UID from the list of faded out apps, unfade out its players * @param uid the uid for the app to unfade out * @param players map of current available players (so we can get an APC from piid) */ synchronized void unfadeOutUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) { Log.i(TAG, "unfadeOutUid() uid:" + uid); final FadedOutApp fa = mFadedApps.remove(uid); Loading @@ -157,12 +171,6 @@ public final class FadeOutManager { fa.removeUnfadeAll(players); } synchronized void forgetUid(int uid) { //Log.v(TAG, "forget() uid:" + uid); //mFadedApps.remove(uid); // TODO unfade all players later in case they are reused or the app continued to play } // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED // see {@link PlaybackActivityMonitor#playerEvent} synchronized void checkFade(@NonNull AudioPlaybackConfiguration apc) { Loading
services/core/java/com/android/server/audio/MediaFocusControl.java +56 −1 Original line number Diff line number Diff line Loading @@ -131,6 +131,11 @@ public class MediaFocusControl implements PlayerFocusEnforcer { @Override public void restoreVShapedPlayers(@NonNull FocusRequester winner) { mFocusEnforcer.restoreVShapedPlayers(winner); // remove scheduled events to unfade out offending players (if any) corresponding to // this uid, as we're removing any effects of muting/ducking/fade out now mFocusHandler.removeEqualMessages(MSL_L_FORGET_UID, new ForgetFadeUidInfo(winner.getClientUid())); } @Override Loading Loading @@ -1182,6 +1187,13 @@ public class MediaFocusControl implements PlayerFocusEnforcer { mFocusHandler.obtainMessage(MSG_L_FOCUS_LOSS_AFTER_FADE, focusLoser), FadeOutManager.FADE_OUT_DURATION_MS); } private void postForgetUidLater(int uid) { mFocusHandler.sendMessageDelayed( mFocusHandler.obtainMessage(MSL_L_FORGET_UID, new ForgetFadeUidInfo(uid)), FadeOutManager.DELAY_FADE_IN_OFFENDERS_MS); } //================================================================= // Message handling private Handler mFocusHandler; Loading @@ -1196,6 +1208,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer { */ private static final int MSG_L_FOCUS_LOSS_AFTER_FADE = 1; private static final int MSL_L_FORGET_UID = 2; private void initFocusThreading() { mFocusThread = new HandlerThread(TAG); mFocusThread.start(); Loading @@ -1213,15 +1227,56 @@ public class MediaFocusControl implements PlayerFocusEnforcer { if (loser.isInFocusLossLimbo()) { loser.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS); loser.release(); mFocusEnforcer.forgetUid(loser.getClientUid()); postForgetUidLater(loser.getClientUid()); } } break; case MSL_L_FORGET_UID: final int uid = ((ForgetFadeUidInfo) msg.obj).mUid; if (DEBUG) { Log.d(TAG, "MSL_L_FORGET_UID uid=" + uid); } mFocusEnforcer.forgetUid(uid); break; default: break; } } }; } /** * Class to associate a UID with a scheduled event to "forget" a UID for the fade out behavior. * Having a class with an equals() override allows using Handler.removeEqualsMessage() to * unschedule events when needed. Here we need to unschedule the "unfading out" == "forget uid" * whenever a new, more recent, focus related event happens before this one is handled. */ private static final class ForgetFadeUidInfo { private final int mUid; ForgetFadeUidInfo(int uid) { mUid = uid; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final ForgetFadeUidInfo f = (ForgetFadeUidInfo) o; if (f.mUid != mUid) { return false; } return true; } @Override public int hashCode() { return mUid; } } }
services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +5 −1 Original line number Diff line number Diff line Loading @@ -747,7 +747,11 @@ public final class PlaybackActivityMonitor @Override public void forgetUid(int uid) { mFadingManager.forgetUid(uid); final HashMap<Integer, AudioPlaybackConfiguration> players; synchronized (mPlayerLock) { players = (HashMap<Integer, AudioPlaybackConfiguration>) mPlayers.clone(); } mFadingManager.unfadeOutUid(uid, players); } //================================================================= Loading