FocusRequester.java revision 270f1c9d8ff38be25b8972f7d158ca178da82eb7
183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi/*
283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * Copyright (C) 2013 The Android Open Source Project
383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi *
483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * you may not use this file except in compliance with the License.
683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * You may obtain a copy of the License at
783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi *
883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi *
1083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * See the License for the specific language governing permissions and
1483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * limitations under the License.
1583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi */
1683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
176156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockpackage com.android.server.audio;
1883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Triviimport android.annotation.NonNull;
2099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Triviimport android.annotation.Nullable;
216156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.AudioAttributes;
226156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.AudioFocusInfo;
236156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.AudioManager;
246156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport android.media.IAudioFocusDispatcher;
2583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Triviimport android.os.IBinder;
2683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Triviimport android.util.Log;
2783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
286156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport com.android.server.audio.MediaFocusControl.AudioFocusDeathHandler;
296156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlock
3083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Triviimport java.io.PrintWriter;
3183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
3283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi/**
3383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * @hide
3483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * Class to handle all the information about a user of audio focus. The lifecycle of each
3583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * instance is managed by android.media.MediaFocusControl, from its addition to the audio focus
36126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * stack, or the map of focus owners for an external focus policy, to its release.
3783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi */
386156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockpublic class FocusRequester {
3983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
4083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    // on purpose not using this classe's name, as it will only be used from MediaFocusControl
4183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private static final String TAG = "MediaFocusControl";
42cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi    private static final boolean DEBUG = false;
4383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
44e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi    private AudioFocusDeathHandler mDeathHandler; // may be null
45e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi    private IAudioFocusDispatcher mFocusDispatcher; // may be null
46e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi    private final IBinder mSourceRef; // may be null
4783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final String mClientId;
4883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final String mPackageName;
4983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final int mCallingUid;
500212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private final MediaFocusControl mFocusController; // never null
51461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi    private final int mSdkTarget;
5299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
5383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
5483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * the audio focus gain request that caused the addition of this object in the focus stack.
5583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
5683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final int mFocusGainRequest;
5783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
58fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * the flags associated with the gain request that qualify the type of grant (e.g. accepting
59fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * delay vs grant must be immediate)
60fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     */
61fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    private final int mGrantFlags;
62fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    /**
632380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi     * the audio focus loss received my mFocusDispatcher, is AudioManager.AUDIOFOCUS_NONE if
6483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     *  it never lost focus.
6583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
6683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private int mFocusLossReceived;
6783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
6899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     * whether this focus owner listener was notified when it lost focus
6999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     */
7099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    private boolean mFocusLossWasNotified;
7199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    /**
72fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * the audio attributes associated with the focus request
7383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
74fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    private final AudioAttributes mAttributes;
7583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Class constructor
780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param aa
790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param focusRequest
800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param grantFlags
810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param afl
820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param source
830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param id
840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param hdlr
850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param pn
860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param uid
870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param ctlr cannot be null
880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
89fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags,
9083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr,
91461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi            String pn, int uid, @NonNull MediaFocusControl ctlr, int sdk) {
92fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        mAttributes = aa;
9383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mFocusDispatcher = afl;
9483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mSourceRef = source;
9583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mClientId = id;
9683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mDeathHandler = hdlr;
9783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mPackageName = pn;
9883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mCallingUid = uid;
9983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mFocusGainRequest = focusRequest;
100fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        mGrantFlags = grantFlags;
1012380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi        mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
1020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        mFocusController = ctlr;
103461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi        mSdkTarget = sdk;
10483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
10583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
106126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    FocusRequester(AudioFocusInfo afi, IAudioFocusDispatcher afl,
107126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi             IBinder source, AudioFocusDeathHandler hdlr, @NonNull MediaFocusControl ctlr) {
108126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mAttributes = afi.getAttributes();
109126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mClientId = afi.getClientId();
110126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mPackageName = afi.getPackageName();
111126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mCallingUid = afi.getClientUid();
112126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusGainRequest = afi.getGainRequest();
113126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
114126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mGrantFlags = afi.getFlags();
115461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi        mSdkTarget = afi.getSdkTarget();
116126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
117126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusDispatcher = afl;
118126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mSourceRef = source;
119126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mDeathHandler = hdlr;
120126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusController = ctlr;
121126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
12283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
12383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSameClient(String otherClient) {
12483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
12583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return mClientId.compareTo(otherClient) == 0;
12683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (NullPointerException e) {
12783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return false;
12883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
12983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
13083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
131958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    boolean isLockedFocusOwner() {
132958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        return ((mGrantFlags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0);
133958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    }
134958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi
13583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSameBinder(IBinder ib) {
13683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return (mSourceRef != null) && mSourceRef.equals(ib);
13783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
13883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
139126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    boolean hasSameDispatcher(IAudioFocusDispatcher fd) {
140126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
141126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
142126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
14383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSamePackage(String pack) {
14483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
14583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return mPackageName.compareTo(pack) == 0;
14683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (NullPointerException e) {
14783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return false;
14883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
14983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
15083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
15183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSameUid(int uid) {
15283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return mCallingUid == uid;
15383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
15483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
15599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    int getClientUid() {
15699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        return mCallingUid;
15799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    }
15899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
159958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    String getClientId() {
160958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        return mClientId;
161958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    }
16283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
16383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    int getGainRequest() {
16483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return mFocusGainRequest;
16583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
16683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
167fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    int getGrantFlags() {
168fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        return mGrantFlags;
169fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    }
170fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi
171fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    AudioAttributes getAudioAttributes() {
172fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        return mAttributes;
17383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
17483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
175461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi    int getSdkTarget() {
176461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi        return mSdkTarget;
177461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi    }
17883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
17983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private static String focusChangeToString(int focus) {
18083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        switch(focus) {
1812380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            case AudioManager.AUDIOFOCUS_NONE:
18283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "none";
18383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN:
18483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "GAIN";
18583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
18683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "GAIN_TRANSIENT";
18783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
18883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "GAIN_TRANSIENT_MAY_DUCK";
1892380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
1902380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                return "GAIN_TRANSIENT_EXCLUSIVE";
19183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_LOSS:
19283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "LOSS";
19383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
19483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "LOSS_TRANSIENT";
19583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
19683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "LOSS_TRANSIENT_CAN_DUCK";
19783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            default:
19883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "[invalid focus change" + focus + "]";
19983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
20083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
20183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
20283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private String focusGainToString() {
20383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return focusChangeToString(mFocusGainRequest);
20483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
20583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
20683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private String focusLossToString() {
20783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return focusChangeToString(mFocusLossReceived);
20883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
20983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
210958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    private static String flagsToString(int flags) {
211958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        String msg = new String();
2120212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) != 0) {
2130212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            msg += "DELAY_OK";
2140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
2150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0)     {
2160212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (!msg.isEmpty()) { msg += "|"; }
2170212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            msg += "LOCK";
2180212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
2190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if ((flags & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
2200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (!msg.isEmpty()) { msg += "|"; }
2210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            msg += "PAUSES_ON_DUCKABLE_LOSS";
2220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
223958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        return msg;
224958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    }
225958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi
22683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    void dump(PrintWriter pw) {
22783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        pw.println("  source:" + mSourceRef
22883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- pack: " + mPackageName
22983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- client: " + mClientId
23083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- gain: " + focusGainToString()
231958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi                + " -- flags: " + flagsToString(mGrantFlags)
23283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- loss: " + focusLossToString()
23399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                + " -- notified: " + mFocusLossWasNotified
23483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- uid: " + mCallingUid
235461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                + " -- attr: " + mAttributes
236461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                + " -- sdk:" + mSdkTarget);
23783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
23883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
23983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
24083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    void release() {
24183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
24283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            if (mSourceRef != null && mDeathHandler != null) {
24383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                mSourceRef.unlinkToDeath(mDeathHandler, 0);
24483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                mDeathHandler = null;
245e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                mFocusDispatcher = null;
24683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            }
24783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (java.util.NoSuchElementException e) {
24883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            Log.e(TAG, "FocusRequester.release() hit ", e);
24983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
25083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
25183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
25283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    @Override
25383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    protected void finalize() throws Throwable {
25483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        release();
25583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        super.finalize();
25683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
25783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
25883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
25983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * For a given audio focus gain request, return the audio focus loss type that will result
26053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi     * from it, taking into account any previous focus loss.
26183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * @param gainRequest
26283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * @return the audio focus loss type that matches the gain request
26383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
26483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private int focusLossForGainRequest(int gainRequest) {
26553e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi        switch(gainRequest) {
26653e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN:
26753e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                switch(mFocusLossReceived) {
26853e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
26953e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
27053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS:
2712380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                    case AudioManager.AUDIOFOCUS_NONE:
27253e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS;
27353e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                }
2742380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
27553e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
27653e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                switch(mFocusLossReceived) {
27753e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
27853e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
2792380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                    case AudioManager.AUDIOFOCUS_NONE:
28053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT;
28153e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS:
28253e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS;
28353e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                }
28453e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
28553e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                switch(mFocusLossReceived) {
2862380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                    case AudioManager.AUDIOFOCUS_NONE:
28753e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
288cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK;
28953e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
29053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT;
29153e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS:
29253e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS;
29353e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                }
29453e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            default:
29553e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                Log.e(TAG, "focusLossForGainRequest() for invalid focus request "+ gainRequest);
2962380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                        return AudioManager.AUDIOFOCUS_NONE;
29753e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi        }
29883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
29983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
3000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
3010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Called synchronized on MediaFocusControl.mAudioFocusLock
3020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
30399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    void handleExternalFocusGain(int focusGain, final FocusRequester fr) {
304cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi        int focusLoss = focusLossForGainRequest(focusGain);
30599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        handleFocusLoss(focusLoss, fr);
30683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
30783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
3080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
3090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Called synchronized on MediaFocusControl.mAudioFocusLock
3100212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
31183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    void handleFocusGain(int focusGain) {
31283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
3130212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
3140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mFocusController.notifyExtPolicyFocusGrant_syncAf(toAudioFocusInfo(),
3150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
316e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi            final IAudioFocusDispatcher fd = mFocusDispatcher;
317e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi            if (fd != null) {
318cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                if (DEBUG) {
319cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                    Log.v(TAG, "dispatching " + focusChangeToString(focusGain) + " to "
320cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                        + mClientId);
321cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                }
32299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                if (mFocusLossWasNotified) {
32399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    fd.dispatchAudioFocusChange(focusGain, mClientId);
32499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                }
325cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi            }
326270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi            mFocusController.unduckPlayers(this);
32799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi            mFocusLossWasNotified = false;
32883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (android.os.RemoteException e) {
32983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            Log.e(TAG, "Failure to signal gain of audio focus due to: ", e);
33083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
33183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
33283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
3330212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
3340212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Called synchronized on MediaFocusControl.mAudioFocusLock
3350212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
336270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi    void handleFocusGainFromRequest(int focusRequestResult) {
337270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi        if (focusRequestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
338270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi            mFocusController.unduckPlayers(this);
339270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi        }
340270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi    }
341270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi
342270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi    /**
343270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi     * Called synchronized on MediaFocusControl.mAudioFocusLock
344270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi     */
34599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    void handleFocusLoss(int focusLoss, @Nullable final FocusRequester fr) {
34683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
347cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi            if (focusLoss != mFocusLossReceived) {
3480212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                mFocusLossReceived = focusLoss;
34999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                mFocusLossWasNotified = false;
3500212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // before dispatching a focus loss, check if the following conditions are met:
3510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // 1/ the framework is not supposed to notify the focus loser on a DUCK loss
3527b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                //    (i.e. it has a focus controller that implements a ducking policy)
3530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // 2/ it is a DUCK loss
3540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // 3/ the focus loser isn't flagged as pausing in a DUCK loss
3550212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // if they are, do not notify the focus loser
3560212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                if (!mFocusController.mustNotifyFocusOwnerOnDuck()
3570212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        && mFocusLossReceived == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
3580212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        && (mGrantFlags
3590212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                                & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) == 0) {
3600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    if (DEBUG) {
3610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        Log.v(TAG, "NOT dispatching " + focusChangeToString(mFocusLossReceived)
3620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                                + " to " + mClientId + ", to be handled externally");
3630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    }
3640212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    mFocusController.notifyExtPolicyFocusLoss_syncAf(
3650212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                            toAudioFocusInfo(), false /* wasDispatched */);
3660212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    return;
3670212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                }
36899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
36999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                // check enforcement by the framework
37099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                boolean handled = false;
37199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                if (focusLoss == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
37299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                        && MediaFocusControl.ENFORCE_DUCKING
37399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                        && fr != null) {
37499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    // candidate for enforcement by the framework
37599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    if (fr.mCallingUid != this.mCallingUid) {
3767b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                        if ((mGrantFlags
3777b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                                & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
3787b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                            // the focus loser declared it would pause instead of duck, let it
3797b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                            // handle it (the framework doesn't pause for apps)
3807b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                            handled = false;
3817b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                        } else {
3827b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                            handled = mFocusController.duckPlayers(fr, this);
3837b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                        }
38499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    } // else: the focus change is within the same app, so let the dispatching
38599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                      //       happen as if the framework was not involved.
38699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                }
38799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
38899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                if (handled) {
38999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    if (DEBUG) {
39099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                        Log.v(TAG, "NOT dispatching " + focusChangeToString(mFocusLossReceived)
39199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                            + " to " + mClientId + ", ducking implemented by framework");
39299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    }
393081249282005640682da315d6f0e0e3697fe4b37Jean-Michel Trivi                    mFocusController.notifyExtPolicyFocusLoss_syncAf(
394081249282005640682da315d6f0e0e3697fe4b37Jean-Michel Trivi                            toAudioFocusInfo(), false /* wasDispatched */);
39599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    return; // with mFocusLossWasNotified = false
39699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                }
39799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
398e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                final IAudioFocusDispatcher fd = mFocusDispatcher;
399e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                if (fd != null) {
400cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                    if (DEBUG) {
4010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        Log.v(TAG, "dispatching " + focusChangeToString(mFocusLossReceived) + " to "
402cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                            + mClientId);
403cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                    }
4040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    mFocusController.notifyExtPolicyFocusLoss_syncAf(
4050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                            toAudioFocusInfo(), true /* wasDispatched */);
40699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    mFocusLossWasNotified = true;
407e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                    fd.dispatchAudioFocusChange(mFocusLossReceived, mClientId);
408cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                }
409cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi            }
41083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (android.os.RemoteException e) {
41183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            Log.e(TAG, "Failure to signal loss of audio focus due to:", e);
41283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
41383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
41483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
415126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    int dispatchFocusChange(int focusChange) {
416126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (mFocusDispatcher == null) {
417126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: no focus dispatcher"); }
418126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
419126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
420126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (focusChange == AudioManager.AUDIOFOCUS_NONE) {
421126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: AUDIOFOCUS_NONE"); }
422126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
423126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } else if ((focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
424126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
425126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
426126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_GAIN)
427126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                && (mFocusGainRequest != focusChange)){
428126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            Log.w(TAG, "focus gain was requested with " + mFocusGainRequest
429126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    + ", dispatching " + focusChange);
430126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
431126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
432126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_LOSS) {
433126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusLossReceived = focusChange;
434126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
435126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        try {
436126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusDispatcher.dispatchAudioFocusChange(focusChange, mClientId);
437126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } catch (android.os.RemoteException e) {
438126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            Log.v(TAG, "dispatchFocusChange: error talking to focus listener", e);
439126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
440126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
441126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
442126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
443126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
4440212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    AudioFocusInfo toAudioFocusInfo() {
44599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        return new AudioFocusInfo(mAttributes, mCallingUid, mClientId, mPackageName,
446461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                mFocusGainRequest, mFocusLossReceived, mGrantFlags, mSdkTarget);
4470212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
44883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi}
449