/*
 * Copyright (C) 2016 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.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.AudioSystem;
import android.media.IPlaybackConfigDispatcher;
import android.media.PlayerBase;
import android.media.VolumeShaper;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;

import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;

/**
 * Class to receive and dispatch updates from AudioSystem about recording configurations.
 */
public final class PlaybackActivityMonitor
        implements AudioPlaybackConfiguration.PlayerDeathMonitor, PlayerFocusEnforcer {

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

    /*package*/ static final boolean DEBUG = false;
    /*package*/ static final int VOLUME_SHAPER_SYSTEM_DUCK_ID = 1;
    /*package*/ static final int VOLUME_SHAPER_SYSTEM_FADEOUT_ID = 2;
    /*package*/ static final int VOLUME_SHAPER_SYSTEM_MUTE_AWAIT_CONNECTION_ID = 3;

    private static final VolumeShaper.Configuration DUCK_VSHAPE =
            new VolumeShaper.Configuration.Builder()
                .setId(VOLUME_SHAPER_SYSTEM_DUCK_ID)
                .setCurve(new float[] { 0.f, 1.f } /* times */,
                    new float[] { 1.f, 0.2f } /* volumes */)
                .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
                .setDuration(MediaFocusControl.getFocusRampTimeMs(
                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
                    new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
                            .build()))
                .build();
    private static final VolumeShaper.Configuration DUCK_ID =
            new VolumeShaper.Configuration(VOLUME_SHAPER_SYSTEM_DUCK_ID);
    private static final VolumeShaper.Operation PLAY_CREATE_IF_NEEDED =
            new VolumeShaper.Operation.Builder(VolumeShaper.Operation.PLAY)
                    .createIfNeeded()
                    .build();

    private static final long UNMUTE_DURATION_MS = 100;
    private static final VolumeShaper.Configuration MUTE_AWAIT_CONNECTION_VSHAPE =
            new VolumeShaper.Configuration.Builder()
                    .setId(VOLUME_SHAPER_SYSTEM_MUTE_AWAIT_CONNECTION_ID)
                    .setCurve(new float[] { 0.f, 1.f } /* times */,
                            new float[] { 1.f, 0.f } /* volumes */)
                    .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
                    // even though we specify a duration, it's only used for the unmute,
                    // for muting this volume shaper is run with PLAY_SKIP_RAMP
                    .setDuration(UNMUTE_DURATION_MS)
                    .build();

    // TODO support VolumeShaper on those players
    private static final int[] UNDUCKABLE_PLAYER_TYPES = {
            AudioPlaybackConfiguration.PLAYER_TYPE_AAUDIO,
            AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL,
    };

    // 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();

    private final ConcurrentLinkedQueue<PlayMonitorClient> mClients = new ConcurrentLinkedQueue<>();

    private final Object mPlayerLock = new Object();
    @GuardedBy("mPlayerLock")
    private final HashMap<Integer, AudioPlaybackConfiguration> mPlayers =
            new HashMap<Integer, AudioPlaybackConfiguration>();

    private final Context mContext;
    private int mSavedAlarmVolume = -1;
    private final int mMaxAlarmVolume;
    private int mPrivilegedAlarmActiveCount = 0;
    private final Consumer<AudioDeviceAttributes> mMuteAwaitConnectionTimeoutCb;

    PlaybackActivityMonitor(Context context, int maxAlarmVolume,
            Consumer<AudioDeviceAttributes> muteTimeoutCallback) {
        mContext = context;
        mMaxAlarmVolume = maxAlarmVolume;
        PlayMonitorClient.sListenerDeathMonitor = this;
        AudioPlaybackConfiguration.sPlayerDeathMonitor = this;
        mMuteAwaitConnectionTimeoutCb = muteTimeoutCallback;
        initEventHandler();
    }

    //=================================================================
    private final ArrayList<Integer> mBannedUids = new ArrayList<Integer>();

    // see AudioManagerInternal.disableAudioForUid(boolean disable, int uid)
    public void disableAudioForUid(boolean disable, int uid) {
        synchronized(mPlayerLock) {
            final int index = mBannedUids.indexOf(new Integer(uid));
            if (index >= 0) {
                if (!disable) {
                    if (DEBUG) { // hidden behind DEBUG, too noisy otherwise
                        sEventLogger.log(new AudioEventLogger.StringEvent("unbanning uid:" + uid));
                    }
                    mBannedUids.remove(index);
                    // nothing else to do, future playback requests from this uid are ok
                } // no else to handle, uid already present, so disabling again is no-op
            } else {
                if (disable) {
                    for (AudioPlaybackConfiguration apc : mPlayers.values()) {
                        checkBanPlayer(apc, uid);
                    }
                    if (DEBUG) { // hidden behind DEBUG, too noisy otherwise
                        sEventLogger.log(new AudioEventLogger.StringEvent("banning uid:" + uid));
                    }
                    mBannedUids.add(new Integer(uid));
                } // no else to handle, uid already not in list, so enabling again is no-op
            }
        }
    }

    private boolean checkBanPlayer(@NonNull AudioPlaybackConfiguration apc, int uid) {
        final boolean toBan = (apc.getClientUid() == uid);
        if (toBan) {
            final int piid = apc.getPlayerInterfaceId();
            try {
                Log.v(TAG, "banning player " + piid + " uid:" + uid);
                apc.getPlayerProxy().pause();
            } catch (Exception e) {
                Log.e(TAG, "error banning player " + piid + " uid:" + uid, e);
            }
        }
        return toBan;
    }

    //=================================================================
    // Track players and their states
    // methods playerAttributes, playerEvent, releasePlayer are all oneway calls
    //  into AudioService. They trigger synchronous dispatchPlaybackChange() which updates
    //  all listeners as oneway calls.

    public int trackPlayer(PlayerBase.PlayerIdCard pic) {
        final int newPiid = AudioSystem.newAudioPlayerId();
        if (DEBUG) { Log.v(TAG, "trackPlayer() new piid=" + newPiid); }
        final AudioPlaybackConfiguration apc =
                new AudioPlaybackConfiguration(pic, newPiid,
                        Binder.getCallingUid(), Binder.getCallingPid());
        apc.init();
        synchronized (mAllowedCapturePolicies) {
            int uid = apc.getClientUid();
            if (mAllowedCapturePolicies.containsKey(uid)) {
                updateAllowedCapturePolicy(apc, mAllowedCapturePolicies.get(uid));
            }
        }
        sEventLogger.log(new NewPlayerEvent(apc));
        synchronized(mPlayerLock) {
            mPlayers.put(newPiid, apc);
            maybeMutePlayerAwaitingConnection(apc);
        }
        return newPiid;
    }

    public void playerAttributes(int piid, @NonNull AudioAttributes attr, int binderUid) {
        final boolean change;
        synchronized (mAllowedCapturePolicies) {
            if (mAllowedCapturePolicies.containsKey(binderUid)
                    && attr.getAllowedCapturePolicy() < mAllowedCapturePolicies.get(binderUid)) {
                attr = new AudioAttributes.Builder(attr)
                        .setAllowedCapturePolicy(mAllowedCapturePolicies.get(binderUid)).build();
            }
        }
        synchronized(mPlayerLock) {
            final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
            if (checkConfigurationCaller(piid, apc, binderUid)) {
                sEventLogger.log(new AudioAttrEvent(piid, attr));
                change = apc.handleAudioAttributesEvent(attr);
            } else {
                Log.e(TAG, "Error updating audio attributes");
                change = false;
            }
        }
        if (change) {
            dispatchPlaybackChange(false);
        }
    }

    /**
     * Update player session ID
     * @param piid Player id to update
     * @param sessionId The new audio session ID
     * @param binderUid Calling binder uid
     */
    public void playerSessionId(int piid, int sessionId, int binderUid) {
        final boolean change;
        synchronized (mPlayerLock) {
            final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
            if (checkConfigurationCaller(piid, apc, binderUid)) {
                change = apc.handleSessionIdEvent(sessionId);
            } else {
                Log.e(TAG, "Error updating audio session");
                change = false;
            }
        }
        if (change) {
            dispatchPlaybackChange(false);
        }
    }

    private static final int FLAGS_FOR_SILENCE_OVERRIDE =
            AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY |
            AudioAttributes.FLAG_BYPASS_MUTE;

    private void checkVolumeForPrivilegedAlarm(AudioPlaybackConfiguration apc, int event) {
        if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID) {
            return;
        }
        if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED ||
                apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
            if ((apc.getAudioAttributes().getAllFlags() & FLAGS_FOR_SILENCE_OVERRIDE)
                        == FLAGS_FOR_SILENCE_OVERRIDE  &&
                    apc.getAudioAttributes().getUsage() == AudioAttributes.USAGE_ALARM &&
                    mContext.checkPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
                            apc.getClientPid(), apc.getClientUid()) ==
                            PackageManager.PERMISSION_GRANTED) {
                if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED &&
                        apc.getPlayerState() != AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    if (mPrivilegedAlarmActiveCount++ == 0) {
                        mSavedAlarmVolume = AudioSystem.getStreamVolumeIndex(
                                AudioSystem.STREAM_ALARM, AudioSystem.DEVICE_OUT_SPEAKER);
                        AudioSystem.setStreamVolumeIndexAS(AudioSystem.STREAM_ALARM,
                                mMaxAlarmVolume, AudioSystem.DEVICE_OUT_SPEAKER);
                    }
                } else if (event != AudioPlaybackConfiguration.PLAYER_STATE_STARTED &&
                        apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    if (--mPrivilegedAlarmActiveCount == 0) {
                        if (AudioSystem.getStreamVolumeIndex(
                                AudioSystem.STREAM_ALARM, AudioSystem.DEVICE_OUT_SPEAKER) ==
                                mMaxAlarmVolume) {
                            AudioSystem.setStreamVolumeIndexAS(AudioSystem.STREAM_ALARM,
                                    mSavedAlarmVolume, AudioSystem.DEVICE_OUT_SPEAKER);
                        }
                    }
                }
            }
        }
    }

    /**
     * Update player event
     * @param piid Player id to update
     * @param event The new player event
     * @param deviceId The new player device id
     * @param binderUid Calling binder uid
     */
    public void playerEvent(int piid, int event, int deviceId, int binderUid) {
        if (DEBUG) {
            Log.v(TAG, String.format("playerEvent(piid=%d, deviceId=%d, event=%s)",
                    piid, deviceId, AudioPlaybackConfiguration.playerStateToString(event)));
        }
        final boolean change;
        synchronized(mPlayerLock) {
            final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
            if (apc == null) {
                return;
            }
            sEventLogger.log(new PlayerEvent(piid, event, deviceId));
            if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                for (Integer uidInteger: mBannedUids) {
                    if (checkBanPlayer(apc, uidInteger.intValue())) {
                        // player was banned, do not update its state
                        sEventLogger.log(new AudioEventLogger.StringEvent(
                                "not starting piid:" + piid + " ,is banned"));
                        return;
                    }
                }
            }
            if (apc.getPlayerType() == AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL) {
                // FIXME SoundPool not ready for state reporting
                return;
            }
            if (checkConfigurationCaller(piid, apc, binderUid)) {
                //TODO add generation counter to only update to the latest state
                checkVolumeForPrivilegedAlarm(apc, event);
                change = apc.handleStateEvent(event, deviceId);
            } else {
                Log.e(TAG, "Error handling event " + event);
                change = false;
            }
            if (change && event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                mDuckingManager.checkDuck(apc);
                mFadingManager.checkFade(apc);
            }
        }
        if (change) {
            dispatchPlaybackChange(event == AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
        }
    }

    public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio, int binderUid) {
        // no check on UID yet because this is only for logging at the moment
        sEventLogger.log(new PlayerOpPlayAudioEvent(piid, hasOpPlayAudio, binderUid));
    }

    public void releasePlayer(int piid, int binderUid) {
        if (DEBUG) { Log.v(TAG, "releasePlayer() for piid=" + piid); }
        boolean change = false;
        synchronized(mPlayerLock) {
            final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
            if (checkConfigurationCaller(piid, apc, binderUid)) {
                sEventLogger.log(new AudioEventLogger.StringEvent(
                        "releasing player piid:" + piid));
                mPlayers.remove(new Integer(piid));
                mDuckingManager.removeReleased(apc);
                mFadingManager.removeReleased(apc);
                mMutedPlayersAwaitingConnection.remove(Integer.valueOf(piid));
                checkVolumeForPrivilegedAlarm(apc, AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
                change = apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED,
                        AudioPlaybackConfiguration.PLAYER_DEVICEID_INVALID);
            }
        }
        if (change) {
            dispatchPlaybackChange(true /*iplayerreleased*/);
        }
    }

    /**
     * A map of uid to capture policy.
     */
    private final HashMap<Integer, Integer> mAllowedCapturePolicies =
            new HashMap<Integer, Integer>();

    /**
     * Cache allowed capture policy, which specifies whether the audio played by the app may or may
     * not be captured by other apps or the system.
     *
     * @param uid the uid of requested app
     * @param capturePolicy one of
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
     *     {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
     */
    public void setAllowedCapturePolicy(int uid, int capturePolicy) {
        synchronized (mAllowedCapturePolicies) {
            if (capturePolicy == AudioAttributes.ALLOW_CAPTURE_BY_ALL) {
                // When the capture policy is ALLOW_CAPTURE_BY_ALL, it is okay to
                // remove it from cached capture policy as it is the default value.
                mAllowedCapturePolicies.remove(uid);
                return;
            } else {
                mAllowedCapturePolicies.put(uid, capturePolicy);
            }
        }
        synchronized (mPlayerLock) {
            for (AudioPlaybackConfiguration apc : mPlayers.values()) {
                if (apc.getClientUid() == uid) {
                    updateAllowedCapturePolicy(apc, capturePolicy);
                }
            }
        }
    }

    /**
     * Return the capture policy for given uid.
     * @param uid the uid to query its cached capture policy.
     * @return cached capture policy for given uid or AudioAttributes.ALLOW_CAPTURE_BY_ALL
     *         if there is not cached capture policy.
     */
    public int getAllowedCapturePolicy(int uid) {
        return mAllowedCapturePolicies.getOrDefault(uid, AudioAttributes.ALLOW_CAPTURE_BY_ALL);
    }

    /**
     * Return a copy of all cached capture policies.
     */
    public HashMap<Integer, Integer> getAllAllowedCapturePolicies() {
        synchronized (mAllowedCapturePolicies) {
            return (HashMap<Integer, Integer>) mAllowedCapturePolicies.clone();
        }
    }

    private void updateAllowedCapturePolicy(AudioPlaybackConfiguration apc, int capturePolicy) {
        AudioAttributes attr = apc.getAudioAttributes();
        if (attr.getAllowedCapturePolicy() >= capturePolicy) {
            return;
        }
        apc.handleAudioAttributesEvent(
                new AudioAttributes.Builder(apc.getAudioAttributes())
                        .setAllowedCapturePolicy(capturePolicy).build());
    }

    // Implementation of AudioPlaybackConfiguration.PlayerDeathMonitor
    @Override
    public void playerDeath(int piid) {
        releasePlayer(piid, 0);
    }

    /**
     * Returns true if a player belonging to the app with given uid is active.
     *
     * @param uid the app uid
     * @return true if a player is active, false otherwise
     */
    public boolean isPlaybackActiveForUid(int uid) {
        synchronized (mPlayerLock) {
            for (AudioPlaybackConfiguration apc : mPlayers.values()) {
                if (apc.isActive() && apc.getClientUid() == uid) {
                    return true;
                }
            }
        }
        return false;
    }

    protected void dump(PrintWriter pw) {
        // players
        pw.println("\nPlaybackActivityMonitor dump time: "
                + DateFormat.getTimeInstance().format(new Date()));
        synchronized(mPlayerLock) {
            pw.println("\n  playback listeners:");
            for (PlayMonitorClient pmc : mClients) {
                pw.print(" " + (pmc.isPrivileged() ? "(S)" : "(P)")
                        + pmc.toString());
            }
            pw.println("\n");
            // all players
            pw.println("\n  players:");
            final List<Integer> piidIntList = new ArrayList<Integer>(mPlayers.keySet());
            Collections.sort(piidIntList);
            for (Integer piidInt : piidIntList) {
                final AudioPlaybackConfiguration apc = mPlayers.get(piidInt);
                if (apc != null) {
                    apc.dump(pw);
                }
            }
            // ducked players
            pw.println("\n  ducked players piids:");
            mDuckingManager.dump(pw);
            // faded out players
            pw.println("\n  faded out players piids:");
            mFadingManager.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) {
                pw.print(" " + piid);
            }
            pw.println();
            // banned players:
            pw.print("\n  banned uids:");
            for (int uid : mBannedUids) {
                pw.print(" " + uid);
            }
            pw.println("\n");
            // muted players:
            pw.print("\n  muted players (piids) awaiting device connection:");
            for (int piid : mMutedPlayersAwaitingConnection) {
                pw.print(" " + piid);
            }
            pw.println("\n");
            // log
            sEventLogger.dump(pw);
        }
        synchronized (mAllowedCapturePolicies) {
            pw.println("\n  allowed capture policies:");
            for (HashMap.Entry<Integer, Integer> entry : mAllowedCapturePolicies.entrySet()) {
                pw.println("  uid: " + entry.getKey() + " policy: " + entry.getValue());
            }
        }
    }

    /**
     * Check that piid and uid are valid for the given valid configuration.
     * @param piid the piid of the player.
     * @param apc the configuration found for this piid.
     * @param binderUid actual uid of client trying to signal a player state/event/attributes.
     * @return true if the call is valid and the change should proceed, false otherwise. Always
     *      returns false when apc is null.
     */
    private static boolean checkConfigurationCaller(int piid,
            final AudioPlaybackConfiguration apc, int binderUid) {
        if (apc == null) {
            return false;
        } else if ((binderUid != 0) && (apc.getClientUid() != binderUid)) {
            Log.e(TAG, "Forbidden operation from uid " + binderUid + " for player " + piid);
            return false;
        }
        return true;
    }

    /**
     * Sends new list after update of playback configurations
     * @param iplayerReleased indicates if the change was due to a player being released
     */
    private void dispatchPlaybackChange(boolean iplayerReleased) {
        if (DEBUG) { Log.v(TAG, "dispatchPlaybackChange to " + mClients.size() + " clients"); }
        final List<AudioPlaybackConfiguration> configsSystem;
        // list of playback configurations for "public consumption". It is computed lazy if there
        // are non-system playback activity listeners.
        List<AudioPlaybackConfiguration> configsPublic = null;
        synchronized (mPlayerLock) {
            if (mPlayers.isEmpty()) {
                return;
            }
            configsSystem = new ArrayList<>(mPlayers.values());
        }

        final Iterator<PlayMonitorClient> clientIterator = mClients.iterator();
        while (clientIterator.hasNext()) {
            final PlayMonitorClient pmc = clientIterator.next();
            // do not spam the logs if there are problems communicating with this client
            if (!pmc.reachedMaxErrorCount()) {
                if (pmc.isPrivileged()) {
                    pmc.dispatchPlaybackConfigChange(configsSystem,
                            iplayerReleased);
                } else {
                    if (configsPublic == null) {
                        configsPublic = anonymizeForPublicConsumption(configsSystem);
                    }
                    // non-system clients don't have the control interface IPlayer, so
                    // they don't need to flush commands when a player was released
                    pmc.dispatchPlaybackConfigChange(configsPublic, false);
                }
            }
        }
    }

    private ArrayList<AudioPlaybackConfiguration> anonymizeForPublicConsumption(
            List<AudioPlaybackConfiguration> sysConfigs) {
        ArrayList<AudioPlaybackConfiguration> publicConfigs =
                new ArrayList<AudioPlaybackConfiguration>();
        // only add active anonymized configurations,
        for (AudioPlaybackConfiguration config : sysConfigs) {
            if (config.isActive()) {
                publicConfigs.add(AudioPlaybackConfiguration.anonymizedCopy(config));
            }
        }
        return publicConfigs;
    }


    //=================================================================
    // PlayerFocusEnforcer implementation
    private final ArrayList<Integer> mMutedPlayers = new ArrayList<Integer>();

    private final DuckingManager mDuckingManager = new DuckingManager();

    @Override
    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()));
        }
        synchronized (mPlayerLock) {
            if (mPlayers.isEmpty()) {
                return true;
            }
            // check if this UID needs to be ducked (return false if not), and gather list of
            // eligible players to duck
            final Iterator<AudioPlaybackConfiguration> apcIterator = mPlayers.values().iterator();
            final ArrayList<AudioPlaybackConfiguration> apcsToDuck =
                    new ArrayList<AudioPlaybackConfiguration>();
            while (apcIterator.hasNext()) {
                final AudioPlaybackConfiguration apc = apcIterator.next();
                if (!winner.hasSameUid(apc.getClientUid())
                        && loser.hasSameUid(apc.getClientUid())
                        && apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED)
                {
                    if (!forceDuck && (apc.getAudioAttributes().getContentType() ==
                            AudioAttributes.CONTENT_TYPE_SPEECH)) {
                        // the player is speaking, ducking will make the speech unintelligible
                        // so let the app handle it instead
                        Log.v(TAG, "not ducking player " + apc.getPlayerInterfaceId()
                                + " uid:" + apc.getClientUid() + " pid:" + apc.getClientPid()
                                + " - SPEECH");
                        return false;
                    } else if (ArrayUtils.contains(UNDUCKABLE_PLAYER_TYPES, apc.getPlayerType())) {
                        Log.v(TAG, "not ducking player " + apc.getPlayerInterfaceId()
                                + " uid:" + apc.getClientUid() + " pid:" + apc.getClientPid()
                                + " due to type:"
                                + AudioPlaybackConfiguration.toLogFriendlyPlayerType(
                                        apc.getPlayerType()));
                        return false;
                    }
                    apcsToDuck.add(apc);
                }
            }
            // add the players eligible for ducking to the list, and duck them
            // (if apcsToDuck is empty, this will at least mark this uid as ducked, so when
            //  players of the same uid start, they will be ducked by DuckingManager.checkDuck())
            mDuckingManager.duckUid(loser.getClientUid(), apcsToDuck);
        }
        return true;
    }

    @Override
    public void restoreVShapedPlayers(@NonNull FocusRequester winner) {
        if (DEBUG) { Log.v(TAG, "unduckPlayers: uids winner=" + winner.getClientUid()); }
        synchronized (mPlayerLock) {
            mDuckingManager.unduckUid(winner.getClientUid(), mPlayers);
            mFadingManager.unfadeOutUid(winner.getClientUid(), mPlayers);
        }
    }

    @Override
    public void mutePlayersForCall(int[] usagesToMute) {
        if (DEBUG) {
            String log = new String("mutePlayersForCall: usages=");
            for (int usage : usagesToMute) { log += " " + usage; }
            Log.v(TAG, log);
        }
        synchronized (mPlayerLock) {
            final Set<Integer> piidSet = mPlayers.keySet();
            final Iterator<Integer> piidIterator = piidSet.iterator();
            // find which players to mute
            while (piidIterator.hasNext()) {
                final Integer piid = piidIterator.next();
                final AudioPlaybackConfiguration apc = mPlayers.get(piid);
                if (apc == null) {
                    continue;
                }
                final int playerUsage = apc.getAudioAttributes().getUsage();
                boolean mute = false;
                for (int usageToMute : usagesToMute) {
                    if (playerUsage == usageToMute) {
                        mute = true;
                        break;
                    }
                }
                if (mute) {
                    try {
                        sEventLogger.log((new AudioEventLogger.StringEvent("call: muting piid:"
                                + piid + " uid:" + apc.getClientUid())).printLog(TAG));
                        apc.getPlayerProxy().setVolume(0.0f);
                        mMutedPlayers.add(new Integer(piid));
                    } catch (Exception e) {
                        Log.e(TAG, "call: error muting player " + piid, e);
                    }
                }
            }
        }
    }

    @Override
    public void unmutePlayersForCall() {
        if (DEBUG) {
            Log.v(TAG, "unmutePlayersForCall()");
        }
        synchronized (mPlayerLock) {
            if (mMutedPlayers.isEmpty()) {
                return;
            }
            for (int piid : mMutedPlayers) {
                final AudioPlaybackConfiguration apc = mPlayers.get(piid);
                if (apc != null) {
                    try {
                        sEventLogger.log(new AudioEventLogger.StringEvent("call: unmuting piid:"
                                + piid).printLog(TAG));
                        apc.getPlayerProxy().setVolume(1.0f);
                    } catch (Exception e) {
                        Log.e(TAG, "call: error unmuting player " + piid + " uid:"
                                + apc.getClientUid(), e);
                    }
                }
            }
            mMutedPlayers.clear();
        }
    }

    private final FadeOutManager mFadingManager = new FadeOutManager();

    /**
     *
     * @param winner the new non-transient focus owner
     * @param loser the previous focus owner
     * @return true if there are players being faded out
     */
    @Override
    public boolean fadeOutPlayers(@NonNull FocusRequester winner, @NonNull FocusRequester loser) {
        if (DEBUG) {
            Log.v(TAG, "fadeOutPlayers: winner=" + winner.getPackageName()
                    +  " loser=" + loser.getPackageName());
        }
        boolean loserHasActivePlayers = false;

        // find which players to fade out
        synchronized (mPlayerLock) {
            if (mPlayers.isEmpty()) {
                if (DEBUG) { Log.v(TAG, "no players to fade out"); }
                return false;
            }
            if (!FadeOutManager.canCauseFadeOut(winner, loser)) {
                return false;
            }
            // check if this UID needs to be faded out (return false if not), and gather list of
            // eligible players to fade out
            final Iterator<AudioPlaybackConfiguration> apcIterator = mPlayers.values().iterator();
            final ArrayList<AudioPlaybackConfiguration> apcsToFadeOut =
                    new ArrayList<AudioPlaybackConfiguration>();
            while (apcIterator.hasNext()) {
                final AudioPlaybackConfiguration apc = apcIterator.next();
                if (!winner.hasSameUid(apc.getClientUid())
                        && loser.hasSameUid(apc.getClientUid())
                        && apc.getPlayerState()
                        == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
                    if (!FadeOutManager.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()
                                + " type:"
                                + AudioPlaybackConfiguration.toLogFriendlyPlayerType(
                                        apc.getPlayerType())
                                + " attr:" + apc.getAudioAttributes());
                        return false;
                    }
                    loserHasActivePlayers = true;
                    apcsToFadeOut.add(apc);
                }
            }
            if (loserHasActivePlayers) {
                mFadingManager.fadeOutUid(loser.getClientUid(), apcsToFadeOut);
            }
        }

        return loserHasActivePlayers;
    }

    @Override
    public void forgetUid(int uid) {
        final HashMap<Integer, AudioPlaybackConfiguration> players;
        synchronized (mPlayerLock) {
            players = (HashMap<Integer, AudioPlaybackConfiguration>) mPlayers.clone();
        }
        mFadingManager.unfadeOutUid(uid, players);
    }

    //=================================================================
    // Track playback activity listeners

    void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb, boolean isPrivileged) {
        if (pcdb == null) {
            return;
        }
        final PlayMonitorClient pmc = new PlayMonitorClient(pcdb, isPrivileged);
        if (pmc.init()) {
            mClients.add(pmc);
        }
    }

    void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
        if (pcdb == null) {
            return;
        }
        final Iterator<PlayMonitorClient> clientIterator = mClients.iterator();
        // iterate over the clients to remove the dispatcher
        while (clientIterator.hasNext()) {
            PlayMonitorClient pmc = clientIterator.next();
            if (pmc.equalsDispatcher(pcdb)) {
                pmc.release();
                clientIterator.remove();
            }
        }
    }

    List<AudioPlaybackConfiguration> getActivePlaybackConfigurations(boolean isPrivileged) {
        synchronized(mPlayers) {
            if (isPrivileged) {
                return new ArrayList<AudioPlaybackConfiguration>(mPlayers.values());
            } else {
                final List<AudioPlaybackConfiguration> configsPublic;
                synchronized (mPlayerLock) {
                    configsPublic = anonymizeForPublicConsumption(
                            new ArrayList<AudioPlaybackConfiguration>(mPlayers.values()));
                }
                return configsPublic;
            }
        }
    }


    /**
     * Inner class to track clients that want to be notified of playback updates
     */
    private static final class PlayMonitorClient implements IBinder.DeathRecipient {

        // can afford to be static because only one PlaybackActivityMonitor ever instantiated
        static PlaybackActivityMonitor sListenerDeathMonitor;

        // number of errors after which we don't update this client anymore to not spam the logs
        private static final int MAX_ERRORS = 5;

        private final IPlaybackConfigDispatcher mDispatcherCb;

        @GuardedBy("this")
        private final boolean mIsPrivileged;
        @GuardedBy("this")
        private boolean mIsReleased = false;
        @GuardedBy("this")
        private int mErrorCount = 0;

        PlayMonitorClient(IPlaybackConfigDispatcher pcdb, boolean isPrivileged) {
            mDispatcherCb = pcdb;
            mIsPrivileged = isPrivileged;
        }

        @Override
        public void binderDied() {
            Log.w(TAG, "client died");
            sListenerDeathMonitor.unregisterPlaybackCallback(mDispatcherCb);
        }

        synchronized boolean init() {
            if (mIsReleased) {
                // Do not init after release
                return false;
            }
            try {
                mDispatcherCb.asBinder().linkToDeath(this, 0);
                return true;
            } catch (RemoteException e) {
                Log.w(TAG, "Could not link to client death", e);
                return false;
            }
        }

        synchronized void release() {
            mDispatcherCb.asBinder().unlinkToDeath(this, 0);
            mIsReleased = true;
        }

        void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
                boolean flush) {
            synchronized (this) {
                if (mIsReleased) {
                    // Do not dispatch anything after release
                    return;
                }
            }
            try {
                mDispatcherCb.dispatchPlaybackConfigChange(configs, flush);
            } catch (RemoteException e) {
                synchronized (this) {
                    mErrorCount++;
                    Log.e(TAG, "Error (" + mErrorCount
                            + ") trying to dispatch playback config change to " + this, e);
                }
            }
        }

        synchronized boolean isPrivileged() {
            return mIsPrivileged;
        }

        synchronized boolean reachedMaxErrorCount() {
            return mErrorCount >= MAX_ERRORS;
        }

        synchronized boolean equalsDispatcher(IPlaybackConfigDispatcher pcdb) {
            if (pcdb == null) {
                return false;
            }
            return pcdb.asBinder().equals(mDispatcherCb.asBinder());
        }
    }

    //=================================================================
    // Class to handle ducking related operations for a given UID
    private static final class DuckingManager {
        private final HashMap<Integer, DuckedApp> mDuckers = new HashMap<Integer, DuckedApp>();

        synchronized void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) {
            if (DEBUG) {  Log.v(TAG, "DuckingManager: duckUid() uid:"+ uid); }
            if (!mDuckers.containsKey(uid)) {
                mDuckers.put(uid, new DuckedApp(uid));
            }
            final DuckedApp da = mDuckers.get(uid);
            for (AudioPlaybackConfiguration apc : apcsToDuck) {
                da.addDuck(apc, false /*skipRamp*/);
            }
        }

        synchronized void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) {
            if (DEBUG) {  Log.v(TAG, "DuckingManager: unduckUid() uid:"+ uid); }
            final DuckedApp da = mDuckers.remove(uid);
            if (da == null) {
                return;
            }
            da.removeUnduckAll(players);
        }

        // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
        synchronized void checkDuck(@NonNull AudioPlaybackConfiguration apc) {
            if (DEBUG) {  Log.v(TAG, "DuckingManager: checkDuck() player piid:"
                    + apc.getPlayerInterfaceId()+ " uid:"+ apc.getClientUid()); }
            final DuckedApp da = mDuckers.get(apc.getClientUid());
            if (da == null) {
                return;
            }
            da.addDuck(apc, true /*skipRamp*/);
        }

        synchronized void dump(PrintWriter pw) {
            for (DuckedApp da : mDuckers.values()) {
                da.dump(pw);
            }
        }

        synchronized void removeReleased(@NonNull AudioPlaybackConfiguration apc) {
            final int uid = apc.getClientUid();
            if (DEBUG) {  Log.v(TAG, "DuckingManager: removedReleased() player piid: "
                    + apc.getPlayerInterfaceId() + " uid:" + uid); }
            final DuckedApp da = mDuckers.get(uid);
            if (da == null) {
                return;
            }
            da.removeReleased(apc);
        }

        private static final class DuckedApp {
            private final int mUid;
            private final ArrayList<Integer> mDuckedPlayers = new ArrayList<Integer>();

            DuckedApp(int uid) {
                mUid = uid;
            }

            void dump(PrintWriter pw) {
                pw.print("\t uid:" + mUid + " piids:");
                for (int piid : mDuckedPlayers) {
                    pw.print(" " + piid);
                }
                pw.println("");
            }

            // pre-conditions:
            //  * apc != null
            //  * apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
            void addDuck(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) {
                final int piid = new Integer(apc.getPlayerInterfaceId());
                if (mDuckedPlayers.contains(piid)) {
                    if (DEBUG) { Log.v(TAG, "player piid:" + piid + " already ducked"); }
                    return;
                }
                try {
                    sEventLogger.log((new DuckEvent(apc, skipRamp)).printLog(TAG));
                    apc.getPlayerProxy().applyVolumeShaper(
                            DUCK_VSHAPE,
                            skipRamp ? PLAY_SKIP_RAMP : PLAY_CREATE_IF_NEEDED);
                    mDuckedPlayers.add(piid);
                } catch (Exception e) {
                    Log.e(TAG, "Error ducking player piid:" + piid + " uid:" + mUid, e);
                }
            }

            void removeUnduckAll(HashMap<Integer, AudioPlaybackConfiguration> players) {
                for (int piid : mDuckedPlayers) {
                    final AudioPlaybackConfiguration apc = players.get(piid);
                    if (apc != null) {
                        try {
                            sEventLogger.log((new AudioEventLogger.StringEvent("unducking piid:"
                                    + piid)).printLog(TAG));
                            apc.getPlayerProxy().applyVolumeShaper(
                                    DUCK_ID,
                                    VolumeShaper.Operation.REVERSE);
                        } catch (Exception e) {
                            Log.e(TAG, "Error unducking player piid:" + piid + " uid:" + mUid, e);
                        }
                    } else {
                        // this piid was in the list of ducked players, but wasn't found
                        if (DEBUG) {
                            Log.v(TAG, "Error unducking player piid:" + piid
                                    + ", player not found for uid " + mUid);
                        }
                    }
                }
                mDuckedPlayers.clear();
            }

            void removeReleased(@NonNull AudioPlaybackConfiguration apc) {
                mDuckedPlayers.remove(new Integer(apc.getPlayerInterfaceId()));
            }
        }
    }

    //=================================================================
    // For logging
    private final static class PlayerEvent extends AudioEventLogger.Event {
        // only keeping the player interface ID as it uniquely identifies the player in the event
        final int mPlayerIId;
        final int mState;
        final int mDeviceId;

        PlayerEvent(int piid, int state, int deviceId) {
            mPlayerIId = piid;
            mState = state;
            mDeviceId = deviceId;
        }

        @Override
        public String eventToString() {
            return new StringBuilder("player piid:").append(mPlayerIId).append(" state:")
                    .append(AudioPlaybackConfiguration.toLogFriendlyPlayerState(mState))
                    .append(" DeviceId:").append(mDeviceId).toString();
        }
    }

    private final static class PlayerOpPlayAudioEvent extends AudioEventLogger.Event {
        // only keeping the player interface ID as it uniquely identifies the player in the event
        final int mPlayerIId;
        final boolean mHasOp;
        final int mUid;

        PlayerOpPlayAudioEvent(int piid, boolean hasOp, int uid) {
            mPlayerIId = piid;
            mHasOp = hasOp;
            mUid = uid;
        }

        @Override
        public String eventToString() {
            return new StringBuilder("player piid:").append(mPlayerIId)
                    .append(" has OP_PLAY_AUDIO:").append(mHasOp)
                    .append(" in uid:").append(mUid).toString();
        }
    }

    private final static class NewPlayerEvent extends AudioEventLogger.Event {
        private final int mPlayerIId;
        private final int mPlayerType;
        private final int mClientUid;
        private final int mClientPid;
        private final AudioAttributes mPlayerAttr;
        private final int mSessionId;

        NewPlayerEvent(AudioPlaybackConfiguration apc) {
            mPlayerIId = apc.getPlayerInterfaceId();
            mPlayerType = apc.getPlayerType();
            mClientUid = apc.getClientUid();
            mClientPid = apc.getClientPid();
            mPlayerAttr = apc.getAudioAttributes();
            mSessionId = apc.getSessionId();
        }

        @Override
        public String eventToString() {
            return new String("new player piid:" + mPlayerIId + " uid/pid:" + mClientUid + "/"
                    + mClientPid + " type:"
                    + AudioPlaybackConfiguration.toLogFriendlyPlayerType(mPlayerType)
                    + " attr:" + mPlayerAttr
                    + " session:" + mSessionId);
        }
    }

    private abstract static class VolumeShaperEvent extends AudioEventLogger.Event {
        private final int mPlayerIId;
        private final boolean mSkipRamp;
        private final int mClientUid;
        private final int mClientPid;

        abstract String getVSAction();

        VolumeShaperEvent(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) {
            mPlayerIId = apc.getPlayerInterfaceId();
            mSkipRamp = skipRamp;
            mClientUid = apc.getClientUid();
            mClientPid = apc.getClientPid();
        }

        @Override
        public String eventToString() {
            return new StringBuilder(getVSAction()).append(" player piid:").append(mPlayerIId)
                    .append(" uid/pid:").append(mClientUid).append("/").append(mClientPid)
                    .append(" skip ramp:").append(mSkipRamp).toString();
        }
    }

    static final class DuckEvent extends VolumeShaperEvent {
        @Override
        String getVSAction() {
            return "ducking";
        }

        DuckEvent(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) {
            super(apc, skipRamp);
        }
    }

    static final class FadeOutEvent extends VolumeShaperEvent {
        @Override
        String getVSAction() {
            return "fading out";
        }

        FadeOutEvent(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) {
            super(apc, skipRamp);
        }
    }

    private static final class AudioAttrEvent extends AudioEventLogger.Event {
        private final int mPlayerIId;
        private final AudioAttributes mPlayerAttr;

        AudioAttrEvent(int piid, AudioAttributes attr) {
            mPlayerIId = piid;
            mPlayerAttr = attr;
        }

        @Override
        public String eventToString() {
            return new String("player piid:" + mPlayerIId + " new AudioAttributes:" + mPlayerAttr);
        }
    }

    private static final class MuteAwaitConnectionEvent extends AudioEventLogger.Event {
        private final @NonNull int[] mUsagesToMute;

        MuteAwaitConnectionEvent(@NonNull int[] usagesToMute) {
            mUsagesToMute = usagesToMute;
        }

        @Override
        public String eventToString() {
            return "muteAwaitConnection muting usages " + Arrays.toString(mUsagesToMute);
        }
    }

    static final AudioEventLogger sEventLogger = new AudioEventLogger(100,
            "playback activity as reported through PlayerBase");

    //==========================================================================================
    // Mute conditional on device connection
    //==========================================================================================
    void muteAwaitConnection(@NonNull int[] usagesToMute,
            @NonNull AudioDeviceAttributes dev, long timeOutMs) {
        sEventLogger.loglogi(
                "muteAwaitConnection() dev:" + dev + " timeOutMs:" + timeOutMs, TAG);
        synchronized (mPlayerLock) {
            mutePlayersExpectingDevice(usagesToMute);
            // schedule timeout (remove previously scheduled first)
            mEventHandler.removeMessages(MSG_L_TIMEOUT_MUTE_AWAIT_CONNECTION);
            mEventHandler.sendMessageDelayed(
                    mEventHandler.obtainMessage(MSG_L_TIMEOUT_MUTE_AWAIT_CONNECTION, dev),
                    timeOutMs);
        }
    }

    void cancelMuteAwaitConnection(String source) {
        sEventLogger.loglogi("cancelMuteAwaitConnection() from:" + source, TAG);
        synchronized (mPlayerLock) {
            // cancel scheduled timeout, ignore device, only one expected device at a time
            mEventHandler.removeMessages(MSG_L_TIMEOUT_MUTE_AWAIT_CONNECTION);
            // unmute immediately
            unmutePlayersExpectingDevice();
        }
    }

    /**
     * List of the piids of the players that are muted until a specific audio device connects
     */
    @GuardedBy("mPlayerLock")
    private final ArrayList<Integer> mMutedPlayersAwaitingConnection = new ArrayList<Integer>();

    /**
     * List of AudioAttributes usages to mute until a specific audio device connects
     */
    @GuardedBy("mPlayerLock")
    private @Nullable int[] mMutedUsagesAwaitingConnection = null;

    @GuardedBy("mPlayerLock")
    private void mutePlayersExpectingDevice(@NonNull int[] usagesToMute) {
        sEventLogger.log(new MuteAwaitConnectionEvent(usagesToMute));
        mMutedUsagesAwaitingConnection = usagesToMute;
        final Set<Integer> piidSet = mPlayers.keySet();
        final Iterator<Integer> piidIterator = piidSet.iterator();
        // find which players to mute
        while (piidIterator.hasNext()) {
            final Integer piid = piidIterator.next();
            final AudioPlaybackConfiguration apc = mPlayers.get(piid);
            if (apc == null) {
                continue;
            }
            maybeMutePlayerAwaitingConnection(apc);
        }
    }

    @GuardedBy("mPlayerLock")
    private void maybeMutePlayerAwaitingConnection(@NonNull AudioPlaybackConfiguration apc) {
        if (mMutedUsagesAwaitingConnection == null) {
            return;
        }
        for (int usage : mMutedUsagesAwaitingConnection) {
            if (usage == apc.getAudioAttributes().getUsage()) {
                try {
                    sEventLogger.log((new AudioEventLogger.StringEvent(
                            "awaiting connection: muting piid:"
                                    + apc.getPlayerInterfaceId()
                                    + " uid:" + apc.getClientUid())).printLog(TAG));
                    apc.getPlayerProxy().applyVolumeShaper(
                            MUTE_AWAIT_CONNECTION_VSHAPE,
                            PLAY_SKIP_RAMP);
                    mMutedPlayersAwaitingConnection.add(apc.getPlayerInterfaceId());
                } catch (Exception e) {
                    Log.e(TAG, "awaiting connection: error muting player "
                            + apc.getPlayerInterfaceId(), e);
                }
            }
        }
    }

    @GuardedBy("mPlayerLock")
    private void unmutePlayersExpectingDevice() {
        mMutedUsagesAwaitingConnection = null;
        for (int piid : mMutedPlayersAwaitingConnection) {
            final AudioPlaybackConfiguration apc = mPlayers.get(piid);
            if (apc == null) {
                continue;
            }
            try {
                sEventLogger.log(new AudioEventLogger.StringEvent(
                        "unmuting piid:" + piid).printLog(TAG));
                apc.getPlayerProxy().applyVolumeShaper(MUTE_AWAIT_CONNECTION_VSHAPE,
                        VolumeShaper.Operation.REVERSE);
            } catch (Exception e) {
                Log.e(TAG, "Error unmuting player " + piid + " uid:"
                        + apc.getClientUid(), e);
            }
        }
        mMutedPlayersAwaitingConnection.clear();
    }

    //=================================================================
    // Message handling
    private Handler mEventHandler;
    private HandlerThread mEventThread;

    /**
     * timeout for a mute awaiting a device connection
     * args:
     *     msg.obj: the audio device being expected
     *         type: AudioDeviceAttributes
     */
    private static final int MSG_L_TIMEOUT_MUTE_AWAIT_CONNECTION = 1;

    private void initEventHandler() {
        mEventThread = new HandlerThread(TAG);
        mEventThread.start();
        mEventHandler = new Handler(mEventThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_L_TIMEOUT_MUTE_AWAIT_CONNECTION:
                        sEventLogger.loglogi("Timeout for muting waiting for "
                                + (AudioDeviceAttributes) msg.obj + ", unmuting", TAG);
                        synchronized (mPlayerLock) {
                            unmutePlayersExpectingDevice();
                        }
                        mMuteAwaitConnectionTimeoutCb.accept((AudioDeviceAttributes) msg.obj);
                        break;
                    default:
                        break;
                }
            }
        };
    }
}
