/*
 * Copyright (C) 2014 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 android.media.audiopolicy;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioFocusInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.IAudioService;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @hide
 * AudioPolicy provides access to the management of audio routing and audio focus.
 */
@TestApi
@SystemApi
public class AudioPolicy {

    private static final String TAG = "AudioPolicy";
    private static final boolean DEBUG = false;
    private final Object mLock = new Object();

    /**
     * The status of an audio policy that is valid but cannot be used because it is not registered.
     */
    public static final int POLICY_STATUS_UNREGISTERED = 1;
    /**
     * The status of an audio policy that is valid, successfully registered and thus active.
     */
    public static final int POLICY_STATUS_REGISTERED = 2;

    private int mStatus;
    private String mRegistrationId;
    private AudioPolicyStatusListener mStatusListener;
    private boolean mIsFocusPolicy;
    private boolean mIsTestFocusPolicy;

    /**
     * The list of AudioTrack instances created to inject audio into the associated mixes
     * Lazy initialization in {@link #createAudioTrackSource(AudioMix)}
     */
    @GuardedBy("mLock")
    @Nullable private ArrayList<WeakReference<AudioTrack>> mInjectors;
    /**
     * The list AudioRecord instances created to capture audio from the associated mixes
     * Lazy initialization in {@link #createAudioRecordSink(AudioMix)}
     */
    @GuardedBy("mLock")
    @Nullable private ArrayList<WeakReference<AudioRecord>> mCaptors;

    /**
     * The behavior of a policy with regards to audio focus where it relies on the application
     * to do the ducking, the is the legacy and default behavior.
     */
    public static final int FOCUS_POLICY_DUCKING_IN_APP = 0;
    public static final int FOCUS_POLICY_DUCKING_DEFAULT = FOCUS_POLICY_DUCKING_IN_APP;
    /**
     * The behavior of a policy with regards to audio focus where it handles ducking instead
     * of the application losing focus and being signaled it can duck (as communicated by
     * {@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}).
     * <br>Can only be used after having set a listener with
     * {@link AudioPolicy#setAudioPolicyFocusListener(AudioPolicyFocusListener)}.
     */
    public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1;

    private AudioPolicyFocusListener mFocusListener;

    private final AudioPolicyVolumeCallback mVolCb;

    private Context mContext;

    private AudioPolicyConfig mConfig;

    private final MediaProjection mProjection;

    /** @hide */
    public AudioPolicyConfig getConfig() { return mConfig; }
    /** @hide */
    public boolean hasFocusListener() { return mFocusListener != null; }
    /** @hide */
    public boolean isFocusPolicy() { return mIsFocusPolicy; }
    /** @hide */
    public boolean isTestFocusPolicy() {
        return mIsTestFocusPolicy;
    }
    /** @hide */
    public boolean isVolumeController() { return mVolCb != null; }
    /** @hide */
    public @Nullable MediaProjection getMediaProjection() {
        return mProjection;
    }

