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