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);
92fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
93fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
9499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    //=================================================================
9599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    // PlayerFocusEnforcer implementation
9699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    @Override
9799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    public boolean duckPlayers(FocusRequester winner, FocusRequester loser) {
9899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        return mFocusEnforcer.duckPlayers(winner, loser);
9999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    }
10099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
10199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    @Override
10299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    public void unduckPlayers(FocusRequester winner) {
10399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        mFocusEnforcer.unduckPlayers(winner);
10499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    }
105fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
10662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    @Override
10762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    public void mutePlayersForCall(int[] usagesToMute) {
10862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        mFocusEnforcer.mutePlayersForCall(usagesToMute);
10962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    }
11062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi
11162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    @Override
11262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    public void unmutePlayersForCall() {
11362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        mFocusEnforcer.unmutePlayersForCall();
11462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    }
11562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi
116fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    //==========================================================================================
117fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    // AudioFocus
118fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    //==========================================================================================
119fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
120fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    private final static Object mAudioFocusLock = new Object();
121fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
122fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    /**
123fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Discard the current audio focus owner.
124fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Notify top of audio focus stack that it lost focus (regardless of possibility to reassign
125fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * focus), remove it from the stack, and clear the remote control display.
126fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     */
127fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    protected void discardAudioFocusOwner() {
128fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        synchronized(mAudioFocusLock) {
129cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi            if (!mFocusStack.empty()) {
130fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                // notify the current focus owner it lost focus after removing it from stack
13183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                final FocusRequester exFocusOwner = mFocusStack.pop();
13299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null);
13383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                exFocusOwner.release();
134fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
135fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
136fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
137fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
1380212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
1390212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Called synchronized on mAudioFocusLock
1400212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
141fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    private void notifyTopOfAudioFocusStack() {
142fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // notify the top of the stack it gained focus
143cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi        if (!mFocusStack.empty()) {
144fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            if (canReassignAudioFocus()) {
14500bf4b18173b8921d7a5cecbd8b8d3745470b5d0Jean-Michel Trivi                mFocusStack.peek().handleFocusGain(AudioManager.AUDIOFOCUS_GAIN);
146fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
147fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
148fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
149fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
150cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi    /**
151cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi     * Focus is requested, propagate the associated loss throughout the stack.
152cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi     * @param focusGain the new focus gain that will later be added at the top of the stack
153cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi     */
15499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    private void propagateFocusLossFromGain_syncAf(int focusGain, final FocusRequester fr) {
155cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi        // going through the audio focus stack to signal new focus, traversing order doesn't
156cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi        // matter as all entries respond to the same external focus gain
157cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi        Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
158cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi        while(stackIterator.hasNext()) {
15999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            stackIterator.next().handleExternalFocusGain(focusGain, fr);
160cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi        }
161cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi    }
162cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi
16383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final Stack<FocusRequester> mFocusStack = new Stack<FocusRequester>();
164fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
165fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    /**
166fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Helper function:
167fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Display in the log the current entries in the audio focus stack
168fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     */
169fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    private void dumpFocusStack(PrintWriter pw) {
170fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        pw.println("\nAudio Focus stack entries (last is top of stack):");
171fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        synchronized(mAudioFocusLock) {
17283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
173fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            while(stackIterator.hasNext()) {
17483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                stackIterator.next().dump(pw);
175fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
176126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            pw.println("\n");
177126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (mFocusPolicy == null) {
178126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                pw.println("No external focus policy\n");
179126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            } else {
180126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                pw.println("External focus policy: "+ mFocusPolicy + ", focus owners:\n");
181126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                dumpExtFocusPolicyFocusOwners(pw);
182126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
183fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
18462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        pw.println("\n");
18562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        pw.println(" Notify on duck:  " + mNotifyFocusOwnerOnDuck + "\n");
18662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        pw.println(" In ring or call: " + mRingOrCallActive + "\n");
187fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
188fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
189fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    /**
190fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Helper function:
191fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Called synchronized on mAudioFocusLock
192fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Remove a focus listener from the focus stack.
193fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * @param clientToRemove the focus listener
194fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * @param signal if true and the listener was at the top of the focus stack, i.e. it was holding
195fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     *   focus, notify the next item in the stack it gained focus.
196fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     */
1970212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private void removeFocusStackEntry(String clientToRemove, boolean signal,
1980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            boolean notifyFocusFollowers) {
199fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // is the current top of the focus stack abandoning focus? (because of request, not death)
20083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        if (!mFocusStack.empty() && mFocusStack.peek().hasSameClient(clientToRemove))
201fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        {
202fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            //Log.i(TAG, "   removeFocusStackEntry() removing top of stack");
20383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            FocusRequester fr = mFocusStack.pop();
20483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            fr.release();
2050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (notifyFocusFollowers) {
2060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                final AudioFocusInfo afi = fr.toAudioFocusInfo();
2070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                afi.clearLossReceived();
2080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                notifyExtPolicyFocusLoss_syncAf(afi, false);
2090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
210fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            if (signal) {
211fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                // notify the new top of the stack it gained focus
212fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                notifyTopOfAudioFocusStack();
213fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
214fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        } else {
215fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // focus is abandoned by a client that's not at the top of the stack,
216fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // no need to update focus.
217fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // (using an iterator on the stack so we can safely remove an entry after having
218fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            //  evaluated it, traversal order doesn't matter here)
21983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
220fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            while(stackIterator.hasNext()) {
22101fe661ae5da3739215d93922412df4b24c859a2RoboErik                FocusRequester fr = stackIterator.next();
22283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                if(fr.hasSameClient(clientToRemove)) {
22300bf4b18173b8921d7a5cecbd8b8d3745470b5d0Jean-Michel Trivi                    Log.i(TAG, "AudioFocus  removeFocusStackEntry(): removing entry for "
22483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                            + clientToRemove);
225fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                    stackIterator.remove();
226e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                    // stack entry not used anymore, clear references
22783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                    fr.release();
228fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                }
229fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
230fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
231fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
232fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
233fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    /**
234fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Helper function:
235fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Called synchronized on mAudioFocusLock
236fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Remove focus listeners from the focus stack for a particular client when it has died.
237fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     */
238e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi    private void removeFocusStackEntryOnDeath(IBinder cb) {
239fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // is the owner of the audio focus part of the client to remove?
240fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        boolean isTopOfStackForClientToRemove = !mFocusStack.isEmpty() &&
24183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                mFocusStack.peek().hasSameBinder(cb);
242fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // (using an iterator on the stack so we can safely remove an entry after having
243fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        //  evaluated it, traversal order doesn't matter here)
24483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
245fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        while(stackIterator.hasNext()) {
24601fe661ae5da3739215d93922412df4b24c859a2RoboErik            FocusRequester fr = stackIterator.next();
24783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            if(fr.hasSameBinder(cb)) {
248e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                Log.i(TAG, "AudioFocus  removeFocusStackEntryOnDeath(): removing entry for " + cb);
249fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                stackIterator.remove();
250e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                // stack entry not used anymore, clear references
251e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                fr.release();
252fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
253fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
254fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        if (isTopOfStackForClientToRemove) {
255fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // we removed an entry at the top of the stack:
256fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            //  notify the new top of the stack it gained focus.
257fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            notifyTopOfAudioFocusStack();
258fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
259fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
260fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
261fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    /**
262126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * Helper function for external focus policy:
263126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * Called synchronized on mAudioFocusLock
264126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * Remove focus listeners from the list of potential focus owners for a particular client when
265126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * it has died.
266126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     */
267126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    private void removeFocusEntryForExtPolicy(IBinder cb) {
268126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (mFocusOwnersForFocusPolicy.isEmpty()) {
269126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return;
270126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
271126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        boolean released = false;
272126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
273126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
274126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        while (ownerIterator.hasNext()) {
275126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final Entry<String, FocusRequester> owner = ownerIterator.next();
276126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final FocusRequester fr = owner.getValue();
277126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (fr.hasSameBinder(cb)) {
278126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                ownerIterator.remove();
279126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                fr.release();
280126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                notifyExtFocusPolicyFocusAbandon_syncAf(fr.toAudioFocusInfo());
281126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                break;
282126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
283126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
284126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
285126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
286126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    /**
287fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Helper function:
288fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Returns true if the system is in a state where the focus can be reevaluated, false otherwise.
289fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * The implementation guarantees that a state where focus cannot be immediately reassigned
290958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi     * implies that an "locked" focus owner is at the top of the focus stack.
291fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * Modifications to the implementation that break this assumption will cause focus requests to
292fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * misbehave when honoring the AudioManager.AUDIOFOCUS_FLAG_DELAY_OK flag.
293fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     */
294fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    private boolean canReassignAudioFocus() {
295fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // focus requests are rejected during a phone call or when the phone is ringing
296fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus
297958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        if (!mFocusStack.isEmpty() && isLockedFocusOwner(mFocusStack.peek())) {
298fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            return false;
299fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
300fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        return true;
301fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
302fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
303958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    private boolean isLockedFocusOwner(FocusRequester fr) {
3046156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlock        return (fr.hasSameClient(AudioSystem.IN_VOICE_COMM_FOCUS_ID) || fr.isLockedFocusOwner());
305fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    }
306fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi
307fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    /**
308fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * Helper function
309958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi     * Pre-conditions: focus stack is not empty, there is one or more locked focus owner
310fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     *                 at the top of the focus stack
311fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * Push the focus requester onto the audio focus stack at the first position immediately
312958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi     * following the locked focus owners.
313fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * @return {@link AudioManager#AUDIOFOCUS_REQUEST_GRANTED} or
314fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     *     {@link AudioManager#AUDIOFOCUS_REQUEST_DELAYED}
315fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     */
316958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    private int pushBelowLockedFocusOwners(FocusRequester nfr) {
317958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        int lastLockedFocusOwnerIndex = mFocusStack.size();
318fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        for (int index = mFocusStack.size()-1; index >= 0; index--) {
319958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi            if (isLockedFocusOwner(mFocusStack.elementAt(index))) {
320958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi                lastLockedFocusOwnerIndex = index;
321fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            }
322fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        }
323958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        if (lastLockedFocusOwnerIndex == mFocusStack.size()) {
324fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            // this should not happen, but handle it and log an error
325fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            Log.e(TAG, "No exclusive focus owner found in propagateFocusLossFromGain_syncAf()",
326fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    new Exception());
327fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            // no exclusive owner, push at top of stack, focus is granted, propagate change
32899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            propagateFocusLossFromGain_syncAf(nfr.getGainRequest(), nfr);
329fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            mFocusStack.push(nfr);
330fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
331fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        } else {
332958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi            mFocusStack.insertElementAt(nfr, lastLockedFocusOwnerIndex);
333fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_DELAYED;
334fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        }
335fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    }
336fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi
337fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    /**
338fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * Inner class to monitor audio focus client deaths, and remove them from the audio focus
339fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     * stack if necessary.
340fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi     */
34183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    protected class AudioFocusDeathHandler implements IBinder.DeathRecipient {
342fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        private IBinder mCb; // To be notified of client's death
343fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
344fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        AudioFocusDeathHandler(IBinder cb) {
345fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            mCb = cb;
346fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
347fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
348fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        public void binderDied() {
349fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            synchronized(mAudioFocusLock) {
350126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                if (mFocusPolicy != null) {
351126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    removeFocusEntryForExtPolicy(mCb);
352126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                } else {
353126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    removeFocusStackEntryOnDeath(mCb);
354126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                }
355fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
356fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
357fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
358fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
3590212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
3600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Indicates whether to notify an audio focus owner when it loses focus
3610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * with {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK} if it will only duck.
3620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * This variable being false indicates an AudioPolicy has been registered and has signaled
3630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * it will handle audio ducking.
3640212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
3650212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private boolean mNotifyFocusOwnerOnDuck = true;
3660212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
3670212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    protected void setDuckingInExtPolicyAvailable(boolean available) {
3680212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        mNotifyFocusOwnerOnDuck = !available;
3690212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
3700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
3710212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    boolean mustNotifyFocusOwnerOnDuck() { return mNotifyFocusOwnerOnDuck; }
3720212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
3730212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private ArrayList<IAudioPolicyCallback> mFocusFollowers = new ArrayList<IAudioPolicyCallback>();
3740212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
3750212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    void addFocusFollower(IAudioPolicyCallback ff) {
3760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if (ff == null) {
3770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            return;
3780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
3790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        synchronized(mAudioFocusLock) {
3800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            boolean found = false;
3810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            for (IAudioPolicyCallback pcb : mFocusFollowers) {
3820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                if (pcb.asBinder().equals(ff.asBinder())) {
3830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    found = true;
3840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    break;
3850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                }
3860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
3870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (found) {
3880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return;
3890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            } else {
3900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                mFocusFollowers.add(ff);
39160fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                notifyExtPolicyCurrentFocusAsync(ff);
3920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
3930212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
3940212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
3950212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
3960212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    void removeFocusFollower(IAudioPolicyCallback ff) {
3970212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if (ff == null) {
3980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            return;
3990212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
4000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        synchronized(mAudioFocusLock) {
4010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            for (IAudioPolicyCallback pcb : mFocusFollowers) {
4020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                if (pcb.asBinder().equals(ff.asBinder())) {
4030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    mFocusFollowers.remove(pcb);
4040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    break;
4050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                }
4060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
4070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
4080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
4090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
410126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    private IAudioPolicyCallback mFocusPolicy = null;
411126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
412126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    // Since we don't have a stack of focus owners when using an external focus policy, we keep
413126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    // track of all the focus requesters in this map, with their clientId as the key. This is
414126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    // used both for focus dispatch and death handling
415126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    private HashMap<String, FocusRequester> mFocusOwnersForFocusPolicy =
416126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            new HashMap<String, FocusRequester>();
417126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
418126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    void setFocusPolicy(IAudioPolicyCallback policy) {
419126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (policy == null) {
420126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return;
421126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
422126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        synchronized (mAudioFocusLock) {
423126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusPolicy = policy;
424126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
425126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
426126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
427126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    void unsetFocusPolicy(IAudioPolicyCallback policy) {
428126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (policy == null) {
429126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return;
430126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
431126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        synchronized (mAudioFocusLock) {
432126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (mFocusPolicy == policy) {
433126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                mFocusPolicy = null;
434126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
435126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
436126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
437126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
4380212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
43960fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi     * @param pcb non null
44060fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi     */
44160fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi    void notifyExtPolicyCurrentFocusAsync(IAudioPolicyCallback pcb) {
44260fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi        final IAudioPolicyCallback pcb2 = pcb;
44360fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi        final Thread thread = new Thread() {
44460fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi            @Override
44560fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi            public void run() {
44660fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                synchronized(mAudioFocusLock) {
44760fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                    if (mFocusStack.isEmpty()) {
44860fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                        return;
44960fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                    }
45060fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                    try {
45160fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                        pcb2.notifyAudioFocusGrant(mFocusStack.peek().toAudioFocusInfo(),
45260fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                                // top of focus stack always has focus
45360fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                                AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
45460fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                    } catch (RemoteException e) {
45560fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                        Log.e(TAG, "Can't call notifyAudioFocusGrant() on IAudioPolicyCallback "
45660fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                                + pcb2.asBinder(), e);
45760fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                    }
45860fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                }
45960fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi            }
46060fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi        };
46160fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi        thread.start();
46260fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi    }
46360fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi
46460fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi    /**
4650212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Called synchronized on mAudioFocusLock
4660212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
4670212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    void notifyExtPolicyFocusGrant_syncAf(AudioFocusInfo afi, int requestResult) {
4680212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        for (IAudioPolicyCallback pcb : mFocusFollowers) {
4690212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            try {
4700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // oneway
4710212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                pcb.notifyAudioFocusGrant(afi, requestResult);
4720212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            } catch (RemoteException e) {
47360fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                Log.e(TAG, "Can't call notifyAudioFocusGrant() on IAudioPolicyCallback "
4740212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        + pcb.asBinder(), e);
4750212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
4760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
4770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
4780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
4790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
4800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Called synchronized on mAudioFocusLock
4810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
4820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    void notifyExtPolicyFocusLoss_syncAf(AudioFocusInfo afi, boolean wasDispatched) {
4830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        for (IAudioPolicyCallback pcb : mFocusFollowers) {
4840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            try {
4850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // oneway
4860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                pcb.notifyAudioFocusLoss(afi, wasDispatched);
4870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            } catch (RemoteException e) {
48860fd084331c2a50321ff399267f981488c852b6fJean-Michel Trivi                Log.e(TAG, "Can't call notifyAudioFocusLoss() on IAudioPolicyCallback "
4890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        + pcb.asBinder(), e);
4900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            }
4910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
4920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
4930212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi
494126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    /**
495126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * Called synchronized on mAudioFocusLock
496126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * @param afi
497126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * @param requestResult
498126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * @return true if the external audio focus policy (if any) is handling the focus request
499126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     */
500126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    boolean notifyExtFocusPolicyFocusRequest_syncAf(AudioFocusInfo afi, int requestResult,
501126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            IAudioFocusDispatcher fd, IBinder cb) {
502126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (mFocusPolicy == null) {
503126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return false;
504126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
505126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (DEBUG) {
506126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            Log.v(TAG, "notifyExtFocusPolicyFocusRequest client="+afi.getClientId()
507126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            + " dispatcher=" + fd);
508126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
509126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        final FocusRequester existingFr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
510126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (existingFr != null) {
511126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (!existingFr.hasSameDispatcher(fd)) {
512126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                existingFr.release();
513126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
514126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                mFocusOwnersForFocusPolicy.put(afi.getClientId(),
515126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        new FocusRequester(afi, fd, cb, hdlr, this));
516126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
517126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } else if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
518126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                 || requestResult == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
519126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            // new focus (future) focus owner to keep track of
520126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final AudioFocusDeathHandler hdlr = new AudioFocusDeathHandler(cb);
521126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusOwnersForFocusPolicy.put(afi.getClientId(),
522126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    new FocusRequester(afi, fd, cb, hdlr, this));
523126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
524126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        try {
525126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            //oneway
526126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusPolicy.notifyAudioFocusRequest(afi, requestResult);
527126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } catch (RemoteException e) {
528126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            Log.e(TAG, "Can't call notifyAudioFocusRequest() on IAudioPolicyCallback "
529126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    + mFocusPolicy.asBinder(), e);
530126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
531126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        return true;
532126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
533126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
534126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    /**
535126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * Called synchronized on mAudioFocusLock
536126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * @param afi
537126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * @param requestResult
538126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     * @return true if the external audio focus policy (if any) is handling the focus request
539126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi     */
540126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    boolean notifyExtFocusPolicyFocusAbandon_syncAf(AudioFocusInfo afi) {
541126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (mFocusPolicy == null) {
542126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return false;
543126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
544126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        final FocusRequester fr = mFocusOwnersForFocusPolicy.remove(afi.getClientId());
545126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (fr != null) {
546126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            fr.release();
547126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
548126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        try {
549126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            //oneway
550126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusPolicy.notifyAudioFocusAbandon(afi);
551126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } catch (RemoteException e) {
552126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            Log.e(TAG, "Can't call notifyAudioFocusAbandon() on IAudioPolicyCallback "
553126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    + mFocusPolicy.asBinder(), e);
554126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
555126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        return true;
556126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
557126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
558126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    /** see AudioManager.dispatchFocusChange(AudioFocusInfo afi, int focusChange, AudioPolicy ap) */
559126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    int dispatchFocusChange(AudioFocusInfo afi, int focusChange) {
560126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (DEBUG) {
561126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            Log.v(TAG, "dispatchFocusChange " + focusChange + " to afi client="
562126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    + afi.getClientId());
563126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
564126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        synchronized (mAudioFocusLock) {
565126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (mFocusPolicy == null) {
566126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                if (DEBUG) { Log.v(TAG, "> failed: no focus policy" ); }
567126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
568126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
569126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final FocusRequester fr = mFocusOwnersForFocusPolicy.get(afi.getClientId());
570126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (fr == null) {
571126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                if (DEBUG) { Log.v(TAG, "> failed: no such focus requester known" ); }
572126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
573126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
574126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return fr.dispatchFocusChange(focusChange);
575126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
576126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
577126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
578126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    private void dumpExtFocusPolicyFocusOwners(PrintWriter pw) {
579126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        final Set<Entry<String, FocusRequester>> owners = mFocusOwnersForFocusPolicy.entrySet();
580126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        final Iterator<Entry<String, FocusRequester>> ownerIterator = owners.iterator();
581126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        while (ownerIterator.hasNext()) {
582126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final Entry<String, FocusRequester> owner = ownerIterator.next();
583126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final FocusRequester fr = owner.getValue();
584126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            fr.dump(pw);
585126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
586126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
587126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
5882380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi    protected int getCurrentAudioFocus() {
5892380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi        synchronized(mAudioFocusLock) {
5902380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            if (mFocusStack.empty()) {
5912380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                return AudioManager.AUDIOFOCUS_NONE;
5922380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            } else {
5932380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                return mFocusStack.peek().getGainRequest();
5942380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            }
5952380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi        }
5962380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi    }
597fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
59899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    /**
59962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi     * Delay after entering ringing or call mode after which the framework will mute streams
60062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi     * that are still playing.
60162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi     */
60262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    private static final int RING_CALL_MUTING_ENFORCEMENT_DELAY_MS = 100;
60362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi
60462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    /**
60562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi     * Usages to mute when the device rings or is in a call
60662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi     */
60762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    private final static int[] USAGES_TO_MUTE_IN_RING_OR_CALL =
60862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        { AudioAttributes.USAGE_MEDIA, AudioAttributes.USAGE_GAME };
60962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi
61062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    /**
61199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     * Return the volume ramp time expected before playback with the given AudioAttributes would
61299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     * start after gaining audio focus.
61399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     * @param attr attributes of the sound about to start playing
61499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     * @return time in ms
61599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     */
616dce82ab7bfd5ec7c1ef658825c18506a89e567d6Jean-Michel Trivi    protected static int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
61799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        switch (attr.getUsage()) {
61899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_MEDIA:
61999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_GAME:
62099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                return 1000;
62199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_ALARM:
62299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
62399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_ASSISTANT:
62499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
62599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
62699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                return 700;
62799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_VOICE_COMMUNICATION:
62899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
62999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_NOTIFICATION:
63099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
63199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
63299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
63399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_NOTIFICATION_EVENT:
63499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
63599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                return 500;
63699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            case AudioAttributes.USAGE_UNKNOWN:
63799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            default:
63899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                return 0;
63999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        }
64099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    }
64199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
642fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    /** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */
643fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb,
644461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi            IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
645461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi            int sdk) {
64640399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi        Log.i(TAG, " AudioFocus  requestAudioFocus() from uid/pid " + Binder.getCallingUid()
64740399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi                + "/" + Binder.getCallingPid()
64840399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi                + " clientId=" + clientId
64940399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi                + " req=" + focusChangeHint
65040399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi                + " flags=0x" + Integer.toHexString(flags));
651fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        // we need a valid binder callback for clients
652fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        if (!cb.pingBinder()) {
653fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            Log.e(TAG, " AudioFocus DOA client for requestAudioFocus(), aborting.");
654fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
655fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
656fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
657fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        if (mAppOps.noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, Binder.getCallingUid(),
658fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                callingPackageName) != AppOpsManager.MODE_ALLOWED) {
659fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
660fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
661fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
662fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        synchronized(mAudioFocusLock) {
66362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi            boolean enteringRingOrCall = !mRingOrCallActive
66462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
66562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi            if (enteringRingOrCall) { mRingOrCallActive = true; }
66662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi
667126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final AudioFocusInfo afiForExtPolicy;
668126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (mFocusPolicy != null) {
669126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                // construct AudioFocusInfo as it will be communicated to audio focus policy
670126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                afiForExtPolicy = new AudioFocusInfo(aa, Binder.getCallingUid(),
671126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        clientId, callingPackageName, focusChangeHint, 0 /*lossReceived*/,
672461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                        flags, sdk);
673126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            } else {
674126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                afiForExtPolicy = null;
675126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
676126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
677126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            // handle delayed focus
678fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            boolean focusGrantDelayed = false;
679fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            if (!canReassignAudioFocus()) {
680fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) == 0) {
681126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    final int result = AudioManager.AUDIOFOCUS_REQUEST_FAILED;
682126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    notifyExtFocusPolicyFocusRequest_syncAf(afiForExtPolicy, result, fd, cb);
683126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    return result;
684fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                } else {
685fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    // request has AUDIOFOCUS_FLAG_DELAY_OK: focus can't be
686fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    // granted right now, so the requester will be inserted in the focus stack
687fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    // to receive focus later
688fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    focusGrantDelayed = true;
689fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                }
690fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
691fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
692126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            // external focus policy: delay request for focus gain?
693126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            final int resultWithExtPolicy = AudioManager.AUDIOFOCUS_REQUEST_DELAYED;
694126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (notifyExtFocusPolicyFocusRequest_syncAf(
695126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    afiForExtPolicy, resultWithExtPolicy, fd, cb)) {
696126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                // stop handling focus request here as it is handled by external audio focus policy
697126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                return resultWithExtPolicy;
698126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            }
699126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
700fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // handle the potential premature death of the new holder of the focus
701fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // (premature death == death before abandoning focus)
702fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // Register for client death notification
703fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            AudioFocusDeathHandler afdh = new AudioFocusDeathHandler(cb);
704e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi
705fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            try {
706fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                cb.linkToDeath(afdh, 0);
707fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            } catch (RemoteException e) {
708fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                // client has already died!
709fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                Log.w(TAG, "AudioFocus  requestAudioFocus() could not link to "+cb+" binder death");
710fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
711fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
712fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
71383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            if (!mFocusStack.empty() && mFocusStack.peek().hasSameClient(clientId)) {
714fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                // if focus is already owned by this client and the reason for acquiring the focus
715fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                // hasn't changed, don't do anything
716fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                final FocusRequester fr = mFocusStack.peek();
717fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                if (fr.getGainRequest() == focusChangeHint && fr.getGrantFlags() == flags) {
718fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                    // unlink death handler so it can be gc'ed.
719fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                    // linkToDeath() creates a JNI global reference preventing collection.
720fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                    cb.unlinkToDeath(afdh, 0);
7210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    notifyExtPolicyFocusGrant_syncAf(fr.toAudioFocusInfo(),
7220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                            AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
723fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                    return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
724fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                }
725fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                // the reason for the audio focus request has changed: remove the current top of
726fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi                // stack and respond as if we had a new focus owner
727fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                if (!focusGrantDelayed) {
728fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    mFocusStack.pop();
729fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    // the entry that was "popped" is the same that was "peeked" above
730fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                    fr.release();
731fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                }
732fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
733fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
734fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // focus requester might already be somewhere below in the stack, remove it
7350212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            removeFocusStackEntry(clientId, false /* signal */, false /*notifyFocusFollowers*/);
736fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
737fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            final FocusRequester nfr = new FocusRequester(aa, focusChangeHint, flags, fd, cb,
738461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                    clientId, afdh, callingPackageName, Binder.getCallingUid(), this, sdk);
739fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            if (focusGrantDelayed) {
740fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                // focusGrantDelayed being true implies we can't reassign focus right now
741fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                // which implies the focus stack is not empty.
7420212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                final int requestResult = pushBelowLockedFocusOwners(nfr);
7430212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                if (requestResult != AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
7440212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(), requestResult);
7450212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                }
7460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                return requestResult;
747fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            } else {
748fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                // propagate the focus change through the stack
749fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                if (!mFocusStack.empty()) {
75099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    propagateFocusLossFromGain_syncAf(focusChangeHint, nfr);
751fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                }
752cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi
753fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                // push focus requester at the top of the audio focus stack
754fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi                mFocusStack.push(nfr);
755270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi                nfr.handleFocusGainFromRequest(AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
756fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi            }
7570212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            notifyExtPolicyFocusGrant_syncAf(nfr.toAudioFocusInfo(),
7580212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
759fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
76062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi            if (ENFORCE_MUTING_FOR_RING_OR_CALL & enteringRingOrCall) {
76162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                runAudioCheckerForRingOrCallAsync(true/*enteringRingOrCall*/);
76262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi            }
763fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }//synchronized(mAudioFocusLock)
764fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
765fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
766fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
767fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
768958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    /**
769958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi     * @see AudioManager#abandonAudioFocus(AudioManager.OnAudioFocusChangeListener, AudioAttributes)
770958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi     * */
771126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    protected int abandonAudioFocus(IAudioFocusDispatcher fl, String clientId, AudioAttributes aa,
772126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            String callingPackageName) {
773958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        // AudioAttributes are currently ignored, to be used for zones
77440399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi        Log.i(TAG, " AudioFocus  abandonAudioFocus() from uid/pid " + Binder.getCallingUid()
77540399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi                + "/" + Binder.getCallingPid()
77640399053d19a59fafe7493ca6d7bfd52df5626b6Jean-Michel Trivi                + " clientId=" + clientId);
777fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        try {
778fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // this will take care of notifying the new focus owner if needed
779fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            synchronized(mAudioFocusLock) {
780126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                // external focus policy?
781126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                if (mFocusPolicy != null) {
782126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    final AudioFocusInfo afi = new AudioFocusInfo(aa, Binder.getCallingUid(),
783126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                            clientId, callingPackageName, 0 /*gainRequest*/, 0 /*lossReceived*/,
784461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                            0 /*flags*/, 0 /* sdk n/a here*/);
785126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    if (notifyExtFocusPolicyFocusAbandon_syncAf(afi)) {
786126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
787126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    }
788126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                }
789126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
79062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                boolean exitingRingOrCall = mRingOrCallActive
79162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                        & (AudioSystem.IN_VOICE_COMM_FOCUS_ID.compareTo(clientId) == 0);
79262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                if (exitingRingOrCall) { mRingOrCallActive = false; }
79362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi
7940212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                removeFocusStackEntry(clientId, true /*signal*/, true /*notifyFocusFollowers*/);
79562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi
79662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                if (ENFORCE_MUTING_FOR_RING_OR_CALL & exitingRingOrCall) {
79762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    runAudioCheckerForRingOrCallAsync(false/*enteringRingOrCall*/);
79862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                }
799fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            }
800fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        } catch (java.util.ConcurrentModificationException cme) {
801fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // Catching this exception here is temporary. It is here just to prevent
802fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // a crash seen when the "Silent" notification is played. This is believed to be fixed
803fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            // but this try catch block is left just to be safe.
804fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            Log.e(TAG, "FATAL EXCEPTION AudioFocus  abandonAudioFocus() caused " + cme);
805fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi            cme.printStackTrace();
806fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
807fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
808fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
809fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
810fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
811fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
812fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    protected void unregisterAudioFocusClient(String clientId) {
813fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        synchronized(mAudioFocusLock) {
8140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            removeFocusStackEntry(clientId, false, true /*notifyFocusFollowers*/);
815fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi        }
816fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi    }
817fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi
81862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    private void runAudioCheckerForRingOrCallAsync(final boolean enteringRingOrCall) {
81962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        new Thread() {
82062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi            public void run() {
82162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                if (enteringRingOrCall) {
82262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    try {
82362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                        Thread.sleep(RING_CALL_MUTING_ENFORCEMENT_DELAY_MS);
82462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    } catch (InterruptedException e) {
82562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                        e.printStackTrace();
82662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    }
82762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                }
82862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                synchronized (mAudioFocusLock) {
82962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    // since the new thread starting running the state could have changed, so
83062b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    // we need to check again mRingOrCallActive, not enteringRingOrCall
83162b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    if (mRingOrCallActive) {
83262b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                        mFocusEnforcer.mutePlayersForCall(USAGES_TO_MUTE_IN_RING_OR_CALL);
83362b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    } else {
83462b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                        mFocusEnforcer.unmutePlayersForCall();
83562b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                    }
83662b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi                }
83762b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi            }
83862b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi        }.start();
83962b8634f06b32f17eced8020ecd9240f70838124Jean-Michel Trivi    }
840fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi}
841