LocalBluetoothProfileManager.java revision 498d12bac0df509a4f74a4df8a8c69ec22583a1a
1/* 2 * Copyright (C) 2008 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.settings.bluetooth; 18 19import com.android.settings.R; 20 21import android.bluetooth.BluetoothA2dp; 22import android.bluetooth.BluetoothAdapter; 23import android.bluetooth.BluetoothDevice; 24import android.bluetooth.BluetoothHeadset; 25import android.bluetooth.BluetoothInputDevice; 26import android.bluetooth.BluetoothPan; 27import android.bluetooth.BluetoothProfile; 28import android.bluetooth.BluetoothUuid; 29import android.os.Handler; 30import android.os.ParcelUuid; 31import android.util.Log; 32 33import java.util.HashMap; 34import java.util.Iterator; 35import java.util.LinkedList; 36import java.util.List; 37import java.util.Map; 38 39/** 40 * LocalBluetoothProfileManager is an abstract class defining the basic 41 * functionality related to a profile. 42 */ 43public abstract class LocalBluetoothProfileManager { 44 private static final String TAG = "LocalBluetoothProfileManager"; 45 46 /* package */ static final ParcelUuid[] HEADSET_PROFILE_UUIDS = new ParcelUuid[] { 47 BluetoothUuid.HSP, 48 BluetoothUuid.Handsfree, 49 }; 50 51 /* package */ static final ParcelUuid[] A2DP_SINK_PROFILE_UUIDS = new ParcelUuid[] { 52 BluetoothUuid.AudioSink, 53 BluetoothUuid.AdvAudioDist, 54 }; 55 56 /* package */ static final ParcelUuid[] A2DP_SRC_PROFILE_UUIDS = new ParcelUuid[] { 57 BluetoothUuid.AudioSource 58 }; 59 60 /* package */ static final ParcelUuid[] OPP_PROFILE_UUIDS = new ParcelUuid[] { 61 BluetoothUuid.ObexObjectPush 62 }; 63 64 /* package */ static final ParcelUuid[] HID_PROFILE_UUIDS = new ParcelUuid[] { 65 BluetoothUuid.Hid 66 }; 67 68 /* package */ static final ParcelUuid[] PANU_PROFILE_UUIDS = new ParcelUuid[] { 69 BluetoothUuid.PANU 70 }; 71 72 /* package */ static final ParcelUuid[] NAP_PROFILE_UUIDS = new ParcelUuid[] { 73 BluetoothUuid.NAP 74 }; 75 76 /** 77 * An interface for notifying BluetoothHeadset IPC clients when they have 78 * been connected to the BluetoothHeadset service. 79 */ 80 public interface ServiceListener { 81 /** 82 * Called to notify the client when this proxy object has been 83 * connected to the BluetoothHeadset service. Clients must wait for 84 * this callback before making IPC calls on the BluetoothHeadset 85 * service. 86 */ 87 public void onServiceConnected(); 88 89 /** 90 * Called to notify the client that this proxy object has been 91 * disconnected from the BluetoothHeadset service. Clients must not 92 * make IPC calls on the BluetoothHeadset service after this callback. 93 * This callback will currently only occur if the application hosting 94 * the BluetoothHeadset service, but may be called more often in future. 95 */ 96 public void onServiceDisconnected(); 97 } 98 99 // TODO: close profiles when we're shutting down 100 private static Map<Profile, LocalBluetoothProfileManager> sProfileMap = 101 new HashMap<Profile, LocalBluetoothProfileManager>(); 102 103 protected LocalBluetoothManager mLocalManager; 104 105 public static void init(LocalBluetoothManager localManager) { 106 synchronized (sProfileMap) { 107 if (sProfileMap.size() == 0) { 108 LocalBluetoothProfileManager profileManager; 109 110 profileManager = new A2dpProfileManager(localManager); 111 sProfileMap.put(Profile.A2DP, profileManager); 112 113 profileManager = new HeadsetProfileManager(localManager); 114 sProfileMap.put(Profile.HEADSET, profileManager); 115 116 profileManager = new OppProfileManager(localManager); 117 sProfileMap.put(Profile.OPP, profileManager); 118 119 profileManager = new HidProfileManager(localManager); 120 sProfileMap.put(Profile.HID, profileManager); 121 122 profileManager = new PanProfileManager(localManager); 123 sProfileMap.put(Profile.PAN, profileManager); 124 } 125 } 126 } 127 128 // TODO(): Combine the init and updateLocalProfiles codes. 129 // init can get called from various paths, it makes no sense to add and then delete. 130 public static void updateLocalProfiles(LocalBluetoothManager localManager, ParcelUuid[] uuids) { 131 if (!BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree_AG) && 132 !BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP_AG)) { 133 sProfileMap.remove(Profile.HEADSET); 134 } 135 136 if (!BluetoothUuid.containsAnyUuid(uuids, A2DP_SRC_PROFILE_UUIDS)) { 137 sProfileMap.remove(Profile.A2DP); 138 } 139 140 if (!BluetoothUuid.containsAnyUuid(uuids, OPP_PROFILE_UUIDS)) { 141 sProfileMap.remove(Profile.OPP); 142 } 143 144 if (!BluetoothUuid.containsAnyUuid(uuids, PANU_PROFILE_UUIDS)) { 145 sProfileMap.remove(Profile.PAN); 146 } 147 148 // There is no local SDP record for HID and Settings app doesn't control PBAP 149 } 150 151 private static LinkedList<ServiceListener> mServiceListeners = 152 new LinkedList<ServiceListener>(); 153 154 public static void addServiceListener(ServiceListener l) { 155 mServiceListeners.add(l); 156 } 157 158 public static void removeServiceListener(ServiceListener l) { 159 mServiceListeners.remove(l); 160 } 161 162 public static boolean isManagerReady() { 163 // Getting just the headset profile is fine for now. Will need to deal with A2DP 164 // and others if they aren't always in a ready state. 165 LocalBluetoothProfileManager profileManager = sProfileMap.get(Profile.HEADSET); 166 if (profileManager == null) { 167 return sProfileMap.size() > 0; 168 } 169 return profileManager.isProfileReady(); 170 } 171 172 public static LocalBluetoothProfileManager getProfileManager(LocalBluetoothManager localManager, 173 Profile profile) { 174 // Note: This code assumes that "localManager" is same as the 175 // LocalBluetoothManager that was used to initialize the sProfileMap. 176 // If that every changes, we can't just keep one copy of sProfileMap. 177 synchronized (sProfileMap) { 178 LocalBluetoothProfileManager profileManager = sProfileMap.get(profile); 179 if (profileManager == null) { 180 Log.e(TAG, "profileManager can't be found for " + profile.toString()); 181 } 182 return profileManager; 183 } 184 } 185 186 /** 187 * Temporary method to fill profiles based on a device's class. 188 * 189 * NOTE: This list happens to define the connection order. We should put this logic in a more 190 * well known place when this method is no longer temporary. 191 * @param uuids of the remote device 192 * @param localUuids UUIDs of the local device 193 * @param profiles The list of profiles to fill 194 */ 195 public static void updateProfiles(ParcelUuid[] uuids, ParcelUuid[] localUuids, 196 List<Profile> profiles) { 197 profiles.clear(); 198 199 if (uuids == null) { 200 return; 201 } 202 203 if (sProfileMap.containsKey(Profile.HEADSET)) { 204 if ((BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.HSP_AG) && 205 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HSP)) || 206 (BluetoothUuid.isUuidPresent(localUuids, BluetoothUuid.Handsfree_AG) && 207 BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.Handsfree))) { 208 profiles.add(Profile.HEADSET); 209 } 210 } 211 212 213 if (BluetoothUuid.containsAnyUuid(uuids, A2DP_SINK_PROFILE_UUIDS) && 214 sProfileMap.containsKey(Profile.A2DP)) { 215 profiles.add(Profile.A2DP); 216 } 217 218 if (BluetoothUuid.containsAnyUuid(uuids, OPP_PROFILE_UUIDS) && 219 sProfileMap.containsKey(Profile.OPP)) { 220 profiles.add(Profile.OPP); 221 } 222 223 if (BluetoothUuid.containsAnyUuid(uuids, HID_PROFILE_UUIDS) && 224 sProfileMap.containsKey(Profile.HID)) { 225 profiles.add(Profile.HID); 226 } 227 228 if (BluetoothUuid.containsAnyUuid(uuids, PANU_PROFILE_UUIDS) && 229 sProfileMap.containsKey(Profile.PAN)) { 230 profiles.add(Profile.PAN); 231 } 232 } 233 234 protected LocalBluetoothProfileManager(LocalBluetoothManager localManager) { 235 mLocalManager = localManager; 236 } 237 238 public abstract List<BluetoothDevice> getConnectedDevices(); 239 240 public abstract boolean connect(BluetoothDevice device); 241 242 public abstract boolean disconnect(BluetoothDevice device); 243 244 public abstract int getConnectionStatus(BluetoothDevice device); 245 246 public abstract int getSummary(BluetoothDevice device); 247 248 public abstract int convertState(int a2dpState); 249 250 public abstract boolean isPreferred(BluetoothDevice device); 251 252 public abstract int getPreferred(BluetoothDevice device); 253 254 public abstract void setPreferred(BluetoothDevice device, boolean preferred); 255 256 public boolean isConnected(BluetoothDevice device) { 257 return SettingsBtStatus.isConnectionStatusConnected(getConnectionStatus(device)); 258 } 259 260 public abstract boolean isProfileReady(); 261 262 public int getDrawableResource() { 263 return R.drawable.ic_bt_headphones_a2dp; 264 } 265 266 public static enum Profile { 267 HEADSET(R.string.bluetooth_profile_headset), 268 A2DP(R.string.bluetooth_profile_a2dp), 269 OPP(R.string.bluetooth_profile_opp), 270 HID(R.string.bluetooth_profile_hid), 271 PAN(R.string.bluetooth_profile_pan); 272 273 public final int localizedString; 274 275 private Profile(int localizedString) { 276 this.localizedString = localizedString; 277 } 278 } 279 280 /** 281 * A2dpProfileManager is an abstraction for the {@link BluetoothA2dp} service. 282 */ 283 private static class A2dpProfileManager extends LocalBluetoothProfileManager 284 implements BluetoothProfile.ServiceListener { 285 private BluetoothA2dp mService; 286 287 // TODO(): The calls must wait for mService. Its not null just 288 // because it runs in the system server. 289 public A2dpProfileManager(LocalBluetoothManager localManager) { 290 super(localManager); 291 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 292 adapter.getProfileProxy(localManager.getContext(), this, BluetoothProfile.A2DP); 293 294 } 295 296 public void onServiceConnected(int profile, BluetoothProfile proxy) { 297 mService = (BluetoothA2dp) proxy; 298 } 299 300 public void onServiceDisconnected(int profile) { 301 mService = null; 302 } 303 304 @Override 305 public List<BluetoothDevice> getConnectedDevices() { 306 return mService.getDevicesMatchingConnectionStates( 307 new int[] {BluetoothProfile.STATE_CONNECTED, 308 BluetoothProfile.STATE_CONNECTING, 309 BluetoothProfile.STATE_DISCONNECTING}); 310 } 311 312 @Override 313 public boolean connect(BluetoothDevice device) { 314 List<BluetoothDevice> sinks = getConnectedDevices(); 315 if (sinks != null) { 316 for (BluetoothDevice sink : sinks) { 317 mService.disconnect(sink); 318 } 319 } 320 return mService.connect(device); 321 } 322 323 @Override 324 public boolean disconnect(BluetoothDevice device) { 325 // Downgrade priority as user is disconnecting the sink. 326 if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) { 327 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 328 } 329 return mService.disconnect(device); 330 } 331 332 @Override 333 public int getConnectionStatus(BluetoothDevice device) { 334 return convertState(mService.getConnectionState(device)); 335 } 336 337 @Override 338 public int getSummary(BluetoothDevice device) { 339 int connectionStatus = getConnectionStatus(device); 340 341 if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) { 342 return R.string.bluetooth_a2dp_profile_summary_connected; 343 } else { 344 return SettingsBtStatus.getConnectionStatusSummary(connectionStatus); 345 } 346 } 347 348 @Override 349 public boolean isPreferred(BluetoothDevice device) { 350 return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 351 } 352 353 @Override 354 public int getPreferred(BluetoothDevice device) { 355 return mService.getPriority(device); 356 } 357 358 @Override 359 public void setPreferred(BluetoothDevice device, boolean preferred) { 360 if (preferred) { 361 if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 362 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 363 } 364 } else { 365 mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 366 } 367 } 368 369 @Override 370 public int convertState(int a2dpState) { 371 switch (a2dpState) { 372 case BluetoothProfile.STATE_CONNECTED: 373 return SettingsBtStatus.CONNECTION_STATUS_CONNECTED; 374 case BluetoothProfile.STATE_CONNECTING: 375 return SettingsBtStatus.CONNECTION_STATUS_CONNECTING; 376 case BluetoothProfile.STATE_DISCONNECTED: 377 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; 378 case BluetoothProfile.STATE_DISCONNECTING: 379 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING; 380 case BluetoothA2dp.STATE_PLAYING: 381 return SettingsBtStatus.CONNECTION_STATUS_ACTIVE; 382 default: 383 return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; 384 } 385 } 386 387 @Override 388 public boolean isProfileReady() { 389 return true; 390 } 391 392 @Override 393 public int getDrawableResource() { 394 return R.drawable.ic_bt_headphones_a2dp; 395 } 396 } 397 398 /** 399 * HeadsetProfileManager is an abstraction for the {@link BluetoothHeadset} service. 400 */ 401 private static class HeadsetProfileManager extends LocalBluetoothProfileManager 402 implements BluetoothProfile.ServiceListener { 403 private BluetoothHeadset mService; 404 private Handler mUiHandler = new Handler(); 405 private boolean profileReady = false; 406 407 // TODO(): The calls must get queued if mService becomes null. 408 // It can happen when phone app crashes for some reason. 409 // All callers should have service listeners. Dock Service is the only 410 // one right now. 411 public HeadsetProfileManager(LocalBluetoothManager localManager) { 412 super(localManager); 413 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 414 adapter.getProfileProxy(localManager.getContext(), this, BluetoothProfile.HEADSET); 415 } 416 417 public void onServiceConnected(int profile, BluetoothProfile proxy) { 418 mService = (BluetoothHeadset) proxy; 419 profileReady = true; 420 // This could be called on a non-UI thread, funnel to UI thread. 421 mUiHandler.post(new Runnable() { 422 public void run() { 423 /* 424 * We just bound to the service, so refresh the UI of the 425 * headset device. 426 */ 427 List<BluetoothDevice> deviceList = mService.getConnectedDevices(); 428 if (deviceList.size() == 0) return; 429 430 mLocalManager.getCachedDeviceManager() 431 .onProfileStateChanged(deviceList.get(0), Profile.HEADSET, 432 BluetoothProfile.STATE_CONNECTED); 433 } 434 }); 435 436 if (mServiceListeners.size() > 0) { 437 Iterator<ServiceListener> it = mServiceListeners.iterator(); 438 while(it.hasNext()) { 439 it.next().onServiceConnected(); 440 } 441 } 442 } 443 444 public void onServiceDisconnected(int profile) { 445 mService = null; 446 profileReady = false; 447 if (mServiceListeners.size() > 0) { 448 Iterator<ServiceListener> it = mServiceListeners.iterator(); 449 while(it.hasNext()) { 450 it.next().onServiceDisconnected(); 451 } 452 } 453 } 454 455 @Override 456 public boolean isProfileReady() { 457 return profileReady; 458 } 459 460 @Override 461 public List<BluetoothDevice> getConnectedDevices() { 462 return mService.getConnectedDevices(); 463 } 464 465 @Override 466 public boolean connect(BluetoothDevice device) { 467 return mService.connect(device); 468 } 469 470 @Override 471 public boolean disconnect(BluetoothDevice device) { 472 List<BluetoothDevice> deviceList = getConnectedDevices(); 473 if (deviceList.size() != 0 && deviceList.get(0).equals(device)) { 474 // Downgrade priority as user is disconnecting the headset. 475 if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) { 476 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 477 } 478 return mService.disconnect(device); 479 } else { 480 return false; 481 } 482 } 483 484 @Override 485 public int getConnectionStatus(BluetoothDevice device) { 486 List<BluetoothDevice> deviceList = getConnectedDevices(); 487 488 return deviceList.size() > 0 && deviceList.get(0).equals(device) 489 ? convertState(mService.getConnectionState(device)) 490 : SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; 491 } 492 493 @Override 494 public int getSummary(BluetoothDevice device) { 495 int connectionStatus = getConnectionStatus(device); 496 497 if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) { 498 return R.string.bluetooth_headset_profile_summary_connected; 499 } else { 500 return SettingsBtStatus.getConnectionStatusSummary(connectionStatus); 501 } 502 } 503 504 @Override 505 public boolean isPreferred(BluetoothDevice device) { 506 return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF; 507 } 508 509 @Override 510 public int getPreferred(BluetoothDevice device) { 511 return mService.getPriority(device); 512 } 513 514 @Override 515 public void setPreferred(BluetoothDevice device, boolean preferred) { 516 if (preferred) { 517 if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) { 518 mService.setPriority(device, BluetoothProfile.PRIORITY_ON); 519 } 520 } else { 521 mService.setPriority(device, BluetoothProfile.PRIORITY_OFF); 522 } 523 } 524 525 @Override 526 public int convertState(int headsetState) { 527 switch (headsetState) { 528 case BluetoothProfile.STATE_CONNECTED: 529 return SettingsBtStatus.CONNECTION_STATUS_CONNECTED; 530 case BluetoothProfile.STATE_CONNECTING: 531 return SettingsBtStatus.CONNECTION_STATUS_CONNECTING; 532 case BluetoothProfile.STATE_DISCONNECTED: 533 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; 534 default: 535 return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; 536 } 537 } 538 539 @Override 540 public int getDrawableResource() { 541 return R.drawable.ic_bt_headset_hfp; 542 } 543 } 544 545 /** 546 * OppProfileManager 547 */ 548 private static class OppProfileManager extends LocalBluetoothProfileManager { 549 550 public OppProfileManager(LocalBluetoothManager localManager) { 551 super(localManager); 552 } 553 554 @Override 555 public List<BluetoothDevice> getConnectedDevices() { 556 return null; 557 } 558 559 @Override 560 public boolean connect(BluetoothDevice device) { 561 return false; 562 } 563 564 @Override 565 public boolean disconnect(BluetoothDevice device) { 566 return false; 567 } 568 569 @Override 570 public int getConnectionStatus(BluetoothDevice device) { 571 return -1; 572 } 573 574 @Override 575 public int getSummary(BluetoothDevice device) { 576 int connectionStatus = getConnectionStatus(device); 577 578 if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) { 579 return R.string.bluetooth_opp_profile_summary_connected; 580 } else { 581 return R.string.bluetooth_opp_profile_summary_not_connected; 582 } 583 } 584 585 @Override 586 public boolean isPreferred(BluetoothDevice device) { 587 return false; 588 } 589 590 @Override 591 public int getPreferred(BluetoothDevice device) { 592 return -1; 593 } 594 595 @Override 596 public void setPreferred(BluetoothDevice device, boolean preferred) { 597 } 598 599 @Override 600 public boolean isProfileReady() { 601 return true; 602 } 603 604 @Override 605 public int convertState(int oppState) { 606 switch (oppState) { 607 case 0: 608 return SettingsBtStatus.CONNECTION_STATUS_CONNECTED; 609 case 1: 610 return SettingsBtStatus.CONNECTION_STATUS_CONNECTING; 611 case 2: 612 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; 613 default: 614 return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; 615 } 616 } 617 618 @Override 619 public int getDrawableResource() { 620 // TODO: 621 return 0; 622 } 623 } 624 625 private static class HidProfileManager extends LocalBluetoothProfileManager { 626 private BluetoothInputDevice mService; 627 628 public HidProfileManager(LocalBluetoothManager localManager) { 629 super(localManager); 630 mService = new BluetoothInputDevice(localManager.getContext()); 631 } 632 633 @Override 634 public boolean connect(BluetoothDevice device) { 635 return mService.connectInputDevice(device); 636 } 637 638 @Override 639 public int convertState(int hidState) { 640 switch (hidState) { 641 case BluetoothInputDevice.STATE_CONNECTED: 642 return SettingsBtStatus.CONNECTION_STATUS_CONNECTED; 643 case BluetoothInputDevice.STATE_CONNECTING: 644 return SettingsBtStatus.CONNECTION_STATUS_CONNECTING; 645 case BluetoothInputDevice.STATE_DISCONNECTED: 646 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; 647 case BluetoothInputDevice.STATE_DISCONNECTING: 648 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING; 649 default: 650 return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; 651 } 652 } 653 654 @Override 655 public boolean disconnect(BluetoothDevice device) { 656 return mService.disconnectInputDevice(device); 657 } 658 659 @Override 660 public List<BluetoothDevice> getConnectedDevices() { 661 return mService.getConnectedInputDevices(); 662 } 663 664 @Override 665 public int getConnectionStatus(BluetoothDevice device) { 666 return convertState(mService.getInputDeviceState(device)); 667 } 668 669 @Override 670 public int getPreferred(BluetoothDevice device) { 671 return mService.getInputDevicePriority(device); 672 } 673 674 @Override 675 public int getSummary(BluetoothDevice device) { 676 final int connectionStatus = getConnectionStatus(device); 677 678 if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) { 679 return R.string.bluetooth_hid_profile_summary_connected; 680 } else { 681 return SettingsBtStatus.getConnectionStatusSummary(connectionStatus); 682 } 683 } 684 685 @Override 686 public boolean isPreferred(BluetoothDevice device) { 687 return mService.getInputDevicePriority(device) > BluetoothInputDevice.PRIORITY_OFF; 688 } 689 690 @Override 691 public boolean isProfileReady() { 692 return true; 693 } 694 695 @Override 696 public void setPreferred(BluetoothDevice device, boolean preferred) { 697 if (preferred) { 698 if (mService.getInputDevicePriority(device) < BluetoothInputDevice.PRIORITY_ON) { 699 mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_ON); 700 } 701 } else { 702 mService.setInputDevicePriority(device, BluetoothInputDevice.PRIORITY_OFF); 703 } 704 } 705 706 @Override 707 public int getDrawableResource() { 708 // TODO: 709 return 0; 710 } 711 } 712 713 private static class PanProfileManager extends LocalBluetoothProfileManager { 714 private BluetoothPan mService; 715 716 public PanProfileManager(LocalBluetoothManager localManager) { 717 super(localManager); 718 mService = new BluetoothPan(localManager.getContext()); 719 } 720 721 @Override 722 public boolean connect(BluetoothDevice device) { 723 return mService.connect(device); 724 } 725 726 @Override 727 public int convertState(int panState) { 728 switch (panState) { 729 case BluetoothPan.STATE_CONNECTED: 730 return SettingsBtStatus.CONNECTION_STATUS_CONNECTED; 731 case BluetoothPan.STATE_CONNECTING: 732 return SettingsBtStatus.CONNECTION_STATUS_CONNECTING; 733 case BluetoothPan.STATE_DISCONNECTED: 734 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED; 735 case BluetoothPan.STATE_DISCONNECTING: 736 return SettingsBtStatus.CONNECTION_STATUS_DISCONNECTING; 737 default: 738 return SettingsBtStatus.CONNECTION_STATUS_UNKNOWN; 739 } 740 } 741 742 @Override 743 public boolean disconnect(BluetoothDevice device) { 744 return mService.disconnect(device); 745 } 746 747 @Override 748 public int getSummary(BluetoothDevice device) { 749 final int connectionStatus = getConnectionStatus(device); 750 751 if (SettingsBtStatus.isConnectionStatusConnected(connectionStatus)) { 752 return R.string.bluetooth_pan_profile_summary_connected; 753 } else { 754 return SettingsBtStatus.getConnectionStatusSummary(connectionStatus); 755 } 756 } 757 758 @Override 759 public boolean isProfileReady() { 760 return true; 761 } 762 763 @Override 764 public List<BluetoothDevice> getConnectedDevices() { 765 return mService.getConnectedDevices(); 766 } 767 768 @Override 769 public int getConnectionStatus(BluetoothDevice device) { 770 return convertState(mService.getPanDeviceState(device)); 771 } 772 773 @Override 774 public int getPreferred(BluetoothDevice device) { 775 return -1; 776 } 777 778 @Override 779 public boolean isPreferred(BluetoothDevice device) { 780 return false; 781 } 782 783 @Override 784 public void setPreferred(BluetoothDevice device, boolean preferred) { 785 return; 786 } 787 788 @Override 789 public int getDrawableResource() { 790 // TODO: 791 return 0; 792 } 793 } 794} 795