Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 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 | package com.android.server.audio; |
| 17 | |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 18 | import static com.android.server.audio.AudioService.CONNECTION_STATE_CONNECTED; |
| 19 | import static com.android.server.audio.AudioService.CONNECTION_STATE_DISCONNECTED; |
| 20 | |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 21 | import android.annotation.NonNull; |
| 22 | import android.bluetooth.BluetoothA2dp; |
| 23 | import android.bluetooth.BluetoothDevice; |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 24 | import android.bluetooth.BluetoothHeadset; |
| 25 | import android.bluetooth.BluetoothHearingAid; |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 26 | import android.bluetooth.BluetoothProfile; |
| 27 | import android.content.ContentResolver; |
| 28 | import android.content.Context; |
| 29 | import android.content.Intent; |
| 30 | import android.media.AudioManager; |
| 31 | import android.media.AudioRoutesInfo; |
| 32 | import android.media.AudioSystem; |
| 33 | import android.media.IAudioRoutesObserver; |
| 34 | import android.os.Binder; |
| 35 | import android.os.Handler; |
| 36 | import android.os.IBinder; |
| 37 | import android.os.Looper; |
| 38 | import android.os.Message; |
| 39 | import android.os.PowerManager; |
| 40 | import android.os.SystemClock; |
| 41 | import android.os.UserHandle; |
| 42 | import android.util.Log; |
| 43 | |
| 44 | import com.android.internal.annotations.GuardedBy; |
| 45 | |
| 46 | import java.util.ArrayList; |
| 47 | |
| 48 | /** @hide */ |
| 49 | /*package*/ final class AudioDeviceBroker { |
| 50 | |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 51 | private static final String TAG = "AS.AudioDeviceBroker"; |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 52 | |
| 53 | private static final long BROKER_WAKELOCK_TIMEOUT_MS = 5000; //5s |
| 54 | |
| 55 | /*package*/ static final int BTA2DP_DOCK_TIMEOUT_MS = 8000; |
| 56 | // Timeout for connection to bluetooth headset service |
| 57 | /*package*/ static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; |
| 58 | |
| 59 | private final @NonNull AudioService mAudioService; |
| 60 | private final @NonNull Context mContext; |
| 61 | |
| 62 | /** Forced device usage for communications sent to AudioSystem */ |
| 63 | private int mForcedUseForComm; |
| 64 | /** |
| 65 | * Externally reported force device usage state returned by getters: always consistent |
| 66 | * with requests by setters */ |
| 67 | private int mForcedUseForCommExt; |
| 68 | |
| 69 | // Manages all connected devices, only ever accessed on the message loop |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 70 | private final AudioDeviceInventory mDeviceInventory; |
| 71 | // Manages notifications to BT service |
| 72 | private final BtHelper mBtHelper; |
| 73 | |
| 74 | |
| 75 | //------------------------------------------------------------------- |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 76 | // we use a different lock than mDeviceStateLock so as not to create |
| 77 | // lock contention between enqueueing a message and handling them |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 78 | private static final Object sLastDeviceConnectionMsgTimeLock = new Object(); |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 79 | @GuardedBy("sLastDeviceConnectionMsgTimeLock") |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 80 | private static long sLastDeviceConnectMsgTime = 0; |
| 81 | |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 82 | // General lock to be taken whenever the state of the audio devices is to be checked or changed |
| 83 | private final Object mDeviceStateLock = new Object(); |
| 84 | |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 85 | // Request to override default use of A2DP for media. |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 86 | @GuardedBy("mDeviceStateLock") |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 87 | private boolean mBluetoothA2dpEnabled; |
| 88 | |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 89 | // lock always taken when accessing AudioService.mSetModeDeathHandlers |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 90 | // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055 |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 91 | /*package*/ final Object mSetModeLock = new Object(); |
| 92 | |
| 93 | //------------------------------------------------------------------- |
| 94 | /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) { |
| 95 | mContext = context; |
| 96 | mAudioService = service; |
| 97 | setupMessaging(context); |
| 98 | mBtHelper = new BtHelper(this); |
| 99 | mDeviceInventory = new AudioDeviceInventory(this); |
| 100 | |
| 101 | mForcedUseForComm = AudioSystem.FORCE_NONE; |
| 102 | mForcedUseForCommExt = mForcedUseForComm; |
| 103 | |
| 104 | } |
| 105 | |
| 106 | /*package*/ Context getContext() { |
| 107 | return mContext; |
| 108 | } |
| 109 | |
| 110 | //--------------------------------------------------------------------- |
| 111 | // Communication from AudioService |
| 112 | // All methods are asynchronous and never block |
| 113 | // All permission checks are done in AudioService, all incoming calls are considered "safe" |
| 114 | // All post* methods are asynchronous |
| 115 | |
| 116 | /*package*/ void onSystemReady() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 117 | synchronized (mDeviceStateLock) { |
| 118 | mBtHelper.onSystemReady(); |
| 119 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | /*package*/ void onAudioServerDied() { |
| 123 | // Restore forced usage for communications and record |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 124 | synchronized (mDeviceStateLock) { |
| 125 | onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied"); |
| 126 | onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied"); |
| 127 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 128 | // restore devices |
| 129 | sendMsgNoDelay(MSG_RESTORE_DEVICES, SENDMSG_REPLACE); |
| 130 | } |
| 131 | |
| 132 | /*package*/ void setForceUse_Async(int useCase, int config, String eventSource) { |
| 133 | sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, |
| 134 | useCase, config, eventSource); |
| 135 | } |
| 136 | |
| 137 | /*package*/ void toggleHdmiIfConnected_Async() { |
| 138 | sendMsgNoDelay(MSG_TOGGLE_HDMI, SENDMSG_QUEUE); |
| 139 | } |
| 140 | |
| 141 | /*package*/ void disconnectAllBluetoothProfiles() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 142 | synchronized (mDeviceStateLock) { |
| 143 | mBtHelper.disconnectAllBluetoothProfiles(); |
| 144 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 145 | } |
| 146 | |
| 147 | /** |
| 148 | * Handle BluetoothHeadset intents where the action is one of |
| 149 | * {@link BluetoothHeadset#ACTION_ACTIVE_DEVICE_CHANGED} or |
| 150 | * {@link BluetoothHeadset#ACTION_AUDIO_STATE_CHANGED}. |
| 151 | * @param intent |
| 152 | */ |
| 153 | /*package*/ void receiveBtEvent(@NonNull Intent intent) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 154 | synchronized (mDeviceStateLock) { |
| 155 | mBtHelper.receiveBtEvent(intent); |
| 156 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 157 | } |
| 158 | |
| 159 | /*package*/ void setBluetoothA2dpOn_Async(boolean on, String source) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 160 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 161 | if (mBluetoothA2dpEnabled == on) { |
| 162 | return; |
| 163 | } |
| 164 | mBluetoothA2dpEnabled = on; |
| 165 | mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); |
| 166 | sendIILMsgNoDelay(MSG_IIL_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, |
| 167 | AudioSystem.FOR_MEDIA, |
| 168 | mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, |
| 169 | source); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | /*package*/ void setSpeakerphoneOn(boolean on, String eventSource) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 174 | synchronized (mDeviceStateLock) { |
| 175 | if (on) { |
| 176 | if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { |
| 177 | setForceUse_Async(AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource); |
| 178 | } |
| 179 | mForcedUseForComm = AudioSystem.FORCE_SPEAKER; |
| 180 | } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) { |
| 181 | mForcedUseForComm = AudioSystem.FORCE_NONE; |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 182 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 183 | |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 184 | mForcedUseForCommExt = mForcedUseForComm; |
| 185 | setForceUse_Async(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); |
| 186 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | /*package*/ boolean isSpeakerphoneOn() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 190 | synchronized (mDeviceStateLock) { |
| 191 | return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); |
| 192 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 193 | } |
| 194 | |
| 195 | /*package*/ void setWiredDeviceConnectionState(int type, |
| 196 | @AudioService.ConnectionState int state, String address, String name, |
| 197 | String caller) { |
| 198 | //TODO move logging here just like in setBluetooth* methods |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 199 | synchronized (mDeviceStateLock) { |
| 200 | mDeviceInventory.setWiredDeviceConnectionState(type, state, address, name, caller); |
| 201 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 202 | } |
| 203 | |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 204 | private static final class BtDeviceConnectionInfo { |
| 205 | final @NonNull BluetoothDevice mDevice; |
| 206 | final @AudioService.BtProfileConnectionState int mState; |
| 207 | final int mProfile; |
| 208 | final boolean mSupprNoisy; |
| 209 | final int mVolume; |
| 210 | |
| 211 | BtDeviceConnectionInfo(@NonNull BluetoothDevice device, |
| 212 | @AudioService.BtProfileConnectionState int state, |
| 213 | int profile, boolean suppressNoisyIntent, int vol) { |
| 214 | mDevice = device; |
| 215 | mState = state; |
| 216 | mProfile = profile; |
| 217 | mSupprNoisy = suppressNoisyIntent; |
| 218 | mVolume = vol; |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent( |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 223 | @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, |
| 224 | int profile, boolean suppressNoisyIntent, int a2dpVolume) { |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 225 | final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile, |
| 226 | suppressNoisyIntent, a2dpVolume); |
| 227 | |
| 228 | // TODO add a check to try to remove unprocessed messages for the same device (the old |
| 229 | // check didn't work), and make sure it doesn't conflict with config change message |
| 230 | sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info); |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | /*package*/ int handleBluetoothA2dpActiveDeviceChange( |
| 234 | @NonNull BluetoothDevice device, |
| 235 | @AudioService.BtProfileConnectionState int state, int profile, |
| 236 | boolean suppressNoisyIntent, int a2dpVolume) { |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 237 | // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior |
| 238 | // of handleBluetoothA2dpDeviceConfigChange and |
| 239 | // setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 240 | synchronized (mDeviceStateLock) { |
| 241 | return mDeviceInventory.handleBluetoothA2dpActiveDeviceChange(device, state, profile, |
| 242 | suppressNoisyIntent, a2dpVolume); |
| 243 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 244 | } |
| 245 | |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 246 | private static final class HearingAidDeviceConnectionInfo { |
| 247 | final @NonNull BluetoothDevice mDevice; |
| 248 | final @AudioService.BtProfileConnectionState int mState; |
| 249 | final boolean mSupprNoisy; |
| 250 | final int mMusicDevice; |
| 251 | final @NonNull String mEventSource; |
| 252 | |
| 253 | HearingAidDeviceConnectionInfo(@NonNull BluetoothDevice device, |
| 254 | @AudioService.BtProfileConnectionState int state, |
| 255 | boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) { |
| 256 | mDevice = device; |
| 257 | mState = state; |
| 258 | mSupprNoisy = suppressNoisyIntent; |
| 259 | mMusicDevice = musicDevice; |
| 260 | mEventSource = eventSource; |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | /*package*/ void postBluetoothHearingAidDeviceConnectionState( |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 265 | @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state, |
| 266 | boolean suppressNoisyIntent, int musicDevice, @NonNull String eventSource) { |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 267 | final HearingAidDeviceConnectionInfo info = new HearingAidDeviceConnectionInfo( |
| 268 | device, state, suppressNoisyIntent, musicDevice, eventSource); |
| 269 | sendLMsgNoDelay(MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info); |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | // never called by system components |
| 273 | /*package*/ void setBluetoothScoOnByApp(boolean on) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 274 | synchronized (mDeviceStateLock) { |
| 275 | mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; |
| 276 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 277 | } |
| 278 | |
| 279 | /*package*/ boolean isBluetoothScoOnForApp() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 280 | synchronized (mDeviceStateLock) { |
| 281 | return mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO; |
| 282 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 283 | } |
| 284 | |
| 285 | /*package*/ void setBluetoothScoOn(boolean on, String eventSource) { |
| 286 | //Log.i(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource); |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 287 | synchronized (mDeviceStateLock) { |
| 288 | if (on) { |
| 289 | // do not accept SCO ON if SCO audio is not connected |
| 290 | if (!mBtHelper.isBluetoothScoOn()) { |
| 291 | mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; |
| 292 | return; |
| 293 | } |
| 294 | mForcedUseForComm = AudioSystem.FORCE_BT_SCO; |
| 295 | } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { |
| 296 | mForcedUseForComm = AudioSystem.FORCE_NONE; |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 297 | } |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 298 | mForcedUseForCommExt = mForcedUseForComm; |
| 299 | AudioSystem.setParameters("BT_SCO=" + (on ? "on" : "off")); |
| 300 | sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, |
| 301 | AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource); |
| 302 | sendIILMsgNoDelay(MSG_IIL_SET_FORCE_USE, SENDMSG_QUEUE, |
| 303 | AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource); |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 304 | } |
Jean-Michel Trivi | ca49d31 | 2019-02-14 15:55:39 -0800 | [diff] [blame] | 305 | // Un-mute ringtone stream volume |
| 306 | mAudioService.postUpdateRingerModeServiceInt(); |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 307 | } |
| 308 | |
| 309 | /*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 310 | synchronized (mDeviceStateLock) { |
| 311 | return mDeviceInventory.startWatchingRoutes(observer); |
| 312 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 313 | } |
| 314 | |
| 315 | /*package*/ AudioRoutesInfo getCurAudioRoutes() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 316 | synchronized (mDeviceStateLock) { |
| 317 | return mDeviceInventory.getCurAudioRoutes(); |
| 318 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 319 | } |
| 320 | |
| 321 | /*package*/ boolean isAvrcpAbsoluteVolumeSupported() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 322 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 323 | return mBtHelper.isAvrcpAbsoluteVolumeSupported(); |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | /*package*/ boolean isBluetoothA2dpOn() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 328 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 329 | return mBluetoothA2dpEnabled; |
| 330 | } |
| 331 | } |
| 332 | |
| 333 | /*package*/ void postSetAvrcpAbsoluteVolumeIndex(int index) { |
| 334 | sendIMsgNoDelay(MSG_I_SET_AVRCP_ABSOLUTE_VOLUME, SENDMSG_REPLACE, index); |
| 335 | } |
| 336 | |
| 337 | /*package*/ void postSetHearingAidVolumeIndex(int index, int streamType) { |
| 338 | sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType); |
| 339 | } |
| 340 | |
| 341 | /*package*/ void postDisconnectBluetoothSco(int exceptPid) { |
| 342 | sendIMsgNoDelay(MSG_I_DISCONNECT_BT_SCO, SENDMSG_REPLACE, exceptPid); |
| 343 | } |
| 344 | |
| 345 | /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) { |
| 346 | sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device); |
| 347 | } |
| 348 | |
| 349 | /*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode, |
| 350 | @NonNull String eventSource) { |
| 351 | mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource); |
| 352 | } |
| 353 | |
| 354 | /*package*/ void stopBluetoothScoForClient_Sync(IBinder cb, @NonNull String eventSource) { |
| 355 | mBtHelper.stopBluetoothScoForClient(cb, eventSource); |
| 356 | } |
| 357 | |
| 358 | //--------------------------------------------------------------------- |
| 359 | // Communication with (to) AudioService |
| 360 | //TODO check whether the AudioService methods are candidates to move here |
| 361 | /*package*/ void postAccessoryPlugMediaUnmute(int device) { |
| 362 | mAudioService.postAccessoryPlugMediaUnmute(device); |
| 363 | } |
| 364 | |
| 365 | /*package*/ AudioService.VolumeStreamState getStreamState(int streamType) { |
| 366 | return mAudioService.getStreamState(streamType); |
| 367 | } |
| 368 | |
| 369 | /*package*/ ArrayList<AudioService.SetModeDeathHandler> getSetModeDeathHandlers() { |
| 370 | return mAudioService.mSetModeDeathHandlers; |
| 371 | } |
| 372 | |
| 373 | /*package*/ int getDeviceForStream(int streamType) { |
| 374 | return mAudioService.getDeviceForStream(streamType); |
| 375 | } |
| 376 | |
| 377 | /*package*/ void setDeviceVolume(AudioService.VolumeStreamState streamState, int device) { |
| 378 | mAudioService.setDeviceVolume(streamState, device); |
| 379 | } |
| 380 | |
| 381 | /*packages*/ void observeDevicesForAllStreams() { |
| 382 | mAudioService.observeDevicesForAllStreams(); |
| 383 | } |
| 384 | |
| 385 | /*package*/ boolean isInCommunication() { |
| 386 | return mAudioService.isInCommunication(); |
| 387 | } |
| 388 | |
| 389 | /*package*/ boolean hasMediaDynamicPolicy() { |
| 390 | return mAudioService.hasMediaDynamicPolicy(); |
| 391 | } |
| 392 | |
| 393 | /*package*/ ContentResolver getContentResolver() { |
| 394 | return mAudioService.getContentResolver(); |
| 395 | } |
| 396 | |
| 397 | /*package*/ void checkMusicActive(int deviceType, String caller) { |
| 398 | mAudioService.checkMusicActive(deviceType, caller); |
| 399 | } |
| 400 | |
| 401 | /*package*/ void checkVolumeCecOnHdmiConnection(int state, String caller) { |
| 402 | mAudioService.checkVolumeCecOnHdmiConnection(state, caller); |
| 403 | } |
| 404 | |
| 405 | //--------------------------------------------------------------------- |
| 406 | // Message handling on behalf of helper classes |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 407 | /*package*/ void postBroadcastScoConnectionState(int state) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 408 | sendIMsgNoDelay(MSG_I_BROADCAST_BT_CONNECTION_STATE, SENDMSG_QUEUE, state); |
| 409 | } |
| 410 | |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 411 | /*package*/ void postBroadcastBecomingNoisy() { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 412 | sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE); |
| 413 | } |
| 414 | |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 415 | /*package*/ void postA2dpSinkConnection(int state, |
| 416 | @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { |
| 417 | sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE, |
| 418 | state, btDeviceInfo, delay); |
| 419 | } |
| 420 | |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 421 | /*package*/ void postA2dpSourceConnection(int state, |
| 422 | @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) { |
| 423 | sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, |
| 424 | state, btDeviceInfo, delay); |
| 425 | } |
| 426 | |
| 427 | /*package*/ void postSetWiredDeviceConnectionState( |
| 428 | AudioDeviceInventory.WiredDeviceConnectionState connectionState, int delay) { |
| 429 | sendLMsg(MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE, SENDMSG_QUEUE, connectionState, delay); |
| 430 | } |
| 431 | |
| 432 | /*package*/ void postSetHearingAidConnectionState( |
| 433 | @AudioService.BtProfileConnectionState int state, |
| 434 | @NonNull BluetoothDevice device, int delay) { |
| 435 | sendILMsg(MSG_IL_SET_HEARING_AID_CONNECTION_STATE, SENDMSG_QUEUE, |
| 436 | state, |
| 437 | device, |
| 438 | delay); |
| 439 | } |
| 440 | |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 441 | /*package*/ void postDisconnectA2dp() { |
| 442 | sendMsgNoDelay(MSG_DISCONNECT_A2DP, SENDMSG_QUEUE); |
| 443 | } |
| 444 | |
| 445 | /*package*/ void postDisconnectA2dpSink() { |
| 446 | sendMsgNoDelay(MSG_DISCONNECT_A2DP_SINK, SENDMSG_QUEUE); |
| 447 | } |
| 448 | |
| 449 | /*package*/ void postDisconnectHearingAid() { |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 450 | sendMsgNoDelay(MSG_DISCONNECT_BT_HEARING_AID, SENDMSG_QUEUE); |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 451 | } |
| 452 | |
| 453 | /*package*/ void postDisconnectHeadset() { |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 454 | sendMsgNoDelay(MSG_DISCONNECT_BT_HEADSET, SENDMSG_QUEUE); |
| 455 | } |
| 456 | |
| 457 | /*package*/ void postBtA2dpProfileConnected(BluetoothA2dp a2dpProfile) { |
| 458 | sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP, SENDMSG_QUEUE, a2dpProfile); |
| 459 | } |
| 460 | |
| 461 | /*package*/ void postBtA2dpSinkProfileConnected(BluetoothProfile profile) { |
| 462 | sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK, SENDMSG_QUEUE, profile); |
| 463 | } |
| 464 | |
| 465 | /*package*/ void postBtHeasetProfileConnected(BluetoothHeadset headsetProfile) { |
| 466 | sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET, SENDMSG_QUEUE, headsetProfile); |
| 467 | } |
| 468 | |
| 469 | /*package*/ void postBtHearingAidProfileConnected(BluetoothHearingAid hearingAidProfile) { |
| 470 | sendLMsgNoDelay(MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID, SENDMSG_QUEUE, |
| 471 | hearingAidProfile); |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 472 | } |
| 473 | |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 474 | //--------------------------------------------------------------------- |
| 475 | // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) |
| 476 | // only call from a "handle"* method or "on"* method |
| 477 | |
| 478 | // Handles request to override default use of A2DP for media. |
| 479 | //@GuardedBy("mConnectedDevices") |
| 480 | /*package*/ void setBluetoothA2dpOnInt(boolean on, String source) { |
| 481 | // for logging only |
| 482 | final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on) |
| 483 | .append(") from u/pid:").append(Binder.getCallingUid()).append("/") |
| 484 | .append(Binder.getCallingPid()).append(" src:").append(source).toString(); |
| 485 | |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 486 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 487 | mBluetoothA2dpEnabled = on; |
| 488 | mBrokerHandler.removeMessages(MSG_IIL_SET_FORCE_BT_A2DP_USE); |
| 489 | onSetForceUse( |
| 490 | AudioSystem.FOR_MEDIA, |
| 491 | mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, |
| 492 | eventSource); |
| 493 | } |
| 494 | } |
| 495 | |
| 496 | /*package*/ boolean handleDeviceConnection(boolean connect, int device, String address, |
| 497 | String deviceName) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 498 | synchronized (mDeviceStateLock) { |
| 499 | return mDeviceInventory.handleDeviceConnection(connect, device, address, deviceName); |
| 500 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 501 | } |
| 502 | |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 503 | @GuardedBy("mDeviceStateLock") |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 504 | /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state, |
| 505 | @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 506 | final int intState = (state == BluetoothA2dp.STATE_CONNECTED) |
| 507 | ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED; |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 508 | final int delay = mDeviceInventory.checkSendBecomingNoisyIntent( |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 509 | AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState, |
| 510 | AudioSystem.DEVICE_NONE); |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 511 | final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress(); |
| 512 | |
| 513 | if (AudioService.DEBUG_DEVICES) { |
| 514 | Log.d(TAG, "handleSetA2dpSinkConnectionState btDevice= " + btDeviceInfo |
| 515 | + " state= " + state |
| 516 | + " is dock: " + btDeviceInfo.getBtDevice().isBluetoothDock()); |
| 517 | } |
| 518 | sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE, |
| 519 | state, btDeviceInfo, delay); |
| 520 | } |
| 521 | |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 522 | /*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state, |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 523 | @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { |
| 524 | final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0; |
| 525 | sendILMsgNoDelay(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE, state, |
| 526 | btDeviceInfo); |
| 527 | } |
| 528 | |
| 529 | /*package*/ void handleFailureToConnectToBtHeadsetService(int delay) { |
| 530 | sendMsg(MSG_BT_HEADSET_CNCT_FAILED, SENDMSG_REPLACE, delay); |
| 531 | } |
| 532 | |
| 533 | /*package*/ void handleCancelFailureToConnectToBtHeadsetService() { |
| 534 | mBrokerHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); |
| 535 | } |
| 536 | |
| 537 | /*package*/ void postReportNewRoutes() { |
| 538 | sendMsgNoDelay(MSG_REPORT_NEW_ROUTES, SENDMSG_NOOP); |
| 539 | } |
| 540 | |
| 541 | /*package*/ void cancelA2dpDockTimeout() { |
| 542 | mBrokerHandler.removeMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT); |
| 543 | } |
| 544 | |
| 545 | /*package*/ void postA2dpActiveDeviceChange(BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) { |
| 546 | sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE, SENDMSG_QUEUE, btDeviceInfo); |
| 547 | } |
| 548 | |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 549 | /*package*/ boolean hasScheduledA2dpDockTimeout() { |
| 550 | return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT); |
| 551 | } |
| 552 | |
| 553 | //### |
| 554 | // must be called synchronized on mConnectedDevices |
| 555 | /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) { |
| 556 | return mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, |
| 557 | new BtHelper.BluetoothA2dpDeviceInfo(btDevice)); |
| 558 | } |
| 559 | |
| 560 | /*package*/ void setA2dpDockTimeout(String address, int a2dpCodec, int delayMs) { |
| 561 | sendILMsg(MSG_IL_BTA2DP_DOCK_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs); |
| 562 | } |
| 563 | |
| 564 | /*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 565 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 566 | mBtHelper.setAvrcpAbsoluteVolumeSupported(supported); |
| 567 | } |
| 568 | } |
| 569 | |
| 570 | /*package*/ boolean getBluetoothA2dpEnabled() { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 571 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 572 | return mBluetoothA2dpEnabled; |
| 573 | } |
| 574 | } |
| 575 | |
| 576 | /*package*/ int getA2dpCodec(@NonNull BluetoothDevice device) { |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 577 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 578 | return mBtHelper.getA2dpCodec(device); |
| 579 | } |
| 580 | } |
| 581 | |
| 582 | //--------------------------------------------------------------------- |
| 583 | // Internal handling of messages |
| 584 | // These methods are ALL synchronous, in response to message handling in BrokerHandler |
| 585 | // Blocking in any of those will block the message queue |
| 586 | |
| 587 | private void onSetForceUse(int useCase, int config, String eventSource) { |
| 588 | if (useCase == AudioSystem.FOR_MEDIA) { |
| 589 | postReportNewRoutes(); |
| 590 | } |
| 591 | AudioService.sForceUseLogger.log( |
| 592 | new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource)); |
| 593 | AudioSystem.setForceUse(useCase, config); |
| 594 | } |
| 595 | |
| 596 | private void onSendBecomingNoisyIntent() { |
| 597 | AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( |
| 598 | "broadcast ACTION_AUDIO_BECOMING_NOISY")).printLog(TAG)); |
| 599 | sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); |
| 600 | } |
| 601 | |
| 602 | //--------------------------------------------------------------------- |
| 603 | // Message handling |
| 604 | private BrokerHandler mBrokerHandler; |
| 605 | private BrokerThread mBrokerThread; |
| 606 | private PowerManager.WakeLock mBrokerEventWakeLock; |
| 607 | |
| 608 | private void setupMessaging(Context ctxt) { |
| 609 | final PowerManager pm = (PowerManager) ctxt.getSystemService(Context.POWER_SERVICE); |
| 610 | mBrokerEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, |
| 611 | "handleAudioDeviceEvent"); |
| 612 | mBrokerThread = new BrokerThread(); |
| 613 | mBrokerThread.start(); |
| 614 | waitForBrokerHandlerCreation(); |
| 615 | } |
| 616 | |
| 617 | private void waitForBrokerHandlerCreation() { |
| 618 | synchronized (this) { |
| 619 | while (mBrokerHandler == null) { |
| 620 | try { |
| 621 | wait(); |
| 622 | } catch (InterruptedException e) { |
| 623 | Log.e(TAG, "Interruption while waiting on BrokerHandler"); |
| 624 | } |
| 625 | } |
| 626 | } |
| 627 | } |
| 628 | |
| 629 | /** Class that handles the device broker's message queue */ |
| 630 | private class BrokerThread extends Thread { |
| 631 | BrokerThread() { |
| 632 | super("AudioDeviceBroker"); |
| 633 | } |
| 634 | |
| 635 | @Override |
| 636 | public void run() { |
| 637 | // Set this thread up so the handler will work on it |
| 638 | Looper.prepare(); |
| 639 | |
| 640 | synchronized (AudioDeviceBroker.this) { |
| 641 | mBrokerHandler = new BrokerHandler(); |
| 642 | |
| 643 | // Notify that the handler has been created |
| 644 | AudioDeviceBroker.this.notify(); |
| 645 | } |
| 646 | |
| 647 | Looper.loop(); |
| 648 | } |
| 649 | } |
| 650 | |
| 651 | /** Class that handles the message queue */ |
| 652 | private class BrokerHandler extends Handler { |
| 653 | |
| 654 | @Override |
| 655 | public void handleMessage(Message msg) { |
| 656 | switch (msg.what) { |
| 657 | case MSG_RESTORE_DEVICES: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 658 | synchronized (mDeviceStateLock) { |
| 659 | mDeviceInventory.onRestoreDevices(); |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 660 | mBtHelper.onAudioServerDiedRestoreA2dp(); |
| 661 | } |
| 662 | break; |
| 663 | case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 664 | synchronized (mDeviceStateLock) { |
| 665 | mDeviceInventory.onSetWiredDeviceConnectionState( |
| 666 | (AudioDeviceInventory.WiredDeviceConnectionState) msg.obj); |
| 667 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 668 | break; |
| 669 | case MSG_I_BROADCAST_BT_CONNECTION_STATE: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 670 | synchronized (mDeviceStateLock) { |
| 671 | mBtHelper.onBroadcastScoConnectionState(msg.arg1); |
| 672 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 673 | break; |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 674 | case MSG_IIL_SET_FORCE_USE: // intended fall-through |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 675 | case MSG_IIL_SET_FORCE_BT_A2DP_USE: |
| 676 | onSetForceUse(msg.arg1, msg.arg2, (String) msg.obj); |
| 677 | break; |
| 678 | case MSG_REPORT_NEW_ROUTES: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 679 | synchronized (mDeviceStateLock) { |
| 680 | mDeviceInventory.onReportNewRoutes(); |
| 681 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 682 | break; |
| 683 | case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 684 | synchronized (mDeviceStateLock) { |
| 685 | mDeviceInventory.onSetA2dpSinkConnectionState( |
| 686 | (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); |
| 687 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 688 | break; |
| 689 | case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 690 | synchronized (mDeviceStateLock) { |
| 691 | mDeviceInventory.onSetA2dpSourceConnectionState( |
| 692 | (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1); |
| 693 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 694 | break; |
| 695 | case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 696 | synchronized (mDeviceStateLock) { |
| 697 | mDeviceInventory.onSetHearingAidConnectionState( |
| 698 | (BluetoothDevice) msg.obj, msg.arg1); |
| 699 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 700 | break; |
| 701 | case MSG_BT_HEADSET_CNCT_FAILED: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 702 | synchronized (mDeviceStateLock) { |
| 703 | mBtHelper.resetBluetoothSco(); |
| 704 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 705 | break; |
| 706 | case MSG_IL_BTA2DP_DOCK_TIMEOUT: |
| 707 | // msg.obj == address of BTA2DP device |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 708 | synchronized (mDeviceStateLock) { |
| 709 | mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1); |
| 710 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 711 | break; |
| 712 | case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: |
| 713 | final int a2dpCodec; |
| 714 | final BluetoothDevice btDevice = (BluetoothDevice) msg.obj; |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 715 | synchronized (mDeviceStateLock) { |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 716 | a2dpCodec = mBtHelper.getA2dpCodec(btDevice); |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 717 | mDeviceInventory.onBluetoothA2dpDeviceConfigChange( |
| 718 | new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec)); |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 719 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 720 | break; |
| 721 | case MSG_BROADCAST_AUDIO_BECOMING_NOISY: |
| 722 | onSendBecomingNoisyIntent(); |
| 723 | break; |
| 724 | case MSG_II_SET_HEARING_AID_VOLUME: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 725 | synchronized (mDeviceStateLock) { |
| 726 | mBtHelper.setHearingAidVolume(msg.arg1, msg.arg2); |
| 727 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 728 | break; |
| 729 | case MSG_I_SET_AVRCP_ABSOLUTE_VOLUME: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 730 | synchronized (mDeviceStateLock) { |
| 731 | mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); |
| 732 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 733 | break; |
| 734 | case MSG_I_DISCONNECT_BT_SCO: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 735 | synchronized (mDeviceStateLock) { |
| 736 | mBtHelper.disconnectBluetoothSco(msg.arg1); |
| 737 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 738 | break; |
| 739 | case MSG_TOGGLE_HDMI: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 740 | synchronized (mDeviceStateLock) { |
| 741 | mDeviceInventory.onToggleHdmi(); |
| 742 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 743 | break; |
| 744 | case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: |
Jean-Michel Trivi | c4b9c96 | 2019-02-01 09:58:54 -0800 | [diff] [blame] | 745 | synchronized (mDeviceStateLock) { |
| 746 | mDeviceInventory.onBluetoothA2dpActiveDeviceChange( |
| 747 | (BtHelper.BluetoothA2dpDeviceInfo) msg.obj); |
| 748 | } |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 749 | break; |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 750 | case MSG_DISCONNECT_A2DP: |
| 751 | synchronized (mDeviceStateLock) { |
| 752 | mDeviceInventory.disconnectA2dp(); |
| 753 | } |
| 754 | break; |
| 755 | case MSG_DISCONNECT_A2DP_SINK: |
| 756 | synchronized (mDeviceStateLock) { |
| 757 | mDeviceInventory.disconnectA2dpSink(); |
| 758 | } |
| 759 | break; |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 760 | case MSG_DISCONNECT_BT_HEARING_AID: |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 761 | synchronized (mDeviceStateLock) { |
| 762 | mDeviceInventory.disconnectHearingAid(); |
| 763 | } |
| 764 | break; |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 765 | case MSG_DISCONNECT_BT_HEADSET: |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 766 | synchronized (mDeviceStateLock) { |
| 767 | mBtHelper.disconnectHeadset(); |
| 768 | } |
| 769 | break; |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 770 | case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP: |
| 771 | synchronized (mDeviceStateLock) { |
| 772 | mBtHelper.onA2dpProfileConnected((BluetoothA2dp) msg.obj); |
| 773 | } |
| 774 | break; |
| 775 | case MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK: |
| 776 | synchronized (mDeviceStateLock) { |
| 777 | mBtHelper.onA2dpSinkProfileConnected((BluetoothProfile) msg.obj); |
| 778 | } |
| 779 | break; |
| 780 | case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID: |
| 781 | synchronized (mDeviceStateLock) { |
| 782 | mBtHelper.onHearingAidProfileConnected((BluetoothHearingAid) msg.obj); |
| 783 | } |
| 784 | break; |
| 785 | case MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET: |
| 786 | synchronized (mDeviceStateLock) { |
| 787 | mBtHelper.onHeadsetProfileConnected((BluetoothHeadset) msg.obj); |
| 788 | } |
| 789 | break; |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 790 | case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: { |
| 791 | final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj; |
| 792 | AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( |
| 793 | "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent " |
| 794 | + " state=" + info.mState |
| 795 | // only querying address as this is the only readily available |
| 796 | // field on the device |
| 797 | + " addr=" + info.mDevice.getAddress() |
| 798 | + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy |
| 799 | + " vol=" + info.mVolume)).printLog(TAG)); |
| 800 | synchronized (mDeviceStateLock) { |
| 801 | mDeviceInventory.setBluetoothA2dpDeviceConnectionState( |
| 802 | info.mDevice, info.mState, info.mProfile, info.mSupprNoisy, |
| 803 | AudioSystem.DEVICE_NONE, info.mVolume); |
| 804 | } |
| 805 | } break; |
| 806 | case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: { |
| 807 | final HearingAidDeviceConnectionInfo info = |
| 808 | (HearingAidDeviceConnectionInfo) msg.obj; |
| 809 | AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent( |
| 810 | "setHearingAidDeviceConnectionState state=" + info.mState |
| 811 | + " addr=" + info.mDevice.getAddress() |
| 812 | + " supprNoisy=" + info.mSupprNoisy |
| 813 | + " src=" + info.mEventSource)).printLog(TAG)); |
| 814 | synchronized (mDeviceStateLock) { |
| 815 | mDeviceInventory.setBluetoothHearingAidDeviceConnectionState( |
| 816 | info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice); |
| 817 | } |
| 818 | } break; |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 819 | default: |
| 820 | Log.wtf(TAG, "Invalid message " + msg.what); |
| 821 | } |
| 822 | if (isMessageHandledUnderWakelock(msg.what)) { |
| 823 | try { |
| 824 | mBrokerEventWakeLock.release(); |
| 825 | } catch (Exception e) { |
| 826 | Log.e(TAG, "Exception releasing wakelock", e); |
| 827 | } |
| 828 | } |
| 829 | } |
| 830 | } |
| 831 | |
| 832 | // List of all messages. If a message has be handled under wakelock, add it to |
| 833 | // the isMessageHandledUnderWakelock(int) method |
| 834 | // Naming of msg indicates arguments, using JNI argument grammar |
| 835 | // (e.g. II indicates two int args, IL indicates int and Obj arg) |
| 836 | private static final int MSG_RESTORE_DEVICES = 1; |
| 837 | private static final int MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE = 2; |
| 838 | private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3; |
| 839 | private static final int MSG_IIL_SET_FORCE_USE = 4; |
| 840 | private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5; |
| 841 | private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE = 6; |
| 842 | private static final int MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE = 7; |
| 843 | private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8; |
| 844 | private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; |
| 845 | private static final int MSG_IL_BTA2DP_DOCK_TIMEOUT = 10; |
| 846 | private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11; |
| 847 | private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12; |
| 848 | private static final int MSG_REPORT_NEW_ROUTES = 13; |
| 849 | private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; |
| 850 | private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; |
| 851 | private static final int MSG_I_DISCONNECT_BT_SCO = 16; |
| 852 | private static final int MSG_TOGGLE_HDMI = 17; |
| 853 | private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18; |
Jean-Michel Trivi | b946515 | 2019-02-06 15:20:19 -0800 | [diff] [blame] | 854 | private static final int MSG_DISCONNECT_A2DP = 19; |
| 855 | private static final int MSG_DISCONNECT_A2DP_SINK = 20; |
Jean-Michel Trivi | 43ff4f3 | 2019-02-07 12:08:39 -0800 | [diff] [blame] | 856 | private static final int MSG_DISCONNECT_BT_HEARING_AID = 21; |
| 857 | private static final int MSG_DISCONNECT_BT_HEADSET = 22; |
| 858 | private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP = 23; |
| 859 | private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24; |
| 860 | private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25; |
| 861 | private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26; |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 862 | // process external command to (dis)connect an A2DP device |
| 863 | private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27; |
| 864 | // process external command to (dis)connect a hearing aid device |
| 865 | private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28; |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 866 | |
| 867 | |
| 868 | private static boolean isMessageHandledUnderWakelock(int msgId) { |
| 869 | switch(msgId) { |
| 870 | case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: |
| 871 | case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE: |
| 872 | case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: |
| 873 | case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: |
| 874 | case MSG_IL_BTA2DP_DOCK_TIMEOUT: |
| 875 | case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: |
| 876 | case MSG_TOGGLE_HDMI: |
| 877 | case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: |
Jean-Michel Trivi | fc86cfa | 2019-03-01 10:15:47 -0800 | [diff] [blame] | 878 | case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: |
| 879 | case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT: |
Jean-Michel Trivi | 5885037 | 2018-09-14 16:01:28 -0700 | [diff] [blame] | 880 | return true; |
| 881 | default: |
| 882 | return false; |
| 883 | } |
| 884 | } |
| 885 | |
| 886 | // Message helper methods |
| 887 | |
| 888 | // sendMsg() flags |
| 889 | /** If the msg is already queued, replace it with this one. */ |
| 890 | private static final int SENDMSG_REPLACE = 0; |
| 891 | /** If the msg is already queued, ignore this one and leave the old. */ |
| 892 | private static final int SENDMSG_NOOP = 1; |
| 893 | /** If the msg is already queued, queue this one and leave the old. */ |
| 894 | private static final int SENDMSG_QUEUE = 2; |
| 895 | |
| 896 | private void sendMsg(int msg, int existingMsgPolicy, int delay) { |
| 897 | sendIILMsg(msg, existingMsgPolicy, 0, 0, null, delay); |
| 898 | } |
| 899 | |
| 900 | private void sendILMsg(int msg, int existingMsgPolicy, int arg, Object obj, int delay) { |
| 901 | sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, delay); |
| 902 | } |
| 903 | |
| 904 | private void sendLMsg(int msg, int existingMsgPolicy, Object obj, int delay) { |
| 905 | sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, delay); |
| 906 | } |
| 907 | |
| 908 | private void sendIMsg(int msg, int existingMsgPolicy, int arg, int delay) { |
| 909 | sendIILMsg(msg, existingMsgPolicy, arg, 0, null, delay); |
| 910 | } |
| 911 | |
| 912 | private void sendMsgNoDelay(int msg, int existingMsgPolicy) { |
| 913 | sendIILMsg(msg, existingMsgPolicy, 0, 0, null, 0); |
| 914 | } |
| 915 | |
| 916 | private void sendIMsgNoDelay(int msg, int existingMsgPolicy, int arg) { |
| 917 | sendIILMsg(msg, existingMsgPolicy, arg, 0, null, 0); |
| 918 | } |
| 919 | |
| 920 | private void sendIIMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2) { |
| 921 | sendIILMsg(msg, existingMsgPolicy, arg1, arg2, null, 0); |
| 922 | } |
| 923 | |
| 924 | private void sendILMsgNoDelay(int msg, int existingMsgPolicy, int arg, Object obj) { |
| 925 | sendIILMsg(msg, existingMsgPolicy, arg, 0, obj, 0); |
| 926 | } |
| 927 | |
| 928 | private void sendLMsgNoDelay(int msg, int existingMsgPolicy, Object obj) { |
| 929 | sendIILMsg(msg, existingMsgPolicy, 0, 0, obj, 0); |
| 930 | } |
| 931 | |
| 932 | private void sendIILMsgNoDelay(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj) { |
| 933 | sendIILMsg(msg, existingMsgPolicy, arg1, arg2, obj, 0); |
| 934 | } |
| 935 | |
| 936 | private void sendIILMsg(int msg, int existingMsgPolicy, int arg1, int arg2, Object obj, |
| 937 | int delay) { |
| 938 | if (existingMsgPolicy == SENDMSG_REPLACE) { |
| 939 | mBrokerHandler.removeMessages(msg); |
| 940 | } else if (existingMsgPolicy == SENDMSG_NOOP && mBrokerHandler.hasMessages(msg)) { |
| 941 | return; |
| 942 | } |
| 943 | |
| 944 | if (isMessageHandledUnderWakelock(msg)) { |
| 945 | final long identity = Binder.clearCallingIdentity(); |
| 946 | try { |
| 947 | mBrokerEventWakeLock.acquire(BROKER_WAKELOCK_TIMEOUT_MS); |
| 948 | } catch (Exception e) { |
| 949 | Log.e(TAG, "Exception acquiring wakelock", e); |
| 950 | } |
| 951 | Binder.restoreCallingIdentity(identity); |
| 952 | } |
| 953 | |
| 954 | synchronized (sLastDeviceConnectionMsgTimeLock) { |
| 955 | long time = SystemClock.uptimeMillis() + delay; |
| 956 | |
| 957 | switch (msg) { |
| 958 | case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE: |
| 959 | case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE: |
| 960 | case MSG_IL_SET_HEARING_AID_CONNECTION_STATE: |
| 961 | case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE: |
| 962 | case MSG_IL_BTA2DP_DOCK_TIMEOUT: |
| 963 | case MSG_L_A2DP_DEVICE_CONFIG_CHANGE: |
| 964 | case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE: |
| 965 | if (sLastDeviceConnectMsgTime >= time) { |
| 966 | // add a little delay to make sure messages are ordered as expected |
| 967 | time = sLastDeviceConnectMsgTime + 30; |
| 968 | } |
| 969 | sLastDeviceConnectMsgTime = time; |
| 970 | break; |
| 971 | default: |
| 972 | break; |
| 973 | } |
| 974 | |
| 975 | mBrokerHandler.sendMessageAtTime(mBrokerHandler.obtainMessage(msg, arg1, arg2, obj), |
| 976 | time); |
| 977 | } |
| 978 | } |
| 979 | |
| 980 | //------------------------------------------------------------- |
| 981 | // internal utilities |
| 982 | private void sendBroadcastToAll(Intent intent) { |
| 983 | intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); |
| 984 | intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); |
| 985 | final long ident = Binder.clearCallingIdentity(); |
| 986 | try { |
| 987 | mContext.sendBroadcastAsUser(intent, UserHandle.ALL); |
| 988 | } finally { |
| 989 | Binder.restoreCallingIdentity(ident); |
| 990 | } |
| 991 | } |
| 992 | } |