Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2013 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
John Spurlock | 6156017 | 2015-02-06 19:46:04 -0500 | [diff] [blame] | 17 | package com.android.server.audio; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 18 | |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 19 | import android.annotation.NonNull; |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 20 | import android.annotation.Nullable; |
John Spurlock | 6156017 | 2015-02-06 19:46:04 -0500 | [diff] [blame] | 21 | import android.media.AudioAttributes; |
| 22 | import android.media.AudioFocusInfo; |
| 23 | import android.media.AudioManager; |
| 24 | import android.media.IAudioFocusDispatcher; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 25 | import android.os.IBinder; |
| 26 | import android.util.Log; |
| 27 | |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 28 | import com.android.internal.annotations.GuardedBy; |
John Spurlock | 6156017 | 2015-02-06 19:46:04 -0500 | [diff] [blame] | 29 | import com.android.server.audio.MediaFocusControl.AudioFocusDeathHandler; |
| 30 | |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 31 | import java.io.PrintWriter; |
| 32 | |
| 33 | /** |
| 34 | * @hide |
| 35 | * Class to handle all the information about a user of audio focus. The lifecycle of each |
| 36 | * instance is managed by android.media.MediaFocusControl, from its addition to the audio focus |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 37 | * stack, or the map of focus owners for an external focus policy, to its release. |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 38 | */ |
John Spurlock | 6156017 | 2015-02-06 19:46:04 -0500 | [diff] [blame] | 39 | public class FocusRequester { |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 40 | |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 41 | // on purpose not using this classe's name, as it will only be used from MediaFocusControl |
| 42 | private static final String TAG = "MediaFocusControl"; |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 43 | private static final boolean DEBUG = false; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 44 | |
Jean-Michel Trivi | e898772 | 2016-07-07 15:38:32 -0700 | [diff] [blame] | 45 | private AudioFocusDeathHandler mDeathHandler; // may be null |
| 46 | private IAudioFocusDispatcher mFocusDispatcher; // may be null |
| 47 | private final IBinder mSourceRef; // may be null |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 48 | private final String mClientId; |
| 49 | private final String mPackageName; |
| 50 | private final int mCallingUid; |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 51 | private final MediaFocusControl mFocusController; // never null |
Jean-Michel Trivi | 461922f | 2017-04-25 15:23:17 -0700 | [diff] [blame] | 52 | private final int mSdkTarget; |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 53 | |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 54 | /** |
| 55 | * the audio focus gain request that caused the addition of this object in the focus stack. |
| 56 | */ |
| 57 | private final int mFocusGainRequest; |
| 58 | /** |
Jean-Michel Trivi | fd6ad74 | 2014-11-10 14:38:30 -0800 | [diff] [blame] | 59 | * the flags associated with the gain request that qualify the type of grant (e.g. accepting |
| 60 | * delay vs grant must be immediate) |
| 61 | */ |
| 62 | private final int mGrantFlags; |
| 63 | /** |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 64 | * the audio focus loss received my mFocusDispatcher, is AudioManager.AUDIOFOCUS_NONE if |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 65 | * it never lost focus. |
| 66 | */ |
| 67 | private int mFocusLossReceived; |
| 68 | /** |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 69 | * whether this focus owner listener was notified when it lost focus |
| 70 | */ |
| 71 | private boolean mFocusLossWasNotified; |
| 72 | /** |
Jean-Michel Trivi | fd6ad74 | 2014-11-10 14:38:30 -0800 | [diff] [blame] | 73 | * the audio attributes associated with the focus request |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 74 | */ |
Jean-Michel Trivi | fd6ad74 | 2014-11-10 14:38:30 -0800 | [diff] [blame] | 75 | private final AudioAttributes mAttributes; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 76 | |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 77 | /** |
| 78 | * Class constructor |
| 79 | * @param aa |
| 80 | * @param focusRequest |
| 81 | * @param grantFlags |
| 82 | * @param afl |
| 83 | * @param source |
| 84 | * @param id |
| 85 | * @param hdlr |
| 86 | * @param pn |
| 87 | * @param uid |
| 88 | * @param ctlr cannot be null |
| 89 | */ |
Jean-Michel Trivi | fd6ad74 | 2014-11-10 14:38:30 -0800 | [diff] [blame] | 90 | FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags, |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 91 | IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr, |
Jean-Michel Trivi | 461922f | 2017-04-25 15:23:17 -0700 | [diff] [blame] | 92 | String pn, int uid, @NonNull MediaFocusControl ctlr, int sdk) { |
Jean-Michel Trivi | fd6ad74 | 2014-11-10 14:38:30 -0800 | [diff] [blame] | 93 | mAttributes = aa; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 94 | mFocusDispatcher = afl; |
| 95 | mSourceRef = source; |
| 96 | mClientId = id; |
| 97 | mDeathHandler = hdlr; |
| 98 | mPackageName = pn; |
| 99 | mCallingUid = uid; |
| 100 | mFocusGainRequest = focusRequest; |
Jean-Michel Trivi | fd6ad74 | 2014-11-10 14:38:30 -0800 | [diff] [blame] | 101 | mGrantFlags = grantFlags; |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 102 | mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE; |
Jean-Michel Trivi | 087b672 | 2017-05-10 13:05:06 -0700 | [diff] [blame] | 103 | mFocusLossWasNotified = true; |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 104 | mFocusController = ctlr; |
Jean-Michel Trivi | 461922f | 2017-04-25 15:23:17 -0700 | [diff] [blame] | 105 | mSdkTarget = sdk; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 106 | } |
| 107 | |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 108 | FocusRequester(AudioFocusInfo afi, IAudioFocusDispatcher afl, |
| 109 | IBinder source, AudioFocusDeathHandler hdlr, @NonNull MediaFocusControl ctlr) { |
| 110 | mAttributes = afi.getAttributes(); |
| 111 | mClientId = afi.getClientId(); |
| 112 | mPackageName = afi.getPackageName(); |
| 113 | mCallingUid = afi.getClientUid(); |
| 114 | mFocusGainRequest = afi.getGainRequest(); |
| 115 | mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE; |
Jean-Michel Trivi | 087b672 | 2017-05-10 13:05:06 -0700 | [diff] [blame] | 116 | mFocusLossWasNotified = true; |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 117 | mGrantFlags = afi.getFlags(); |
Jean-Michel Trivi | 461922f | 2017-04-25 15:23:17 -0700 | [diff] [blame] | 118 | mSdkTarget = afi.getSdkTarget(); |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 119 | |
| 120 | mFocusDispatcher = afl; |
| 121 | mSourceRef = source; |
| 122 | mDeathHandler = hdlr; |
| 123 | mFocusController = ctlr; |
| 124 | } |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 125 | |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 126 | boolean hasSameClient(String otherClient) { |
| 127 | try { |
| 128 | return mClientId.compareTo(otherClient) == 0; |
| 129 | } catch (NullPointerException e) { |
| 130 | return false; |
| 131 | } |
| 132 | } |
| 133 | |
Jean-Michel Trivi | 958876f | 2014-11-16 15:40:22 -0800 | [diff] [blame] | 134 | boolean isLockedFocusOwner() { |
| 135 | return ((mGrantFlags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0); |
| 136 | } |
| 137 | |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 138 | boolean hasSameBinder(IBinder ib) { |
| 139 | return (mSourceRef != null) && mSourceRef.equals(ib); |
| 140 | } |
| 141 | |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 142 | boolean hasSameDispatcher(IAudioFocusDispatcher fd) { |
| 143 | return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd); |
| 144 | } |
| 145 | |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 146 | boolean hasSamePackage(String pack) { |
| 147 | try { |
| 148 | return mPackageName.compareTo(pack) == 0; |
| 149 | } catch (NullPointerException e) { |
| 150 | return false; |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | boolean hasSameUid(int uid) { |
| 155 | return mCallingUid == uid; |
| 156 | } |
| 157 | |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 158 | int getClientUid() { |
| 159 | return mCallingUid; |
| 160 | } |
| 161 | |
Jean-Michel Trivi | 958876f | 2014-11-16 15:40:22 -0800 | [diff] [blame] | 162 | String getClientId() { |
| 163 | return mClientId; |
| 164 | } |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 165 | |
| 166 | int getGainRequest() { |
| 167 | return mFocusGainRequest; |
| 168 | } |
| 169 | |
Jean-Michel Trivi | fd6ad74 | 2014-11-10 14:38:30 -0800 | [diff] [blame] | 170 | int getGrantFlags() { |
| 171 | return mGrantFlags; |
| 172 | } |
| 173 | |
| 174 | AudioAttributes getAudioAttributes() { |
| 175 | return mAttributes; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 176 | } |
| 177 | |
Jean-Michel Trivi | 461922f | 2017-04-25 15:23:17 -0700 | [diff] [blame] | 178 | int getSdkTarget() { |
| 179 | return mSdkTarget; |
| 180 | } |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 181 | |
| 182 | private static String focusChangeToString(int focus) { |
| 183 | switch(focus) { |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 184 | case AudioManager.AUDIOFOCUS_NONE: |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 185 | return "none"; |
| 186 | case AudioManager.AUDIOFOCUS_GAIN: |
| 187 | return "GAIN"; |
| 188 | case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT: |
| 189 | return "GAIN_TRANSIENT"; |
| 190 | case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK: |
| 191 | return "GAIN_TRANSIENT_MAY_DUCK"; |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 192 | case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE: |
| 193 | return "GAIN_TRANSIENT_EXCLUSIVE"; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 194 | case AudioManager.AUDIOFOCUS_LOSS: |
| 195 | return "LOSS"; |
| 196 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: |
| 197 | return "LOSS_TRANSIENT"; |
| 198 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: |
| 199 | return "LOSS_TRANSIENT_CAN_DUCK"; |
| 200 | default: |
| 201 | return "[invalid focus change" + focus + "]"; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | private String focusGainToString() { |
| 206 | return focusChangeToString(mFocusGainRequest); |
| 207 | } |
| 208 | |
| 209 | private String focusLossToString() { |
| 210 | return focusChangeToString(mFocusLossReceived); |
| 211 | } |
| 212 | |
Jean-Michel Trivi | 958876f | 2014-11-16 15:40:22 -0800 | [diff] [blame] | 213 | private static String flagsToString(int flags) { |
| 214 | String msg = new String(); |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 215 | if ((flags & AudioManager.AUDIOFOCUS_FLAG_DELAY_OK) != 0) { |
| 216 | msg += "DELAY_OK"; |
| 217 | } |
| 218 | if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) != 0) { |
| 219 | if (!msg.isEmpty()) { msg += "|"; } |
| 220 | msg += "LOCK"; |
| 221 | } |
| 222 | if ((flags & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0) { |
| 223 | if (!msg.isEmpty()) { msg += "|"; } |
| 224 | msg += "PAUSES_ON_DUCKABLE_LOSS"; |
| 225 | } |
Jean-Michel Trivi | 958876f | 2014-11-16 15:40:22 -0800 | [diff] [blame] | 226 | return msg; |
| 227 | } |
| 228 | |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 229 | void dump(PrintWriter pw) { |
| 230 | pw.println(" source:" + mSourceRef |
| 231 | + " -- pack: " + mPackageName |
| 232 | + " -- client: " + mClientId |
| 233 | + " -- gain: " + focusGainToString() |
Jean-Michel Trivi | 958876f | 2014-11-16 15:40:22 -0800 | [diff] [blame] | 234 | + " -- flags: " + flagsToString(mGrantFlags) |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 235 | + " -- loss: " + focusLossToString() |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 236 | + " -- notified: " + mFocusLossWasNotified |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 237 | + " -- uid: " + mCallingUid |
Jean-Michel Trivi | 461922f | 2017-04-25 15:23:17 -0700 | [diff] [blame] | 238 | + " -- attr: " + mAttributes |
| 239 | + " -- sdk:" + mSdkTarget); |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | |
| 243 | void release() { |
Jean-Michel Trivi | e2d8aae | 2018-01-30 15:09:47 -0800 | [diff] [blame] | 244 | final IBinder srcRef = mSourceRef; |
| 245 | final AudioFocusDeathHandler deathHdlr = mDeathHandler; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 246 | try { |
Jean-Michel Trivi | e2d8aae | 2018-01-30 15:09:47 -0800 | [diff] [blame] | 247 | if (srcRef != null && deathHdlr != null) { |
| 248 | srcRef.unlinkToDeath(deathHdlr, 0); |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 249 | } |
Jean-Michel Trivi | e2d8aae | 2018-01-30 15:09:47 -0800 | [diff] [blame] | 250 | } catch (java.util.NoSuchElementException e) { } |
| 251 | mDeathHandler = null; |
| 252 | mFocusDispatcher = null; |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | @Override |
| 256 | protected void finalize() throws Throwable { |
| 257 | release(); |
| 258 | super.finalize(); |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | * For a given audio focus gain request, return the audio focus loss type that will result |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 263 | * from it, taking into account any previous focus loss. |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 264 | * @param gainRequest |
| 265 | * @return the audio focus loss type that matches the gain request |
| 266 | */ |
| 267 | private int focusLossForGainRequest(int gainRequest) { |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 268 | switch(gainRequest) { |
| 269 | case AudioManager.AUDIOFOCUS_GAIN: |
| 270 | switch(mFocusLossReceived) { |
| 271 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: |
| 272 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: |
| 273 | case AudioManager.AUDIOFOCUS_LOSS: |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 274 | case AudioManager.AUDIOFOCUS_NONE: |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 275 | return AudioManager.AUDIOFOCUS_LOSS; |
| 276 | } |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 277 | case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE: |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 278 | case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT: |
| 279 | switch(mFocusLossReceived) { |
| 280 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: |
| 281 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 282 | case AudioManager.AUDIOFOCUS_NONE: |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 283 | return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT; |
| 284 | case AudioManager.AUDIOFOCUS_LOSS: |
| 285 | return AudioManager.AUDIOFOCUS_LOSS; |
| 286 | } |
| 287 | case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK: |
| 288 | switch(mFocusLossReceived) { |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 289 | case AudioManager.AUDIOFOCUS_NONE: |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 290 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 291 | return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK; |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 292 | case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: |
| 293 | return AudioManager.AUDIOFOCUS_LOSS_TRANSIENT; |
| 294 | case AudioManager.AUDIOFOCUS_LOSS: |
| 295 | return AudioManager.AUDIOFOCUS_LOSS; |
| 296 | } |
| 297 | default: |
| 298 | Log.e(TAG, "focusLossForGainRequest() for invalid focus request "+ gainRequest); |
Jean-Michel Trivi | 2380566 | 2013-07-31 14:19:18 -0700 | [diff] [blame] | 299 | return AudioManager.AUDIOFOCUS_NONE; |
Jean-Michel Trivi | 53e6e28 | 2013-07-30 14:21:34 -0700 | [diff] [blame] | 300 | } |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 301 | } |
| 302 | |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 303 | /** |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 304 | * Handle the loss of focus resulting from a given focus gain. |
| 305 | * @param focusGain the focus gain from which the loss of focus is resulting |
| 306 | * @param frWinner the new focus owner |
| 307 | * @return true if the focus loss is definitive, false otherwise. |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 308 | */ |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 309 | @GuardedBy("MediaFocusControl.mAudioFocusLock") |
Jean-Michel Trivi | 9228af6 | 2018-01-05 17:06:17 -0800 | [diff] [blame] | 310 | boolean handleFocusLossFromGain(int focusGain, final FocusRequester frWinner, boolean forceDuck) |
| 311 | { |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 312 | final int focusLoss = focusLossForGainRequest(focusGain); |
Jean-Michel Trivi | 9228af6 | 2018-01-05 17:06:17 -0800 | [diff] [blame] | 313 | handleFocusLoss(focusLoss, frWinner, forceDuck); |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 314 | return (focusLoss == AudioManager.AUDIOFOCUS_LOSS); |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 315 | } |
| 316 | |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 317 | @GuardedBy("MediaFocusControl.mAudioFocusLock") |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 318 | void handleFocusGain(int focusGain) { |
| 319 | try { |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 320 | mFocusLossReceived = AudioManager.AUDIOFOCUS_NONE; |
| 321 | mFocusController.notifyExtPolicyFocusGrant_syncAf(toAudioFocusInfo(), |
| 322 | AudioManager.AUDIOFOCUS_REQUEST_GRANTED); |
Jean-Michel Trivi | e898772 | 2016-07-07 15:38:32 -0700 | [diff] [blame] | 323 | final IAudioFocusDispatcher fd = mFocusDispatcher; |
| 324 | if (fd != null) { |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 325 | if (DEBUG) { |
| 326 | Log.v(TAG, "dispatching " + focusChangeToString(focusGain) + " to " |
| 327 | + mClientId); |
| 328 | } |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 329 | if (mFocusLossWasNotified) { |
| 330 | fd.dispatchAudioFocusChange(focusGain, mClientId); |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 331 | } |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 332 | } |
Jean-Michel Trivi | 270f1c9 | 2017-05-05 11:43:31 -0700 | [diff] [blame] | 333 | mFocusController.unduckPlayers(this); |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 334 | } catch (android.os.RemoteException e) { |
| 335 | Log.e(TAG, "Failure to signal gain of audio focus due to: ", e); |
| 336 | } |
| 337 | } |
| 338 | |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 339 | @GuardedBy("MediaFocusControl.mAudioFocusLock") |
Jean-Michel Trivi | 270f1c9 | 2017-05-05 11:43:31 -0700 | [diff] [blame] | 340 | void handleFocusGainFromRequest(int focusRequestResult) { |
| 341 | if (focusRequestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { |
| 342 | mFocusController.unduckPlayers(this); |
| 343 | } |
| 344 | } |
| 345 | |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 346 | @GuardedBy("MediaFocusControl.mAudioFocusLock") |
Jean-Michel Trivi | 9228af6 | 2018-01-05 17:06:17 -0800 | [diff] [blame] | 347 | void handleFocusLoss(int focusLoss, @Nullable final FocusRequester frWinner, boolean forceDuck) |
| 348 | { |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 349 | try { |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 350 | if (focusLoss != mFocusLossReceived) { |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 351 | mFocusLossReceived = focusLoss; |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 352 | mFocusLossWasNotified = false; |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 353 | // before dispatching a focus loss, check if the following conditions are met: |
| 354 | // 1/ the framework is not supposed to notify the focus loser on a DUCK loss |
Jean-Michel Trivi | 7b8da92 | 2017-05-01 17:51:14 -0700 | [diff] [blame] | 355 | // (i.e. it has a focus controller that implements a ducking policy) |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 356 | // 2/ it is a DUCK loss |
| 357 | // 3/ the focus loser isn't flagged as pausing in a DUCK loss |
| 358 | // if they are, do not notify the focus loser |
| 359 | if (!mFocusController.mustNotifyFocusOwnerOnDuck() |
| 360 | && mFocusLossReceived == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK |
| 361 | && (mGrantFlags |
| 362 | & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) == 0) { |
| 363 | if (DEBUG) { |
| 364 | Log.v(TAG, "NOT dispatching " + focusChangeToString(mFocusLossReceived) |
| 365 | + " to " + mClientId + ", to be handled externally"); |
| 366 | } |
| 367 | mFocusController.notifyExtPolicyFocusLoss_syncAf( |
| 368 | toAudioFocusInfo(), false /* wasDispatched */); |
| 369 | return; |
| 370 | } |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 371 | |
| 372 | // check enforcement by the framework |
| 373 | boolean handled = false; |
| 374 | if (focusLoss == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK |
| 375 | && MediaFocusControl.ENFORCE_DUCKING |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 376 | && frWinner != null) { |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 377 | // candidate for enforcement by the framework |
Jean-Michel Trivi | d9fef5c | 2017-12-28 15:25:35 -0800 | [diff] [blame] | 378 | if (frWinner.mCallingUid != this.mCallingUid) { |
Jean-Michel Trivi | 9228af6 | 2018-01-05 17:06:17 -0800 | [diff] [blame] | 379 | if (!forceDuck && ((mGrantFlags |
| 380 | & AudioManager.AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS) != 0)) { |
Jean-Michel Trivi | 7b8da92 | 2017-05-01 17:51:14 -0700 | [diff] [blame] | 381 | // the focus loser declared it would pause instead of duck, let it |
| 382 | // handle it (the framework doesn't pause for apps) |
| 383 | handled = false; |
Jean-Michel Trivi | 087b672 | 2017-05-10 13:05:06 -0700 | [diff] [blame] | 384 | Log.v(TAG, "not ducking uid " + this.mCallingUid + " - flags"); |
Jean-Michel Trivi | 9228af6 | 2018-01-05 17:06:17 -0800 | [diff] [blame] | 385 | } else if (!forceDuck && (MediaFocusControl.ENFORCE_DUCKING_FOR_NEW && |
| 386 | this.getSdkTarget() <= MediaFocusControl.DUCKING_IN_APP_SDK_LEVEL)) |
| 387 | { |
Jean-Michel Trivi | 087b672 | 2017-05-10 13:05:06 -0700 | [diff] [blame] | 388 | // legacy behavior, apps used to be notified when they should be ducking |
| 389 | handled = false; |
| 390 | Log.v(TAG, "not ducking uid " + this.mCallingUid + " - old SDK"); |
Jean-Michel Trivi | 7b8da92 | 2017-05-01 17:51:14 -0700 | [diff] [blame] | 391 | } else { |
Jean-Michel Trivi | 9228af6 | 2018-01-05 17:06:17 -0800 | [diff] [blame] | 392 | handled = mFocusController.duckPlayers(frWinner, this, forceDuck); |
Jean-Michel Trivi | 7b8da92 | 2017-05-01 17:51:14 -0700 | [diff] [blame] | 393 | } |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 394 | } // else: the focus change is within the same app, so let the dispatching |
| 395 | // happen as if the framework was not involved. |
| 396 | } |
| 397 | |
| 398 | if (handled) { |
| 399 | if (DEBUG) { |
| 400 | Log.v(TAG, "NOT dispatching " + focusChangeToString(mFocusLossReceived) |
| 401 | + " to " + mClientId + ", ducking implemented by framework"); |
| 402 | } |
Jean-Michel Trivi | 0812492 | 2017-05-05 09:44:28 -0700 | [diff] [blame] | 403 | mFocusController.notifyExtPolicyFocusLoss_syncAf( |
| 404 | toAudioFocusInfo(), false /* wasDispatched */); |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 405 | return; // with mFocusLossWasNotified = false |
| 406 | } |
| 407 | |
Jean-Michel Trivi | e898772 | 2016-07-07 15:38:32 -0700 | [diff] [blame] | 408 | final IAudioFocusDispatcher fd = mFocusDispatcher; |
| 409 | if (fd != null) { |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 410 | if (DEBUG) { |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 411 | Log.v(TAG, "dispatching " + focusChangeToString(mFocusLossReceived) + " to " |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 412 | + mClientId); |
| 413 | } |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 414 | mFocusController.notifyExtPolicyFocusLoss_syncAf( |
| 415 | toAudioFocusInfo(), true /* wasDispatched */); |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 416 | mFocusLossWasNotified = true; |
Jean-Michel Trivi | e898772 | 2016-07-07 15:38:32 -0700 | [diff] [blame] | 417 | fd.dispatchAudioFocusChange(mFocusLossReceived, mClientId); |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 418 | } |
Jean-Michel Trivi | cbb212f | 2013-07-30 15:09:33 -0700 | [diff] [blame] | 419 | } |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 420 | } catch (android.os.RemoteException e) { |
| 421 | Log.e(TAG, "Failure to signal loss of audio focus due to:", e); |
| 422 | } |
| 423 | } |
| 424 | |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 425 | int dispatchFocusChange(int focusChange) { |
| 426 | if (mFocusDispatcher == null) { |
Jean-Michel Trivi | e2d8aae | 2018-01-30 15:09:47 -0800 | [diff] [blame] | 427 | if (MediaFocusControl.DEBUG) { Log.e(TAG, "dispatchFocusChange: no focus dispatcher"); } |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 428 | return AudioManager.AUDIOFOCUS_REQUEST_FAILED; |
| 429 | } |
| 430 | if (focusChange == AudioManager.AUDIOFOCUS_NONE) { |
| 431 | if (MediaFocusControl.DEBUG) { Log.v(TAG, "dispatchFocusChange: AUDIOFOCUS_NONE"); } |
| 432 | return AudioManager.AUDIOFOCUS_REQUEST_FAILED; |
| 433 | } else if ((focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK |
| 434 | || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE |
| 435 | || focusChange == AudioManager.AUDIOFOCUS_GAIN_TRANSIENT |
| 436 | || focusChange == AudioManager.AUDIOFOCUS_GAIN) |
| 437 | && (mFocusGainRequest != focusChange)){ |
| 438 | Log.w(TAG, "focus gain was requested with " + mFocusGainRequest |
| 439 | + ", dispatching " + focusChange); |
| 440 | } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK |
| 441 | || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT |
| 442 | || focusChange == AudioManager.AUDIOFOCUS_LOSS) { |
| 443 | mFocusLossReceived = focusChange; |
| 444 | } |
| 445 | try { |
| 446 | mFocusDispatcher.dispatchAudioFocusChange(focusChange, mClientId); |
| 447 | } catch (android.os.RemoteException e) { |
Jean-Michel Trivi | e2d8aae | 2018-01-30 15:09:47 -0800 | [diff] [blame] | 448 | Log.e(TAG, "dispatchFocusChange: error talking to focus listener " + mClientId, e); |
Jean-Michel Trivi | 126cf03 | 2017-04-02 23:19:02 -0700 | [diff] [blame] | 449 | return AudioManager.AUDIOFOCUS_REQUEST_FAILED; |
| 450 | } |
| 451 | return AudioManager.AUDIOFOCUS_REQUEST_GRANTED; |
| 452 | } |
| 453 | |
Jean-Michel Trivi | e2d8aae | 2018-01-30 15:09:47 -0800 | [diff] [blame] | 454 | void dispatchFocusResultFromExtPolicy(int requestResult) { |
| 455 | if (mFocusDispatcher == null) { |
| 456 | if (MediaFocusControl.DEBUG) { |
| 457 | Log.e(TAG, "dispatchFocusResultFromExtPolicy: no focus dispatcher"); |
| 458 | } |
| 459 | } |
| 460 | if (DEBUG) { |
| 461 | Log.v(TAG, "dispatching result" + requestResult + " to " + mClientId); |
| 462 | } |
| 463 | try { |
| 464 | mFocusDispatcher.dispatchFocusResultFromExtPolicy(requestResult, mClientId); |
| 465 | } catch (android.os.RemoteException e) { |
| 466 | Log.e(TAG, "dispatchFocusResultFromExtPolicy: error talking to focus listener" |
| 467 | + mClientId, e); |
| 468 | } |
| 469 | } |
| 470 | |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 471 | AudioFocusInfo toAudioFocusInfo() { |
Jean-Michel Trivi | 99489cc | 2017-01-25 19:08:49 -0800 | [diff] [blame] | 472 | return new AudioFocusInfo(mAttributes, mCallingUid, mClientId, mPackageName, |
Jean-Michel Trivi | 461922f | 2017-04-25 15:23:17 -0700 | [diff] [blame] | 473 | mFocusGainRequest, mFocusLossReceived, mGrantFlags, mSdkTarget); |
Jean-Michel Trivi | 0212be5 | 2014-11-24 14:43:10 -0800 | [diff] [blame] | 474 | } |
Jean-Michel Trivi | 83283f2 | 2013-07-29 18:09:41 -0700 | [diff] [blame] | 475 | } |