1a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi/*
2a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Copyright (C) 2014 The Android Open Source Project
3a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *
4a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * you may not use this file except in compliance with the License.
6a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * You may obtain a copy of the License at
7a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *
8a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *
10a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * See the License for the specific language governing permissions and
14a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * limitations under the License.
15a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */
16a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
17a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivipackage android.media.audiopolicy;
18a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
19a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.annotation.IntDef;
201b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.annotation.NonNull;
211b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.annotation.SystemApi;
228fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.content.Context;
238fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.content.pm.PackageManager;
248fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.media.AudioAttributes;
250212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Triviimport android.media.AudioFocusInfo;
26a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.media.AudioFormat;
27a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.media.AudioManager;
288fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.media.AudioRecord;
298fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.media.AudioTrack;
300212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Triviimport android.media.IAudioService;
318fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.media.MediaRecorder;
32a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.os.Binder;
331b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.os.Handler;
34a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.os.IBinder;
351b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.os.Looper;
361b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.os.Message;
370212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Triviimport android.os.RemoteException;
380212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Triviimport android.os.ServiceManager;
39a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.util.Log;
408fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Triviimport android.util.Slog;
41a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
42a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.lang.annotation.Retention;
43a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.lang.annotation.RetentionPolicy;
44a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.util.ArrayList;
45a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
46a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi/**
478fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi * @hide
48a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * AudioPolicy provides access to the management of audio routing and audio focus.
49a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */
501b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi@SystemApi
51a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivipublic class AudioPolicy {
52a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
53a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private static final String TAG = "AudioPolicy";
540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private static final boolean DEBUG = false;
550212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private final Object mLock = new Object();
56a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
57a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
58a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * The status of an audio policy that is valid but cannot be used because it is not registered.
59a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
601b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
61a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static final int POLICY_STATUS_UNREGISTERED = 1;
62a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
63a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * The status of an audio policy that is valid, successfully registered and thus active.
64a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
651b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
66a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static final int POLICY_STATUS_REGISTERED = 2;
67a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
68a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private int mStatus;
698fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    private String mRegistrationId;
708fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    private AudioPolicyStatusListener mStatusListener;
71126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    private boolean mIsFocusPolicy;
72a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
730212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
740212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * The behavior of a policy with regards to audio focus where it relies on the application
750212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * to do the ducking, the is the legacy and default behavior.
760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    @SystemApi
780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public static final int FOCUS_POLICY_DUCKING_IN_APP = 0;
790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public static final int FOCUS_POLICY_DUCKING_DEFAULT = FOCUS_POLICY_DUCKING_IN_APP;
800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * The behavior of a policy with regards to audio focus where it handles ducking instead
820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * of the application losing focus and being signaled it can duck (as communicated by
830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * {@link android.media.AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}).
840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * <br>Can only be used after having set a listener with
850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * {@link AudioPolicy#setAudioPolicyFocusListener(AudioPolicyFocusListener)}.
860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    @SystemApi
880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1;
890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private AudioPolicyFocusListener mFocusListener;
910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
928fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    private Context mContext;
93a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
94a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private AudioPolicyConfig mConfig;
950212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
96a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /** @hide */
97a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public AudioPolicyConfig getConfig() { return mConfig; }
980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /** @hide */
990212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public boolean hasFocusListener() { return mFocusListener != null; }
100126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    /** @hide */
101126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    public boolean isFocusPolicy() { return mIsFocusPolicy; }
102a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
103a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
104a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * The parameter is guaranteed non-null through the Builder
105a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
1060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
107126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy) {
108a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        mConfig = config;
1091b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        mStatus = POLICY_STATUS_UNREGISTERED;
1101b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        mContext = context;
1111b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        if (looper == null) {
1121b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            looper = Looper.getMainLooper();
1131b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
1141b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        if (looper != null) {
1151b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            mEventHandler = new EventHandler(this, looper);
116a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        } else {
1171b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            mEventHandler = null;
1181b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            Log.e(TAG, "No event handler due to looper without a thread");
119a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
1200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        mFocusListener = fl;
1210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        mStatusListener = sl;
122126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mIsFocusPolicy = isFocusPolicy;
123a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
124a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
125a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
126126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * Builder class for {@link AudioPolicy} objects.
127126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * By default the policy to be created doesn't govern audio focus decisions.
128a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
1291b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
130a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static class Builder {
131a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        private ArrayList<AudioMix> mMixes;
1328fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        private Context mContext;
1331b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        private Looper mLooper;
1340212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        private AudioPolicyFocusListener mFocusListener;
1350212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        private AudioPolicyStatusListener mStatusListener;
136126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        private boolean mIsFocusPolicy = false;
137a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
138a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
139a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Constructs a new Builder with no audio mixes.
1408fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi         * @param context the context for the policy
141a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
1420212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        @SystemApi
1438fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        public Builder(Context context) {
144a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mMixes = new ArrayList<AudioMix>();
1458fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            mContext = context;
146a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
147a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
148a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
149a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Add an {@link AudioMix} to be part of the audio policy being built.
150a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @param mix a non-null {@link AudioMix} to be part of the audio policy.
151a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @return the same Builder instance.
152a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @throws IllegalArgumentException
153a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
1540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        @SystemApi
1551b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        public Builder addMix(@NonNull AudioMix mix) throws IllegalArgumentException {
156a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (mix == null) {
157a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioMix argument");
158a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
159a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mMixes.add(mix);
160a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            return this;
161a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
162a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
1631b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        /**
1641b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi         * Sets the {@link Looper} on which to run the event loop.
1651b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi         * @param looper a non-null specific Looper.
1661b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi         * @return the same Builder instance.
1671b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi         * @throws IllegalArgumentException
1681b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi         */
1690212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        @SystemApi
1701b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        public Builder setLooper(@NonNull Looper looper) throws IllegalArgumentException {
1711b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            if (looper == null) {
1721b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                throw new IllegalArgumentException("Illegal null Looper argument");
1731b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            }
1741b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            mLooper = looper;
1751b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            return this;
1761b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
1771b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
1780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        /**
1790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi         * Sets the audio focus listener for the policy.
1800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi         * @param l a {@link AudioPolicy.AudioPolicyFocusListener}
1810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi         */
1820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        @SystemApi
1830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        public void setAudioPolicyFocusListener(AudioPolicyFocusListener l) {
1840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mFocusListener = l;
1850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
1860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
1870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        /**
188126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * Declares whether this policy will grant and deny audio focus through
189126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * the {@link AudioPolicy.AudioPolicyStatusListener}.
190126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * If set to {@code true}, it is mandatory to set an
191126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * {@link AudioPolicy.AudioPolicyStatusListener} in order to successfully build
192126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * an {@code AudioPolicy} instance.
193126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * @param enforce true if the policy will govern audio focus decisions.
194126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * @return the same Builder instance.
195126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         */
196126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        @SystemApi
197126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        public Builder setIsAudioFocusPolicy(boolean isFocusPolicy) {
198126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mIsFocusPolicy = isFocusPolicy;
199126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return this;
200126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
201126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
202126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        /**
2030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi         * Sets the audio policy status listener.
2040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi         * @param l a {@link AudioPolicy.AudioPolicyStatusListener}
2050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi         */
2060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        @SystemApi
2070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        public void setAudioPolicyStatusListener(AudioPolicyStatusListener l) {
2080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mStatusListener = l;
2090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
2100212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
211126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        /**
212126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * Combines all of the attributes that have been set on this {@code Builder} and returns a
213126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * new {@link AudioPolicy} object.
214126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * @return a new {@code AudioPolicy} object.
215126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * @throws IllegalStateException if there is no
216126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         *     {@link AudioPolicy.AudioPolicyStatusListener} but the policy was configured
217126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         *     as an audio focus policy with {@link #setIsAudioFocusPolicy(boolean)}.
218126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         */
2190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        @SystemApi
220a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        public AudioPolicy build() {
2215a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            if (mStatusListener != null) {
2225a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                // the AudioPolicy status listener includes updates on each mix activity state
2235a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                for (AudioMix mix : mMixes) {
2245a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    mix.mCallbackFlags |= AudioMix.CALLBACK_FLAG_NOTIFY_ACTIVITY;
2255a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                }
2265a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            }
227126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (mIsFocusPolicy && mFocusListener == null) {
228126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                throw new IllegalStateException("Cannot be a focus policy without "
229126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        + "an AudioPolicyFocusListener");
230126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
2310212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
232126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    mFocusListener, mStatusListener, mIsFocusPolicy);
233a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
234a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
235a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
2368fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    public void setRegistration(String regId) {
2370212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        synchronized (mLock) {
2380212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mRegistrationId = regId;
2390212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mConfig.setRegistration(regId);
2400212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (regId != null) {
2410212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                mStatus = POLICY_STATUS_REGISTERED;
2420212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            } else {
2430212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                mStatus = POLICY_STATUS_UNREGISTERED;
2440212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
2451b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
2460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        sendMsg(MSG_POLICY_STATUS_CHANGE);
2478fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
2488fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
2498fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    private boolean policyReadyToUse() {
2500212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        synchronized (mLock) {
2510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (mStatus != POLICY_STATUS_REGISTERED) {
2520212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                Log.e(TAG, "Cannot use unregistered AudioPolicy");
2530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return false;
2540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
2550212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (mContext == null) {
2560212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                Log.e(TAG, "Cannot use AudioPolicy without context");
2570212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return false;
2580212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
2590212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (mRegistrationId == null) {
2600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                Log.e(TAG, "Cannot use unregistered AudioPolicy");
2610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return false;
2620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
2638fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
2648fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        if (!(PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
2658fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
2668fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            Slog.w(TAG, "Cannot use AudioPolicy for pid " + Binder.getCallingPid() + " / uid "
2678fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                    + Binder.getCallingUid() + ", needs MODIFY_AUDIO_ROUTING");
2688fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            return false;
2698fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
2708fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        return true;
2718fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
2728fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
2738fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    private void checkMixReadyToUse(AudioMix mix, boolean forTrack)
2748fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            throws IllegalArgumentException{
2758fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        if (mix == null) {
2768fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            String msg = forTrack ? "Invalid null AudioMix for AudioTrack creation"
2778fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                    : "Invalid null AudioMix for AudioRecord creation";
2788fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            throw new IllegalArgumentException(msg);
2798fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
2808fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        if (!mConfig.mMixes.contains(mix)) {
2818fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            throw new IllegalArgumentException("Invalid mix: not part of this policy");
2828fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
2838fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) != AudioMix.ROUTE_FLAG_LOOP_BACK)
2848fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        {
2858fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            throw new IllegalArgumentException("Invalid AudioMix: not defined for loop back");
2868fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
2871b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        if (forTrack && (mix.getMixType() != AudioMix.MIX_TYPE_RECORDERS)) {
2881b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            throw new IllegalArgumentException(
2891b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                    "Invalid AudioMix: not defined for being a recording source");
2901b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
2911b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        if (!forTrack && (mix.getMixType() != AudioMix.MIX_TYPE_PLAYERS)) {
2921b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            throw new IllegalArgumentException(
2931b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                    "Invalid AudioMix: not defined for capturing playback");
2941b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
2958fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
2968fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
2978fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    /**
2980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Returns the current behavior for audio focus-related ducking.
2990212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @return {@link #FOCUS_POLICY_DUCKING_IN_APP} or {@link #FOCUS_POLICY_DUCKING_IN_POLICY}
3000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
3010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    @SystemApi
3020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public int getFocusDuckingBehavior() {
3030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        return mConfig.mDuckingPolicy;
3040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
3050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
3060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    // Note on implementation: not part of the Builder as there can be only one registered policy
3070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    // that handles ducking but there can be multiple policies
3080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
3090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Sets the behavior for audio focus-related ducking.
3100212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * There must be a focus listener if this policy is to handle ducking.
3110212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param behavior {@link #FOCUS_POLICY_DUCKING_IN_APP} or
3120212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     *     {@link #FOCUS_POLICY_DUCKING_IN_POLICY}
3130212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @return {@link AudioManager#SUCCESS} or {@link AudioManager#ERROR} (for instance if there
3140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     *     is already an audio policy that handles ducking).
3150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @throws IllegalArgumentException
3160212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @throws IllegalStateException
3170212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
3180212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    @SystemApi
3190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public int setFocusDuckingBehavior(int behavior)
3200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            throws IllegalArgumentException, IllegalStateException {
3210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if ((behavior != FOCUS_POLICY_DUCKING_IN_APP)
3220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                && (behavior != FOCUS_POLICY_DUCKING_IN_POLICY)) {
3230212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            throw new IllegalArgumentException("Invalid ducking behavior " + behavior);
3240212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
3250212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        synchronized (mLock) {
3260212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (mStatus != POLICY_STATUS_REGISTERED) {
3270212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                throw new IllegalStateException(
3280212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        "Cannot change ducking behavior for unregistered policy");
3290212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
3300212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if ((behavior == FOCUS_POLICY_DUCKING_IN_POLICY)
3310212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    && (mFocusListener == null)) {
3320212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // there must be a focus listener if the policy handles ducking
3330212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                throw new IllegalStateException(
3340212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        "Cannot handle ducking without an audio focus listener");
3350212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
3360212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            IAudioService service = getService();
3370212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            try {
3380212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                final int status = service.setFocusPropertiesForPolicy(behavior /*duckingBehavior*/,
3390212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        this.cb());
3400212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                if (status == AudioManager.SUCCESS) {
3410212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    mConfig.mDuckingPolicy = behavior;
3420212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                }
3430212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return status;
3440212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            } catch (RemoteException e) {
3450212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                Log.e(TAG, "Dead object in setFocusPropertiesForPolicy for behavior", e);
3460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return AudioManager.ERROR;
3470212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
3480212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
3490212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
3500212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
3510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
3528fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * Create an {@link AudioRecord} instance that is associated with the given {@link AudioMix}.
3538fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * Audio buffers recorded through the created instance will contain the mix of the audio
3548fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * streams that fed the given mixer.
3558fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with
3568fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     *     {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy.
3578fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * @return a new {@link AudioRecord} instance whose data format is the one defined in the
3588fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     *     {@link AudioMix}, or null if this policy was not successfully registered
3598fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     *     with {@link AudioManager#registerAudioPolicy(AudioPolicy)}.
3608fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * @throws IllegalArgumentException
3618fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     */
3621b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
3638fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    public AudioRecord createAudioRecordSink(AudioMix mix) throws IllegalArgumentException {
3648fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        if (!policyReadyToUse()) {
3658fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            Log.e(TAG, "Cannot create AudioRecord sink for AudioMix");
3668fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            return null;
3678fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
3688fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        checkMixReadyToUse(mix, false/*not for an AudioTrack*/);
3698dc1031453377d2f9d9c7847027f276e6726a4c8Jean-Michel Trivi        // create an AudioFormat from the mix format compatible with recording, as the mix
3708dc1031453377d2f9d9c7847027f276e6726a4c8Jean-Michel Trivi        // was defined for playback
3718dc1031453377d2f9d9c7847027f276e6726a4c8Jean-Michel Trivi        AudioFormat mixFormat = new AudioFormat.Builder(mix.getFormat())
3728dc1031453377d2f9d9c7847027f276e6726a4c8Jean-Michel Trivi                .setChannelMask(AudioFormat.inChannelMaskFromOutChannelMask(
3738dc1031453377d2f9d9c7847027f276e6726a4c8Jean-Michel Trivi                        mix.getFormat().getChannelMask()))
3748dc1031453377d2f9d9c7847027f276e6726a4c8Jean-Michel Trivi                .build();
3758fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        // create the AudioRecord, configured for loop back, using the same format as the mix
3768fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        AudioRecord ar = new AudioRecord(
3778fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                new AudioAttributes.Builder()
3788fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        .setInternalCapturePreset(MediaRecorder.AudioSource.REMOTE_SUBMIX)
3791b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        .addTag(addressForTag(mix))
3808fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        .build(),
3818dc1031453377d2f9d9c7847027f276e6726a4c8Jean-Michel Trivi                mixFormat,
3828fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                AudioRecord.getMinBufferSize(mix.getFormat().getSampleRate(),
3838fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        // using stereo for buffer size to avoid the current poor support for masks
3848fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        AudioFormat.CHANNEL_IN_STEREO, mix.getFormat().getEncoding()),
3858fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                AudioManager.AUDIO_SESSION_ID_GENERATE
3868fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                );
3878fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        return ar;
3888fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
3898fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
3908fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    /**
3918fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * Create an {@link AudioTrack} instance that is associated with the given {@link AudioMix}.
3928fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * Audio buffers played through the created instance will be sent to the given mix
3938fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * to be recorded through the recording APIs.
3948fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * @param mix a non-null {@link AudioMix} instance whose routing flags was defined with
3958fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     *     {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, previously added to this policy.
3961b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * @return a new {@link AudioTrack} instance whose data format is the one defined in the
3978fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     *     {@link AudioMix}, or null if this policy was not successfully registered
3988fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     *     with {@link AudioManager#registerAudioPolicy(AudioPolicy)}.
3998fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     * @throws IllegalArgumentException
4008fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi     */
4011b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
4028fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    public AudioTrack createAudioTrackSource(AudioMix mix) throws IllegalArgumentException {
4038fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        if (!policyReadyToUse()) {
4048fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            Log.e(TAG, "Cannot create AudioTrack source for AudioMix");
4058fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi            return null;
4068fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
4078fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        checkMixReadyToUse(mix, true/*for an AudioTrack*/);
4088fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        // create the AudioTrack, configured for loop back, using the same format as the mix
4098fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        AudioTrack at = new AudioTrack(
4108fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                new AudioAttributes.Builder()
4118fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        .setUsage(AudioAttributes.USAGE_VIRTUAL_SOURCE)
4121b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        .addTag(addressForTag(mix))
4138fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        .build(),
4148fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                mix.getFormat(),
4158fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                AudioTrack.getMinBufferSize(mix.getFormat().getSampleRate(),
4168fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                        mix.getFormat().getChannelMask(), mix.getFormat().getEncoding()),
4178fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                AudioTrack.MODE_STREAM,
4188fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                AudioManager.AUDIO_SESSION_ID_GENERATE
4198fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi                );
4208fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        return at;
4218fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
422a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
4231b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
424a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public int getStatus() {
425a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        return mStatus;
426a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
427a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
4281b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
429a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static abstract class AudioPolicyStatusListener {
4301b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        public void onStatusChange() {}
4311b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        public void onMixStateUpdate(AudioMix mix) {}
432a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
433a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
4341b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
4350212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public static abstract class AudioPolicyFocusListener {
4360212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        public void onAudioFocusGrant(AudioFocusInfo afi, int requestResult) {}
4370212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        public void onAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {}
438126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        /**
439126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * Called whenever an application requests audio focus.
440126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * Only ever called if the {@link AudioPolicy} was built with
441126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
442126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * @param afi information about the focus request and the requester
443126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * @param requestResult the result that was returned synchronously by the framework to the
444126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         *     application, {@link #AUDIOFOCUS_REQUEST_FAILED},or
445126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         *     {@link #AUDIOFOCUS_REQUEST_DELAYED}.
446126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         */
447126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        public void onAudioFocusRequest(AudioFocusInfo afi, int requestResult) {}
448126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        /**
449126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * Called whenever an application abandons audio focus.
450126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * Only ever called if the {@link AudioPolicy} was built with
451126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * {@link AudioPolicy.Builder#setIsAudioFocusPolicy(boolean)} set to {@code true}.
452126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         * @param afi information about the focus request being abandoned and the original
453126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         *     requester.
454126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi         */
455126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        public void onAudioFocusAbandon(AudioFocusInfo afi) {}
456a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
457a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
4580212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private void onPolicyStatusChange() {
4590212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        AudioPolicyStatusListener l;
4600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        synchronized (mLock) {
4610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (mStatusListener == null) {
4620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return;
4630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
4640212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            l = mStatusListener;
4651b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
4660212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        l.onStatusChange();
4671b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
4681b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
4691b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    //==================================================
4700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    // Callback interface
4710212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
4720212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /** @hide */
4730212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    public IAudioPolicyCallback cb() { return mPolicyCb; }
4740212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
4750212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private final IAudioPolicyCallback mPolicyCb = new IAudioPolicyCallback.Stub() {
4760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
4770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        public void notifyAudioFocusGrant(AudioFocusInfo afi, int requestResult) {
4780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            sendMsg(MSG_FOCUS_GRANT, afi, requestResult);
4790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (DEBUG) {
4800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                Log.v(TAG, "notifyAudioFocusGrant: pack=" + afi.getPackageName() + " client="
4810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        + afi.getClientId() + "reqRes=" + requestResult);
4820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
4830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
4840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
4850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        public void notifyAudioFocusLoss(AudioFocusInfo afi, boolean wasNotified) {
4860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            sendMsg(MSG_FOCUS_LOSS, afi, wasNotified ? 1 : 0);
4870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (DEBUG) {
4880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                Log.v(TAG, "notifyAudioFocusLoss: pack=" + afi.getPackageName() + " client="
4890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        + afi.getClientId() + "wasNotified=" + wasNotified);
4900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
4910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
4925a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi
493126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        public void notifyAudioFocusRequest(AudioFocusInfo afi, int requestResult) {
494126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            sendMsg(MSG_FOCUS_REQUEST, afi, requestResult);
495126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (DEBUG) {
496126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                Log.v(TAG, "notifyAudioFocusRequest: pack=" + afi.getPackageName() + " client="
497126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        + afi.getClientId() + "reqRes=" + requestResult);
498126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
499126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
500126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
501126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        public void notifyAudioFocusAbandon(AudioFocusInfo afi) {
502126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            sendMsg(MSG_FOCUS_ABANDON, afi, 0 /* ignored */);
503126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (DEBUG) {
504126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                Log.v(TAG, "notifyAudioFocusAbandon: pack=" + afi.getPackageName() + " client="
505126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        + afi.getClientId());
506126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
507126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
508126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
5095a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi        public void notifyMixStateUpdate(String regId, int state) {
5105a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            for (AudioMix mix : mConfig.getMixes()) {
5115a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                if (mix.getRegistration().equals(regId)) {
5125a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    mix.mMixState = state;
5135a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    sendMsg(MSG_MIX_STATE_UPDATE, mix, 0/*ignored*/);
5145a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    if (DEBUG) {
5155a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                        Log.v(TAG, "notifyMixStateUpdate: regId=" + regId + " state=" + state);
5165a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    }
5175a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                }
5185a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            }
5195a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi        }
5200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    };
5210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
5220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    //==================================================
5231b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    // Event handling
5241b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    private final EventHandler mEventHandler;
5251b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    private final static int MSG_POLICY_STATUS_CHANGE = 0;
5260212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private final static int MSG_FOCUS_GRANT = 1;
5270212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private final static int MSG_FOCUS_LOSS = 2;
5285a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    private final static int MSG_MIX_STATE_UPDATE = 3;
529126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    private final static int MSG_FOCUS_REQUEST = 4;
530126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    private final static int MSG_FOCUS_ABANDON = 5;
5311b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
5321b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    private class EventHandler extends Handler {
5331b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        public EventHandler(AudioPolicy ap, Looper looper) {
5341b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            super(looper);
5351b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
5361b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
5371b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        @Override
5381b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        public void handleMessage(Message msg) {
5391b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            switch(msg.what) {
5401b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                case MSG_POLICY_STATUS_CHANGE:
5411b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                    onPolicyStatusChange();
5421b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                    break;
5430212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                case MSG_FOCUS_GRANT:
5440212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    if (mFocusListener != null) {
5450212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        mFocusListener.onAudioFocusGrant(
5460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                                (AudioFocusInfo) msg.obj, msg.arg1);
5470212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    }
5480212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    break;
5490212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                case MSG_FOCUS_LOSS:
5500212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    if (mFocusListener != null) {
5510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        mFocusListener.onAudioFocusLoss(
5520212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                                (AudioFocusInfo) msg.obj, msg.arg1 != 0);
5530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    }
5540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    break;
5555a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                case MSG_MIX_STATE_UPDATE:
5565a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    if (mStatusListener != null) {
5575a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                        mStatusListener.onMixStateUpdate((AudioMix) msg.obj);
5585a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    }
5595a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                    break;
560126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                case MSG_FOCUS_REQUEST:
561126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    if (mFocusListener != null) {
562126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        mFocusListener.onAudioFocusRequest((AudioFocusInfo) msg.obj, msg.arg1);
563126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    } else { // should never be null, but don't crash
564126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        Log.e(TAG, "Invalid null focus listener for focus request event");
565126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    }
566126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    break;
567126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                case MSG_FOCUS_ABANDON:
568126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    if (mFocusListener != null) { // should never be null
569126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        mFocusListener.onAudioFocusAbandon((AudioFocusInfo) msg.obj);
570126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    } else { // should never be null, but don't crash
571126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        Log.e(TAG, "Invalid null focus listener for focus abandon event");
572126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    }
573126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    break;
5741b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                default:
5751b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                    Log.e(TAG, "Unknown event " + msg.what);
5761b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            }
5771b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
5781b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
5791b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
5801b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    //==========================================================
5811b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    // Utils
5821b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    private static String addressForTag(AudioMix mix) {
5831b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        return "addr=" + mix.getRegistration();
5841b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
5851b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
5860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private void sendMsg(int msg) {
5870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if (mEventHandler != null) {
5880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mEventHandler.sendEmptyMessage(msg);
5890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
5900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
5910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
5920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private void sendMsg(int msg, Object obj, int i) {
5930212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if (mEventHandler != null) {
5940212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mEventHandler.sendMessage(
5950212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    mEventHandler.obtainMessage(msg, i /*arg1*/, 0 /*arg2, ignored*/, obj));
5960212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
5970212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
5980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
5990212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private static IAudioService sService;
6000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
6010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private static IAudioService getService()
6020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    {
6030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if (sService != null) {
6040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            return sService;
6051b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
6060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
6070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        sService = IAudioService.Stub.asInterface(b);
6080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        return sService;
6091b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
6101b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
6118fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    public String toLogFriendlyString() {
612a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        String textDump = new String("android.media.audiopolicy.AudioPolicy:\n");
6138fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        textDump += "config=" + mConfig.toLogFriendlyString();
614a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        return (textDump);
615a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
616a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
617a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /** @hide */
618a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    @IntDef({
619a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        POLICY_STATUS_REGISTERED,
620a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        POLICY_STATUS_UNREGISTERED
621a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    })
622a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    @Retention(RetentionPolicy.SOURCE)
623a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public @interface PolicyStatus {}
624a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi}
625