blob: e7d7ab39b6c4558875fe98150cef4b1a9caca23f [file] [log] [blame]
Jason Monk7ce96b92015-02-02 11:27:58 -05001/*
2 * Copyright (C) 2011 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
17package com.android.settingslib.bluetooth;
18
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -080019import android.bluetooth.BluetoothA2dp;
Jason Monk7ce96b92015-02-02 11:27:58 -050020import android.bluetooth.BluetoothAdapter;
21import android.bluetooth.BluetoothClass;
22import android.bluetooth.BluetoothDevice;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -080023import android.bluetooth.BluetoothHeadset;
Hansong Zhangd7b35912018-03-16 09:15:48 -070024import android.bluetooth.BluetoothHearingAid;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -080025import android.bluetooth.BluetoothProfile;
Jason Monk7ce96b92015-02-02 11:27:58 -050026import android.content.BroadcastReceiver;
27import android.content.Context;
28import android.content.Intent;
29import android.content.IntentFilter;
timhypenge745e4a2018-04-08 13:55:08 +080030import android.telephony.TelephonyManager;
Jason Monk7ce96b92015-02-02 11:27:58 -050031import android.util.Log;
32
33import com.android.settingslib.R;
34
35import java.util.ArrayList;
36import java.util.Collection;
37import java.util.HashMap;
38import java.util.Map;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -080039import java.util.Objects;
Jason Monk7ce96b92015-02-02 11:27:58 -050040import java.util.Set;
41
42/**
43 * BluetoothEventManager receives broadcasts and callbacks from the Bluetooth
44 * API and dispatches the event on the UI thread to the right class in the
45 * Settings.
46 */
Fan Zhang82dd3b02016-12-27 13:13:00 -080047public class BluetoothEventManager {
Jason Monk7ce96b92015-02-02 11:27:58 -050048 private static final String TAG = "BluetoothEventManager";
49
50 private final LocalBluetoothAdapter mLocalAdapter;
51 private final CachedBluetoothDeviceManager mDeviceManager;
52 private LocalBluetoothProfileManager mProfileManager;
53 private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter;
54 private final Map<String, Handler> mHandlerMap;
55 private Context mContext;
56
57 private final Collection<BluetoothCallback> mCallbacks =
58 new ArrayList<BluetoothCallback>();
59
Jason Monk744cf642015-05-19 12:04:41 -040060 private android.os.Handler mReceiverHandler;
61
Jason Monk7ce96b92015-02-02 11:27:58 -050062 interface Handler {
63 void onReceive(Context context, Intent intent, BluetoothDevice device);
64 }
65
Jason Monk744cf642015-05-19 12:04:41 -040066 private void addHandler(String action, Handler handler) {
Jason Monk7ce96b92015-02-02 11:27:58 -050067 mHandlerMap.put(action, handler);
68 mAdapterIntentFilter.addAction(action);
69 }
70
71 void addProfileHandler(String action, Handler handler) {
72 mHandlerMap.put(action, handler);
73 mProfileIntentFilter.addAction(action);
74 }
75
76 // Set profile manager after construction due to circular dependency
77 void setProfileManager(LocalBluetoothProfileManager manager) {
78 mProfileManager = manager;
79 }
80
81 BluetoothEventManager(LocalBluetoothAdapter adapter,
82 CachedBluetoothDeviceManager deviceManager, Context context) {
83 mLocalAdapter = adapter;
84 mDeviceManager = deviceManager;
85 mAdapterIntentFilter = new IntentFilter();
86 mProfileIntentFilter = new IntentFilter();
87 mHandlerMap = new HashMap<String, Handler>();
88 mContext = context;
89
90 // Bluetooth on/off broadcasts
91 addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());
Jason Monkbe3c5db2015-02-04 13:00:55 -050092 // Generic connected/not broadcast
93 addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED,
94 new ConnectionStateChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -050095
96 // Discovery broadcasts
97 addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
98 addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
99 addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
100 addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler());
101 addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
Jason Monk8c495be2015-06-03 16:00:24 -0400102 addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -0500103
104 // Pairing broadcasts
105 addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -0500106
107 // Fine-grained state broadcasts
108 addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
109 addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
Jack He6258aae2017-06-29 17:01:23 -0700110 addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -0500111
112 // Dock event broadcasts
113 addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler());
114
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800115 // Active device broadcasts
116 addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED,
117 new ActiveDeviceChangedHandler());
118 addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED,
119 new ActiveDeviceChangedHandler());
Hansong Zhangd7b35912018-03-16 09:15:48 -0700120 addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
121 new ActiveDeviceChangedHandler());
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800122
timhypenge745e4a2018-04-08 13:55:08 +0800123 // Headset state changed broadcasts
124 addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
125 new AudioModeChangedHandler());
126 addHandler(TelephonyManager.ACTION_PHONE_STATE_CHANGED,
127 new AudioModeChangedHandler());
128
Jason Monk744cf642015-05-19 12:04:41 -0400129 mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter, null, mReceiverHandler);
Manu Viswanadhand1992952016-10-25 20:38:23 +0530130 mContext.registerReceiver(mProfileBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler);
Jason Monk7ce96b92015-02-02 11:27:58 -0500131 }
132
133 void registerProfileIntentReceiver() {
Manu Viswanadhand1992952016-10-25 20:38:23 +0530134 mContext.registerReceiver(mProfileBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler);
Jason Monk744cf642015-05-19 12:04:41 -0400135 }
136
137 public void setReceiverHandler(android.os.Handler handler) {
138 mContext.unregisterReceiver(mBroadcastReceiver);
Manu Viswanadhand1992952016-10-25 20:38:23 +0530139 mContext.unregisterReceiver(mProfileBroadcastReceiver);
Jason Monk744cf642015-05-19 12:04:41 -0400140 mReceiverHandler = handler;
141 mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter, null, mReceiverHandler);
142 registerProfileIntentReceiver();
Jason Monk7ce96b92015-02-02 11:27:58 -0500143 }
144
145 /** Register to start receiving callbacks for Bluetooth events. */
146 public void registerCallback(BluetoothCallback callback) {
147 synchronized (mCallbacks) {
148 mCallbacks.add(callback);
149 }
150 }
151
152 /** Unregister to stop receiving callbacks for Bluetooth events. */
153 public void unregisterCallback(BluetoothCallback callback) {
154 synchronized (mCallbacks) {
155 mCallbacks.remove(callback);
156 }
157 }
158
159 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
160 @Override
161 public void onReceive(Context context, Intent intent) {
162 String action = intent.getAction();
163 BluetoothDevice device = intent
164 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
165
166 Handler handler = mHandlerMap.get(action);
167 if (handler != null) {
168 handler.onReceive(context, intent, device);
169 }
170 }
171 };
172
Manu Viswanadhand1992952016-10-25 20:38:23 +0530173 private final BroadcastReceiver mProfileBroadcastReceiver = new BroadcastReceiver() {
174 @Override
175 public void onReceive(Context context, Intent intent) {
176 String action = intent.getAction();
177 BluetoothDevice device = intent
178 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
179
180 Handler handler = mHandlerMap.get(action);
181 if (handler != null) {
182 handler.onReceive(context, intent, device);
183 }
184 }
185 };
186
Jason Monk7ce96b92015-02-02 11:27:58 -0500187 private class AdapterStateChangedHandler implements Handler {
188 public void onReceive(Context context, Intent intent,
189 BluetoothDevice device) {
190 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
191 BluetoothAdapter.ERROR);
Manu Viswanadhand1992952016-10-25 20:38:23 +0530192 // Reregister Profile Broadcast Receiver as part of TURN OFF
193 if (state == BluetoothAdapter.STATE_OFF)
194 {
195 context.unregisterReceiver(mProfileBroadcastReceiver);
196 registerProfileIntentReceiver();
197 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500198 // update local profiles and get paired devices
199 mLocalAdapter.setBluetoothStateInt(state);
200 // send callback to update UI and possibly start scanning
201 synchronized (mCallbacks) {
202 for (BluetoothCallback callback : mCallbacks) {
203 callback.onBluetoothStateChanged(state);
204 }
205 }
206 // Inform CachedDeviceManager that the adapter state has changed
207 mDeviceManager.onBluetoothStateChanged(state);
208 }
209 }
210
211 private class ScanningStateChangedHandler implements Handler {
212 private final boolean mStarted;
213
214 ScanningStateChangedHandler(boolean started) {
215 mStarted = started;
216 }
217 public void onReceive(Context context, Intent intent,
218 BluetoothDevice device) {
219 synchronized (mCallbacks) {
220 for (BluetoothCallback callback : mCallbacks) {
221 callback.onScanningStateChanged(mStarted);
222 }
223 }
224 mDeviceManager.onScanningStateChanged(mStarted);
225 }
226 }
227
228 private class DeviceFoundHandler implements Handler {
229 public void onReceive(Context context, Intent intent,
230 BluetoothDevice device) {
231 short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
232 BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
233 String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
234 // TODO Pick up UUID. They should be available for 2.1 devices.
235 // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
236 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
237 if (cachedDevice == null) {
238 cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
239 Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
240 + cachedDevice);
Jason Monk7ce96b92015-02-02 11:27:58 -0500241 }
242 cachedDevice.setRssi(rssi);
243 cachedDevice.setBtClass(btClass);
244 cachedDevice.setNewName(name);
Jack He51520472017-07-24 12:30:08 -0700245 cachedDevice.setJustDiscovered(true);
Jason Monk7ce96b92015-02-02 11:27:58 -0500246 }
247 }
248
Jason Monkbe3c5db2015-02-04 13:00:55 -0500249 private class ConnectionStateChangedHandler implements Handler {
250 @Override
251 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
252 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
253 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
254 BluetoothAdapter.ERROR);
255 dispatchConnectionStateChanged(cachedDevice, state);
256 }
257 }
258
259 private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
260 synchronized (mCallbacks) {
261 for (BluetoothCallback callback : mCallbacks) {
262 callback.onConnectionStateChanged(cachedDevice, state);
263 }
264 }
265 }
266
267 void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
Jason Monk7ce96b92015-02-02 11:27:58 -0500268 synchronized (mCallbacks) {
269 for (BluetoothCallback callback : mCallbacks) {
270 callback.onDeviceAdded(cachedDevice);
271 }
272 }
273 }
274
Isha Bobrac3d94132018-02-08 16:04:36 -0800275 void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
276 synchronized (mCallbacks) {
277 for (BluetoothCallback callback : mCallbacks) {
278 callback.onDeviceDeleted(cachedDevice);
279 }
280 }
281 }
282
Jason Monk7ce96b92015-02-02 11:27:58 -0500283 private class DeviceDisappearedHandler implements Handler {
284 public void onReceive(Context context, Intent intent,
285 BluetoothDevice device) {
286 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
287 if (cachedDevice == null) {
288 Log.w(TAG, "received ACTION_DISAPPEARED for an unknown device: " + device);
289 return;
290 }
291 if (CachedBluetoothDeviceManager.onDeviceDisappeared(cachedDevice)) {
292 synchronized (mCallbacks) {
293 for (BluetoothCallback callback : mCallbacks) {
294 callback.onDeviceDeleted(cachedDevice);
295 }
296 }
297 }
298 }
299 }
300
301 private class NameChangedHandler implements Handler {
302 public void onReceive(Context context, Intent intent,
303 BluetoothDevice device) {
304 mDeviceManager.onDeviceNameUpdated(device);
305 }
306 }
307
308 private class BondStateChangedHandler implements Handler {
309 public void onReceive(Context context, Intent intent,
310 BluetoothDevice device) {
311 if (device == null) {
312 Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
313 return;
314 }
315 int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
316 BluetoothDevice.ERROR);
317 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
318 if (cachedDevice == null) {
319 Log.w(TAG, "CachedBluetoothDevice for device " + device +
320 " not found, calling readPairedDevices().");
Jakub Pawlowski3eb490f2016-07-18 09:18:09 -0700321 if (readPairedDevices()) {
322 cachedDevice = mDeviceManager.findDevice(device);
Jason Monk7ce96b92015-02-02 11:27:58 -0500323 }
Jakub Pawlowski3eb490f2016-07-18 09:18:09 -0700324
Jason Monk7ce96b92015-02-02 11:27:58 -0500325 if (cachedDevice == null) {
Jakub Pawlowski3eb490f2016-07-18 09:18:09 -0700326 Log.w(TAG, "Got bonding state changed for " + device +
327 ", but we have no record of that device.");
328
329 cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
330 dispatchDeviceAdded(cachedDevice);
Jason Monk7ce96b92015-02-02 11:27:58 -0500331 }
332 }
333
334 synchronized (mCallbacks) {
335 for (BluetoothCallback callback : mCallbacks) {
336 callback.onDeviceBondStateChanged(cachedDevice, bondState);
337 }
338 }
339 cachedDevice.onBondingStateChanged(bondState);
340
341 if (bondState == BluetoothDevice.BOND_NONE) {
Isha Bobrac3d94132018-02-08 16:04:36 -0800342 /* Check if we need to remove other Hearing Aid devices */
343 if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
344 mDeviceManager.onDeviceUnpaired(cachedDevice);
345 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500346 int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
347 BluetoothDevice.ERROR);
348
349 showUnbondMessage(context, cachedDevice.getName(), reason);
350 }
351 }
352
353 /**
354 * Called when we have reached the unbonded state.
355 *
356 * @param reason one of the error reasons from
357 * BluetoothDevice.UNBOND_REASON_*
358 */
359 private void showUnbondMessage(Context context, String name, int reason) {
360 int errorMsg;
361
362 switch(reason) {
363 case BluetoothDevice.UNBOND_REASON_AUTH_FAILED:
364 errorMsg = R.string.bluetooth_pairing_pin_error_message;
365 break;
366 case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED:
367 errorMsg = R.string.bluetooth_pairing_rejected_error_message;
368 break;
369 case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN:
370 errorMsg = R.string.bluetooth_pairing_device_down_error_message;
371 break;
372 case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS:
373 case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT:
374 case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS:
375 case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED:
376 errorMsg = R.string.bluetooth_pairing_error_message;
377 break;
378 default:
379 Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason);
380 return;
381 }
382 Utils.showError(context, name, errorMsg);
383 }
384 }
385
386 private class ClassChangedHandler implements Handler {
387 public void onReceive(Context context, Intent intent,
388 BluetoothDevice device) {
389 mDeviceManager.onBtClassChanged(device);
390 }
391 }
392
393 private class UuidChangedHandler implements Handler {
394 public void onReceive(Context context, Intent intent,
395 BluetoothDevice device) {
396 mDeviceManager.onUuidChanged(device);
397 }
398 }
399
Jason Monk7ce96b92015-02-02 11:27:58 -0500400 private class DockEventHandler implements Handler {
401 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
402 // Remove if unpair device upon undocking
403 int anythingButUnDocked = Intent.EXTRA_DOCK_STATE_UNDOCKED + 1;
404 int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, anythingButUnDocked);
405 if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
406 if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) {
407 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
408 if (cachedDevice != null) {
Jack He51520472017-07-24 12:30:08 -0700409 cachedDevice.setJustDiscovered(false);
Jason Monk7ce96b92015-02-02 11:27:58 -0500410 }
411 }
412 }
413 }
414 }
Jack He6258aae2017-06-29 17:01:23 -0700415
416 private class BatteryLevelChangedHandler implements Handler {
417 public void onReceive(Context context, Intent intent,
418 BluetoothDevice device) {
419 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
420 if (cachedDevice != null) {
421 cachedDevice.refresh();
422 }
423 }
424 }
425
Jason Monk7ce96b92015-02-02 11:27:58 -0500426 boolean readPairedDevices() {
427 Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices();
428 if (bondedDevices == null) {
429 return false;
430 }
431
432 boolean deviceAdded = false;
433 for (BluetoothDevice device : bondedDevices) {
434 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
435 if (cachedDevice == null) {
436 cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
437 dispatchDeviceAdded(cachedDevice);
438 deviceAdded = true;
439 }
440 }
441
442 return deviceAdded;
443 }
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800444
445 private class ActiveDeviceChangedHandler implements Handler {
446 @Override
447 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
448 String action = intent.getAction();
449 if (action == null) {
450 Log.w(TAG, "ActiveDeviceChangedHandler: action is null");
451 return;
452 }
453 CachedBluetoothDevice activeDevice = mDeviceManager.findDevice(device);
454 int bluetoothProfile = 0;
455 if (Objects.equals(action, BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) {
456 bluetoothProfile = BluetoothProfile.A2DP;
457 } else if (Objects.equals(action, BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
458 bluetoothProfile = BluetoothProfile.HEADSET;
Hansong Zhangd7b35912018-03-16 09:15:48 -0700459 } else if (Objects.equals(action, BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED)) {
460 bluetoothProfile = BluetoothProfile.HEARING_AID;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800461 } else {
462 Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action);
463 return;
464 }
465 dispatchActiveDeviceChanged(activeDevice, bluetoothProfile);
466 }
467 }
468
469 private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
470 int bluetoothProfile) {
Pavlin Radoslavovc285d552018-02-06 16:14:00 -0800471 mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800472 synchronized (mCallbacks) {
473 for (BluetoothCallback callback : mCallbacks) {
474 callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
475 }
476 }
477 }
timhypenge745e4a2018-04-08 13:55:08 +0800478
479 private class AudioModeChangedHandler implements Handler {
480
481 @Override
482 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
483 final String action = intent.getAction();
484 if (action == null) {
485 Log.w(TAG, "AudioModeChangedHandler() action is null");
486 return;
487 }
488 dispatchAudioModeChanged();
489 }
490 }
491
492 private void dispatchAudioModeChanged() {
timhypengf0509322018-03-29 14:23:21 +0800493 mDeviceManager.dispatchAudioModeChanged();
timhypenge745e4a2018-04-08 13:55:08 +0800494 synchronized (mCallbacks) {
495 for (BluetoothCallback callback : mCallbacks) {
496 callback.onAudioModeChanged();
497 }
498 }
499 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500500}