    /**
     * The parameters are guaranteed non-null through the Builder
     */
    private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
            AudioPolicyFocusListener fl, AudioPolicyStatusListener sl,
            boolean isFocusPolicy, boolean isTestFocusPolicy,
            AudioPolicyVolumeCallback vc, @Nullable MediaProjection projection) {
        mConfig = config;
        mStatus = POLICY_STATUS_UNREGISTERED;
        mContext = context;
        if (looper == null) {
            looper = Looper.getMainLooper();
        }
        if (looper != null) {
            mEventHandler = new EventHandler(this, looper);
        } else {
            mEventHandler = null;
            Log.e(TAG, "No event handler due to looper without a thread");
        }
        mFocusListener = fl;
        mStatusListener = sl;
        mIsFocusPolicy = isFocusPolicy;
        mIsTestFocusPolicy = isTestFocusPolicy;
        mVolCb = vc;
        mProjection = projection;
    }

    /**
     * Builder class for {@link AudioPolicy} objects.
     * By default the policy to be created doesn't govern audio focus decisions.
     */
    public static class Builder {
        private ArrayList<AudioMix> mMixes;
        private Context mContext;
        private Looper mLooper;
        private AudioPolicyFocusListener mFocusListener;
        private AudioPolicyStatusListener mStatusListener;
        private boolean mIsFocusPolicy = false;
        private boolean mIsTestFocusPolicy = false;
        private AudioPolicyVolumeCallback mVolCb;
        private MediaProjection mProjection;

        /**
         * Constructs a new Builder with no audio mixes.
         * @param context the context for the policy
         */
        public Builder(Context context) {
            mMixes = new ArrayList<AudioMix>();
            mContext = context;
        }

        /**
         * Add an {@link AudioMix} to be part of the audio policy being built.
         * @param mix a non-null {@link AudioMix} to be part of the audio policy.
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        @NonNull
        public Builder addMix(@NonNull AudioMix mix) throws IllegalArgumentException {
            if (mix == null) {
                throw new IllegalArgumentException("Illegal null AudioMix argument");
            }
            mMixes.add(mix);
            return this;
        }

        /**
         * Sets the {@link Looper} on which to run the event loop.
         * @param looper a non-null specific Looper.
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        @NonNull
        public Builder setLooper(@NonNull Looper looper) throws IllegalArgumentException {
            if (looper == null) {
                throw new IllegalArgumentException("Illegal null Looper argument");
            }
            mLooper = looper;
            return this;
        }

        /**
         * Sets the audio focus listener for the policy.
         * @param l a {@link AudioPolicy.AudioPolicyFocusListener}
         */
        public void setAudioPolicyFocusListener(AudioPolicyFocusListener l) {
            mFocusListener = l;
        }

        /**
         * Declares whether this policy will grant and deny audio focus through
         * the {@link AudioPolicy.AudioPolicyFocusListener}.
         * If set to {@code true}, it is mandatory to set an
         * {@link AudioPolicy.AudioPolicyFocusListener} in order to successfully build
         * an {@code AudioPolicy} instance.
         * @param enforce true if the policy will govern audio focus decisions.
         * @return the same Builder instance.
         */
        @NonNull
        public Builder setIsAudioFocusPolicy(boolean isFocusPolicy) {
            mIsFocusPolicy = isFocusPolicy;
            return this;
        }

        /**
         * @hide
         * Test method to declare whether this audio focus policy is for test purposes only.
         * Having a test policy registered will disable the current focus policy and replace it
         * with this test policy. When unregistered, the previous focus policy will be restored.
         * <p>A value of <code>true</code> will be ignored if the AudioPolicy is not also
         * focus policy.
         * @param isTestFocusPolicy true if the focus policy to register is for testing purposes.
         * @return the same Builder instance
         */
        @TestApi
        @NonNull
        public Builder setIsTestFocusPolicy(boolean isTestFocusPolicy) {
            mIsTestFocusPolicy = isTestFocusPolicy;
            return this;
        }

        /**
         * Sets the audio policy status listener.
         * @param l a {@link AudioPolicy.AudioPolicyStatusListener}
         */
        public void setAudioPolicyStatusListener(AudioPolicyStatusListener l) {
            mStatusListener = l;
        }

        /**
         * Sets the callback to receive all volume key-related events.
         * The callback will only be called if the device is configured to handle volume events
         * in the PhoneWindowManager (see config_handleVolumeKeysInWindowManager)
         * @param vc
         * @return the same Builder instance.
         */
        @NonNull
        public Builder setAudioPolicyVolumeCallback(@NonNull AudioPolicyVolumeCallback vc) {
            if (vc == null) {
                throw new IllegalArgumentException("Invalid null volume callback");
            }
            mVolCb = vc;
            return this;
        }

        /**
         * Set a media projection obtained through createMediaProjection().
         *
         * A MediaProjection that can project audio allows to register an audio
         * policy LOOPBACK|RENDER without the MODIFY_AUDIO_ROUTING permission.
         *
         * @hide
         */
        @NonNull
        public Builder setMediaProjection(@NonNull MediaProjection projection) {
            if (projection == null) {
                throw new IllegalArgumentException("Invalid null volume callback");
            }
            mProjection = projection;
            return this;

        }

        /**
         * Combines all of the attributes that have been set on this {@code Builder} and returns a
         * new {@link AudioPolicy} object.
         * @return a new {@code AudioPolicy} object.
         * @throws IllegalStateException if there is no
         *     {@link AudioPolicy.AudioPolicyStatusListener} but the policy was configured
         *     as an audio focus policy with {@link #setIsAudioFocusPolicy(boolean)}.
         */
        @NonNull
        public AudioPolicy build() {
            if (mStatusListener != null) {
                // the AudioPolicy status listener includes updates on each mix activity state
                for (AudioMix mix : mMixes) {
                    mix.mCallbackFlags |= AudioMix.CALLBACK_FLAG_NOTIFY_ACTIVITY;
                }
            }
            if (mIsFocusPolicy && mFocusListener == null) {
                throw new IllegalStateException("Cannot be a focus policy without "
                        + "an AudioPolicyFocusListener");
            }
            return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
                    mFocusListener, mStatusListener, mIsFocusPolicy, mIsTestFocusPolicy,
                    mVolCb, mProjection);
        }
    }

    /**
     * Update the current configuration of the set of audio mixes by adding new ones, while
     * keeping the policy registered.
     * This method can only be called on a registered policy.
     * @param mixes the list of {@link AudioMix} to add
     * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR}
     *    otherwise.
     */
    public int attachMixes(@NonNull List<AudioMix> mixes) {
        if (mixes == null) {
            throw new IllegalArgumentException("Illegal null list of AudioMix");
        }
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                throw new IllegalStateException("Cannot alter unregistered AudioPolicy");
            }
            final ArrayList<AudioMix> zeMixes = new ArrayList<AudioMix>(mixes.size());
            for (AudioMix mix : mixes) {
                if (mix == null) {
                    throw new IllegalArgumentException("Illegal null AudioMix in attachMixes");
                } else {
                    zeMixes.add(mix);
                }
            }
            final AudioPolicyConfig cfg = new AudioPolicyConfig(zeMixes);
            IAudioService service = getService();
            try {
                final int status = service.addMixForPolicy(cfg, this.cb());
                if (status == AudioManager.SUCCESS) {
                    mConfig.add(zeMixes);
                }
                return status;
            } catch (RemoteException e) {
                Log.e(TAG, "Dead object in attachMixes", e);
                return AudioManager.ERROR;
            }
        }
    }

    /**
     * Update the current configuration of the set of audio mixes by removing some, while
     * keeping the policy registered.
     * This method can only be called on a registered policy.
     * @param mixes the list of {@link AudioMix} to remove
     * @return {@link AudioManager#SUCCESS} if the change was successful, {@link AudioManager#ERROR}
     *    otherwise.
     */
    public int detachMixes(@NonNull List<AudioMix> mixes) {
        if (mixes == null) {
            throw new IllegalArgumentException("Illegal null list of AudioMix");
        }
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                throw new IllegalStateException("Cannot alter unregistered AudioPolicy");
            }
            final ArrayList<AudioMix> zeMixes = new ArrayList<AudioMix>(mixes.size());
            for (AudioMix mix : mixes) {
                if (mix == null) {
                    throw new IllegalArgumentException("Illegal null AudioMix in detachMixes");
                    // TODO also check mix is currently contained in list of mixes
                } else {
                    zeMixes.add(mix);
                }
            }
            final AudioPolicyConfig cfg = new AudioPolicyConfig(zeMixes);
            IAudioService service = getService();
            try {
                final int status = service.removeMixForPolicy(cfg, this.cb());
                if (status == AudioManager.SUCCESS) {
                    mConfig.remove(zeMixes);
                }
                return status;
            } catch (RemoteException e) {
                Log.e(TAG, "Dead object in detachMixes", e);
                return AudioManager.ERROR;
            }
        }
    }

    /**
     * @hide
     * Configures the audio framework so that all audio streams originating from the given UID
     * can only come from a set of audio devices.
     * For this routing to be operational, a number of {@link AudioMix} instances must have been
     * previously registered on this policy, and routed to a super-set of the given audio devices
     * with {@link AudioMix.Builder#setDevice(android.media.AudioDeviceInfo)}. Note that having
     * multiple devices in the list doesn't imply the signals will be duplicated on the different
     * audio devices, final routing will depend on the {@link AudioAttributes} of the sounds being
     * played.
     * @param uid UID of the application to affect.
     * @param devices list of devices to which the audio stream of the application may be routed.
     * @return true if the change was successful, false otherwise.
     */
    @TestApi
    @SystemApi
    public boolean setUidDeviceAffinity(int uid, @NonNull List<AudioDeviceInfo> devices) {
        if (devices == null) {
            throw new IllegalArgumentException("Illegal null list of audio devices");
        }
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                throw new IllegalStateException("Cannot use unregistered AudioPolicy");
            }
            final int[] deviceTypes = new int[devices.size()];
            final String[] deviceAdresses = new String[devices.size()];
            int i = 0;
            for (AudioDeviceInfo device : devices) {
                if (device == null) {
                    throw new IllegalArgumentException(
                            "Illegal null AudioDeviceInfo in setUidDeviceAffinity");
                }
                deviceTypes[i] =
                        AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
                deviceAdresses[i] = device.getAddress();
                i++;
            }
            final IAudioService service = getService();
            try {
                final int status = service.setUidDeviceAffinity(this.cb(),
                        uid, deviceTypes, deviceAdresses);
                return (status == AudioManager.SUCCESS);
            } catch (RemoteException e) {
                Log.e(TAG, "Dead object in setUidDeviceAffinity", e);
                return false;
            }
        }
    }

    /**
     * @hide
     * Removes audio device affinity previously set by
     * {@link #setUidDeviceAffinity(int, java.util.List)}.
     * @param uid UID of the application affected.
     * @return true if the change was successful, false otherwise.
     */
    @TestApi
    @SystemApi
    public boolean removeUidDeviceAffinity(int uid) {
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                throw new IllegalStateException("Cannot use unregistered AudioPolicy");
            }
            final IAudioService service = getService();
            try {
                final int status = service.removeUidDeviceAffinity(this.cb(), uid);
                return (status == AudioManager.SUCCESS);
            } catch (RemoteException e) {
                Log.e(TAG, "Dead object in removeUidDeviceAffinity", e);
                return false;
            }
        }
    }

    /**
     * @hide
     * Removes audio device affinity previously set by
     * {@link #setUserIdDeviceAffinity(int, java.util.List)}.
     * @param userId userId of the application affected, as obtained via
     * {@link UserHandle#getIdentifier}. Not to be confused with application uid.
     * @return true if the change was successful, false otherwise.
     */
    @TestApi
    @SystemApi
    public boolean removeUserIdDeviceAffinity(@UserIdInt int userId) {
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                throw new IllegalStateException("Cannot use unregistered AudioPolicy");
            }
            final IAudioService service = getService();
            try {
                final int status = service.removeUserIdDeviceAffinity(this.cb(), userId);
                return (status == AudioManager.SUCCESS);
            } catch (RemoteException e) {
                Log.e(TAG, "Dead object in removeUserIdDeviceAffinity", e);
                return false;
            }
        }
    }

    /**
     * @hide
     * Configures the audio framework so that all audio streams originating from the given user
     * can only come from a set of audio devices.
     * For this routing to be operational, a number of {@link AudioMix} instances must have been
     * previously registered on this policy, and routed to a super-set of the given audio devices
     * with {@link AudioMix.Builder#setDevice(android.media.AudioDeviceInfo)}. Note that having
     * multiple devices in the list doesn't imply the signals will be duplicated on the different
     * audio devices, final routing will depend on the {@link AudioAttributes} of the sounds being
     * played.
     * @param userId userId of the application affected, as obtained via
     * {@link UserHandle#getIdentifier}. Not to be confused with application uid.
     * @param devices list of devices to which the audio stream of the application may be routed.
     * @return true if the change was successful, false otherwise.
     */
    @TestApi
    @SystemApi
    public boolean setUserIdDeviceAffinity(@UserIdInt int userId,
            @NonNull List<AudioDeviceInfo> devices) {
        Objects.requireNonNull(devices, "Illegal null list of audio devices");
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                throw new IllegalStateException("Cannot use unregistered AudioPolicy");
            }
            final int[] deviceTypes = new int[devices.size()];
            final String[] deviceAddresses = new String[devices.size()];
            int i = 0;
            for (AudioDeviceInfo device : devices) {
                if (device == null) {
                    throw new IllegalArgumentException(
                            "Illegal null AudioDeviceInfo in setUserIdDeviceAffinity");
                }
                deviceTypes[i] =
                        AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
                deviceAddresses[i] = device.getAddress();
                i++;
            }
            final IAudioService service = getService();
            try {
                final int status = service.setUserIdDeviceAffinity(this.cb(),
                        userId, deviceTypes, deviceAddresses);
                return (status == AudioManager.SUCCESS);
            } catch (RemoteException e) {
                Log.e(TAG, "Dead object in setUserIdDeviceAffinity", e);
                return false;
            }
        }
    }

    public void setRegistration(String regId) {
        synchronized (mLock) {
            mRegistrationId = regId;
            mConfig.setRegistration(regId);
            if (regId != null) {
                mStatus = POLICY_STATUS_REGISTERED;
            } else {
                mStatus = POLICY_STATUS_UNREGISTERED;
            }
        }
        sendMsg(MSG_POLICY_STATUS_CHANGE);
    }

    private boolean policyReadyToUse() {
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                Log.e(TAG, "Cannot use unregistered AudioPolicy");
                return false;
            }
            if (mRegistrationId == null) {
                Log.e(TAG, "Cannot use unregistered AudioPolicy");
                return false;
            }
        }

        // Loopback|capture only need an audio projection, everything else need MODIFY_AUDIO_ROUTING
        boolean canModifyAudioRouting = PackageManager.PERMISSION_GRANTED
                == checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING);

        boolean canProjectAudio;
        try {
            canProjectAudio = mProjection != null && mProjection.getProjection().canProjectAudio();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to check if MediaProjection#canProjectAudio");
            throw e.rethrowFromSystemServer();
        }

        if (!((isLoopbackRenderPolicy() && canProjectAudio) || canModifyAudioRouting)) {
            Slog.w(TAG, "Cannot use AudioPolicy for pid " + Binder.getCallingPid() + " / uid "
                    + Binder.getCallingUid() + ", needs MODIFY_AUDIO_ROUTING or "
                    + "MediaProjection that can project audio.");
            return false;
        }
        return true;
    }

    private boolean isLoopbackRenderPolicy() {
        synchronized (mLock) {
            return mConfig.mMixes.stream().allMatch(mix -> mix.getRouteFlags()
                    == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK));
        }
    }

    /**
     * Returns {@link PackageManager#PERMISSION_GRANTED} if the caller has the given permission.
     */
    private @PackageManager.PermissionResult int checkCallingOrSelfPermission(String permission) {
        if (mContext != null) {
            return mContext.checkCallingOrSelfPermission(permission);
        }
        Slog.v(TAG, "Null context, checking permission via ActivityManager");
        int pid = Binder.getCallingPid();
        int uid = Binder.getCallingUid();
        try {
            return ActivityManager.getService().checkPermission(permission, pid, uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private void checkMixReadyToUse(AudioMix mix, boolean forTrack)
            throws IllegalArgumentException{
        if (mix == null) {
            String msg = forTrack ? "Invalid null AudioMix for AudioTrack creation"
                    : "Invalid null AudioMix for AudioRecord creation";
            throw new IllegalArgumentException(msg);
        }
        if (!mConfig.mMixes.contains(mix)) {
            throw new IllegalArgumentException("Invalid mix: not part of this policy");
        }
        if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) != AudioMix.ROUTE_FLAG_LOOP_BACK)
        {
            throw new IllegalArgumentException("Invalid AudioMix: not defined for loop back");
        }
        if (forTrack && (mix.getMixType() != AudioMix.MIX_TYPE_RECORDERS)) {
            throw new IllegalArgumentException(
                    "Invalid AudioMix: not defined for being a recording source");
        }
        if (!forTrack && (mix.getMixType() != AudioMix.MIX_TYPE_PLAYERS)) {
            throw new IllegalArgumentException(
                    "Invalid AudioMix: not defined for capturing playback");
        }
    }

    /**
     * Returns the current behavior for audio focus-related ducking.
     * @return {@link #FOCUS_POLICY_DUCKING_IN_APP} or {@link #FOCUS_POLICY_DUCKING_IN_POLICY}
     */
    public int getFocusDuckingBehavior() {
        return mConfig.mDuckingPolicy;
    }

    // Note on implementation: not part of the Builder as there can be only one registered policy
    // that handles ducking but there can be multiple policies
    /**
     * Sets the behavior for audio focus-related ducking.
     * There must be a focus listener if this policy is to handle ducking.
     * @param behavior {@link #FOCUS_POLICY_DUCKING_IN_APP} or
     *     {@link #FOCUS_POLICY_DUCKING_IN_POLICY}
     * @return {@link AudioManager#SUCCESS} or {@link AudioManager#ERROR} (for instance if there
     *     is already an audio policy that handles ducking).
     * @throws IllegalArgumentException
     * @throws IllegalStateException
     */
    public int setFocusDuckingBehavior(int behavior)
            throws IllegalArgumentException, IllegalStateException {
        if ((behavior != FOCUS_POLICY_DUCKING_IN_APP)
                && (behavior != FOCUS_POLICY_DUCKING_IN_POLICY)) {
            throw new IllegalArgumentException("Invalid ducking behavior " + behavior);
        }
        synchronized (mLock) {
            if (mStatus != POLICY_STATUS_REGISTERED) {
                throw new IllegalStateException(
                        "Cannot change ducking behavior for unregistered policy");
            }
            if ((behavior == FOCUS_POLICY_DUCKING_IN_POLICY)
                    && (mFocusListener == null)) {
                // there must be a focus listener if the policy handles ducking
                throw new IllegalStateException(
                        "Cannot handle ducking without an audio focus listener");
            }
            IAudioService service = getService();
            try {
                final int status = service.setFocusPropertiesForPolicy(behavior /*duckingBehavior*/,
                        this.cb());
                if (status == AudioManager.SUCCESS) {
                    mConfig.mDuckingPolicy = behavior;
                }
                return status;
            } catch (RemoteException e) {
                Log.e(TAG, "Dead object in setFocusPropertiesForPolicy for behavior", e);
                return AudioManager.ERROR;
            }
        }
    }

    /**
     * Create an {@link AudioRecord} instance that is associated with the given {@link AudioMix}.
     * Audio buffers recorded through the created instance will contain the mix of the audio
     * streams that fed the given mixer.
     * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with
     *     {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy.
     * @return a new {@link AudioRecord} instance whose data format is the one defined in the
     *     {@link AudioMix}, or null if this policy was not successfully registered
     *     with {@link AudioManager#registerAudioPolicy(AudioPolicy)}.
     * @throws IllegalArgumentException
     */
    public AudioRecord createAudioRecordSink(AudioMix mix) throws IllegalArgumentException {
        if (!policyReadyToUse()) {
            Log.e(TAG, "Cannot create AudioRecord sink for AudioMix");
            return null;
        }
        checkMixReadyToUse(mix, false/*not for an AudioTrack*/);
        // create an AudioFormat from the mix format compatible with recording, as the mix
        // was defined for playback
        AudioFormat mixFormat = new AudioFormat.Builder(mix.getFormat())
                .setChannelMask(AudioFormat.inChannelMaskFromOutChannelMask(
                        mix.getFormat().getChannelMask()))
                .build();
        // create the AudioRecord, configured for loop back, using the same format as the mix
        AudioRecord ar = new AudioRecord(
                new AudioAttributes.Builder()
                        .setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX)
                        .addTag(addressForTag(mix))
                        .addTag(AudioRecord.SUBMIX_FIXED_VOLUME)
                        .build(),
                mixFormat,
                AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(),
                        // using stereo for buffer size to avoid the current poor support for masks
                        AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),
                AudioManager.AUDIO_SESSION_ID_GENERATE
                );
        synchronized (mLock) {
            if (mCaptors == null) {
                mCaptors = new ArrayList<>(1);
            }
            mCaptors.add(new WeakReference<AudioRecord>(ar));
        }
        return ar;
    }

    /**
     * Create an {@link AudioTrack} instance that is associated with the given {@link AudioMix}.
     * Audio buffers played through the created instance will be sent to the given mix
     * to be recorded through the recording APIs.
     * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with
     *     {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy.
     * @return a new {@link AudioTrack} instance whose data format is the one defined in the
     *     {@link AudioMix}, or null if this policy was not successfully registered
     *     with {@link AudioManager#registerAudioPolicy(AudioPolicy)}.
     * @throws IllegalArgumentException
     */
    public AudioTrack createAudioTrackSource(AudioMix mix) throws IllegalArgumentException {
        if (!policyReadyToUse()) {
            Log.e(TAG, "Cannot create AudioTrack source for AudioMix");
            return null;
        }
        checkMixReadyToUse(mix, true/*for an AudioTrack*/);
        // create the AudioTrack, configured for loop back, using the same format as the mix
        AudioTrack at = new AudioTrack(
                new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_VIRTUAL_SOURCE)
                        .addTag(addressForTag(mix))
                        .build(),
                mix.getFormat(),
                AudioTrack.getMinBufferSize(mix.getFormat().getSampleRate(),
                        mix.getFormat().getChannelMask(), mix.getFormat().getEncoding()),
                AudioTrack.MODE_STREAM,
                AudioManager.AUDIO_SESSION_ID_GENERATE
                );
        synchronized (mLock) {
            if (mInjectors == null) {
                mInjectors = new ArrayList<>(1);
            }
            mInjectors.add(new WeakReference<AudioTrack>(at));
        }
        return at;
    }

    /**
     * @hide
     */
    public void invalidateCaptorsAndInjectors() {
        if (!policyReadyToUse()) {
            return;
        }
        synchronized (mLock) {
            if (mInjectors != null) {
                for (final WeakReference<AudioTrack> weakTrack : mInjectors) {
                    final AudioTrack track = weakTrack.get();
                    if (track == null) {
                        break;
                    }
                    try {
                        // TODO: add synchronous versions
                        track.stop();
                        track.flush();
                    } catch (IllegalStateException e) {
                        // ignore exception, AudioTrack could have already been stopped or
                        // released by the user of the AudioPolicy
                    }
                }
            }
            if (mCaptors != null) {
                for (final WeakReference<AudioRecord> weakRecord : mCaptors) {
                    final AudioRecord record = weakRecord.get();
                    if (record == null) {
                        break;
                    }
                    try {
                        // TODO: if needed: implement an invalidate method
                        record.stop();
                    } catch (IllegalStateException e) {
                        // ignore exception, AudioRecord could have already been stopped or
                        // released by the user of the AudioPolicy
                    }
                }
            }
        }
    }

    public int getStatus() {
        return mStatus;
    }

    public static abstract class AudioPolicyStatusListener {
        public void onStatusChange() {}
        public void onMixStateUpdate(AudioMix mix) {}
    }

    public static abstract class AudioPolicyFocusListener {
        public void onAudioFocusGrant(AudioFocusInfo afi, int requestResult) {}
        public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {}
        /**
         * Called whenever an application requests audio focus.
         * Only ever called if the {@link AudioPolicy} was built with
         * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
         * @param afi information about the focus request and the requester
         * @param requestResult deprecated after the addition of
         *     {@link AudioManager#setFocusRequestResult(AudioFocusInfo, int, AudioPolicy)}
         *     in Android P, always equal to {@link #AUDIOFOCUS_REQUEST_GRANTED}.
         */
        public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {}
        /**
         * Called whenever an application abandons audio focus.
         * Only ever called if the {@link AudioPolicy} was built with
         * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
         * @param afi information about the focus request being abandoned and the original
         *     requester.
         */
        public void onAudioFocusAbandon(AudioFocusInfo afi) {}
    }

    /**
     * Callback class to receive volume change-related events.
     * See {@link #Builder.setAudioPolicyVolumeCallback(AudioPolicyCallback)} to configure the
     * {@link AudioPolicy} to receive those events.
     *
     */
    public static abstract class AudioPolicyVolumeCallback {
        public AudioPolicyVolumeCallback() {}
        /**
         * Called when volume key-related changes are triggered, on the key down event.
         * @param adjustment the type of volume adjustment for the key.
         */
        public void onVolumeAdjustment(@AudioManager.VolumeAdjustment int adjustment) {}
    }

    private void onPolicyStatusChange() {
        AudioPolicyStatusListener l;
        synchronized (mLock) {
            if (mStatusListener == null) {
                return;
            }
            l = mStatusListener;
        }
        l.onStatusChange();
    }

    //==================================================
    // Callback interface

    /** @hide */
    public IAudioPolicyCallback cb() { return mPolicyCb; }

    private final IAudioPolicyCallback mPolicyCb = new IAudioPolicyCallback.Stub() {

        public void notifyAudioFocusGrant(AudioFocusInfo afi, int requestResult) {
            sendMsg(MSG_FOCUS_GRANT, afi, requestResult);
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusGrant: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId() + "reqRes=" + requestResult);
            }
        }

        public void notifyAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {
            sendMsg(MSG_FOCUS_LOSS, afi, wasNotified ? 1 : 0);
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusLoss: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId() + "wasNotified=" + wasNotified);
            }
        }

        public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
            sendMsg(MSG_FOCUS_REQUEST, afi, requestResult);
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId() + " gen=" + afi.getGen());
            }
        }

        public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
            sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */);
            if (DEBUG) {
                Log.v(TAG, "notifyAudioFocusAbandon: pack=" + afi.getPackageName() + " client="
                        + afi.getClientId());
            }
        }

        public void notifyMixStateUpdate(String regId, int state) {
            for (AudioMix mix : mConfig.getMixes()) {
                if (mix.getRegistration().equals(regId)) {
                    mix.mMixState = state;
                    sendMsg(MSG_MIX_STATE_UPDATE, mix, 0/*ignored*/);
                    if (DEBUG) {
                        Log.v(TAG, "notifyMixStateUpdate: regId=" + regId + " state=" + state);
                    }
                }
            }
        }

        public void notifyVolumeAdjust(int adjustment) {
            sendMsg(MSG_VOL_ADJUST, null /* ignored */, adjustment);
            if (DEBUG) {
                Log.v(TAG, "notifyVolumeAdjust: " + adjustment);
            }
        }

        public void notifyUnregistration() {
            setRegistration(null);
        }
    };

    //==================================================
    // Event handling
    private final EventHandler mEventHandler;
    private final static int MSG_POLICY_STATUS_CHANGE = 0;
    private final static int MSG_FOCUS_GRANT = 1;
    private final static int MSG_FOCUS_LOSS = 2;
    private final static int MSG_MIX_STATE_UPDATE = 3;
    private final static int MSG_FOCUS_REQUEST = 4;
    private final static int MSG_FOCUS_ABANDON = 5;
    private final static int MSG_VOL_ADJUST = 6;

    private class EventHandler extends Handler {
        public EventHandler(AudioPolicy ap, Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case MSG_POLICY_STATUS_CHANGE:
                    onPolicyStatusChange();
                    break;
                case MSG_FOCUS_GRANT:
                    if (mFocusListener != null) {
                        mFocusListener.onAudioFocusGrant(
                                (AudioFocusInfo) msg.obj, msg.arg1);
                    }
                    break;
                case MSG_FOCUS_LOSS:
                    if (mFocusListener != null) {
                        mFocusListener.onAudioFocusLoss(
                                (AudioFocusInfo) msg.obj, msg.arg1 != 0);
                    }
                    break;
                case MSG_MIX_STATE_UPDATE:
                    if (mStatusListener != null) {
                        mStatusListener.onMixStateUpdate((AudioMix) msg.obj);
                    }
                    break;
                case MSG_FOCUS_REQUEST:
                    if (mFocusListener != null) {
                        mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
                    } else { // should never be null, but don't crash
                        Log.e(TAG, "Invalid null focus listener for focus request event");
                    }
                    break;
                case MSG_FOCUS_ABANDON:
                    if (mFocusListener != null) { // should never be null
                        mFocusListener.onAudioFocusAbandon((AudioFocusInfo) msg.obj);
                    } else { // should never be null, but don't crash
                        Log.e(TAG, "Invalid null focus listener for focus abandon event");
                    }
                    break;
                case MSG_VOL_ADJUST:
                    if (mVolCb != null) {
                        mVolCb.onVolumeAdjustment(msg.arg1);
                    } else { // should never be null, but don't crash
                        Log.e(TAG, "Invalid null volume event");
                    }
                    break;
                default:
                    Log.e(TAG, "Unknown event " + msg.what);
            }
        }
    }

    //==========================================================
    // Utils
    private static String addressForTag(AudioMix mix) {
        return "addr=" + mix.getRegistration();
    }

    private void sendMsg(int msg) {
        if (mEventHandler != null) {
            mEventHandler.sendEmptyMessage(msg);
        }
    }

    private void sendMsg(int msg, Object obj, int i) {
        if (mEventHandler != null) {
            mEventHandler.sendMessage(
                    mEventHandler.obtainMessage(msg, i /*arg1*/, 0 /*arg2, ignored*/, obj));
        }
    }

    private static IAudioService sService;

    private static IAudioService getService()
    {
        if (sService != null) {
            return sService;
        }
        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
        sService = IAudioService.Stub.asInterface(b);
        return sService;
    }

    public String toLogFriendlyString() {
        String textDump = new String("android.media.audiopolicy.AudioPolicy:\n");
        textDump += "config=" + mConfig.toLogFriendlyString();
        return (textDump);
    }

    /** @hide */
    @IntDef({
        POLICY_STATUS_REGISTERED,
        POLICY_STATUS_UNREGISTERED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PolicyStatus {}
}
