Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb16bd19 authored by Raj Goparaju's avatar Raj Goparaju
Browse files

Refactor to ecapsulate FadeOutManager configurations

In preperation of supporting configurable fade parameters,
move the default configurations into a separate class.
The fade apis use the getter methods to query the fade
parameters instead of directly accessing the default
static values. This separates the concern of fade parameter
settings from applying them on players. Changes to
configurations in future shall be localized to the new class.

Bug: 186905459
Bug: 302870089
Test: atest -c --rerun-until-failure 1000 AudioFocusTest
        FadeConfigurationsTest FadeOutManagerTest

Change-Id: Id3cc1063d48c0ad5c1935a8ec6603bca8f1720c3
parent f17c3146
Loading
Loading
Loading
Loading
+180 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.audio;

import android.annotation.NonNull;
import android.media.AudioAttributes;
import android.media.AudioPlaybackConfiguration;
import android.media.VolumeShaper;
import android.util.Slog;

import java.util.List;

/**
 * Class to encapsulate configurations used for fading players
 */
public final class FadeConfigurations {
    public static final String TAG = "AS.FadeConfigurations";

    private static final boolean DEBUG = PlaybackActivityMonitor.DEBUG;


    /** duration of the fade out curve */
    private static final long DEFAULT_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
     */
    private static final long DEFAULT_DELAY_FADE_IN_OFFENDERS_MS = 2000;

    private static final List<Integer> DEFAULT_UNFADEABLE_PLAYER_TYPES = List.of(
            AudioPlaybackConfiguration.PLAYER_TYPE_AAUDIO,
            AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL
    );

    private static final List<Integer> DEFAULT_UNFADEABLE_CONTENT_TYPES = List.of(
            AudioAttributes.CONTENT_TYPE_SPEECH
    );

    private static final List<Integer> DEFAULT_FADEABLE_USAGES = List.of(
            AudioAttributes.USAGE_GAME,
            AudioAttributes.USAGE_MEDIA
    );

    private static final VolumeShaper.Configuration DEFAULT_FADEOUT_VSHAPE =
            new VolumeShaper.Configuration.Builder()
                    .setId(PlaybackActivityMonitor.VOLUME_SHAPER_SYSTEM_FADEOUT_ID)
                    .setCurve(new float[]{0.f, 0.25f, 1.0f} /* times */,
                            new float[]{1.f, 0.65f, 0.0f} /* volumes */)
                    .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
                    .setDuration(DEFAULT_FADE_OUT_DURATION_MS)
                    .build();

    private static final int INVALID_UID = -1;

    /**
     * Query {@link android.media.AudioAttributes.AttributeUsage usages} that are allowed to
     * fade
     * @return list of {@link android.media.AudioAttributes.AttributeUsage}
     */
    @NonNull
    public List<Integer> getFadeableUsages() {
        return DEFAULT_FADEABLE_USAGES;
    }

    /**
     * Query {@link android.media.AudioAttributes.AttributeContentType content types} that are
     * exempted from fade enforcement
     * @return list of {@link android.media.AudioAttributes.AttributeContentType}
     */
    @NonNull
    public List<Integer> getUnfadeableContentTypes() {
        return DEFAULT_UNFADEABLE_CONTENT_TYPES;
    }

    /**
     * Query {@link android.media.AudioPlaybackConfiguration.PlayerType player types} that are
     * exempted from fade enforcement
     * @return list of {@link android.media.AudioPlaybackConfiguration.PlayerType}
     */
    @NonNull
    public List<Integer> getUnfadeablePlayerTypes() {
        return DEFAULT_UNFADEABLE_PLAYER_TYPES;
    }

    /**
     * Get the {@link android.media.VolumeShaper.Configuration} configuration to be applied
     * for the fade-out
     * @param aa The {@link android.media.AudioAttributes}
     * @return {@link android.media.VolumeShaper.Configuration} for the
     * {@link android.media.AudioAttributes.AttributeUsage} or default volume shaper if not
     * configured
     */
    @NonNull
    public VolumeShaper.Configuration getFadeOutVolumeShaperConfig(@NonNull AudioAttributes aa) {
        return DEFAULT_FADEOUT_VSHAPE;
    }

