blob: 1ea592d7785d508858b76d27ab90024b35ec051c [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
19import android.bluetooth.BluetoothA2dp;
Sanket Agarwal1bec6a52015-10-21 18:23:27 -070020import android.bluetooth.BluetoothA2dpSink;
Jason Monk7ce96b92015-02-02 11:27:58 -050021import android.bluetooth.BluetoothDevice;
22import android.bluetooth.BluetoothHeadset;
Sanket Agarwalf8a1c912016-01-26 20:12:52 -080023import android.bluetooth.BluetoothHeadsetClient;
Jason Monk7ce96b92015-02-02 11:27:58 -050024import android.bluetooth.BluetoothMap;
Joseph Pirozzo631768d2016-09-01 14:19:28 -070025import android.bluetooth.BluetoothMapClient;
Jason Monk7ce96b92015-02-02 11:27:58 -050026import android.bluetooth.BluetoothInputDevice;
27import android.bluetooth.BluetoothPan;
Joseph Pirozzo563c7002016-03-21 15:49:48 -070028import android.bluetooth.BluetoothPbapClient;
Jason Monk7ce96b92015-02-02 11:27:58 -050029import android.bluetooth.BluetoothProfile;
30import android.bluetooth.BluetoothUuid;
31import android.content.Context;
32import android.content.Intent;
33import android.os.ParcelUuid;
34import android.util.Log;
Joseph Pirozzo563c7002016-03-21 15:49:48 -070035import com.android.settingslib.R;
Jason Monk7ce96b92015-02-02 11:27:58 -050036import java.util.ArrayList;
37import java.util.Collection;
38import java.util.HashMap;
39import java.util.Map;
Jason Monk7ce96b92015-02-02 11:27:58 -050040
41/**
42 * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
43 * objects for the available Bluetooth profiles.
44 */
45public final class LocalBluetoothProfileManager {
46 private static final String TAG = "LocalBluetoothProfileManager";
47 private static final boolean DEBUG = Utils.D;
48 /** Singleton instance. */
49 private static LocalBluetoothProfileManager sInstance;
50
51 /**
52 * An interface for notifying BluetoothHeadset IPC clients when they have
53 * been connected to the BluetoothHeadset service.
54 * Only used by com.android.settings.bluetooth.DockService.
55 */
56 public interface ServiceListener {
57 /**
58 * Called to notify the client when this proxy object has been
59 * connected to the BluetoothHeadset service. Clients must wait for
60 * this callback before making IPC calls on the BluetoothHeadset
61 * service.
62 */
63 void onServiceConnected();
64
65 /**
66 * Called to notify the client that this proxy object has been
67 * disconnected from the BluetoothHeadset service. Clients must not
68 * make IPC calls on the BluetoothHeadset service after this callback.
69 * This callback will currently only occur if the application hosting
70 * the BluetoothHeadset service, but may be called more often in future.
71 */
72 void onServiceDisconnected();
73 }
74
75 private final Context mContext;
76 private final LocalBluetoothAdapter mLocalAdapter;
77 private final CachedBluetoothDeviceManager mDeviceManager;
78 private final BluetoothEventManager mEventManager;
79
80 private A2dpProfile mA2dpProfile;
Sanket Agarwal1bec6a52015-10-21 18:23:27 -070081 private A2dpSinkProfile mA2dpSinkProfile;
Jason Monk7ce96b92015-02-02 11:27:58 -050082 private HeadsetProfile mHeadsetProfile;
Sanket Agarwalf8a1c912016-01-26 20:12:52 -080083 private HfpClientProfile mHfpClientProfile;
Jason Monk7ce96b92015-02-02 11:27:58 -050084 private MapProfile mMapProfile;
Joseph Pirozzo631768d2016-09-01 14:19:28 -070085 private MapClientProfile mMapClientProfile;
Jason Monk7ce96b92015-02-02 11:27:58 -050086 private final HidProfile mHidProfile;
87 private OppProfile mOppProfile;
88 private final PanProfile mPanProfile;
Joseph Pirozzo563c7002016-03-21 15:49:48 -070089 private PbapClientProfile mPbapClientProfile;
Jason Monk7ce96b92015-02-02 11:27:58 -050090 private final PbapServerProfile mPbapProfile;
Joseph Pirozzo563c7002016-03-21 15:49:48 -070091 private final boolean mUsePbapPce;
Joseph Pirozzo631768d2016-09-01 14:19:28 -070092 private final boolean mUseMapClient;
Jason Monk7ce96b92015-02-02 11:27:58 -050093
94 /**
95 * Mapping from profile name, e.g. "HEADSET" to profile object.
96 */
97 private final Map<String, LocalBluetoothProfile>
98 mProfileNameMap = new HashMap<String, LocalBluetoothProfile>();
99
100 LocalBluetoothProfileManager(Context context,
101 LocalBluetoothAdapter adapter,
102 CachedBluetoothDeviceManager deviceManager,
103 BluetoothEventManager eventManager) {
104 mContext = context;
105
106 mLocalAdapter = adapter;
107 mDeviceManager = deviceManager;
108 mEventManager = eventManager;
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700109 mUsePbapPce = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700110 // MAP Client is typically used in the same situations as PBAP Client
111 mUseMapClient = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
Jason Monk7ce96b92015-02-02 11:27:58 -0500112 // pass this reference to adapter and event manager (circular dependency)
113 mLocalAdapter.setProfileManager(this);
114 mEventManager.setProfileManager(this);
115
116 ParcelUuid[] uuids = adapter.getUuids();
117
118 // uuids may be null if Bluetooth is turned off
119 if (uuids != null) {
120 updateLocalProfiles(uuids);
121 }
122
123 // Always add HID and PAN profiles
124 mHidProfile = new HidProfile(context, mLocalAdapter, mDeviceManager, this);
125 addProfile(mHidProfile, HidProfile.NAME,
126 BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED);
127
128 mPanProfile = new PanProfile(context);
129 addPanProfile(mPanProfile, PanProfile.NAME,
130 BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
131
132 if(DEBUG) Log.d(TAG, "Adding local MAP profile");
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700133 if (mUseMapClient) {
134 mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
135 addProfile(mMapClientProfile, MapClientProfile.NAME,
136 BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
137 } else {
138 mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
139 addProfile(mMapProfile, MapProfile.NAME,
140 BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
141 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500142
143 //Create PBAP server profile, but do not add it to list of profiles
144 // as we do not need to monitor the profile as part of profile list
145 mPbapProfile = new PbapServerProfile(context);
146
147 if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
148 }
149
150 /**
151 * Initialize or update the local profile objects. If a UUID was previously
152 * present but has been removed, we print a warning but don't remove the
153 * profile object as it might be referenced elsewhere, or the UUID might
154 * come back and we don't want multiple copies of the profile objects.
155 * @param uuids
156 */
157 void updateLocalProfiles(ParcelUuid[] uuids) {
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700158 // A2DP SRC
Jason Monk7ce96b92015-02-02 11:27:58 -0500159 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSource)) {
160 if (mA2dpProfile == null) {
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700161 if(DEBUG) Log.d(TAG, "Adding local A2DP SRC profile");
Jason Monk7ce96b92015-02-02 11:27:58 -0500162 mA2dpProfile = new A2dpProfile(mContext, mLocalAdapter, mDeviceManager, this);
163 addProfile(mA2dpProfile, A2dpProfile.NAME,
164 BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
165 }
166 } else if (mA2dpProfile != null) {
167 Log.w(TAG, "Warning: A2DP profile was previously added but the UUID is now missing.");
168 }
169
Sanket Agarwalf8a1c912016-01-26 20:12:52 -0800170 // A2DP SINK
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700171 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
172 if (mA2dpSinkProfile == null) {
173 if(DEBUG) Log.d(TAG, "Adding local A2DP Sink profile");
174 mA2dpSinkProfile = new A2dpSinkProfile(mContext, mLocalAdapter, mDeviceManager, this);
175 addProfile(mA2dpSinkProfile, A2dpSinkProfile.NAME,
176 BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
177 }
178 } else if (mA2dpSinkProfile != null) {
179 Log.w(TAG, "Warning: A2DP Sink profile was previously added but the UUID is now missing.");
180 }
181
Jason Monk7ce96b92015-02-02 11:27:58 -0500182 // Headset / Handsfree
183 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) ||
184 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) {
185 if (mHeadsetProfile == null) {
186 if (DEBUG) Log.d(TAG, "Adding local HEADSET profile");
187 mHeadsetProfile = new HeadsetProfile(mContext, mLocalAdapter,
188 mDeviceManager, this);
189 addProfile(mHeadsetProfile, HeadsetProfile.NAME,
190 BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
191 }
192 } else if (mHeadsetProfile != null) {
193 Log.w(TAG, "Warning: HEADSET profile was previously added but the UUID is now missing.");
194 }
195
Sanket Agarwalf8a1c912016-01-26 20:12:52 -0800196 // Headset HF
197 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree)) {
198 if (mHfpClientProfile == null) {
199 if(DEBUG) Log.d(TAG, "Adding local HfpClient profile");
200 mHfpClientProfile =
201 new HfpClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
202 addProfile(mHfpClientProfile, HfpClientProfile.NAME,
203 BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
204 }
205 } else if (mHfpClientProfile != null) {
206 Log.w(TAG,
207 "Warning: Hfp Client profile was previously added but the UUID is now missing.");
208 } else {
209 Log.d(TAG, "Handsfree Uuid not found.");
210 }
211
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700212 // Message Access Profile Client
213 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.MNS)) {
214 if (mMapClientProfile == null) {
215 if(DEBUG) Log.d(TAG, "Adding local Map Client profile");
216 mMapClientProfile =
217 new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
218 addProfile(mMapClientProfile, MapClientProfile.NAME,
219 BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
220 }
221 } else if (mMapClientProfile != null) {
222 Log.w(TAG,
223 "Warning: MAP Client profile was previously added but the UUID is now missing.");
224 } else {
225 Log.d(TAG, "MAP Client Uuid not found.");
226 }
227
Jason Monk7ce96b92015-02-02 11:27:58 -0500228 // OPP
229 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
230 if (mOppProfile == null) {
231 if(DEBUG) Log.d(TAG, "Adding local OPP profile");
232 mOppProfile = new OppProfile();
233 // Note: no event handler for OPP, only name map.
234 mProfileNameMap.put(OppProfile.NAME, mOppProfile);
235 }
236 } else if (mOppProfile != null) {
237 Log.w(TAG, "Warning: OPP profile was previously added but the UUID is now missing.");
238 }
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700239
240 //PBAP Client
241 if (mUsePbapPce) {
242 if (mPbapClientProfile == null) {
243 if(DEBUG) Log.d(TAG, "Adding local PBAP Client profile");
244 mPbapClientProfile = new PbapClientProfile(mContext, mLocalAdapter, mDeviceManager,
245 this);
246 addProfile(mPbapClientProfile, PbapClientProfile.NAME,
247 BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED);
248 }
249 } else if (mPbapClientProfile != null) {
250 Log.w(TAG,
251 "Warning: PBAP Client profile was previously added but the UUID is now missing.");
252 }
253
Jason Monk7ce96b92015-02-02 11:27:58 -0500254 mEventManager.registerProfileIntentReceiver();
255
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700256 // There is no local SDP record for HID and Settings app doesn't control PBAP Server.
Jason Monk7ce96b92015-02-02 11:27:58 -0500257 }
258
259 private final Collection<ServiceListener> mServiceListeners =
260 new ArrayList<ServiceListener>();
261
262 private void addProfile(LocalBluetoothProfile profile,
263 String profileName, String stateChangedAction) {
264 mEventManager.addProfileHandler(stateChangedAction, new StateChangedHandler(profile));
265 mProfileNameMap.put(profileName, profile);
266 }
267
268 private void addPanProfile(LocalBluetoothProfile profile,
269 String profileName, String stateChangedAction) {
270 mEventManager.addProfileHandler(stateChangedAction,
271 new PanStateChangedHandler(profile));
272 mProfileNameMap.put(profileName, profile);
273 }
274
275 public LocalBluetoothProfile getProfileByName(String name) {
276 return mProfileNameMap.get(name);
277 }
278
279 // Called from LocalBluetoothAdapter when state changes to ON
280 void setBluetoothStateOn() {
281 ParcelUuid[] uuids = mLocalAdapter.getUuids();
282 if (uuids != null) {
283 updateLocalProfiles(uuids);
284 }
285 mEventManager.readPairedDevices();
286 }
287
288 /**
289 * Generic handler for connection state change events for the specified profile.
290 */
291 private class StateChangedHandler implements BluetoothEventManager.Handler {
292 final LocalBluetoothProfile mProfile;
293
294 StateChangedHandler(LocalBluetoothProfile profile) {
295 mProfile = profile;
296 }
297
298 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
299 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
300 if (cachedDevice == null) {
301 Log.w(TAG, "StateChangedHandler found new device: " + device);
302 cachedDevice = mDeviceManager.addDevice(mLocalAdapter,
303 LocalBluetoothProfileManager.this, device);
304 }
305 int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
306 int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
307 if (newState == BluetoothProfile.STATE_DISCONNECTED &&
308 oldState == BluetoothProfile.STATE_CONNECTING) {
309 Log.i(TAG, "Failed to connect " + mProfile + " device");
310 }
311
312 cachedDevice.onProfileStateChanged(mProfile, newState);
313 cachedDevice.refresh();
314 }
315 }
316
317 /** State change handler for NAP and PANU profiles. */
318 private class PanStateChangedHandler extends StateChangedHandler {
319
320 PanStateChangedHandler(LocalBluetoothProfile profile) {
321 super(profile);
322 }
323
324 @Override
325 public void onReceive(Context context, Intent intent, BluetoothDevice device) {
326 PanProfile panProfile = (PanProfile) mProfile;
327 int role = intent.getIntExtra(BluetoothPan.EXTRA_LOCAL_ROLE, 0);
328 panProfile.setLocalRole(device, role);
329 super.onReceive(context, intent, device);
330 }
331 }
332
333 // called from DockService
334 public void addServiceListener(ServiceListener l) {
335 mServiceListeners.add(l);
336 }
337
338 // called from DockService
339 public void removeServiceListener(ServiceListener l) {
340 mServiceListeners.remove(l);
341 }
342
343 // not synchronized: use only from UI thread! (TODO: verify)
344 void callServiceConnectedListeners() {
345 for (ServiceListener l : mServiceListeners) {
346 l.onServiceConnected();
347 }
348 }
349
350 // not synchronized: use only from UI thread! (TODO: verify)
351 void callServiceDisconnectedListeners() {
352 for (ServiceListener listener : mServiceListeners) {
353 listener.onServiceDisconnected();
354 }
355 }
356
357 // This is called by DockService, so check Headset and A2DP.
358 public synchronized boolean isManagerReady() {
359 // Getting just the headset profile is fine for now. Will need to deal with A2DP
360 // and others if they aren't always in a ready state.
361 LocalBluetoothProfile profile = mHeadsetProfile;
362 if (profile != null) {
363 return profile.isProfileReady();
364 }
365 profile = mA2dpProfile;
366 if (profile != null) {
367 return profile.isProfileReady();
368 }
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700369 profile = mA2dpSinkProfile;
370 if (profile != null) {
371 return profile.isProfileReady();
372 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500373 return false;
374 }
375
376 public A2dpProfile getA2dpProfile() {
377 return mA2dpProfile;
378 }
379
Sanket Agarwalf8a1c912016-01-26 20:12:52 -0800380 public A2dpSinkProfile getA2dpSinkProfile() {
381 if ((mA2dpSinkProfile != null) && (mA2dpSinkProfile.isProfileReady())) {
382 return mA2dpSinkProfile;
383 } else {
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700384 return null;
Sanket Agarwalf8a1c912016-01-26 20:12:52 -0800385 }
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700386 }
387
Jason Monk7ce96b92015-02-02 11:27:58 -0500388 public HeadsetProfile getHeadsetProfile() {
389 return mHeadsetProfile;
390 }
391
Sanket Agarwalf8a1c912016-01-26 20:12:52 -0800392 public HfpClientProfile getHfpClientProfile() {
393 if ((mHfpClientProfile != null) && (mHfpClientProfile.isProfileReady())) {
394 return mHfpClientProfile;
395 } else {
396 return null;
397 }
398 }
399
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700400 public PbapClientProfile getPbapClientProfile() {
401 return mPbapClientProfile;
402 }
403
Jason Monk7ce96b92015-02-02 11:27:58 -0500404 public PbapServerProfile getPbapProfile(){
405 return mPbapProfile;
406 }
407
408 public MapProfile getMapProfile(){
409 return mMapProfile;
410 }
411
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700412 public MapClientProfile getMapClientProfile() {
413 return mMapClientProfile;
414 }
415
Jason Monk7ce96b92015-02-02 11:27:58 -0500416 /**
417 * Fill in a list of LocalBluetoothProfile objects that are supported by
418 * the local device and the remote device.
419 *
420 * @param uuids of the remote device
421 * @param localUuids UUIDs of the local device
422 * @param profiles The list of profiles to fill
423 * @param removedProfiles list of profiles that were removed
424 */
425 synchronized void updateProfiles(ParcelUuid[] uuids, ParcelUuid[] localUuids,
426 Collection<LocalBluetoothProfile> profiles,
427 Collection<LocalBluetoothProfile> removedProfiles,
428 boolean isPanNapConnected, BluetoothDevice device) {
429 // Copy previous profile list into removedProfiles
430 removedProfiles.clear();
431 removedProfiles.addAll(profiles);
Joseph Pirozzo99fecc02016-04-07 13:43:49 -0700432 if (DEBUG) {
433 Log.d(TAG,"Current Profiles" + profiles.toString());
434 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500435 profiles.clear();
436
437 if (uuids == null) {
438 return;
439 }
440
441 if (mHeadsetProfile != null) {
442 if ((BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.HSP_AG) &&
443 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)) ||
444 (BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree_AG) &&
445 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree))) {
446 profiles.add(mHeadsetProfile);
447 removedProfiles.remove(mHeadsetProfile);
448 }
449 }
450
Joseph Pirozzo99fecc02016-04-07 13:43:49 -0700451 if ((mHfpClientProfile != null) &&
452 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) &&
453 BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree)) {
454 profiles.add(mHfpClientProfile);
455 removedProfiles.remove(mHfpClientProfile);
456 }
457
Jason Monk7ce96b92015-02-02 11:27:58 -0500458 if (BluetoothUuid.containsAnyUuid(uuids, A2dpProfile.SINK_UUIDS) &&
459 mA2dpProfile != null) {
460 profiles.add(mA2dpProfile);
461 removedProfiles.remove(mA2dpProfile);
462 }
463
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700464 if (BluetoothUuid.containsAnyUuid(uuids, A2dpSinkProfile.SRC_UUIDS) &&
465 mA2dpSinkProfile != null) {
466 profiles.add(mA2dpSinkProfile);
467 removedProfiles.remove(mA2dpSinkProfile);
Joseph Pirozzo99fecc02016-04-07 13:43:49 -0700468 }
Sanket Agarwal1bec6a52015-10-21 18:23:27 -0700469
Jason Monk7ce96b92015-02-02 11:27:58 -0500470 if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush) &&
471 mOppProfile != null) {
472 profiles.add(mOppProfile);
473 removedProfiles.remove(mOppProfile);
474 }
475
476 if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hid) ||
477 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Hogp)) &&
478 mHidProfile != null) {
479 profiles.add(mHidProfile);
480 removedProfiles.remove(mHidProfile);
481 }
482
483 if(isPanNapConnected)
484 if(DEBUG) Log.d(TAG, "Valid PAN-NAP connection exists.");
485 if ((BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.NAP) &&
486 mPanProfile != null) || isPanNapConnected) {
487 profiles.add(mPanProfile);
488 removedProfiles.remove(mPanProfile);
489 }
490
491 if ((mMapProfile != null) &&
492 (mMapProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) {
493 profiles.add(mMapProfile);
494 removedProfiles.remove(mMapProfile);
495 mMapProfile.setPreferred(device, true);
496 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500497
Joseph Pirozzo631768d2016-09-01 14:19:28 -0700498 if (mMapClientProfile != null) {
499 profiles.add(mMapClientProfile);
500 removedProfiles.remove(mMapClientProfile);
501 }
502
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700503 if (mUsePbapPce) {
504 profiles.add(mPbapClientProfile);
505 removedProfiles.remove(mPbapClientProfile);
506 profiles.remove(mPbapProfile);
507 removedProfiles.add(mPbapProfile);
508 }
Joseph Pirozzo99fecc02016-04-07 13:43:49 -0700509
510 if (DEBUG) {
511 Log.d(TAG,"New Profiles" + profiles.toString());
512 }
Joseph Pirozzo563c7002016-03-21 15:49:48 -0700513 }
Jason Monk7ce96b92015-02-02 11:27:58 -0500514}