Merge "Audio focus: make media fade out temporary" into sc-qpr1-dev am: cee2cddebe

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15916332

Change-Id: Ifc5fff4223376f5e58d280362eec7fb9274ba1c3
This commit is contained in:
TreeHugger Robot
2021-09-27 20:33:44 +00:00
committed by Automerger Merge Worker
3 changed files with 75 additions and 8 deletions

View File

@@ -36,7 +36,16 @@ public final class FadeOutManager {
public static final String TAG = "AudioService.FadeOutManager"; public static final String TAG = "AudioService.FadeOutManager";
/** duration of the fade out curve */
/*package*/ static final long FADE_OUT_DURATION_MS = 2000; /*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; private static final boolean DEBUG = PlaybackActivityMonitor.DEBUG;
@@ -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) { synchronized void unfadeOutUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) {
Log.i(TAG, "unfadeOutUid() uid:" + uid); Log.i(TAG, "unfadeOutUid() uid:" + uid);
final FadedOutApp fa = mFadedApps.remove(uid); final FadedOutApp fa = mFadedApps.remove(uid);
@@ -157,12 +171,6 @@ public final class FadeOutManager {
fa.removeUnfadeAll(players); 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 // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
// see {@link PlaybackActivityMonitor#playerEvent} // see {@link PlaybackActivityMonitor#playerEvent}
synchronized void checkFade(@NonNull AudioPlaybackConfiguration apc) { synchronized void checkFade(@NonNull AudioPlaybackConfiguration apc) {

View File

@@ -131,6 +131,11 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
@Override @Override
public void restoreVShapedPlayers(@NonNull FocusRequester winner) { public void restoreVShapedPlayers(@NonNull FocusRequester winner) {
mFocusEnforcer.restoreVShapedPlayers(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 @Override
@@ -1182,6 +1187,13 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
mFocusHandler.obtainMessage(MSG_L_FOCUS_LOSS_AFTER_FADE, focusLoser), mFocusHandler.obtainMessage(MSG_L_FOCUS_LOSS_AFTER_FADE, focusLoser),
FadeOutManager.FADE_OUT_DURATION_MS); 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 // Message handling
private Handler mFocusHandler; private Handler mFocusHandler;
@@ -1196,6 +1208,8 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
*/ */
private static final int MSG_L_FOCUS_LOSS_AFTER_FADE = 1; private static final int MSG_L_FOCUS_LOSS_AFTER_FADE = 1;
private static final int MSL_L_FORGET_UID = 2;
private void initFocusThreading() { private void initFocusThreading() {
mFocusThread = new HandlerThread(TAG); mFocusThread = new HandlerThread(TAG);
mFocusThread.start(); mFocusThread.start();
@@ -1213,15 +1227,56 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
if (loser.isInFocusLossLimbo()) { if (loser.isInFocusLossLimbo()) {
loser.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS); loser.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS);
loser.release(); loser.release();
mFocusEnforcer.forgetUid(loser.getClientUid()); postForgetUidLater(loser.getClientUid());
} }
} }
break; 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: default:
break; 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;
}
} }
} }

View File

@@ -747,7 +747,11 @@ public final class PlaybackActivityMonitor
@Override @Override
public void forgetUid(int uid) { 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);
} }
//================================================================= //=================================================================