1fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi/* 2fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Copyright (C) 2013 The Android Open Source Project 3fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * 4fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 5fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * you may not use this file except in compliance with the License. 6fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * You may obtain a copy of the License at 7fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * 8fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 9fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * 10fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 11fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 12fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * See the License for the specific language governing permissions and 14fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * limitations under the License. 15fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 16fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 176156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockpackage com.android.server.audio; 18fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 19126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Triviimport android.annotation.NonNull; 20fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport android.app.AppOpsManager; 21fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport android.content.Context; 226156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.AudioAttributes; 236156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.AudioFocusInfo; 246156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.AudioManager; 256156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.AudioSystem; 266156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.IAudioFocusDispatcher; 27126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Triviimport android.media.audiopolicy.AudioPolicy; 280212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Triviimport android.media.audiopolicy.IAudioPolicyCallback; 29fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport android.os.Binder; 30461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Triviimport android.os.Build; 31fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport android.os.IBinder; 32fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport android.os.RemoteException; 33fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport android.util.Log; 346156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlock 35fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport java.io.PrintWriter; 36fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport java.util.ArrayList; 37545fcf8d11399845fbf1b53488c82b492da06d46Jean-Michel Triviimport java.util.Date; 38126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Triviimport java.util.HashMap; 39fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport java.util.Iterator; 40126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Triviimport java.util.Map.Entry; 41126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Triviimport java.util.Set; 42fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Triviimport java.util.Stack; 43545fcf8d11399845fbf1b53488c82b492da06d46Jean-Michel Triviimport java.text.DateFormat; 44fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 45fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi/** 46fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * @hide 47fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * 48fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 4999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivipublic class MediaFocusControl implements PlayerFocusEnforcer { 50fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 51fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final String TAG = "MediaFocusControl"; 52126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi static final boolean DEBUG = false; 53fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 5499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi /** 5599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * set to true so the framework enforces ducking itself, without communicating to apps 56952f2341abc398d245f3c0a577ebe1b28f93f368Jean-Michel Trivi * that they lost focus for most use cases. 5799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi */ 58952f2341abc398d245f3c0a577ebe1b28f93f368Jean-Michel Trivi static final boolean ENFORCE_DUCKING = true; 5962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi /** 60461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi * set to true to the framework enforces ducking itself only with apps above a given SDK 61461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi * target level. Is ignored if ENFORCE_DUCKING is false. 62461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi */ 63461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi static final boolean ENFORCE_DUCKING_FOR_NEW = true; 64461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi /** 65461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi * the SDK level (included) up to which the framework doesn't enforce ducking itself. Is ignored 66461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi * if ENFORCE_DUCKING_FOR_NEW is false; 67461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi */ 68461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi // automatic ducking was introduced for Android O 69461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi static final int DUCKING_IN_APP_SDK_LEVEL = Build.VERSION_CODES.N_MR1; 70461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi /** 7162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi * set to true so the framework enforces muting media/game itself when the device is ringing 7262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi * or in a call. 7362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi */ 7462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi static final boolean ENFORCE_MUTING_FOR_RING_OR_CALL = true; 7599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 76fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private final Context mContext; 77fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private final AppOpsManager mAppOps; 7899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi private PlayerFocusEnforcer mFocusEnforcer; // never null 79fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 8062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi private boolean mRingOrCallActive = false; 8162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 8299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi protected MediaFocusControl(Context cntxt, PlayerFocusEnforcer pfe) { 83fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mContext = cntxt; 84fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE); 8599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mFocusEnforcer = pfe; 86fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 87fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 8873673ab7988adc80fc179e9910c7a19fcabef884Jean-Michel Trivi protected void dump(PrintWriter pw) { 89545fcf8d11399845fbf1b53488c82b492da06d46Jean-Michel Trivi pw.println("\nMediaFocusControl dump time: " 90545fcf8d11399845fbf1b53488c82b492da06d46Jean-Michel Trivi + DateFormat.getTimeInstance().format(new Date())); 9173673ab7988adc80fc179e9910c7a19fcabef884Jean-Michel Trivi dumpFocusStack(pw); 920b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi pw.println("\n"); 930b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi // log 940b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi mEventLogger.dump(pw); 95fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 96fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 9799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi //================================================================= 9899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi // PlayerFocusEnforcer implementation 9999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi @Override 10099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi public boolean duckPlayers(FocusRequester winner, FocusRequester loser) { 10199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi return mFocusEnforcer.duckPlayers(winner, loser); 10299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 10399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 10499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi @Override 10599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi public void unduckPlayers(FocusRequester winner) { 10699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mFocusEnforcer.unduckPlayers(winner); 10799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 108fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 10962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi @Override 11062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi public void mutePlayersForCall(int[] usagesToMute) { 11162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi mFocusEnforcer.mutePlayersForCall(usagesToMute); 11262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 11362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 11462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi @Override 11562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi public void unmutePlayersForCall() { 11662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi mFocusEnforcer.unmutePlayersForCall(); 11762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 11862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 119fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 120fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // AudioFocus 121fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 122fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 123fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private final static Object mAudioFocusLock = new Object(); 124fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 125fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi /** 1260b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi * Arbitrary maximum size of audio focus stack to prevent apps OOM'ing this process. 1270b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi */ 1280b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi private static final int MAX_STACK_SIZE = 100; 1290b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi 1300b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi private static final AudioEventLogger mEventLogger = new AudioEventLogger(50, 1310b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi "focus commands as seen by MediaFocusControl"); 1320b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi 1330b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi /** 134fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Discard the current audio focus owner. 135fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Notify top of audio focus stack that it lost focus (regardless of possibility to reassign 136fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * focus), remove it from the stack, and clear the remote control display. 137fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 138fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi protected void discardAudioFocusOwner() { 139fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi synchronized(mAudioFocusLock) { 140cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi if (!mFocusStack.empty()) { 141fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // notify the current focus owner it lost focus after removing it from stack 14283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi final FocusRequester exFocusOwner = mFocusStack.pop(); 14399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null); 14483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi exFocusOwner.release(); 145fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 146fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 147fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 148fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 1490212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi /** 1500212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * Called synchronized on mAudioFocusLock 1510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi */ 152fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private void notifyTopOfAudioFocusStack() { 153fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // notify the top of the stack it gained focus 154cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi if (!mFocusStack.empty()) { 155fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi if (canReassignAudioFocus()) { 15600bf4b18173b8921d7a5cecbd8b8d3745470b5d0Jean-Michel Trivi mFocusStack.peek().handleFocusGain(AudioManager.AUDIOFOCUS_GAIN); 157fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 158fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 159fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 160fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 161cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi /** 162cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi * Focus is requested, propagate the associated loss throughout the stack. 163cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi * @param focusGain the new focus gain that will later be added at the top of the stack 164cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi */ 16599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi private void propagateFocusLossFromGain_syncAf(int focusGain, final FocusRequester fr) { 166cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi // going through the audio focus stack to signal new focus, traversing order doesn't 167cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi // matter as all entries respond to the same external focus gain 168cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi Iterator<FocusRequester> stackIterator = mFocusStack.iterator(); 169cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi while(stackIterator.hasNext()) { 17099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi stackIterator.next().handleExternalFocusGain(focusGain, fr); 171cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi } 172cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi } 173cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi 17483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi private final Stack<FocusRequester> mFocusStack = new Stack<FocusRequester>(); 175fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 176fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi /** 177fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Helper function: 178fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Display in the log the current entries in the audio focus stack 179fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 180fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private void dumpFocusStack(PrintWriter pw) { 181fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi pw.println("\nAudio Focus stack entries (last is top of stack):"); 182fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi synchronized(mAudioFocusLock) { 18383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi Iterator<FocusRequester> stackIterator = mFocusStack.iterator(); 184fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi while(stackIterator.hasNext()) { 18583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi stackIterator.next().dump(pw); 186fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 187126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi pw.println("\n"); 188126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy == null) { 189126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi pw.println("No external focus policy\n"); 190126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } else { 191126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi pw.println("External focus policy: "+ mFocusPolicy + ", focus owners:\n"); 192126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi dumpExtFocusPolicyFocusOwners(pw); 193126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 194fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 19562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi pw.println("\n"); 19662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi pw.println(" Notify on duck: " + mNotifyFocusOwnerOnDuck + "\n"); 19762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi pw.println(" In ring or call: " + mRingOrCallActive + "\n"); 198fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 199fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 200fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi /** 201fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Helper function: 202fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Called synchronized on mAudioFocusLock 203fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Remove a focus listener from the focus stack. 204fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * @param clientToRemove the focus listener 205fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * @param signal if true and the listener was at the top of the focus stack, i.e. it was holding 206fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * focus, notify the next item in the stack it gained focus. 207fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 2080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi private void removeFocusStackEntry(String clientToRemove, boolean signal, 2090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean notifyFocusFollowers) { 210fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // is the current top of the focus stack abandoning focus? (because of request, not death) 21183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi if (!mFocusStack.empty() && mFocusStack.peek().hasSameClient(clientToRemove)) 212fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi { 213fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //Log.i(TAG, " removeFocusStackEntry() removing top of stack"); 21483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi FocusRequester fr = mFocusStack.pop(); 21583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi fr.release(); 2160212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (notifyFocusFollowers) { 2170212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi final AudioFocusInfo afi = fr.toAudioFocusInfo(); 2180212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi afi.clearLossReceived(); 2190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi notifyExtPolicyFocusLoss_syncAf(afi, false); 2200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 221fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi if (signal) { 222fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // notify the new top of the stack it gained focus 223fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi notifyTopOfAudioFocusStack(); 224fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 225fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } else { 226fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // focus is abandoned by a client that's not at the top of the stack, 227fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // no need to update focus. 228fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // (using an iterator on the stack so we can safely remove an entry after having 229fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // evaluated it, traversal order doesn't matter here) 23083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi Iterator<FocusRequester> stackIterator = mFocusStack.iterator(); 231fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi while(stackIterator.hasNext()) { 23201fe661ae5da3739215d93922412df4b24c859a2RoboErik FocusRequester fr = stackIterator.next(); 23383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi if(fr.hasSameClient(clientToRemove)) { 23400bf4b18173b8921d7a5cecbd8b8d3745470b5d0Jean-Michel Trivi Log.i(TAG, "AudioFocus removeFocusStackEntry(): removing entry for " 23583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi + clientToRemove); 236fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi stackIterator.remove(); 237e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi // stack entry not used anymore, clear references 23883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi fr.release(); 239fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 240fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 241fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 242fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 243fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 244fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi /** 245fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Helper function: 246fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Called synchronized on mAudioFocusLock 247fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Remove focus listeners from the focus stack for a particular client when it has died. 248fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 249e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi private void removeFocusStackEntryOnDeath(IBinder cb) { 250fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // is the owner of the audio focus part of the client to remove? 251fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi boolean isTopOfStackForClientToRemove = !mFocusStack.isEmpty() && 25283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi mFocusStack.peek().hasSameBinder(cb); 253fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // (using an iterator on the stack so we can safely remove an entry after having 254fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // evaluated it, traversal order doesn't matter here) 25583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi Iterator<FocusRequester> stackIterator = mFocusStack.iterator(); 256fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi while(stackIterator.hasNext()) { 25701fe661ae5da3739215d93922412df4b24c859a2RoboErik FocusRequester fr = stackIterator.next(); 25883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi if(fr.hasSameBinder(cb)) { 259e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi Log.i(TAG, "AudioFocus removeFocusStackEntryOnDeath(): removing entry for " + cb); 260fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi stackIterator.remove(); 261e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi // stack entry not used anymore, clear references 262e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi fr.release(); 263fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 264fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 265fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi if (isTopOfStackForClientToRemove) { 266fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // we removed an entry at the top of the stack: 267fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // notify the new top of the stack it gained focus. 268fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi notifyTopOfAudioFocusStack(); 269fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 270fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 271fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 272fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi /** 273126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * Helper function for external focus policy: 274126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * Called synchronized on mAudioFocusLock 275126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * Remove focus listeners from the list of potential focus owners for a particular client when 276126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * it has died. 277126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi */ 278126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi private void removeFocusEntryForExtPolicy(IBinder cb) { 279126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusOwnersForFocusPolicy.isEmpty()) { 280126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return; 281126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 282126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi boolean released = false; 283126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet(); 284126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator(); 285126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi while (ownerIterator.hasNext()) { 286126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final Entry<String, FocusRequester> owner = ownerIterator.next(); 287126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final FocusRequester fr = owner.getValue(); 288126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (fr.hasSameBinder(cb)) { 289126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi ownerIterator.remove(); 290126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi fr.release(); 291126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi notifyExtFocusPolicyFocusAbandon_syncAf(fr.toAudioFocusInfo()); 292126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi break; 293126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 294126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 295126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 296126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 297126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi /** 298fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Helper function: 299fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Returns true if the system is in a state where the focus can be reevaluated, false otherwise. 300fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * The implementation guarantees that a state where focus cannot be immediately reassigned 301958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi * implies that an "locked" focus owner is at the top of the focus stack. 302fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * Modifications to the implementation that break this assumption will cause focus requests to 303fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * misbehave when honoring the AudioManager.AUDIOFOCUS_FLAG_DELAY_OK flag. 304fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 305fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private boolean canReassignAudioFocus() { 306fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // focus requests are rejected during a phone call or when the phone is ringing 307fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus 308958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if (!mFocusStack.isEmpty() && isLockedFocusOwner(mFocusStack.peek())) { 309fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return false; 310fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 311fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return true; 312fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 313fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 314958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi private boolean isLockedFocusOwner(FocusRequester fr) { 3156156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlock return (fr.hasSameClient(AudioSystem.IN_VOICE_COMM_FOCUS_ID) || fr.isLockedFocusOwner()); 316fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 317fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi 318fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi /** 319fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * Helper function 320958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi * Pre-conditions: focus stack is not empty, there is one or more locked focus owner 321fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * at the top of the focus stack 322fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * Push the focus requester onto the audio focus stack at the first position immediately 323958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi * following the locked focus owners. 324fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * @return {@link AudioManager#AUDIOFOCUS_REQUEST_GRANTED} or 325fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi * {@link AudioManager#AUDIOFOCUS_REQUEST_DELAYED} 326fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi */ 327958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi private int pushBelowLockedFocusOwners(FocusRequester nfr) { 328958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi int lastLockedFocusOwnerIndex = mFocusStack.size(); 329fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi for (int index = mFocusStack.size()-1; index >= 0; index--) { 330958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if (isLockedFocusOwner(mFocusStack.elementAt(index))) { 331958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi lastLockedFocusOwnerIndex = index; 332fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 333fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 334958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if (lastLockedFocusOwnerIndex == mFocusStack.size()) { 335fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // this should not happen, but handle it and log an error 336fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi Log.e(TAG, "No exclusive focus owner found in propagateFocusLossFromGain_syncAf()", 337fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi new Exception()); 338fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // no exclusive owner, push at top of stack, focus is granted, propagate change 33999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi propagateFocusLossFromGain_syncAf(nfr.getGainRequest(), nfr); 340fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi mFocusStack.push(nfr); 341fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 342fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } else { 343958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi mFocusStack.insertElementAt(nfr, lastLockedFocusOwnerIndex); 344fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_DELAYED; 345fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 346fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 347fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi 348fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi /** 349fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * Inner class to monitor audio focus client deaths, and remove them from the audio focus 350fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi * stack if necessary. 351fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi */ 35283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi protected class AudioFocusDeathHandler implements IBinder.DeathRecipient { 353fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private IBinder mCb; // To be notified of client's death 354fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 355fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi AudioFocusDeathHandler(IBinder cb) { 356fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mCb = cb; 357fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 358fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 359fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void binderDied() { 360fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi synchronized(mAudioFocusLock) { 361126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy != null) { 362126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi removeFocusEntryForExtPolicy(mCb); 363126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } else { 364126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi removeFocusStackEntryOnDeath(mCb); 365126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 366fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 367fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 368fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 369fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 3700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi /** 3710212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * Indicates whether to notify an audio focus owner when it loses focus 3720212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * with {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK} if it will only duck. 3730212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * This variable being false indicates an AudioPolicy has been registered and has signaled 3740212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * it will handle audio ducking. 3750212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi */ 3760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi private boolean mNotifyFocusOwnerOnDuck = true; 3770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 3780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi protected void setDuckingInExtPolicyAvailable(boolean available) { 3790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mNotifyFocusOwnerOnDuck = !available; 3800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 3810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 3820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean mustNotifyFocusOwnerOnDuck() { return mNotifyFocusOwnerOnDuck; } 3830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 3840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi private ArrayList<IAudioPolicyCallback> mFocusFollowers = new ArrayList<IAudioPolicyCallback>(); 3850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 3860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi void addFocusFollower(IAudioPolicyCallback ff) { 3870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (ff == null) { 3880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return; 3890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 3900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi synchronized(mAudioFocusLock) { 3910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean found = false; 3920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi for (IAudioPolicyCallback pcb : mFocusFollowers) { 3930212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (pcb.asBinder().equals(ff.asBinder())) { 3940212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi found = true; 3950212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi break; 3960212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 3970212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 3980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (found) { 3990212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return; 4000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } else { 4010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mFocusFollowers.add(ff); 40260fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi notifyExtPolicyCurrentFocusAsync(ff); 4030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 4070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi void removeFocusFollower(IAudioPolicyCallback ff) { 4080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (ff == null) { 4090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return; 4100212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4110212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi synchronized(mAudioFocusLock) { 4120212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi for (IAudioPolicyCallback pcb : mFocusFollowers) { 4130212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (pcb.asBinder().equals(ff.asBinder())) { 4140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mFocusFollowers.remove(pcb); 4150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi break; 4160212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4170212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4180212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 421126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi private IAudioPolicyCallback mFocusPolicy = null; 422126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 423126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // Since we don't have a stack of focus owners when using an external focus policy, we keep 424126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // track of all the focus requesters in this map, with their clientId as the key. This is 425126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // used both for focus dispatch and death handling 426126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi private HashMap<String, FocusRequester> mFocusOwnersForFocusPolicy = 427126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi new HashMap<String, FocusRequester>(); 428126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 429126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi void setFocusPolicy(IAudioPolicyCallback policy) { 430126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (policy == null) { 431126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return; 432126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 433126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi synchronized (mAudioFocusLock) { 434126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi mFocusPolicy = policy; 435126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 436126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 437126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 438126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi void unsetFocusPolicy(IAudioPolicyCallback policy) { 439126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (policy == null) { 440126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return; 441126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 442126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi synchronized (mAudioFocusLock) { 443126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy == policy) { 444126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi mFocusPolicy = null; 445126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 446126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 447126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 448126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 4490212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi /** 45060fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi * @param pcb non null 45160fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi */ 45260fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi void notifyExtPolicyCurrentFocusAsync(IAudioPolicyCallback pcb) { 45360fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi final IAudioPolicyCallback pcb2 = pcb; 45460fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi final Thread thread = new Thread() { 45560fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi @Override 45660fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi public void run() { 45760fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi synchronized(mAudioFocusLock) { 45860fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi if (mFocusStack.isEmpty()) { 45960fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi return; 46060fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi } 46160fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi try { 46260fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi pcb2.notifyAudioFocusGrant(mFocusStack.peek().toAudioFocusInfo(), 46360fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi // top of focus stack always has focus 46460fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 46560fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi } catch (RemoteException e) { 46660fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi Log.e(TAG, "Can't call notifyAudioFocusGrant() on IAudioPolicyCallback " 46760fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi + pcb2.asBinder(), e); 46860fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi } 46960fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi } 47060fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi } 47160fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi }; 47260fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi thread.start(); 47360fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi } 47460fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi 47560fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi /** 4760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * Called synchronized on mAudioFocusLock 4770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi */ 4780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi void notifyExtPolicyFocusGrant_syncAf(AudioFocusInfo afi, int requestResult) { 4790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi for (IAudioPolicyCallback pcb : mFocusFollowers) { 4800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi try { 4810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // oneway 4820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi pcb.notifyAudioFocusGrant(afi, requestResult); 4830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } catch (RemoteException e) { 48460fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi Log.e(TAG, "Can't call notifyAudioFocusGrant() on IAudioPolicyCallback " 4850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + pcb.asBinder(), e); 4860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 4890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 4900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi /** 4910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * Called synchronized on mAudioFocusLock 4920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi */ 4930212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi void notifyExtPolicyFocusLoss_syncAf(AudioFocusInfo afi, boolean wasDispatched) { 4940212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi for (IAudioPolicyCallback pcb : mFocusFollowers) { 4950212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi try { 4960212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // oneway 4970212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi pcb.notifyAudioFocusLoss(afi, wasDispatched); 4980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } catch (RemoteException e) { 49960fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi Log.e(TAG, "Can't call notifyAudioFocusLoss() on IAudioPolicyCallback " 5000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + pcb.asBinder(), e); 5010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 5020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 5030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 5040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 505126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi /** 506126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * Called synchronized on mAudioFocusLock 507126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * @param afi 508126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * @param requestResult 509126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * @return true if the external audio focus policy (if any) is handling the focus request 510126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi */ 511126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi, int requestResult, 512126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi IAudioFocusDispatcher fd, IBinder cb) { 513126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy == null) { 514126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return false; 515126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 516126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (DEBUG) { 517126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi Log.v(TAG, "notifyExtFocusPolicyFocusRequest client="+afi.getClientId() 518126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi + " dispatcher=" + fd); 519126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 520126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId()); 521126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (existingFr != null) { 522126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (!existingFr.hasSameDispatcher(fd)) { 523126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi existingFr.release(); 524126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb); 525126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi mFocusOwnersForFocusPolicy.put(afi.getClientId(), 526126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi new FocusRequester(afi, fd, cb, hdlr, this)); 527126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 528126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } else if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED 529126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi || requestResult == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) { 530126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // new focus (future) focus owner to keep track of 531126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb); 532126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi mFocusOwnersForFocusPolicy.put(afi.getClientId(), 533126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi new FocusRequester(afi, fd, cb, hdlr, this)); 534126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 535126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi try { 536126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi //oneway 537126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi mFocusPolicy.notifyAudioFocusRequest(afi, requestResult); 538126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } catch (RemoteException e) { 539126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi Log.e(TAG, "Can't call notifyAudioFocusRequest() on IAudioPolicyCallback " 540126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi + mFocusPolicy.asBinder(), e); 541126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 542126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return true; 543126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 544126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 545126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi /** 546126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * Called synchronized on mAudioFocusLock 547126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * @param afi 548126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * @param requestResult 549126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * @return true if the external audio focus policy (if any) is handling the focus request 550126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi */ 551126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi boolean notifyExtFocusPolicyFocusAbandon_syncAf(AudioFocusInfo afi) { 552126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy == null) { 553126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return false; 554126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 555126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final FocusRequester fr = mFocusOwnersForFocusPolicy.remove(afi.getClientId()); 556126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (fr != null) { 557126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi fr.release(); 558126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 559126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi try { 560126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi //oneway 561126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi mFocusPolicy.notifyAudioFocusAbandon(afi); 562126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } catch (RemoteException e) { 563126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi Log.e(TAG, "Can't call notifyAudioFocusAbandon() on IAudioPolicyCallback " 564126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi + mFocusPolicy.asBinder(), e); 565126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 566126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return true; 567126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 568126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 569126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi /** see AudioManager.dispatchFocusChange(AudioFocusInfo afi, int focusChange, AudioPolicy ap) */ 570126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi int dispatchFocusChange(AudioFocusInfo afi, int focusChange) { 571126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (DEBUG) { 572126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi Log.v(TAG, "dispatchFocusChange " + focusChange + " to afi client=" 573126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi + afi.getClientId()); 574126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 575126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi synchronized (mAudioFocusLock) { 576126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy == null) { 577126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (DEBUG) { Log.v(TAG, "> failed: no focus policy" ); } 578126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 579126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 580126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final FocusRequester fr = mFocusOwnersForFocusPolicy.get(afi.getClientId()); 581126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (fr == null) { 582126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (DEBUG) { Log.v(TAG, "> failed: no such focus requester known" ); } 583126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 584126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 585126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return fr.dispatchFocusChange(focusChange); 586126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 587126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 588126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 589126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi private void dumpExtFocusPolicyFocusOwners(PrintWriter pw) { 590126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet(); 591126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator(); 592126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi while (ownerIterator.hasNext()) { 593126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final Entry<String, FocusRequester> owner = ownerIterator.next(); 594126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final FocusRequester fr = owner.getValue(); 595126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi fr.dump(pw); 596126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 597126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 598126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 5992380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi protected int getCurrentAudioFocus() { 6002380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi synchronized(mAudioFocusLock) { 6012380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi if (mFocusStack.empty()) { 6022380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi return AudioManager.AUDIOFOCUS_NONE; 6032380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } else { 6042380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi return mFocusStack.peek().getGainRequest(); 6052380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 6062380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 6072380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 608fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 60999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi /** 61062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi * Delay after entering ringing or call mode after which the framework will mute streams 61162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi * that are still playing. 61262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi */ 61362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi private static final int RING_CALL_MUTING_ENFORCEMENT_DELAY_MS = 100; 61462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 61562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi /** 61662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi * Usages to mute when the device rings or is in a call 61762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi */ 61862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi private final static int[] USAGES_TO_MUTE_IN_RING_OR_CALL = 61962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi { AudioAttributes.USAGE_MEDIA, AudioAttributes.USAGE_GAME }; 62062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 62162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi /** 62299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * Return the volume ramp time expected before playback with the given AudioAttributes would 62399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * start after gaining audio focus. 62499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * @param attr attributes of the sound about to start playing 62599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * @return time in ms 62699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi */ 627dce82ab7bfd5ec7c1ef658825c18506a89e567d6Jean-Michel Trivi protected static int getFocusRampTimeMs(int focusGain, AudioAttributes attr) { 62899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi switch (attr.getUsage()) { 62999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_MEDIA: 63099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_GAME: 63199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi return 1000; 63299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_ALARM: 63399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_NOTIFICATION_RINGTONE: 63499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_ASSISTANT: 63599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY: 63699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE: 63799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi return 700; 63899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_VOICE_COMMUNICATION: 63999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING: 64099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_NOTIFICATION: 64199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST: 64299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT: 64399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED: 64499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_NOTIFICATION_EVENT: 64599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION: 64699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi return 500; 64799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi case AudioAttributes.USAGE_UNKNOWN: 64899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi default: 64999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi return 0; 65099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 65199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 65299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 653fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi /** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */ 654fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb, 655461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags, 656461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi int sdk) { 6570b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi mEventLogger.log((new AudioEventLogger.StringEvent( 6580b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi "requestAudioFocus() from uid/pid " + Binder.getCallingUid() 6590b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi + "/" + Binder.getCallingPid() 6600b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi + " clientId=" + clientId + " callingPack=" + callingPackageName 6610b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi + " req=" + focusChangeHint 6620b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi + " flags=0x" + Integer.toHexString(flags) 6630b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi + " sdk=" + sdk)) 6640b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi .printLog(TAG)); 665fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // we need a valid binder callback for clients 666fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi if (!cb.pingBinder()) { 667fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi Log.e(TAG, " AudioFocus DOA client for requestAudioFocus(), aborting."); 668fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 669fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 670fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 671fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi if (mAppOps.noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, Binder.getCallingUid(), 672fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi callingPackageName) != AppOpsManager.MODE_ALLOWED) { 673fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 674fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 675fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 676fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi synchronized(mAudioFocusLock) { 6770b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi if (mFocusStack.size() > MAX_STACK_SIZE) { 6780b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi Log.e(TAG, "Max AudioFocus stack size reached, failing requestAudioFocus()"); 6790b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 6800b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi } 6810b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi 68262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi boolean enteringRingOrCall = !mRingOrCallActive 68362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0); 68462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi if (enteringRingOrCall) { mRingOrCallActive = true; } 68562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 686126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final AudioFocusInfo afiForExtPolicy; 687126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy != null) { 688126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // construct AudioFocusInfo as it will be communicated to audio focus policy 689126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi afiForExtPolicy = new AudioFocusInfo(aa, Binder.getCallingUid(), 690126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/, 691461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi flags, sdk); 692126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } else { 693126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi afiForExtPolicy = null; 694126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 695126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 696126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // handle delayed focus 697fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi boolean focusGrantDelayed = false; 698fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi if (!canReassignAudioFocus()) { 699fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) { 700126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final int result = AudioManager.AUDIOFOCUS_REQUEST_FAILED; 701126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, result, fd, cb); 702126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return result; 703fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } else { 704fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // request has AUDIOFOCUS_FLAG_DELAY_OK: focus can't be 705fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // granted right now, so the requester will be inserted in the focus stack 706fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // to receive focus later 707fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi focusGrantDelayed = true; 708fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 709fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 710fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 711126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // external focus policy: delay request for focus gain? 712126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final int resultWithExtPolicy = AudioManager.AUDIOFOCUS_REQUEST_DELAYED; 713126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (notifyExtFocusPolicyFocusRequest_syncAf( 714126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi afiForExtPolicy, resultWithExtPolicy, fd, cb)) { 715126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // stop handling focus request here as it is handled by external audio focus policy 716126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return resultWithExtPolicy; 717126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 718126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 719fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // handle the potential premature death of the new holder of the focus 720fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // (premature death == death before abandoning focus) 721fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // Register for client death notification 722fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb); 723e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi 724fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi try { 725fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi cb.linkToDeath(afdh, 0); 726fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } catch (RemoteException e) { 727fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // client has already died! 728fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi Log.w(TAG, "AudioFocus requestAudioFocus() could not link to "+cb+" binder death"); 729fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 730fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 731fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 73283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi if (!mFocusStack.empty() && mFocusStack.peek().hasSameClient(clientId)) { 733fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // if focus is already owned by this client and the reason for acquiring the focus 734fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // hasn't changed, don't do anything 735fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi final FocusRequester fr = mFocusStack.peek(); 736fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi if (fr.getGainRequest() == focusChangeHint && fr.getGrantFlags() == flags) { 737fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // unlink death handler so it can be gc'ed. 738fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // linkToDeath() creates a JNI global reference preventing collection. 739fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi cb.unlinkToDeath(afdh, 0); 7400212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi notifyExtPolicyFocusGrant_syncAf(fr.toAudioFocusInfo(), 7410212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 742fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 743fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 744fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // the reason for the audio focus request has changed: remove the current top of 745fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // stack and respond as if we had a new focus owner 746fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi if (!focusGrantDelayed) { 747fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi mFocusStack.pop(); 748fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // the entry that was "popped" is the same that was "peeked" above 749fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi fr.release(); 750fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 751fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 752fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 753fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // focus requester might already be somewhere below in the stack, remove it 7540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi removeFocusStackEntry(clientId, false /* signal */, false /*notifyFocusFollowers*/); 755fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 756fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi final FocusRequester nfr = new FocusRequester(aa, focusChangeHint, flags, fd, cb, 757461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi clientId, afdh, callingPackageName, Binder.getCallingUid(), this, sdk); 758fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi if (focusGrantDelayed) { 759fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // focusGrantDelayed being true implies we can't reassign focus right now 760fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // which implies the focus stack is not empty. 7610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi final int requestResult = pushBelowLockedFocusOwners(nfr); 7620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (requestResult != AudioManager.AUDIOFOCUS_REQUEST_FAILED) { 7630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(), requestResult); 7640212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 7650212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return requestResult; 766fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } else { 767fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // propagate the focus change through the stack 768fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi if (!mFocusStack.empty()) { 76999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi propagateFocusLossFromGain_syncAf(focusChangeHint, nfr); 770fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 771cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi 772fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi // push focus requester at the top of the audio focus stack 773fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi mFocusStack.push(nfr); 774270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi nfr.handleFocusGainFromRequest(AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 775fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi } 7760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(), 7770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 778fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 77962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi if (ENFORCE_MUTING_FOR_RING_OR_CALL & enteringRingOrCall) { 78062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi runAudioCheckerForRingOrCallAsync(true/*enteringRingOrCall*/); 78162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 782fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi }//synchronized(mAudioFocusLock) 783fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 784fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 785fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 786fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 787958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi /** 788958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi * @see AudioManager#abandonAudioFocus(AudioManager.OnAudioFocusChangeListener, AudioAttributes) 789958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi * */ 790126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa, 791126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi String callingPackageName) { 7920b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi // AudioAttributes are currently ignored, to be used for zones / a11y 7930b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi mEventLogger.log((new AudioEventLogger.StringEvent( 7940b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi "abandonAudioFocus() from uid/pid " + Binder.getCallingUid() 7950b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi + "/" + Binder.getCallingPid() 7960b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi + " clientId=" + clientId)) 7970b67b9fad6733492ffab238a5ba12b98a696ef0cJean-Michel Trivi .printLog(TAG)); 798fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi try { 799fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // this will take care of notifying the new focus owner if needed 800fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi synchronized(mAudioFocusLock) { 801126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi // external focus policy? 802126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (mFocusPolicy != null) { 803126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi final AudioFocusInfo afi = new AudioFocusInfo(aa, Binder.getCallingUid(), 804126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi clientId, callingPackageName, 0 /*gainRequest*/, 0 /*lossReceived*/, 805461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi 0 /*flags*/, 0 /* sdk n/a here*/); 806126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi if (notifyExtFocusPolicyFocusAbandon_syncAf(afi)) { 807126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 808126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 809126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi } 810126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi 81162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi boolean exitingRingOrCall = mRingOrCallActive 81262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0); 81362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi if (exitingRingOrCall) { mRingOrCallActive = false; } 81462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 8150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi removeFocusStackEntry(clientId, true /*signal*/, true /*notifyFocusFollowers*/); 81662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi 81762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi if (ENFORCE_MUTING_FOR_RING_OR_CALL & exitingRingOrCall) { 81862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi runAudioCheckerForRingOrCallAsync(false/*enteringRingOrCall*/); 81962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 820fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 821fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } catch (java.util.ConcurrentModificationException cme) { 822fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // Catching this exception here is temporary. It is here just to prevent 823fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // a crash seen when the "Silent" notification is played. This is believed to be fixed 824fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // but this try catch block is left just to be safe. 825fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi Log.e(TAG, "FATAL EXCEPTION AudioFocus abandonAudioFocus() caused " + cme); 826fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi cme.printStackTrace(); 827fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 828fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 829fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 830fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 831fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 832fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 833fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi protected void unregisterAudioFocusClient(String clientId) { 834fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi synchronized(mAudioFocusLock) { 8350212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi removeFocusStackEntry(clientId, false, true /*notifyFocusFollowers*/); 836fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 837fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 838fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 83962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi private void runAudioCheckerForRingOrCallAsync(final boolean enteringRingOrCall) { 84062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi new Thread() { 84162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi public void run() { 84262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi if (enteringRingOrCall) { 84362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi try { 84462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi Thread.sleep(RING_CALL_MUTING_ENFORCEMENT_DELAY_MS); 84562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } catch (InterruptedException e) { 84662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi e.printStackTrace(); 84762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 84862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 84962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi synchronized (mAudioFocusLock) { 85062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi // since the new thread starting running the state could have changed, so 85162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi // we need to check again mRingOrCallActive, not enteringRingOrCall 85262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi if (mRingOrCallActive) { 85362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi mFocusEnforcer.mutePlayersForCall(USAGES_TO_MUTE_IN_RING_OR_CALL); 85462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } else { 85562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi mFocusEnforcer.unmutePlayersForCall(); 85662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 85762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 85862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 85962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi }.start(); 86062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi } 861fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi} 862