blob: 5a57f19fa1cd0ccead40a11653b1a07c95c4e764 [file] [log] [blame]
Ram Periathiruvadiacb60242017-04-13 16:19:09 -07001/*
2 * Copyright (C) 2017 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.car;
17
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070018import android.bluetooth.BluetoothA2dpSink;
19import android.bluetooth.BluetoothAdapter;
20import android.bluetooth.BluetoothDevice;
21import android.bluetooth.BluetoothHeadsetClient;
22import android.bluetooth.BluetoothMapClient;
Joseph Pirozzo99aeba92018-02-05 14:48:49 -080023import android.bluetooth.BluetoothPan;
Justin Paupore7b17ea62018-12-28 20:27:33 -080024import android.bluetooth.BluetoothPbapClient;
25import android.bluetooth.BluetoothProfile;
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070026import android.car.ICarBluetoothUserService;
27import android.util.Log;
28
29import java.util.Arrays;
30import java.util.List;
31
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070032public class CarBluetoothUserService extends ICarBluetoothUserService.Stub {
Ram Periathiruvadibe7ea0fe2017-05-31 23:31:40 -070033 private static final boolean DBG = true;
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070034 private static final String TAG = "CarBluetoothUsrSvc";
35 private BluetoothAdapter mBluetoothAdapter = null;
36 private final PerUserCarService mService;
37 // Profile Proxies.
38 private BluetoothA2dpSink mBluetoothA2dpSink = null;
39 private BluetoothHeadsetClient mBluetoothHeadsetClient = null;
40 private BluetoothPbapClient mBluetoothPbapClient = null;
41 private BluetoothMapClient mBluetoothMapClient = null;
Joseph Pirozzo99aeba92018-02-05 14:48:49 -080042 private BluetoothPan mBluetoothPan = null;
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070043 private List<Integer> mProfilesToConnect;
44
45 public CarBluetoothUserService(PerUserCarService service) {
46 mService = service;
47 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
48 mProfilesToConnect = Arrays.asList(
49 BluetoothProfile.HEADSET_CLIENT,
50 BluetoothProfile.PBAP_CLIENT,
51 BluetoothProfile.A2DP_SINK,
Joseph Pirozzo99aeba92018-02-05 14:48:49 -080052 BluetoothProfile.MAP_CLIENT,
53 BluetoothProfile.PAN);
Ram Periathiruvadiacb60242017-04-13 16:19:09 -070054 }
55
56 /**
57 * Setup connections to the profile proxy object to talk to the Bluetooth profile services
58 */
59 @Override
60 public void setupBluetoothConnectionProxy() {
61 if (DBG) {
62 Log.d(TAG, "setupProfileProxy()");
63 }
64 if (mBluetoothAdapter == null) {
65 Log.d(TAG, "Null BT Adapter");
66 return;
67 }
68 for (Integer profile : mProfilesToConnect) {
69 mBluetoothAdapter.getProfileProxy(mService.getApplicationContext(), mProfileListener,
70 profile);
71 }
72 }
73
74 /**
75 * Close connections to the profile proxy object
76 */
77 @Override
78 public void closeBluetoothConnectionProxy() {
79 if (mBluetoothAdapter == null) {
80 return;
81 }
82 if (DBG) {
83 Log.d(TAG, "closeProfileProxy()");
84 }
85 // Close those profile proxy objects for profiles that have not yet disconnected
86 if (mBluetoothA2dpSink != null) {
87 mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP_SINK, mBluetoothA2dpSink);
88 }
89 if (mBluetoothHeadsetClient != null) {
90 mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET_CLIENT,
91 mBluetoothHeadsetClient);
92 }
93 if (mBluetoothPbapClient != null) {
94 mBluetoothAdapter.closeProfileProxy(BluetoothProfile.PBAP_CLIENT, mBluetoothPbapClient);
95 }
96 if (mBluetoothMapClient != null) {
97 mBluetoothAdapter.closeProfileProxy(BluetoothProfile.MAP_CLIENT, mBluetoothMapClient);
98 }
Joseph Pirozzo99aeba92018-02-05 14:48:49 -080099 if (mBluetoothPan != null) {
100 mBluetoothAdapter.closeProfileProxy(BluetoothProfile.PAN, mBluetoothPan);
101 }
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700102 }
103
104 /**
105 * Check if a proxy is available for the given profile to talk to the Profile's bluetooth
106 * service.
107 * @param profile - Bluetooth profile to check for
108 * @return - true if proxy available, false if not.
109 */
110 @Override
111 public boolean isBluetoothConnectionProxyAvailable(int profile) {
112 switch (profile) {
113 case BluetoothProfile.A2DP_SINK:
114 if (mBluetoothA2dpSink != null) {
115 return true;
116 }
117 break;
118 case BluetoothProfile.HEADSET_CLIENT:
119 if (mBluetoothHeadsetClient != null) {
120 return true;
121 }
122 break;
123 case BluetoothProfile.PBAP_CLIENT:
124 if (mBluetoothPbapClient != null) {
125 return true;
126 }
127 break;
128 case BluetoothProfile.MAP_CLIENT:
129 if (mBluetoothMapClient != null) {
130 return true;
131 }
132 break;
Joseph Pirozzo99aeba92018-02-05 14:48:49 -0800133 case BluetoothProfile.PAN:
134 if (mBluetoothPan != null) {
135 return true;
136 }
137 break;
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700138 }
139 return false;
140 }
141
142 @Override
143 public void bluetoothConnectToProfile(int profile, BluetoothDevice device) {
144 if (!isBluetoothConnectionProxyAvailable(profile)) {
145 Log.e(TAG, "Cannot connect to Profile. Proxy Unavailable");
146 return;
147 }
Justin Paupore7b17ea62018-12-28 20:27:33 -0800148 if (device == null) {
149 Log.e(TAG, "Cannot connect to profile on null device");
150 return;
151 }
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700152 if (DBG) {
Justin Paupore7b17ea62018-12-28 20:27:33 -0800153 Log.d(TAG, "Trying to connect to " + device.getName() + " (" + device.getAddress()
154 + ") Profile: " + Utils.getProfileName(profile));
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700155 }
156 switch (profile) {
157 case BluetoothProfile.A2DP_SINK:
158 mBluetoothA2dpSink.connect(device);
159 break;
160
161 case BluetoothProfile.HEADSET_CLIENT:
162 mBluetoothHeadsetClient.connect(device);
163 break;
164
165 case BluetoothProfile.MAP_CLIENT:
166 mBluetoothMapClient.connect(device);
167 break;
168
169 case BluetoothProfile.PBAP_CLIENT:
170 mBluetoothPbapClient.connect(device);
171 break;
172
Joseph Pirozzo99aeba92018-02-05 14:48:49 -0800173 case BluetoothProfile.PAN:
174 mBluetoothPan.connect(device);
Justin Paupore7b17ea62018-12-28 20:27:33 -0800175 break;
Joseph Pirozzo99aeba92018-02-05 14:48:49 -0800176
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700177 default:
178 Log.d(TAG, "Unknown profile");
179 break;
180 }
Justin Paupore7b17ea62018-12-28 20:27:33 -0800181 }
182
183 @Override
184 public void bluetoothDisconnectFromProfile(int profile, BluetoothDevice device) {
185 if (!isBluetoothConnectionProxyAvailable(profile)) {
186 Log.e(TAG, "Cannot disconnect from profile. Proxy Unavailable");
187 return;
188 }
189 if (device == null) {
190 Log.e(TAG, "Cannot disconnect from profile on null device");
191 return;
192 }
193 if (DBG) {
194 Log.d(TAG, "Trying to disconnect from " + device.getName() + " (" + device.getAddress()
195 + ") Profile: " + Utils.getProfileName(profile));
196 }
197 switch (profile) {
198 case BluetoothProfile.A2DP_SINK:
199 mBluetoothA2dpSink.disconnect(device);
200 break;
201
202 case BluetoothProfile.HEADSET_CLIENT:
203 mBluetoothHeadsetClient.disconnect(device);
204 break;
205
206 case BluetoothProfile.MAP_CLIENT:
207 mBluetoothMapClient.disconnect(device);
208 break;
209
210 case BluetoothProfile.PBAP_CLIENT:
211 mBluetoothPbapClient.disconnect(device);
212 break;
213
214 case BluetoothProfile.PAN:
215 mBluetoothPan.disconnect(device);
216 break;
217
218 default:
219 Log.d(TAG, "Unknown profile");
220 break;
221 }
222 }
223
224 /**
225 * Get the priority of the given Bluetooth profile for the given remote device
226 * @param profile - Bluetooth profile
227 * @param device - remote Bluetooth device
228 */
229 @Override
230 public int getProfilePriority(int profile, BluetoothDevice device) {
231 if (!isBluetoothConnectionProxyAvailable(profile)) {
232 Log.e(TAG, "Cannot get profile priority. Proxy Unavailable");
233 return BluetoothProfile.PRIORITY_UNDEFINED;
234 }
235 if (device == null) {
236 Log.e(TAG, "Cannot get profile priority on null device");
237 return BluetoothProfile.PRIORITY_UNDEFINED;
238 }
239 int priority;
240 switch (profile) {
241 case BluetoothProfile.A2DP_SINK:
242 priority = mBluetoothA2dpSink.getPriority(device);
243 break;
244 case BluetoothProfile.HEADSET_CLIENT:
245 priority = mBluetoothHeadsetClient.getPriority(device);
246 break;
247 case BluetoothProfile.MAP_CLIENT:
248 priority = mBluetoothMapClient.getPriority(device);
249 break;
250 case BluetoothProfile.PBAP_CLIENT:
251 priority = mBluetoothPbapClient.getPriority(device);
252 break;
253 default:
254 Log.d(TAG, "Unknown Profile");
255 return BluetoothProfile.PRIORITY_UNDEFINED;
256 }
257 if (DBG) {
258 Log.d(TAG, Utils.getProfileName(profile) + " priority for " + device.getName() + " ("
259 + device.getAddress() + ") = " + priority);
260 }
261 return priority;
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700262 }
263
264 /**
Ram Periathiruvadibe7ea0fe2017-05-31 23:31:40 -0700265 * Set the priority of the given Bluetooth profile for the given remote device
266 * @param profile - Bluetooth profile
267 * @param device - remote Bluetooth device
268 * @param priority - priority to set
269 */
270 @Override
271 public void setProfilePriority(int profile, BluetoothDevice device, int priority) {
272 if (!isBluetoothConnectionProxyAvailable(profile)) {
Justin Paupore7b17ea62018-12-28 20:27:33 -0800273 Log.e(TAG, "Cannot set profile priority. Proxy Unavailable");
Ram Periathiruvadibe7ea0fe2017-05-31 23:31:40 -0700274 return;
275 }
Justin Paupore7b17ea62018-12-28 20:27:33 -0800276 if (device == null) {
277 Log.e(TAG, "Cannot set profile priority on null device");
278 return;
279 }
280 if (DBG) {
281 Log.d(TAG, "Setting " + Utils.getProfileName(profile) + " priority for "
282 + device.getName() + " (" + device.getAddress() + ") to " + priority);
283 }
Ram Periathiruvadibe7ea0fe2017-05-31 23:31:40 -0700284 switch (profile) {
285 case BluetoothProfile.A2DP_SINK:
286 mBluetoothA2dpSink.setPriority(device, priority);
287 break;
288 case BluetoothProfile.HEADSET_CLIENT:
289 mBluetoothHeadsetClient.setPriority(device, priority);
290 break;
291 case BluetoothProfile.MAP_CLIENT:
292 mBluetoothMapClient.setPriority(device, priority);
293 break;
294 case BluetoothProfile.PBAP_CLIENT:
295 mBluetoothPbapClient.setPriority(device, priority);
296 break;
297 default:
298 Log.d(TAG, "Unknown Profile");
299 break;
300 }
301 }
302 /**
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700303 * All the BluetoothProfile.ServiceListeners to get the Profile Proxy objects
304 */
305 private BluetoothProfile.ServiceListener mProfileListener =
306 new BluetoothProfile.ServiceListener() {
307 public void onServiceConnected(int profile, BluetoothProfile proxy) {
308 if (DBG) {
309 Log.d(TAG, "OnServiceConnected profile: " + profile);
310 }
311 switch (profile) {
312 case BluetoothProfile.A2DP_SINK:
313 mBluetoothA2dpSink = (BluetoothA2dpSink) proxy;
314 break;
315
316 case BluetoothProfile.HEADSET_CLIENT:
317 mBluetoothHeadsetClient = (BluetoothHeadsetClient) proxy;
318 break;
319
320 case BluetoothProfile.PBAP_CLIENT:
321 mBluetoothPbapClient = (BluetoothPbapClient) proxy;
322 break;
323
324 case BluetoothProfile.MAP_CLIENT:
325 mBluetoothMapClient = (BluetoothMapClient) proxy;
326 break;
327
Joseph Pirozzo99aeba92018-02-05 14:48:49 -0800328 case BluetoothProfile.PAN:
329 mBluetoothPan = (BluetoothPan) proxy;
330 break;
331
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700332 default:
333 if (DBG) {
334 Log.d(TAG, "Unhandled profile");
335 }
336 break;
337 }
338 }
339
340 public void onServiceDisconnected(int profile) {
341 if (DBG) {
342 Log.d(TAG, "onServiceDisconnected profile: " + profile);
343 }
344 switch (profile) {
345 case BluetoothProfile.A2DP_SINK:
346 mBluetoothA2dpSink = null;
347 break;
348
349 case BluetoothProfile.HEADSET_CLIENT:
350 mBluetoothHeadsetClient = null;
351 break;
352
353 case BluetoothProfile.PBAP_CLIENT:
354 mBluetoothPbapClient = null;
355 break;
356
357 case BluetoothProfile.MAP_CLIENT:
358 mBluetoothMapClient = null;
359 break;
360
Joseph Pirozzo99aeba92018-02-05 14:48:49 -0800361 case BluetoothProfile.PAN:
362 mBluetoothPan = null;
363 break;
364
Ram Periathiruvadiacb60242017-04-13 16:19:09 -0700365 default:
366 if (DBG) {
367 Log.d(TAG, "Unhandled profile");
368 }
369 break;
370 }
371 }
372 };
373}