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