blob: 4f18d450462d53b2f50f2a421ef9580d1465c0af [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;
Jason Monk7ce96b92015-02-02 11:27:58 -050021import android.bluetooth.BluetoothDevice;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -080022import android.bluetooth.BluetoothHeadset;
Hansong Zhangd7b35912018-03-16 09:15:48 -070023import android.bluetooth.BluetoothHearingAid;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -080024import android.bluetooth.BluetoothProfile;
Jason Monk7ce96b92015-02-02 11:27:58 -050025import android.content.BroadcastReceiver;
26import android.content.Context;
27import android.content.Intent;
28import android.content.IntentFilter;
jovanak206d6e42018-10-17 10:08:20 -070029import android.os.UserHandle;
timhypenge745e4a2018-04-08 13:55:08 +080030import android.telephony.TelephonyManager;
Jason Monk7ce96b92015-02-02 11:27:58 -050031import android.util.Log;
32
jovanak206d6e42018-10-17 10:08:20 -070033import androidx.annotation.Nullable;
34import androidx.annotation.VisibleForTesting;
35
Jason Monk7ce96b92015-02-02 11:27:58 -050036import com.android.settingslib.R;
37
38import java.util.ArrayList;
39import java.util.Collection;
40import java.util.HashMap;
41import java.util.Map;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -080042import java.util.Objects;
Jason Monk7ce96b92015-02-02 11:27:58 -050043import java.util.Set;
44
45/**
46 * BluetoothEventManager receives broadcasts and callbacks from the Bluetooth
47 * API and dispatches the event on the UI thread to the right class in the
48 * Settings.
49 */
Fan Zhang82dd3b02016-12-27 13:13:00 -080050public class BluetoothEventManager {
Jason Monk7ce96b92015-02-02 11:27:58 -050051 private static final String TAG = "BluetoothEventManager";
52
53 private final LocalBluetoothAdapter mLocalAdapter;
54 private final CachedBluetoothDeviceManager mDeviceManager;
Jason Monk7ce96b92015-02-02 11:27:58 -050055 private final IntentFilter mAdapterIntentFilter, mProfileIntentFilter;
56 private final Map<String, Handler> mHandlerMap;
jackqdyuleic8775892018-07-24 15:41:42 -070057 private final BroadcastReceiver mBroadcastReceiver = new BluetoothBroadcastReceiver();
58 private final BroadcastReceiver mProfileBroadcastReceiver = new BluetoothBroadcastReceiver();
59 private final Collection<BluetoothCallback> mCallbacks = new ArrayList<>();
Amin Shaikh947f76d2018-08-27 15:55:57 -040060 private final android.os.Handler mReceiverHandler;
jovanak206d6e42018-10-17 10:08:20 -070061 private final UserHandle mUserHandle;
Amin Shaikh947f76d2018-08-27 15:55:57 -040062 private final Context mContext;
Jason Monk744cf642015-05-19 12:04:41 -040063
Jason Monk7ce96b92015-02-02 11:27:58 -050064 interface Handler {
65 void onReceive(Context context, Intent intent, BluetoothDevice device);
66 }
67
jovanak206d6e42018-10-17 10:08:20 -070068 /**
69 * Creates BluetoothEventManager with the ability to pass in {@link UserHandle} that tells it to
70 * listen for bluetooth events for that particular userHandle.
71 *
72 * <p> If passing in userHandle that's different from the user running the process,
73 * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission is required. If
74 * userHandle passed in is {@code null}, we register event receiver for the
75 * {@code context.getUser()} handle.
76 */
Jason Monk7ce96b92015-02-02 11:27:58 -050077 BluetoothEventManager(LocalBluetoothAdapter adapter,
Amin Shaikh947f76d2018-08-27 15:55:57 -040078 CachedBluetoothDeviceManager deviceManager, Context context,
jovanak206d6e42018-10-17 10:08:20 -070079 android.os.Handler handler, @Nullable UserHandle userHandle) {
Jason Monk7ce96b92015-02-02 11:27:58 -050080 mLocalAdapter = adapter;
81 mDeviceManager = deviceManager;
82 mAdapterIntentFilter = new IntentFilter();
83 mProfileIntentFilter = new IntentFilter();
jackqdyuleic58e9762018-07-24 16:59:23 -070084 mHandlerMap = new HashMap<>();
Jason Monk7ce96b92015-02-02 11:27:58 -050085 mContext = context;
jovanak206d6e42018-10-17 10:08:20 -070086 mUserHandle = userHandle;
Amin Shaikh947f76d2018-08-27 15:55:57 -040087 mReceiverHandler = handler;
Jason Monk7ce96b92015-02-02 11:27:58 -050088
89 // Bluetooth on/off broadcasts
90 addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());
Jason Monkbe3c5db2015-02-04 13:00:55 -050091 // Generic connected/not broadcast
92 addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED,
93 new ConnectionStateChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -050094
95 // Discovery broadcasts
96 addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
97 addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
98 addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -050099 addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
Jason Monk8c495be2015-06-03 16:00:24 -0400100 addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -0500101
102 // Pairing broadcasts
103 addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -0500104
105 // Fine-grained state broadcasts
106 addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
107 addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
Jack He6258aae2017-06-29 17:01:23 -0700108 addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler());
Jason Monk7ce96b92015-02-02 11:27:58 -0500109
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800110 // Active device broadcasts
jackqdyuleic8775892018-07-24 15:41:42 -0700111 addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
112 addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
Hansong Zhangd7b35912018-03-16 09:15:48 -0700113 addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
jackqdyuleic8775892018-07-24 15:41:42 -0700114 new ActiveDeviceChangedHandler());
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800115
timhypenge745e4a2018-04-08 13:55:08 +0800116 // Headset state changed broadcasts
117 addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
118 new AudioModeChangedHandler());
119 addHandler(TelephonyManager.ACTION_PHONE_STATE_CHANGED,
120 new AudioModeChangedHandler());
121
jackqdyulei29489632018-10-30 11:27:30 -0700122 // ACL connection changed broadcasts
123 addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
124 addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());
125
jovanak206d6e42018-10-17 10:08:20 -0700126 registerAdapterIntentReceiver();
Jason Monk7ce96b92015-02-02 11:27:58 -0500127 }
128
129 /** Register to start receiving callbacks for Bluetooth events. */
130 public void registerCallback(BluetoothCallback callback) {
131 synchronized (mCallbacks) {
132 mCallbacks.add(callback);
133 }
134 }
135
136 /** Unregister to stop receiving callbacks for Bluetooth events. */
137 public void unregisterCallback(BluetoothCallback callback) {
138 synchronized (mCallbacks) {
139 mCallbacks.remove(callback);
140 }
141 }
142
jovanak206d6e42018-10-17 10:08:20 -0700143 @VisibleForTesting
jackqdyuleic58e9762018-07-24 16:59:23 -0700144 void registerProfileIntentReceiver() {
jovanak206d6e42018-10-17 10:08:20 -0700145 registerIntentReceiver(mProfileBroadcastReceiver, mProfileIntentFilter);
jackqdyuleic58e9762018-07-24 16:59:23 -0700146 }
147
jovanak206d6e42018-10-17 10:08:20 -0700148 @VisibleForTesting
149 void registerAdapterIntentReceiver() {
150 registerIntentReceiver(mBroadcastReceiver, mAdapterIntentFilter);
151 }
152
153 /**
154 * Registers the provided receiver to receive the broadcasts that correspond to the
155 * passed intent filter, in the context of the provided handler.
156 */
157 private void registerIntentReceiver(BroadcastReceiver receiver, IntentFilter filter) {
158 if (mUserHandle == null) {
159 // If userHandle has not been provided, simply call registerReceiver.
160 mContext.registerReceiver(receiver, filter, null, mReceiverHandler);
161 } else {
162 // userHandle was explicitly specified, so need to call multi-user aware API.
163 mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler);
164 }
165 }
166
167 @VisibleForTesting
jackqdyuleic58e9762018-07-24 16:59:23 -0700168 void addProfileHandler(String action, Handler handler) {
169 mHandlerMap.put(action, handler);
170 mProfileIntentFilter.addAction(action);
171 }
172
jackqdyuleic58e9762018-07-24 16:59:23 -0700173 boolean readPairedDevices() {
174 Set<BluetoothDevice> bondedDevices = mLocalAdapter.getBondedDevices();
175 if (bondedDevices == null) {
176 return false;
177 }
178
179 boolean deviceAdded = false;
180 for (BluetoothDevice device : bondedDevices) {
181 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
182 if (cachedDevice == null) {
jackqdyuleicc229492018-08-20 14:02:18 -0700183 mDeviceManager.addDevice(device);
jackqdyuleic58e9762018-07-24 16:59:23 -0700184 deviceAdded = true;
185 }
186 }
187
188 return deviceAdded;
189 }
190
191 void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
192 synchronized (mCallbacks) {
193 for (BluetoothCallback callback : mCallbacks) {
194 callback.onDeviceAdded(cachedDevice);
195 }
196 }
197 }
198
199 void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
200 synchronized (mCallbacks) {
201 for (BluetoothCallback callback : mCallbacks) {
202 callback.onDeviceDeleted(cachedDevice);
203 }
204 }
205 }
206
207 void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state,
208 int bluetoothProfile) {
209 synchronized (mCallbacks) {
210 for (BluetoothCallback callback : mCallbacks) {
211 callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
212 }
213 }
jackqdyuleic58e9762018-07-24 16:59:23 -0700214 }
215
216 private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
217 synchronized (mCallbacks) {
218 for (BluetoothCallback callback : mCallbacks) {
219 callback.onConnectionStateChanged(cachedDevice, state);
220 }
221 }
222 }
223
224 private void dispatchAudioModeChanged() {
225 mDeviceManager.dispatchAudioModeChanged();
226 synchronized (mCallbacks) {
227 for (BluetoothCallback callback : mCallbacks) {
228 callback.onAudioModeChanged();
229 }
230 }
231 }
232
233 private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
234 int bluetoothProfile) {
235 mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
236 synchronized (mCallbacks) {
237 for (BluetoothCallback callback : mCallbacks) {
238 callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
239 }
240 }
241 }
242
jackqdyulei29489632018-10-30 11:27:30 -0700243 private void dispatchAclStateChanged(CachedBluetoothDevice activeDevice,
244 int state) {
245 synchronized (mCallbacks) {
246 for (BluetoothCallback callback : mCallbacks) {
247 callback.onAclConnectionStateChanged(activeDevice, state);
248 }
249 }
250 }
251
jovanak206d6e42018-10-17 10:08:20 -0700252 @VisibleForTesting
253 void addHandler(String action, Handler handler) {
jackqdyuleic58e9762018-07-24 16:59:23 -0700254 mHandlerMap.put(action, handler);
255 mAdapterIntentFilter.addAction(action);
256 }
257
jackqdyuleic8775892018-07-24 15:41:42 -0700258 private class BluetoothBroadcastReceiver extends BroadcastReceiver {
Jason Monk7ce96b92015-02-02 11:27:58 -0500259 @Override
260 public void onReceive(Context context, Intent intent) {
261 String action = intent.getAction();
262 BluetoothDevice device = intent
263 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
264
265 Handler handler = mHandlerMap.get(action);
266 if (handler != null) {
267 handler.onReceive(context, intent, device);
268 }
269 }
jackqdyuleic8775892018-07-24 15:41:42 -0700270 }
Manu Viswanadhand1992952016-10-25 20:38:23 +0530271
Jason Monk7ce96b92015-02-02 11:27:58 -0500272 private class AdapterStateChangedHandler implements Handler {
273 public void onReceive(Context context, Intent intent,
274 BluetoothDevice device) {
275 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
jackqdyuleic8775892018-07-24 15:41:42 -0700276 BluetoothAdapter.ERROR);
Jason Monk7ce96b92015-02-02 11:27:58 -0500277 // update local profiles and get paired devices
278 mLocalAdapter.setBluetoothStateInt(state);
279 // send callback to update UI and possibly start scanning
280 synchronized (mCallbacks) {
281 for (BluetoothCallback callback : mCallbacks) {
282 callback.onBluetoothStateChanged(state);
283 }
284 }
285 // Inform CachedDeviceManager that the adapter state has changed
286 mDeviceManager.onBluetoothStateChanged(state);
287 }
288 }
289
290 private class ScanningStateChangedHandler implements Handler {
291 private final boolean mStarted;
292
293 ScanningStateChangedHandler(boolean started) {
294 mStarted = started;
295 }
296 public void onReceive(Context context, Intent intent,
297 BluetoothDevice device) {
298 synchronized (mCallbacks) {
299 for (BluetoothCallback callback : mCallbacks) {
300 callback.onScanningStateChanged(mStarted);
301 }
302 }
303 mDeviceManager.onScanningStateChanged(mStarted);
304 }
305 }
306
307 private class DeviceFoundHandler implements Handler {
308 public void onReceive(Context context, Intent intent,
309 BluetoothDevice device) {
310 short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
Jason Monk7ce96b92015-02-02 11:27:58 -0500311 String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
312 // TODO Pick up UUID. They should be available for 2.1 devices.
313 // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
314 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
315 if (cachedDevice == null) {
timhypengf64f6902018-07-31 15:40:15 +0800316 cachedDevice = mDeviceManager.addDevice(device);
Jason Monk7ce96b92015-02-02 11:27:58 -0500317 Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
318 + cachedDevice);
Ash_Chen26fda9a2018-08-31 21:48:13 +0800319 } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
320 &&!cachedDevice.getDevice().isConnected()) {
321 // Dispatch device add callback to show bonded but
322 // not connected devices in discovery mode
Ash_Chenff54d932018-08-17 22:20:37 +0800323 dispatchDeviceAdded(cachedDevice);
Chienyuan559b7f12018-12-17 15:30:20 +0800324 Log.d(TAG, "DeviceFoundHandler found bonded and not connected device:"
325 + cachedDevice);
326 } else {
327 Log.d(TAG, "DeviceFoundHandler found existing CachedBluetoothDevice:"
328 + cachedDevice);
Jason Monk7ce96b92015-02-02 11:27:58 -0500329 }
330 cachedDevice.setRssi(rssi);
Jack He51520472017-07-24 12:30:08 -0700331 cachedDevice.setJustDiscovered(true);
Jason Monk7ce96b92015-02-02 11:27:58 -0500332 }
333 }
334
Jason Monkbe3c5db2015-02-04 13:00:55 -0500335 private class ConnectionStateChangedHandler implements Handler {
336 @Override
337 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
338 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
339 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
340 BluetoothAdapter.ERROR);
341 dispatchConnectionStateChanged(cachedDevice, state);
342 }
343 }
344
Jason Monk7ce96b92015-02-02 11:27:58 -0500345 private class NameChangedHandler implements Handler {
346 public void onReceive(Context context, Intent intent,
347 BluetoothDevice device) {
348 mDeviceManager.onDeviceNameUpdated(device);
349 }
350 }
351
352 private class BondStateChangedHandler implements Handler {
353 public void onReceive(Context context, Intent intent,
354 BluetoothDevice device) {
355 if (device == null) {
356 Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
357 return;
358 }
359 int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
jackqdyuleic8775892018-07-24 15:41:42 -0700360 BluetoothDevice.ERROR);
Jason Monk7ce96b92015-02-02 11:27:58 -0500361 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
362 if (cachedDevice == null) {
jackqdyuleicc229492018-08-20 14:02:18 -0700363 Log.w(TAG, "Got bonding state changed for " + device +
364 ", but we have no record of that device.");
365 cachedDevice = mDeviceManager.addDevice(device);
Jason Monk7ce96b92015-02-02 11:27:58 -0500366 }
367
368 synchronized (mCallbacks) {
369 for (BluetoothCallback callback : mCallbacks) {
370 callback.onDeviceBondStateChanged(cachedDevice, bondState);
371 }
372 }
373 cachedDevice.onBondingStateChanged(bondState);
374
375 if (bondState == BluetoothDevice.BOND_NONE) {
Isha Bobrac3d94132018-02-08 16:04:36 -0800376 /* Check if we need to remove other Hearing Aid devices */
377 if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
378 mDeviceManager.onDeviceUnpaired(cachedDevice);
379 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500380 int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
381 BluetoothDevice.ERROR);
382
383 showUnbondMessage(context, cachedDevice.getName(), reason);
384 }
385 }
386
387 /**
388 * Called when we have reached the unbonded state.
389 *
390 * @param reason one of the error reasons from
391 * BluetoothDevice.UNBOND_REASON_*
392 */
393 private void showUnbondMessage(Context context, String name, int reason) {
394 int errorMsg;
395
396 switch(reason) {
jackqdyuleic8775892018-07-24 15:41:42 -0700397 case BluetoothDevice.UNBOND_REASON_AUTH_FAILED:
398 errorMsg = R.string.bluetooth_pairing_pin_error_message;
399 break;
400 case BluetoothDevice.UNBOND_REASON_AUTH_REJECTED:
401 errorMsg = R.string.bluetooth_pairing_rejected_error_message;
402 break;
403 case BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN:
404 errorMsg = R.string.bluetooth_pairing_device_down_error_message;
405 break;
406 case BluetoothDevice.UNBOND_REASON_DISCOVERY_IN_PROGRESS:
407 case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT:
408 case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS:
409 case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED:
410 errorMsg = R.string.bluetooth_pairing_error_message;
411 break;
412 default:
413 Log.w(TAG, "showUnbondMessage: Not displaying any message for reason: " + reason);
414 return;
Jason Monk7ce96b92015-02-02 11:27:58 -0500415 }
Kunhung Lie7b7cb82018-05-17 11:04:54 +0800416 BluetoothUtils.showError(context, name, errorMsg);
Jason Monk7ce96b92015-02-02 11:27:58 -0500417 }
418 }
419
420 private class ClassChangedHandler implements Handler {
421 public void onReceive(Context context, Intent intent,
422 BluetoothDevice device) {
423 mDeviceManager.onBtClassChanged(device);
424 }
425 }
426
427 private class UuidChangedHandler implements Handler {
428 public void onReceive(Context context, Intent intent,
429 BluetoothDevice device) {
430 mDeviceManager.onUuidChanged(device);
431 }
432 }
433
Jack He6258aae2017-06-29 17:01:23 -0700434 private class BatteryLevelChangedHandler implements Handler {
435 public void onReceive(Context context, Intent intent,
436 BluetoothDevice device) {
437 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
438 if (cachedDevice != null) {
439 cachedDevice.refresh();
440 }
441 }
442 }
443
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800444 private class ActiveDeviceChangedHandler implements Handler {
445 @Override
446 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
447 String action = intent.getAction();
448 if (action == null) {
449 Log.w(TAG, "ActiveDeviceChangedHandler: action is null");
450 return;
451 }
452 CachedBluetoothDevice activeDevice = mDeviceManager.findDevice(device);
453 int bluetoothProfile = 0;
454 if (Objects.equals(action, BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) {
455 bluetoothProfile = BluetoothProfile.A2DP;
456 } else if (Objects.equals(action, BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
457 bluetoothProfile = BluetoothProfile.HEADSET;
Hansong Zhangd7b35912018-03-16 09:15:48 -0700458 } else if (Objects.equals(action, BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED)) {
459 bluetoothProfile = BluetoothProfile.HEARING_AID;
Pavlin Radoslavov1af33a12018-01-21 02:59:15 -0800460 } else {
461 Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action);
462 return;
463 }
464 dispatchActiveDeviceChanged(activeDevice, bluetoothProfile);
465 }
466 }
467
jackqdyulei29489632018-10-30 11:27:30 -0700468 private class AclStateChangedHandler implements Handler {
469 @Override
470 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
wengsu51945582018-12-17 12:41:04 +0800471 if (device == null) {
472 Log.w(TAG, "AclStateChangedHandler: device is null");
473 return;
474 }
475
476 // Avoid to notify Settings UI for Hearing Aid sub device.
477 if (mDeviceManager.isSubDevice(device)) {
478 return;
479 }
480
jackqdyulei29489632018-10-30 11:27:30 -0700481 final String action = intent.getAction();
482 if (action == null) {
483 Log.w(TAG, "AclStateChangedHandler: action is null");
484 return;
485 }
486 final CachedBluetoothDevice activeDevice = mDeviceManager.findDevice(device);
Chienyuanc42180612018-12-27 15:50:15 +0800487 if (activeDevice == null) {
488 Log.w(TAG, "AclStateChangedHandler: activeDevice is null");
489 return;
490 }
jackqdyulei29489632018-10-30 11:27:30 -0700491 final int state;
492 switch (action) {
493 case BluetoothDevice.ACTION_ACL_CONNECTED:
494 state = BluetoothAdapter.STATE_CONNECTED;
495 break;
496 case BluetoothDevice.ACTION_ACL_DISCONNECTED:
497 state = BluetoothAdapter.STATE_DISCONNECTED;
498 break;
499 default:
500 Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action);
501 return;
502
503 }
504 dispatchAclStateChanged(activeDevice, state);
505 }
506 }
507
timhypenge745e4a2018-04-08 13:55:08 +0800508 private class AudioModeChangedHandler implements Handler {
509
510 @Override
511 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
512 final String action = intent.getAction();
513 if (action == null) {
514 Log.w(TAG, "AudioModeChangedHandler() action is null");
515 return;
516 }
517 dispatchAudioModeChanged();
518 }
519 }
Chienyuan804e7c12018-07-30 19:46:33 +0800520}