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

This commit is contained in:
TreeHugger Robot
2021-09-27 20:07:52 +00:00
committed by Android (Google) Code Review
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";
/** 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;
@@ -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);
@@ -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) {

View File

@@ -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
@@ -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;
@@ -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();
@@ -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;
}
}
}

View File

@@ -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);
}
//=================================================================