    /**
     * Get the duration to fade out a player of type usage
     * @param aa The {@link android.media.AudioAttributes}
     * @return duration in milliseconds for the
     * {@link android.media.AudioAttributes} or default duration if not configured
     */
    public long getFadeOutDuration(@NonNull AudioAttributes aa) {
        if (!isFadeable(aa, INVALID_UID, AudioPlaybackConfiguration.PLAYER_TYPE_UNKNOWN)) {
            return 0;
        }
        return DEFAULT_FADE_OUT_DURATION_MS;
    }

    /**
     * Get the delay to fade in offending players that do not stop after losing audio focus.
     * @param aa The {@link android.media.AudioAttributes}
     * @return delay in milliseconds for the
     * {@link android.media.AudioAttributes.Attribute} or default delay if not configured
     */
    public long getDelayFadeInOffenders(@NonNull AudioAttributes aa) {
        return DEFAULT_DELAY_FADE_IN_OFFENDERS_MS;
    }

    /**
     * Check if it is allowed to fade for the given {@link android.media.AudioAttributes},
     * client uid and {@link android.media.AudioPlaybackConfiguration.PlayerType} config.
     * @param aa The {@link android.media.AudioAttributes}
     * @param uid The uid of the client owning the player
     * @param playerType The {@link android.media.AudioPlaybackConfiguration.PlayerType}
     * @return {@code true} if it the config is fadeable and {@code false} otherwise
     */
    public boolean isFadeable(@NonNull AudioAttributes aa, int uid,
            @AudioPlaybackConfiguration.PlayerType int playerType) {
        if (isPlayerTypeUnfadeable(playerType)) {
            if (DEBUG) {
                Slog.i(TAG, "not fadeable: player type:" + playerType);
            }
            return false;
        }
        if (isContentTypeUnfadeable(aa.getContentType())) {
            if (DEBUG) {
                Slog.i(TAG, "not fadeable: content type:" + aa.getContentType());
            }
            return false;
        }
        if (!isUsageFadeable(aa.getUsage())) {
            if (DEBUG) {
                Slog.i(TAG, "not fadeable: usage:" + aa.getUsage());
            }
            return false;
        }
        return true;
    }

    private boolean isUsageFadeable(int usage) {
        return getFadeableUsages().contains(usage);
    }

    private boolean isContentTypeUnfadeable(int contentType) {
        return getUnfadeableContentTypes().contains(contentType);
    }

    private boolean isPlayerTypeUnfadeable(int playerType) {
        return getUnfadeablePlayerTypes().contains(playerType);
    }
}
+78 −92
Original line number Diff line number Diff line
@@ -25,60 +25,26 @@ import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.server.utils.EventLogger;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;

/**
 * Class to handle fading out players
 */
public final class FadeOutManager {

    public static final String TAG = "AudioService.FadeOutManager";

    /** duration of the fade out curve */
    private 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
     */
    private static final long DELAY_FADE_IN_OFFENDERS_MS = 2000;
    public static final String TAG = "AS.FadeOutManager";

    private static final boolean DEBUG = PlaybackActivityMonitor.DEBUG;

    private static final VolumeShaper.Configuration FADEOUT_VSHAPE =
            new VolumeShaper.Configuration.Builder()
                    .setId(PlaybackActivityMonitor.VOLUME_SHAPER_SYSTEM_FADEOUT_ID)
                    .setCurve(new float[]{0.f, 0.25f, 1.0f} /* times */,
                            new float[]{1.f, 0.65f, 0.0f} /* volumes */)
                    .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
                    .setDuration(FADE_OUT_DURATION_MS)
                    .build();
    private static final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED =
            new VolumeShaper.Operation.Builder(VolumeShaper.Operation.PLAY)
                    .createIfNeeded()
                    .build();

    private static final int[] UNFADEABLE_PLAYER_TYPES = {
            AudioPlaybackConfiguration.PLAYER_TYPE_AAUDIO,
            AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL,
    };

