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
28d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Triviimport com.android.internal.annotations.GuardedBy;
296156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockimport com.android.server.audio.MediaFocusControl.AudioFocusDeathHandler;
306156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlock
3183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Triviimport java.io.PrintWriter;
3283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
3383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi/**
3483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * @hide
3583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * Class to handle all the information about a user of audio focus. The lifecycle of each
3683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi * instance is managed by android.media.MediaFocusControl, from its addition to the audio focus
37126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi * stack, or the map of focus owners for an external focus policy, to its release.
3883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi */
396156017c2217d0fbbbb03434986250ec6bbd69d8John Spurlockpublic class FocusRequester {
4083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
4183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    // on purpose not using this classe's name, as it will only be used from MediaFocusControl
4283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private static final String TAG = "MediaFocusControl";
43cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi    private static final boolean DEBUG = false;
4483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
45e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi    private AudioFocusDeathHandler mDeathHandler; // may be null
46e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi    private IAudioFocusDispatcher mFocusDispatcher; // may be null
47e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi    private final IBinder mSourceRef; // may be null
4883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final String mClientId;
4983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final String mPackageName;
5083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final int mCallingUid;
510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    private final MediaFocusControl mFocusController; // never null
52461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi    private final int mSdkTarget;
5399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
5483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
5583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * the audio focus gain request that caused the addition of this object in the focus stack.
5683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
5783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private final int mFocusGainRequest;
5883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
59fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * the flags associated with the gain request that qualify the type of grant (e.g. accepting
60fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * delay vs grant must be immediate)
61fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     */
62fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    private final int mGrantFlags;
63fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    /**
642380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi     * the audio focus loss received my mFocusDispatcher, is AudioManager.AUDIOFOCUS_NONE if
6583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     *  it never lost focus.
6683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
6783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private int mFocusLossReceived;
6883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
6999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     * whether this focus owner listener was notified when it lost focus
7099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi     */
7199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    private boolean mFocusLossWasNotified;
7299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    /**
73fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi     * the audio attributes associated with the focus request
7483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
75fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    private final AudioAttributes mAttributes;
7683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
780212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * Class constructor
790212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param aa
800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param focusRequest
810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param grantFlags
820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param afl
830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param source
840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param id
850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param hdlr
860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param pn
870212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param uid
880212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     * @param ctlr cannot be null
890212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
90fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags,
9183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr,
92461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi            String pn, int uid, @NonNull MediaFocusControl ctlr, int sdk) {
93fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        mAttributes = aa;
9483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mFocusDispatcher = afl;
9583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mSourceRef = source;
9683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mClientId = id;
9783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mDeathHandler = hdlr;
9883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mPackageName = pn;
9983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mCallingUid = uid;
10083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        mFocusGainRequest = focusRequest;
101fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        mGrantFlags = grantFlags;
1022380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi        mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
103087b672797b23d6c7451f975ca7f825d64fb1bd9Jean-Michel Trivi        mFocusLossWasNotified = true;
1040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        mFocusController = ctlr;
105461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi        mSdkTarget = sdk;
10683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
10783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
108126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    FocusRequester(AudioFocusInfo afi, IAudioFocusDispatcher afl,
109126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi             IBinder source, AudioFocusDeathHandler hdlr, @NonNull MediaFocusControl ctlr) {
110126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mAttributes = afi.getAttributes();
111126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mClientId = afi.getClientId();
112126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mPackageName = afi.getPackageName();
113126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mCallingUid = afi.getClientUid();
114126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusGainRequest = afi.getGainRequest();
115126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
116087b672797b23d6c7451f975ca7f825d64fb1bd9Jean-Michel Trivi        mFocusLossWasNotified = true;
117126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mGrantFlags = afi.getFlags();
118461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi        mSdkTarget = afi.getSdkTarget();
119126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
120126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusDispatcher = afl;
121126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mSourceRef = source;
122126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mDeathHandler = hdlr;
123126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        mFocusController = ctlr;
124126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
12583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
12683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSameClient(String otherClient) {
12783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
12883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return mClientId.compareTo(otherClient) == 0;
12983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (NullPointerException e) {
13083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return false;
13183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
13283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
13383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
134958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    boolean isLockedFocusOwner() {
135958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        return ((mGrantFlags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0);
136958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    }
137958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi
13883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSameBinder(IBinder ib) {
13983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return (mSourceRef != null) && mSourceRef.equals(ib);
14083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
14183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
142126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    boolean hasSameDispatcher(IAudioFocusDispatcher fd) {
143126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
144126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
145126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
14683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSamePackage(String pack) {
14783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
14883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return mPackageName.compareTo(pack) == 0;
14983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (NullPointerException e) {
15083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            return false;
15183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
15283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
15383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
15483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    boolean hasSameUid(int uid) {
15583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return mCallingUid == uid;
15683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
15783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
15899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    int getClientUid() {
15999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        return mCallingUid;
16099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi    }
16199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
162958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    String getClientId() {
163958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        return mClientId;
164958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    }
16583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
16683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    int getGainRequest() {
16783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return mFocusGainRequest;
16883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
16983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
170fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    int getGrantFlags() {
171fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        return mGrantFlags;
172fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    }
173fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi
174fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi    AudioAttributes getAudioAttributes() {
175fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi        return mAttributes;
17683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
17783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
178461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi    int getSdkTarget() {
179461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi        return mSdkTarget;
180461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi    }
18183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
18283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private static String focusChangeToString(int focus) {
18383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        switch(focus) {
1842380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            case AudioManager.AUDIOFOCUS_NONE:
18583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "none";
18683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN:
18783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "GAIN";
18883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
18983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "GAIN_TRANSIENT";
19083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
19183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "GAIN_TRANSIENT_MAY_DUCK";
1922380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
1932380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                return "GAIN_TRANSIENT_EXCLUSIVE";
19483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_LOSS:
19583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "LOSS";
19683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
19783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "LOSS_TRANSIENT";
19883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
19983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "LOSS_TRANSIENT_CAN_DUCK";
20083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            default:
20183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                return "[invalid focus change" + focus + "]";
20283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
20383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
20483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
20583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private String focusGainToString() {
20683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return focusChangeToString(mFocusGainRequest);
20783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
20883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
20983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private String focusLossToString() {
21083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        return focusChangeToString(mFocusLossReceived);
21183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
21283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
213958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    private static String flagsToString(int flags) {
214958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        String msg = new String();
2150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) != 0) {
2160212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            msg += "DELAY_OK";
2170212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
2180212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0)     {
2190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (!msg.isEmpty()) { msg += "|"; }
2200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            msg += "LOCK";
2210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
2220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        if ((flags & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) {
2230212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            if (!msg.isEmpty()) { msg += "|"; }
2240212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            msg += "PAUSES_ON_DUCKABLE_LOSS";
2250212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi        }
226958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi        return msg;
227958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi    }
228958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi
22983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    void dump(PrintWriter pw) {
23083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        pw.println("  source:" + mSourceRef
23183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- pack: " + mPackageName
23283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- client: " + mClientId
23383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- gain: " + focusGainToString()
234958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi                + " -- flags: " + flagsToString(mGrantFlags)
23583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- loss: " + focusLossToString()
23699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                + " -- notified: " + mFocusLossWasNotified
23783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi                + " -- uid: " + mCallingUid
238461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                + " -- attr: " + mAttributes
239461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                + " -- sdk:" + mSdkTarget);
24083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
24183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
24283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
24383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    void release() {
244e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        final IBinder srcRef = mSourceRef;
245e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        final AudioFocusDeathHandler deathHdlr = mDeathHandler;
24683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
247e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            if (srcRef != null && deathHdlr != null) {
248e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi                srcRef.unlinkToDeath(deathHdlr, 0);
24983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            }
250e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        } catch (java.util.NoSuchElementException e) { }
251e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        mDeathHandler = null;
252e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        mFocusDispatcher = null;
25383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
25483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
25583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    @Override
25683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    protected void finalize() throws Throwable {
25783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        release();
25883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        super.finalize();
25983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
26083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
26183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    /**
26283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * For a given audio focus gain request, return the audio focus loss type that will result
26353e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi     * from it, taking into account any previous focus loss.
26483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * @param gainRequest
26583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     * @return the audio focus loss type that matches the gain request
26683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi     */
26783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    private int focusLossForGainRequest(int gainRequest) {
26853e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi        switch(gainRequest) {
26953e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN:
27053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                switch(mFocusLossReceived) {
27153e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
27253e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
27353e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS:
2742380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                    case AudioManager.AUDIOFOCUS_NONE:
27553e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS;
27653e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                }
2772380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
27853e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:
27953e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                switch(mFocusLossReceived) {
28053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
28153e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
2822380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                    case AudioManager.AUDIOFOCUS_NONE:
28353e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT;
28453e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS:
28553e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS;
28653e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                }
28753e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
28853e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                switch(mFocusLossReceived) {
2892380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                    case AudioManager.AUDIOFOCUS_NONE:
29053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
291cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK;
29253e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
29353e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT;
29453e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                    case AudioManager.AUDIOFOCUS_LOSS:
29553e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                        return AudioManager.AUDIOFOCUS_LOSS;
29653e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                }
29753e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi            default:
29853e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi                Log.e(TAG, "focusLossForGainRequest() for invalid focus request "+ gainRequest);
2992380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi                        return AudioManager.AUDIOFOCUS_NONE;
30053e6e287ffe924b6d26237e167a1a8996054e17eJean-Michel Trivi        }
30183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
30283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
3030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    /**
304d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi     * Handle the loss of focus resulting from a given focus gain.
305d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi     * @param focusGain the focus gain from which the loss of focus is resulting
306d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi     * @param frWinner the new focus owner
307d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi     * @return true if the focus loss is definitive, false otherwise.
3080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi     */
309d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi    @GuardedBy("MediaFocusControl.mAudioFocusLock")
3109228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi    boolean handleFocusLossFromGain(int focusGain, final FocusRequester frWinner, boolean forceDuck)
3119228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi    {
312d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi        final int focusLoss = focusLossForGainRequest(focusGain);
3139228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi        handleFocusLoss(focusLoss, frWinner, forceDuck);
314d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi        return (focusLoss == AudioManager.AUDIOFOCUS_LOSS);
31583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
31683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
317d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi    @GuardedBy("MediaFocusControl.mAudioFocusLock")
31883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    void handleFocusGain(int focusGain) {
31983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
3200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE;
3210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi            mFocusController.notifyExtPolicyFocusGrant_syncAf(toAudioFocusInfo(),
3220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
323e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi            final IAudioFocusDispatcher fd = mFocusDispatcher;
324e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi            if (fd != null) {
325cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                if (DEBUG) {
326cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                    Log.v(TAG, "dispatching " + focusChangeToString(focusGain) + " to "
327cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                        + mClientId);
328cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                }
32999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                if (mFocusLossWasNotified) {
33099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    fd.dispatchAudioFocusChange(focusGain, mClientId);
33199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                }
332cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi            }
333270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi            mFocusController.unduckPlayers(this);
33483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (android.os.RemoteException e) {
33583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            Log.e(TAG, "Failure to signal gain of audio focus due to: ", e);
33683283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
33783283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
33883283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
339d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi    @GuardedBy("MediaFocusControl.mAudioFocusLock")
340270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi    void handleFocusGainFromRequest(int focusRequestResult) {
341270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi        if (focusRequestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
342270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi            mFocusController.unduckPlayers(this);
343270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi        }
344270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi    }
345270f1c9d8ff38be25b8972f7d158ca178da82eb7Jean-Michel Trivi
346d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi    @GuardedBy("MediaFocusControl.mAudioFocusLock")
3479228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi    void handleFocusLoss(int focusLoss, @Nullable final FocusRequester frWinner, boolean forceDuck)
3489228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi    {
34983283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        try {
350cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi            if (focusLoss != mFocusLossReceived) {
3510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                mFocusLossReceived = focusLoss;
35299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                mFocusLossWasNotified = false;
3530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // before dispatching a focus loss, check if the following conditions are met:
3540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // 1/ the framework is not supposed to notify the focus loser on a DUCK loss
3557b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                //    (i.e. it has a focus controller that implements a ducking policy)
3560212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // 2/ it is a DUCK loss
3570212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // 3/ the focus loser isn't flagged as pausing in a DUCK loss
3580212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                // if they are, do not notify the focus loser
3590212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                if (!mFocusController.mustNotifyFocusOwnerOnDuck()
3600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        && mFocusLossReceived == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
3610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        && (mGrantFlags
3620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                                & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) == 0) {
3630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    if (DEBUG) {
3640212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        Log.v(TAG, "NOT dispatching " + focusChangeToString(mFocusLossReceived)
3650212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                                + " to " + mClientId + ", to be handled externally");
3660212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    }
3670212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    mFocusController.notifyExtPolicyFocusLoss_syncAf(
3680212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                            toAudioFocusInfo(), false /* wasDispatched */);
3690212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    return;
3700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                }
37199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
37299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                // check enforcement by the framework
37399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                boolean handled = false;
37499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                if (focusLoss == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
37599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                        && MediaFocusControl.ENFORCE_DUCKING
376d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi                        && frWinner != null) {
37799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    // candidate for enforcement by the framework
378d9fef5cf4c62e10ed41ace93a44362b5f0142340Jean-Michel Trivi                    if (frWinner.mCallingUid != this.mCallingUid) {
3799228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi                        if (!forceDuck && ((mGrantFlags
3809228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi                                & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0)) {
3817b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                            // the focus loser declared it would pause instead of duck, let it
3827b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                            // handle it (the framework doesn't pause for apps)
3837b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                            handled = false;
384087b672797b23d6c7451f975ca7f825d64fb1bd9Jean-Michel Trivi                            Log.v(TAG, "not ducking uid " + this.mCallingUid + " - flags");
3859228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi                        } else if (!forceDuck && (MediaFocusControl.ENFORCE_DUCKING_FOR_NEW &&
3869228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi                                this.getSdkTarget() <= MediaFocusControl.DUCKING_IN_APP_SDK_LEVEL))
3879228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi                        {
388087b672797b23d6c7451f975ca7f825d64fb1bd9Jean-Michel Trivi                            // legacy behavior, apps used to be notified when they should be ducking
389087b672797b23d6c7451f975ca7f825d64fb1bd9Jean-Michel Trivi                            handled = false;
390087b672797b23d6c7451f975ca7f825d64fb1bd9Jean-Michel Trivi                            Log.v(TAG, "not ducking uid " + this.mCallingUid + " - old SDK");
3917b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                        } else {
3929228af6bc20c27b9949df36684f9c06ca9cdb27dJean-Michel Trivi                            handled = mFocusController.duckPlayers(frWinner, this, forceDuck);
3937b8da92d49caf965e8616ceeba828275574f09c0Jean-Michel Trivi                        }
39499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    } // else: the focus change is within the same app, so let the dispatching
39599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                      //       happen as if the framework was not involved.
39699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                }
39799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
39899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                if (handled) {
39999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    if (DEBUG) {
40099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                        Log.v(TAG, "NOT dispatching " + focusChangeToString(mFocusLossReceived)
40199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                            + " to " + mClientId + ", ducking implemented by framework");
40299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    }
403081249282005640682da315d6f0e0e3697fe4b37Jean-Michel Trivi                    mFocusController.notifyExtPolicyFocusLoss_syncAf(
404081249282005640682da315d6f0e0e3697fe4b37Jean-Michel Trivi                            toAudioFocusInfo(), false /* wasDispatched */);
40599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    return; // with mFocusLossWasNotified = false
40699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                }
40799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi
408e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                final IAudioFocusDispatcher fd = mFocusDispatcher;
409e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                if (fd != null) {
410cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                    if (DEBUG) {
4110212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                        Log.v(TAG, "dispatching " + focusChangeToString(mFocusLossReceived) + " to "
412cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                            + mClientId);
413cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                    }
4140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                    mFocusController.notifyExtPolicyFocusLoss_syncAf(
4150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi                            toAudioFocusInfo(), true /* wasDispatched */);
41699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi                    mFocusLossWasNotified = true;
417e89877245fc6dd359e435b5202901f9042819c51Jean-Michel Trivi                    fd.dispatchAudioFocusChange(mFocusLossReceived, mClientId);
418cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi                }
419cbb212ff6f06b004ae19dfb6958ee3852716bbdcJean-Michel Trivi            }
42083283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        } catch (android.os.RemoteException e) {
42183283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi            Log.e(TAG, "Failure to signal loss of audio focus due to:", e);
42283283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi        }
42383283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi    }
42483283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi
425126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    int dispatchFocusChange(int focusChange) {
426126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (mFocusDispatcher == null) {
427e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            if (MediaFocusControl.DEBUG) { Log.e(TAG, "dispatchFocusChange: no focus dispatcher"); }
428126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
429126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
430126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        if (focusChange == AudioManager.AUDIOFOCUS_NONE) {
431126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: AUDIOFOCUS_NONE"); }
432126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
433126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } else if ((focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
434126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
435126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
436126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_GAIN)
437126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                && (mFocusGainRequest != focusChange)){
438126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            Log.w(TAG, "focus gain was requested with " + mFocusGainRequest
439126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                    + ", dispatching " + focusChange);
440126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
441126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT
442126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi                || focusChange == AudioManager.AUDIOFOCUS_LOSS) {
443126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusLossReceived = focusChange;
444126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
445126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        try {
446126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            mFocusDispatcher.dispatchAudioFocusChange(focusChange, mClientId);
447126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        } catch (android.os.RemoteException e) {
448e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            Log.e(TAG, "dispatchFocusChange: error talking to focus listener " + mClientId, e);
449126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi            return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
450126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        }
451126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi        return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
452126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi    }
453126cf03f7c8e825a23e47dd133e77eb1b3b7633dJean-Michel Trivi
454e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi    void dispatchFocusResultFromExtPolicy(int requestResult) {
455e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        if (mFocusDispatcher == null) {
456e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            if (MediaFocusControl.DEBUG) {
457e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi                Log.e(TAG, "dispatchFocusResultFromExtPolicy: no focus dispatcher");
458e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            }
459e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        }
460e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        if (DEBUG) {
461e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            Log.v(TAG, "dispatching result" + requestResult + " to " + mClientId);
462e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        }
463e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        try {
464e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            mFocusDispatcher.dispatchFocusResultFromExtPolicy(requestResult, mClientId);
465e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        } catch (android.os.RemoteException e) {
466e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi            Log.e(TAG, "dispatchFocusResultFromExtPolicy: error talking to focus listener"
467e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi                    + mClientId, e);
468e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi        }
469e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi    }
470e2d8aae2ccc51340cf4846ce28f635b825711368Jean-Michel Trivi
4710212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    AudioFocusInfo toAudioFocusInfo() {
47299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi        return new AudioFocusInfo(mAttributes, mCallingUid, mClientId, mPackageName,
473461922fcfc8572415aa39c43c06afce685bd998dJean-Michel Trivi                mFocusGainRequest, mFocusLossReceived, mGrantFlags, mSdkTarget);
4740212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    }
47583283f23eb1b7c1576e253c644b8aade6f657d0aJean-Michel Trivi}
476