blob: ab1cca0084c45c8f05ab36eeef9dffb0e46f3f4e [file] [log] [blame]
hughchena73686f2018-11-12 17:42:08 +08001/*
2 * Copyright 2018 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 */
16package com.android.settingslib.media;
17
18import android.app.Notification;
19import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothDevice;
21import android.content.Context;
22import android.util.Log;
23
24import com.android.settingslib.bluetooth.A2dpProfile;
25import com.android.settingslib.bluetooth.BluetoothCallback;
26import com.android.settingslib.bluetooth.CachedBluetoothDevice;
27import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
28import com.android.settingslib.bluetooth.HearingAidProfile;
29import com.android.settingslib.bluetooth.LocalBluetoothManager;
30import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
31
32import java.util.ArrayList;
33import java.util.List;
34
35/**
36 * BluetoothMediaManager provide interface to get Bluetooth device list.
37 */
38public class BluetoothMediaManager extends MediaManager implements BluetoothCallback {
39
40 private static final String TAG = "BluetoothMediaManager";
41
timhypeng97c6cf62018-12-27 15:40:32 +080042 private final DeviceAttributeChangeCallback mCachedDeviceCallback =
43 new DeviceAttributeChangeCallback();
hughchena73686f2018-11-12 17:42:08 +080044
45 private LocalBluetoothManager mLocalBluetoothManager;
46 private LocalBluetoothProfileManager mProfileManager;
47
48 private MediaDevice mLastAddedDevice;
49 private MediaDevice mLastRemovedDevice;
50
51 BluetoothMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
52 Notification notification) {
53 super(context, notification);
54
55 mLocalBluetoothManager = localBluetoothManager;
56 mProfileManager = mLocalBluetoothManager.getProfileManager();
57 }
58
59 @Override
60 public void startScan() {
61 mMediaDevices.clear();
62 mLocalBluetoothManager.getEventManager().registerCallback(this);
63 buildBluetoothDeviceList();
64 dispatchDeviceListAdded();
65 }
66
67 private void buildBluetoothDeviceList() {
68 addConnectedA2dpDevices();
69 addConnectedHearingAidDevices();
70 }
71
72 private void addConnectedA2dpDevices() {
73 final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
74 if (a2dpProfile == null) {
75 Log.w(TAG, "addConnectedA2dpDevices() a2dp profile is null!");
76 return;
77 }
timhypenga8b826c2018-11-14 15:33:53 +080078
hughchena73686f2018-11-12 17:42:08 +080079 final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
80 final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
81 mLocalBluetoothManager.getCachedDeviceManager();
82
83 for (BluetoothDevice device : devices) {
84 final CachedBluetoothDevice cachedDevice =
85 cachedBluetoothDeviceManager.findDevice(device);
86
87 if (cachedDevice == null) {
88 Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
89 continue;
90 }
91
92 Log.d(TAG, "addConnectedA2dpDevices() device : " + cachedDevice.getName()
93 + ", is connected : " + cachedDevice.isConnected());
94
95 if (cachedDevice.isConnected()) {
96 addMediaDevice(cachedDevice);
97 }
98 }
99 }
100
101 private void addConnectedHearingAidDevices() {
102 final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
103 if (hapProfile == null) {
104 Log.w(TAG, "addConnectedA2dpDevices() hap profile is null!");
105 return;
106 }
timhypenga8b826c2018-11-14 15:33:53 +0800107
hughchena73686f2018-11-12 17:42:08 +0800108 final List<Long> devicesHiSyncIds = new ArrayList<>();
109 final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
110 final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
111 mLocalBluetoothManager.getCachedDeviceManager();
112
113 for (BluetoothDevice device : devices) {
114 final CachedBluetoothDevice cachedDevice =
115 cachedBluetoothDeviceManager.findDevice(device);
116
117 if (cachedDevice == null) {
118 Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
119 continue;
120 }
121
122 Log.d(TAG, "addConnectedHearingAidDevices() device : " + cachedDevice.getName()
123 + ", is connected : " + cachedDevice.isConnected());
124 final long hiSyncId = hapProfile.getHiSyncId(device);
125
126 // device with same hiSyncId should not be shown in the UI.
127 // So do not add it into connectedDevices.
128 if (!devicesHiSyncIds.contains(hiSyncId) && cachedDevice.isConnected()) {
129 devicesHiSyncIds.add(hiSyncId);
130 addMediaDevice(cachedDevice);
131 }
132 }
133 }
134
135 private void addMediaDevice(CachedBluetoothDevice cachedDevice) {
136 MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
137 if (mediaDevice == null) {
138 mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
timhypeng97c6cf62018-12-27 15:40:32 +0800139 cachedDevice.registerCallback(mCachedDeviceCallback);
hughchena73686f2018-11-12 17:42:08 +0800140 mLastAddedDevice = mediaDevice;
141 mMediaDevices.add(mediaDevice);
142 }
143 }
144
145 @Override
146 public void stopScan() {
147 mLocalBluetoothManager.getEventManager().unregisterCallback(this);
timhypeng97c6cf62018-12-27 15:40:32 +0800148 unregisterCachedDeviceCallback();
149 }
150
151 private void unregisterCachedDeviceCallback() {
152 for (MediaDevice device : mMediaDevices) {
153 if (device instanceof BluetoothMediaDevice) {
154 ((BluetoothMediaDevice) device).getCachedDevice()
155 .unregisterCallback(mCachedDeviceCallback);
156 }
157 }
hughchena73686f2018-11-12 17:42:08 +0800158 }
159
160 @Override
161 public void onBluetoothStateChanged(int bluetoothState) {
162 if (BluetoothAdapter.STATE_ON == bluetoothState) {
163 buildBluetoothDeviceList();
164 dispatchDeviceListAdded();
165 } else if (BluetoothAdapter.STATE_OFF == bluetoothState) {
166 final List<MediaDevice> removeDevicesList = new ArrayList<>();
167 for (MediaDevice device : mMediaDevices) {
168 if (device instanceof BluetoothMediaDevice) {
timhypeng97c6cf62018-12-27 15:40:32 +0800169 ((BluetoothMediaDevice) device).getCachedDevice()
170 .unregisterCallback(mCachedDeviceCallback);
hughchena73686f2018-11-12 17:42:08 +0800171 removeDevicesList.add(device);
172 }
173 }
174 mMediaDevices.removeAll(removeDevicesList);
175 dispatchDeviceListRemoved(removeDevicesList);
176 }
177 }
178
179 @Override
180 public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
181 if (isCachedDeviceConnected(cachedDevice)) {
182 addMediaDevice(cachedDevice);
183 dispatchDeviceAdded(cachedDevice);
184 }
185 }
186
187 private boolean isCachedDeviceConnected(CachedBluetoothDevice cachedDevice) {
188 final boolean isConnectedHearingAidDevice = cachedDevice.isConnectedHearingAidDevice();
189 final boolean isConnectedA2dpDevice = cachedDevice.isConnectedA2dpDevice();
timhypenga8b826c2018-11-14 15:33:53 +0800190 Log.d(TAG, "isCachedDeviceConnected() cachedDevice : " + cachedDevice
hughchena73686f2018-11-12 17:42:08 +0800191 + ", is hearing aid connected : " + isConnectedHearingAidDevice
192 + ", is a2dp connected : " + isConnectedA2dpDevice);
193
194 return isConnectedHearingAidDevice || isConnectedA2dpDevice;
195 }
196
197 private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
198 if (mLastAddedDevice != null
199 && MediaDeviceUtils.getId(cachedDevice) == mLastAddedDevice.getId()) {
200 dispatchDeviceAdded(mLastAddedDevice);
201 }
202 }
203
204 @Override
205 public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
206 if (!isCachedDeviceConnected(cachedDevice)) {
207 removeMediaDevice(cachedDevice);
208 dispatchDeviceRemoved(cachedDevice);
209 }
210 }
211
212 private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
213 final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
214 if (mediaDevice != null) {
timhypeng97c6cf62018-12-27 15:40:32 +0800215 cachedDevice.unregisterCallback(mCachedDeviceCallback);
hughchena73686f2018-11-12 17:42:08 +0800216 mLastRemovedDevice = mediaDevice;
217 mMediaDevices.remove(mediaDevice);
218 }
219 }
220
221 void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
222 if (mLastRemovedDevice != null
223 && MediaDeviceUtils.getId(cachedDevice) == mLastRemovedDevice.getId()) {
224 dispatchDeviceRemoved(mLastRemovedDevice);
225 }
226 }
227
228 @Override
229 public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
230 int bluetoothProfile) {
timhypenga8b826c2018-11-14 15:33:53 +0800231 Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice
hughchena73686f2018-11-12 17:42:08 +0800232 + ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
233
234 if (isCachedDeviceConnected(cachedDevice)) {
235 addMediaDevice(cachedDevice);
236 dispatchDeviceAdded(cachedDevice);
237 } else {
238 removeMediaDevice(cachedDevice);
239 dispatchDeviceRemoved(cachedDevice);
240 }
241 }
242
243 @Override
244 public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
timhypenga8b826c2018-11-14 15:33:53 +0800245 Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice + ", state: " + state);
hughchena73686f2018-11-12 17:42:08 +0800246
247 if (isCachedDeviceConnected(cachedDevice)) {
248 addMediaDevice(cachedDevice);
249 dispatchDeviceAdded(cachedDevice);
250 } else {
251 removeMediaDevice(cachedDevice);
252 dispatchDeviceRemoved(cachedDevice);
253 }
254 }
timhypeng97c6cf62018-12-27 15:40:32 +0800255 class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
hughchena73686f2018-11-12 17:42:08 +0800256 @Override
257 public void onDeviceAttributesChanged() {
timhypeng97c6cf62018-12-27 15:40:32 +0800258 dispatchDeviceAttributesChanged();
hughchena73686f2018-11-12 17:42:08 +0800259 }
260 }
261}