    private static final int[] UNFADEABLE_CONTENT_TYPES = {
            AudioAttributes.CONTENT_TYPE_SPEECH,
    };

    private static final int[] FADEABLE_USAGES = {
            AudioAttributes.USAGE_GAME,
            AudioAttributes.USAGE_MEDIA,
    };

    // like a PLAY_CREATE_IF_NEEDED operation but with a skip to the end of the ramp
    private static final VolumeShaper.Operation PLAY_SKIP_RAMP =
            new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build();
@@ -91,6 +57,17 @@ public final class FadeOutManager {
    @GuardedBy("mLock")
    private final SparseArray<FadedOutApp> mUidToFadedAppsMap = new SparseArray<>();

    @GuardedBy("mLock")
    private FadeConfigurations mFadeConfigurations;

    public FadeOutManager() {
        mFadeConfigurations = new FadeConfigurations();
    }

    public FadeOutManager(FadeConfigurations fadeConfigurations) {
        mFadeConfigurations = Objects.requireNonNull(fadeConfigurations,
                "Fade configurations can not be null");
    }

    // TODO explore whether a shorter fade out would be a better UX instead of not fading out at all
    //      (legacy behavior)
@@ -98,7 +75,7 @@ public final class FadeOutManager {
     * Determine whether the focus request would trigger a fade out, given the parameters of the
     * requester and those of the focus loser
     * @param requester the parameters for the focus request
     * @return true if there can be a fade out over the requester starting to play
     * @return {@code true} if there can be a fade out over the requester starting to play
     */
    boolean canCauseFadeOut(@NonNull FocusRequester requester, @NonNull FocusRequester loser) {
        if (requester.getAudioAttributes().getContentType() == AudioAttributes.CONTENT_TYPE_SPEECH)
@@ -114,37 +91,19 @@ public final class FadeOutManager {
            }
            return false;
        }

        return true;
    }

    /**
     * Evaluates whether the player associated with this configuration can and should be faded out
     * @param apc the configuration of the player
     * @return true if player type and AudioAttributes are compatible with fade out
     * @return {@code true} if player type and AudioAttributes are compatible with fade out
     */
    boolean canBeFadedOut(@NonNull AudioPlaybackConfiguration apc) {
        if (ArrayUtils.contains(UNFADEABLE_PLAYER_TYPES, apc.getPlayerType())) {
            if (DEBUG) {
                Slog.i(TAG, "not fading: player type:" + apc.getPlayerType());
            }
            return false;
        }
        if (ArrayUtils.contains(UNFADEABLE_CONTENT_TYPES,
                apc.getAudioAttributes().getContentType())) {
            if (DEBUG) {
                Slog.i(TAG, "not fading: content type:"
                        + apc.getAudioAttributes().getContentType());
            }
            return false;
        }
        if (!ArrayUtils.contains(FADEABLE_USAGES, apc.getAudioAttributes().getUsage())) {
            if (DEBUG) {
                Slog.i(TAG, "not fading: usage:" + apc.getAudioAttributes().getUsage());
            }
            return false;
        synchronized (mLock) {
            return mFadeConfigurations.isFadeable(apc.getAudioAttributes(), apc.getClientUid(),
                    apc.getPlayerType());
        }
        return true;
    }

    /**
@@ -153,13 +112,9 @@ public final class FadeOutManager {
     * @return duration in milliseconds
     */
    long getFadeOutDurationOnFocusLossMillis(@NonNull AudioAttributes aa) {
        if (ArrayUtils.contains(UNFADEABLE_CONTENT_TYPES, aa.getContentType())) {
            return 0;
        }
        if (!ArrayUtils.contains(FADEABLE_USAGES, aa.getUsage())) {
            return 0;
        synchronized (mLock) {
            return mFadeConfigurations.getFadeOutDuration(aa);
        }
        return FADE_OUT_DURATION_MS;
    }

    /**
@@ -168,7 +123,9 @@ public final class FadeOutManager {
     * @return duration in milliseconds
     */
    long getFadeInDelayForOffendersMillis(@NonNull AudioAttributes aa) {
        return DELAY_FADE_IN_OFFENDERS_MS;
        synchronized (mLock) {
            return mFadeConfigurations.getDelayFadeInOffenders(aa);
        }
    }

    void fadeOutUid(int uid, ArrayList<AudioPlaybackConfiguration> players) {
@@ -179,7 +136,9 @@ public final class FadeOutManager {
            }
            final FadedOutApp fa = mUidToFadedAppsMap.get(uid);
            for (AudioPlaybackConfiguration apc : players) {
                fa.addFade(apc, /* skipRamp= */ false);
                final VolumeShaper.Configuration volShaper =
                        mFadeConfigurations.getFadeOutVolumeShaperConfig(apc.getAudioAttributes());
                fa.addFade(apc, /* skipRamp= */ false, volShaper);
            }
        }
    }
@@ -208,12 +167,15 @@ public final class FadeOutManager {
            Slog.v(TAG, "checkFade() player piid:"
                    + apc.getPlayerInterfaceId() + " uid:" + apc.getClientUid());
        }

        synchronized (mLock) {
            final VolumeShaper.Configuration volShaper =
                    mFadeConfigurations.getFadeOutVolumeShaperConfig(apc.getAudioAttributes());
            final FadedOutApp fa = mUidToFadedAppsMap.get(apc.getClientUid());
            if (fa == null) {
                return;
            }
            fa.addFade(apc, /* skipRamp= */ true);
            fa.addFade(apc, /* skipRamp= */ true, volShaper);
        }
    }

@@ -239,7 +201,7 @@ public final class FadeOutManager {
    /**
     * Check if uid is currently faded out
     * @param uid Client id
     * @return true if uid is currently faded out. Othwerwise, false.
     * @return {@code true} if uid is currently faded out. Othwerwise, {@code false}.
     */
    boolean isUidFadedOut(int uid) {
        synchronized (mLock) {
@@ -247,6 +209,16 @@ public final class FadeOutManager {
        }
    }

    /**
     * Update fade configurations used for player fade operations
     * @param fadeConfigurations set of configs that define fade properties
     */
    void setFadeConfigurations(@NonNull FadeConfigurations fadeConfigurations) {
        synchronized (mLock) {
            mFadeConfigurations = fadeConfigurations;
        }
    }

    void dump(PrintWriter pw) {
        synchronized (mLock) {
            for (int index = 0; index < mUidToFadedAppsMap.size(); index++) {
@@ -261,7 +233,8 @@ public final class FadeOutManager {
     */
    private static final class FadedOutApp {
        private final int mUid;
        private final ArrayList<Integer> mFadedPlayers = new ArrayList<Integer>();
        // key -> piid; value -> volume shaper config applied
        private final SparseArray<VolumeShaper.Configuration> mFadedPlayers = new SparseArray<>();

        FadedOutApp(int uid) {
            mUid = uid;
@@ -269,8 +242,9 @@ public final class FadeOutManager {

        void dump(PrintWriter pw) {
            pw.print("\t uid:" + mUid + " piids:");
            for (int piid : mFadedPlayers) {
                pw.print(" " + piid);
            for (int index = 0; index < mFadedPlayers.size(); index++) {
                pw.print("piid: " + mFadedPlayers.keyAt(index) + " Volume shaper: "
                        + mFadedPlayers.valueAt(index));
            }
            pw.println("");
        }
@@ -279,40 +253,52 @@ public final class FadeOutManager {
         * Add this player to the list of faded out players and apply the fade
         * @param apc a config that satisfies
         *      apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
         * @param skipRamp true if the player should be directly into the end of ramp state.
         *      This value would for instance be false when adding players at the start of a fade.
         * @param skipRamp {@code true} if the player should be directly into the end of ramp state.
         *      This value would for instance be {@code false} when adding players at the start
         *      of a fade.
         */
        void addFade(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) {
            final int piid = new Integer(apc.getPlayerInterfaceId());
            if (mFadedPlayers.contains(piid)) {
        void addFade(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp,
                @NonNull VolumeShaper.Configuration volShaper) {
            final int piid = Integer.valueOf(apc.getPlayerInterfaceId());

            // positive index return implies player is already faded
            if (mFadedPlayers.indexOfKey(piid) >= 0) {
                if (DEBUG) {
                    Slog.v(TAG, "player piid:" + piid + " already faded out");
                }
                return;
            }
            if (apc.getPlayerProxy() != null) {
                try {
                    PlaybackActivityMonitor.sEventLogger.enqueue(
                        (new PlaybackActivityMonitor.FadeOutEvent(apc, skipRamp)).printLog(TAG));
                apc.getPlayerProxy().applyVolumeShaper(
                        FADEOUT_VSHAPE,
                            (new PlaybackActivityMonitor.FadeOutEvent(apc, skipRamp)).printLog(
                                    TAG));
                    apc.getPlayerProxy().applyVolumeShaper(volShaper,
                            skipRamp ? PLAY_SKIP_RAMP : PLAY_CREATE_IF_NEEDED);
                mFadedPlayers.add(piid);
                    mFadedPlayers.put(piid, volShaper);
                } catch (Exception e) {
                    Slog.e(TAG, "Error fading out player piid:" + piid
                            + " uid:" + apc.getClientUid(), e);
                }
            } else {
                if (DEBUG) {
                    Slog.v(TAG, "Error fading out player piid:" + piid
                            + ", player not found for uid " + mUid);
                }
            }
        }

        void removeUnfadeAll(HashMap<Integer, AudioPlaybackConfiguration> players) {
            for (int piid : mFadedPlayers) {
            for (int index = 0; index < mFadedPlayers.size(); index++) {
                int piid = mFadedPlayers.keyAt(index);
                final AudioPlaybackConfiguration apc = players.get(piid);
                if (apc != null) {
                if ((apc != null) && (apc.getPlayerProxy() != null)) {
                    final VolumeShaper.Configuration volShaper = mFadedPlayers.valueAt(index);
                    try {
                        PlaybackActivityMonitor.sEventLogger.enqueue(
                                (new EventLogger.StringEvent("unfading out piid:"
                                        + piid)).printLog(TAG));
                        apc.getPlayerProxy().applyVolumeShaper(
                                FADEOUT_VSHAPE,
                        apc.getPlayerProxy().applyVolumeShaper(volShaper,
                                VolumeShaper.Operation.REVERSE);
                    } catch (Exception e) {
                        Slog.e(TAG, "Error unfading out player piid:" + piid + " uid:" + mUid, e);
@@ -329,7 +315,7 @@ public final class FadeOutManager {
        }

        void removeReleased(@NonNull AudioPlaybackConfiguration apc) {
            mFadedPlayers.remove(new Integer(apc.getPlayerInterfaceId()));
            mFadedPlayers.delete(Integer.valueOf(apc.getPlayerInterfaceId()));
        }
    }
}
+13 −12
Original line number Diff line number Diff line
@@ -156,6 +156,8 @@ public final class PlaybackActivityMonitor
    private final int mMaxAlarmVolume;
    private int mPrivilegedAlarmActiveCount = 0;
    private final Consumer<AudioDeviceAttributes> mMuteAwaitConnectionTimeoutCb;
    private final FadeOutManager mFadeOutManager;


    PlaybackActivityMonitor(Context context, int maxAlarmVolume,
            Consumer<AudioDeviceAttributes> muteTimeoutCallback) {
@@ -165,6 +167,7 @@ public final class PlaybackActivityMonitor
        AudioPlaybackConfiguration.sPlayerDeathMonitor = this;
        mMuteAwaitConnectionTimeoutCb = muteTimeoutCallback;
        initEventHandler();
        mFadeOutManager = new FadeOutManager(new FadeConfigurations());
    }

    //=================================================================
@@ -390,7 +393,7 @@ public final class PlaybackActivityMonitor
            if (change) {
                if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    mDuckingManager.checkDuck(apc);
                    mFadingManager.checkFade(apc);
                    mFadeOutManager.checkFade(apc);
                }
                if (doNotLog) {
                    // do not dispatch events for "ignored" players
@@ -473,7 +476,7 @@ public final class PlaybackActivityMonitor
                        "releasing player piid:" + piid));
                mPlayers.remove(new Integer(piid));
                mDuckingManager.removeReleased(apc);
                mFadingManager.removeReleased(apc);
                mFadeOutManager.removeReleased(apc);
                mMutedPlayersAwaitingConnection.remove(Integer.valueOf(piid));
                checkVolumeForPrivilegedAlarm(apc, AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
                change = apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED,
@@ -643,7 +646,7 @@ public final class PlaybackActivityMonitor
            mDuckingManager.dump(pw);
            // faded out players
            pw.println("\n  faded out players piids:");
            mFadingManager.dump(pw);
            mFadeOutManager.dump(pw);
            // players muted due to the device ringing or being in a call
            pw.print("\n  muted player piids due to call/ring:");
            for (int piid : mMutedPlayers) {
@@ -823,7 +826,7 @@ public final class PlaybackActivityMonitor
        if (DEBUG) { Log.v(TAG, "unduckPlayers: uids winner=" + winner.getClientUid()); }
        synchronized (mPlayerLock) {
            mDuckingManager.unduckUid(winner.getClientUid(), mPlayers);
            mFadingManager.unfadeOutUid(winner.getClientUid(), mPlayers);
            mFadeOutManager.unfadeOutUid(winner.getClientUid(), mPlayers);
        }
    }

@@ -892,8 +895,6 @@ public final class PlaybackActivityMonitor
        }
    }

    private final FadeOutManager mFadingManager = new FadeOutManager();

    /**
     *
     * @param winner the new non-transient focus owner
@@ -914,7 +915,7 @@ public final class PlaybackActivityMonitor
                if (DEBUG) { Log.v(TAG, "no players to fade out"); }
                return false;
            }
            if (!mFadingManager.canCauseFadeOut(winner, loser)) {
            if (!mFadeOutManager.canCauseFadeOut(winner, loser)) {
                return false;
            }
            // check if this UID needs to be faded out (return false if not), and gather list of
@@ -928,7 +929,7 @@ public final class PlaybackActivityMonitor
                        && loser.hasSameUid(apc.getClientUid())
                        && apc.getPlayerState()
                        == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    if (!mFadingManager.canBeFadedOut(apc)) {
                    if (!mFadeOutManager.canBeFadedOut(apc)) {
                        // the player is not eligible to be faded out, bail
                        Log.v(TAG, "not fading out player " + apc.getPlayerInterfaceId()
                                + " uid:" + apc.getClientUid() + " pid:" + apc.getClientPid()
@@ -943,7 +944,7 @@ public final class PlaybackActivityMonitor
                }
            }
            if (loserHasActivePlayers) {
                mFadingManager.fadeOutUid(loser.getClientUid(), apcsToFadeOut);
                mFadeOutManager.fadeOutUid(loser.getClientUid(), apcsToFadeOut);
            }
        }

@@ -956,18 +957,18 @@ public final class PlaybackActivityMonitor
        synchronized (mPlayerLock) {
            players = (HashMap<Integer, AudioPlaybackConfiguration>) mPlayers.clone();
        }
        mFadingManager.unfadeOutUid(uid, players);
        mFadeOutManager.unfadeOutUid(uid, players);
        mDuckingManager.unduckUid(uid, players);
    }

    @Override
    public long getFadeOutDurationMillis(@NonNull AudioAttributes aa) {
        return mFadingManager.getFadeOutDurationOnFocusLossMillis(aa);
        return mFadeOutManager.getFadeOutDurationOnFocusLossMillis(aa);
    }

    @Override
    public long getFadeInDelayForOffendersMillis(@NonNull AudioAttributes aa) {
        return mFadingManager.getFadeInDelayForOffendersMillis(aa);
        return mFadeOutManager.getFadeInDelayForOffendersMillis(aa);
    }

    //=================================================================
+159 −0

File added.

Preview size limit exceeded, changes collapsed.

+12 −1

File changed.

Preview size limit exceeded, changes collapsed.