HeadsetClientService.java revision bebc4dd9edb40710d9588b4a2010eef227756a8e
1/* 2 * Copyright (c) 2014 The Android Open Source Project 3 * Copyright (C) 2012 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.bluetooth.hfpclient; 19 20import android.bluetooth.BluetoothDevice; 21import android.bluetooth.BluetoothProfile; 22import android.bluetooth.BluetoothHeadsetClient; 23import android.bluetooth.BluetoothHeadsetClientCall; 24import android.bluetooth.IBluetoothHeadsetClient; 25import android.content.BroadcastReceiver; 26import android.content.Context; 27import android.content.Intent; 28import android.content.IntentFilter; 29import android.media.AudioManager; 30import android.os.Bundle; 31import android.os.Message; 32import android.provider.Settings; 33import android.util.Log; 34import com.android.bluetooth.btservice.ProfileService; 35import com.android.bluetooth.Utils; 36import java.util.ArrayList; 37import java.util.List; 38 39/** 40 * Provides Bluetooth Headset Client (HF Role) profile, as a service in the 41 * Bluetooth application. 42 * 43 * @hide 44 */ 45public class HeadsetClientService extends ProfileService { 46 private static final boolean DBG = false; 47 private static final String TAG = "HeadsetClientService"; 48 49 private HeadsetClientStateMachine mStateMachine; 50 private static HeadsetClientService sHeadsetClientService; 51 52 @Override 53 protected String getName() { 54 return TAG; 55 } 56 57 @Override 58 public IProfileServiceBinder initBinder() { 59 return new BluetoothHeadsetClientBinder(this); 60 } 61 62 @Override 63 protected boolean start() { 64 mStateMachine = HeadsetClientStateMachine.make(this); 65 IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); 66 filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); 67 try { 68 registerReceiver(mBroadcastReceiver, filter); 69 } catch (Exception e) { 70 Log.w(TAG, "Unable to register broadcat receiver", e); 71 } 72 setHeadsetClientService(this); 73 return true; 74 } 75 76 @Override 77 protected boolean stop() { 78 try { 79 unregisterReceiver(mBroadcastReceiver); 80 } catch (Exception e) { 81 Log.w(TAG, "Unable to unregister broadcast receiver", e); 82 } 83 if (mStateMachine != null) { 84 mStateMachine.doQuit(); 85 } 86 return true; 87 } 88 89 @Override 90 protected boolean cleanup() { 91 if (mStateMachine != null) { 92 mStateMachine.cleanup(); 93 } 94 clearHeadsetClientService(); 95 return true; 96 } 97 98 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 99 @Override 100 public void onReceive(Context context, Intent intent) { 101 String action = intent.getAction(); 102 103 if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) { 104 int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); 105 if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) { 106 int streamValue = intent 107 .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); 108 int streamPrevValue = intent.getIntExtra( 109 AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1); 110 111 if (streamValue != -1 && streamValue != streamPrevValue) { 112 mStateMachine.sendMessage(mStateMachine.obtainMessage( 113 HeadsetClientStateMachine.SET_SPEAKER_VOLUME, streamValue, 0)); 114 } 115 } 116 } 117 } 118 }; 119 120 /** 121 * Handlers for incoming service calls 122 */ 123 private static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub 124 implements IProfileServiceBinder { 125 private HeadsetClientService mService; 126 127 public BluetoothHeadsetClientBinder(HeadsetClientService svc) { 128 mService = svc; 129 } 130 131 @Override 132 public boolean cleanup() { 133 mService = null; 134 return true; 135 } 136 137 private HeadsetClientService getService() { 138 if (!Utils.checkCaller()) { 139 Log.w(TAG, "HeadsetClient call not allowed for non-active user"); 140 return null; 141 } 142 143 if (mService != null && mService.isAvailable()) { 144 return mService; 145 } 146 return null; 147 } 148 149 @Override 150 public boolean connect(BluetoothDevice device) { 151 HeadsetClientService service = getService(); 152 if (service == null) { 153 return false; 154 } 155 return service.connect(device); 156 } 157 158 @Override 159 public boolean disconnect(BluetoothDevice device) { 160 HeadsetClientService service = getService(); 161 if (service == null) { 162 return false; 163 } 164 return service.disconnect(device); 165 } 166 167 @Override 168 public List<BluetoothDevice> getConnectedDevices() { 169 HeadsetClientService service = getService(); 170 if (service == null) { 171 return new ArrayList<BluetoothDevice>(0); 172 } 173 return service.getConnectedDevices(); 174 } 175 176 @Override 177 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 178 HeadsetClientService service = getService(); 179 if (service == null) { 180 return new ArrayList<BluetoothDevice>(0); 181 } 182 return service.getDevicesMatchingConnectionStates(states); 183 } 184 185 @Override 186 public int getConnectionState(BluetoothDevice device) { 187 HeadsetClientService service = getService(); 188 if (service == null) { 189 return BluetoothProfile.STATE_DISCONNECTED; 190 } 191 return service.getConnectionState(device); 192 } 193 194 @Override 195 public boolean setPriority(BluetoothDevice device, int priority) { 196 HeadsetClientService service = getService(); 197 if (service == null) { 198 return false; 199 } 200 return service.setPriority(device, priority); 201 } 202 203 @Override 204 public int getPriority(BluetoothDevice device) { 205 HeadsetClientService service = getService(); 206 if (service == null) { 207 return BluetoothProfile.PRIORITY_UNDEFINED; 208 } 209 return service.getPriority(device); 210 } 211 212 @Override 213 public boolean startVoiceRecognition(BluetoothDevice device) { 214 HeadsetClientService service = getService(); 215 if (service == null) { 216 return false; 217 } 218 return service.startVoiceRecognition(device); 219 } 220 221 @Override 222 public boolean stopVoiceRecognition(BluetoothDevice device) { 223 HeadsetClientService service = getService(); 224 if (service == null) { 225 return false; 226 } 227 return service.stopVoiceRecognition(device); 228 } 229 230 @Override 231 public boolean acceptIncomingConnect(BluetoothDevice device) { 232 HeadsetClientService service = getService(); 233 if (service == null) { 234 return false; 235 } 236 return service.acceptIncomingConnect(device); 237 } 238 239 @Override 240 public boolean rejectIncomingConnect(BluetoothDevice device) { 241 HeadsetClientService service = getService(); 242 if (service == null) { 243 return false; 244 } 245 return service.rejectIncomingConnect(device); 246 } 247 248 @Override 249 public int getAudioState(BluetoothDevice device) { 250 HeadsetClientService service = getService(); 251 if (service == null) { 252 return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED; 253 } 254 return service.getAudioState(device); 255 } 256 257 @Override 258 public void setAudioRouteAllowed(boolean allowed) { 259 HeadsetClientService service = getService(); 260 if (service != null) { 261 service.setAudioRouteAllowed(allowed); 262 } 263 } 264 265 @Override 266 public boolean getAudioRouteAllowed() { 267 HeadsetClientService service = getService(); 268 if (service != null) { 269 return service.getAudioRouteAllowed(); 270 } 271 272 return false; 273 } 274 275 @Override 276 public boolean connectAudio() { 277 HeadsetClientService service = getService(); 278 if (service == null) { 279 return false; 280 } 281 return service.connectAudio(); 282 } 283 284 @Override 285 public boolean disconnectAudio() { 286 HeadsetClientService service = getService(); 287 if (service == null) { 288 return false; 289 } 290 return service.disconnectAudio(); 291 } 292 293 @Override 294 public boolean acceptCall(BluetoothDevice device, int flag) { 295 HeadsetClientService service = getService(); 296 if (service == null) { 297 return false; 298 } 299 return service.acceptCall(device, flag); 300 } 301 302 @Override 303 public boolean rejectCall(BluetoothDevice device) { 304 HeadsetClientService service = getService(); 305 if (service == null) { 306 return false; 307 } 308 return service.rejectCall(device); 309 } 310 311 @Override 312 public boolean holdCall(BluetoothDevice device) { 313 HeadsetClientService service = getService(); 314 if (service == null) { 315 return false; 316 } 317 return service.holdCall(device); 318 } 319 320 @Override 321 public boolean terminateCall(BluetoothDevice device, int index) { 322 HeadsetClientService service = getService(); 323 if (service == null) { 324 return false; 325 } 326 return service.terminateCall(device, index); 327 } 328 329 @Override 330 public boolean explicitCallTransfer(BluetoothDevice device) { 331 HeadsetClientService service = getService(); 332 if (service == null) { 333 return false; 334 } 335 return service.explicitCallTransfer(device); 336 } 337 338 @Override 339 public boolean enterPrivateMode(BluetoothDevice device, int index) { 340 HeadsetClientService service = getService(); 341 if (service == null) { 342 return false; 343 } 344 return service.enterPrivateMode(device, index); 345 } 346 347 @Override 348 public boolean redial(BluetoothDevice device) { 349 HeadsetClientService service = getService(); 350 if (service == null) { 351 return false; 352 } 353 return service.redial(device); 354 } 355 356 @Override 357 public boolean dial(BluetoothDevice device, String number) { 358 HeadsetClientService service = getService(); 359 if (service == null) { 360 return false; 361 } 362 return service.dial(device, number); 363 } 364 365 @Override 366 public boolean dialMemory(BluetoothDevice device, int location) { 367 HeadsetClientService service = getService(); 368 if (service == null) { 369 return false; 370 } 371 return service.dialMemory(device, location); 372 } 373 374 @Override 375 public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) { 376 HeadsetClientService service = getService(); 377 if (service == null) { 378 return null; 379 } 380 return service.getCurrentCalls(device); 381 } 382 383 @Override 384 public boolean sendDTMF(BluetoothDevice device, byte code) { 385 HeadsetClientService service = getService(); 386 if (service == null) { 387 return false; 388 } 389 return service.sendDTMF(device, code); 390 } 391 392 @Override 393 public boolean getLastVoiceTagNumber(BluetoothDevice device) { 394 HeadsetClientService service = getService(); 395 if (service == null) { 396 return false; 397 } 398 return service.getLastVoiceTagNumber(device); 399 } 400 401 @Override 402 public Bundle getCurrentAgEvents(BluetoothDevice device) { 403 HeadsetClientService service = getService(); 404 if (service == null) { 405 return null; 406 } 407 return service.getCurrentAgEvents(device); 408 } 409 410 @Override 411 public Bundle getCurrentAgFeatures(BluetoothDevice device) { 412 HeadsetClientService service = getService(); 413 if (service == null) { 414 return null; 415 } 416 return service.getCurrentAgFeatures(device); 417 } 418 }; 419 420 // API methods 421 public static synchronized HeadsetClientService getHeadsetClientService() { 422 if (sHeadsetClientService != null && sHeadsetClientService.isAvailable()) { 423 if (DBG) { 424 Log.d(TAG, "getHeadsetClientService(): returning " + sHeadsetClientService); 425 } 426 return sHeadsetClientService; 427 } 428 if (DBG) { 429 if (sHeadsetClientService == null) { 430 Log.d(TAG, "getHeadsetClientService(): service is NULL"); 431 } else if (!(sHeadsetClientService.isAvailable())) { 432 Log.d(TAG, "getHeadsetClientService(): service is not available"); 433 } 434 } 435 return null; 436 } 437 438 private static synchronized void setHeadsetClientService(HeadsetClientService instance) { 439 if (instance != null && instance.isAvailable()) { 440 if (DBG) { 441 Log.d(TAG, "setHeadsetClientService(): set to: " + sHeadsetClientService); 442 } 443 sHeadsetClientService = instance; 444 } else { 445 if (DBG) { 446 if (sHeadsetClientService == null) { 447 Log.d(TAG, "setHeadsetClientService(): service not available"); 448 } else if (!sHeadsetClientService.isAvailable()) { 449 Log.d(TAG, "setHeadsetClientService(): service is cleaning up"); 450 } 451 } 452 } 453 } 454 455 private static synchronized void clearHeadsetClientService() { 456 sHeadsetClientService = null; 457 } 458 459 public boolean connect(BluetoothDevice device) { 460 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 461 "Need BLUETOOTH ADMIN permission"); 462 463 if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { 464 return false; 465 } 466 467 int connectionState = mStateMachine.getConnectionState(device); 468 if (connectionState == BluetoothProfile.STATE_CONNECTED || 469 connectionState == BluetoothProfile.STATE_CONNECTING) { 470 return false; 471 } 472 473 mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT, device); 474 return true; 475 } 476 477 boolean disconnect(BluetoothDevice device) { 478 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 479 "Need BLUETOOTH ADMIN permission"); 480 int connectionState = mStateMachine.getConnectionState(device); 481 if (connectionState != BluetoothProfile.STATE_CONNECTED && 482 connectionState != BluetoothProfile.STATE_CONNECTING) { 483 return false; 484 } 485 486 mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, device); 487 return true; 488 } 489 490 public List<BluetoothDevice> getConnectedDevices() { 491 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 492 return mStateMachine.getConnectedDevices(); 493 } 494 495 private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 496 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 497 return mStateMachine.getDevicesMatchingConnectionStates(states); 498 } 499 500 int getConnectionState(BluetoothDevice device) { 501 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 502 return mStateMachine.getConnectionState(device); 503 } 504 505 // TODO Should new setting for HeadsetClient priority be created? 506 public boolean setPriority(BluetoothDevice device, int priority) { 507 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 508 "Need BLUETOOTH_ADMIN permission"); 509 Settings.Global.putInt(getContentResolver(), 510 Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()), 511 priority); 512 if (DBG) { 513 Log.d(TAG, "Saved priority " + device + " = " + priority); 514 } 515 return true; 516 } 517 518 public int getPriority(BluetoothDevice device) { 519 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, 520 "Need BLUETOOTH_ADMIN permission"); 521 int priority = Settings.Global.getInt(getContentResolver(), 522 Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()), 523 BluetoothProfile.PRIORITY_UNDEFINED); 524 return priority; 525 } 526 527 boolean startVoiceRecognition(BluetoothDevice device) { 528 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 529 int connectionState = mStateMachine.getConnectionState(device); 530 if (connectionState != BluetoothProfile.STATE_CONNECTED && 531 connectionState != BluetoothProfile.STATE_CONNECTING) { 532 return false; 533 } 534 mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START); 535 return true; 536 } 537 538 boolean stopVoiceRecognition(BluetoothDevice device) { 539 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 540 // It seem that we really need to check the AudioOn state. 541 // But since we allow startVoiceRecognition in STATE_CONNECTED and 542 // STATE_CONNECTING state, we do these 2 in this method 543 int connectionState = mStateMachine.getConnectionState(device); 544 if (connectionState != BluetoothProfile.STATE_CONNECTED && 545 connectionState != BluetoothProfile.STATE_CONNECTING) { 546 return false; 547 } 548 mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_STOP); 549 return true; 550 } 551 552 boolean acceptIncomingConnect(BluetoothDevice device) { 553 // TODO(BT) remove it if stack does access control 554 return false; 555 } 556 557 boolean rejectIncomingConnect(BluetoothDevice device) { 558 // TODO(BT) remove it if stack does access control 559 return false; 560 } 561 562 int getAudioState(BluetoothDevice device) { 563 return mStateMachine.getAudioState(device); 564 } 565 566 public void setAudioRouteAllowed(boolean allowed) { 567 mStateMachine.setAudioRouteAllowed(allowed); 568 } 569 570 public boolean getAudioRouteAllowed() { 571 return mStateMachine.getAudioRouteAllowed(); 572 } 573 574 boolean connectAudio() { 575 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 576 if (!mStateMachine.isConnected()) { 577 return false; 578 } 579 if (mStateMachine.isAudioOn()) { 580 return false; 581 } 582 mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO); 583 return true; 584 } 585 586 boolean disconnectAudio() { 587 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 588 if (!mStateMachine.isAudioOn()) { 589 return false; 590 } 591 mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO); 592 return true; 593 } 594 595 boolean holdCall(BluetoothDevice device) { 596 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 597 int connectionState = mStateMachine.getConnectionState(device); 598 if (connectionState != BluetoothProfile.STATE_CONNECTED && 599 connectionState != BluetoothProfile.STATE_CONNECTING) { 600 return false; 601 } 602 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.HOLD_CALL); 603 mStateMachine.sendMessage(msg); 604 return true; 605 } 606 607 boolean acceptCall(BluetoothDevice device, int flag) { 608 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 609 int connectionState = mStateMachine.getConnectionState(device); 610 if (connectionState != BluetoothProfile.STATE_CONNECTED && 611 connectionState != BluetoothProfile.STATE_CONNECTING) { 612 return false; 613 } 614 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ACCEPT_CALL); 615 msg.arg1 = flag; 616 mStateMachine.sendMessage(msg); 617 return true; 618 } 619 620 boolean rejectCall(BluetoothDevice device) { 621 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 622 int connectionState = mStateMachine.getConnectionState(device); 623 if (connectionState != BluetoothProfile.STATE_CONNECTED && 624 connectionState != BluetoothProfile.STATE_CONNECTING) { 625 return false; 626 } 627 628 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REJECT_CALL); 629 mStateMachine.sendMessage(msg); 630 return true; 631 } 632 633 boolean terminateCall(BluetoothDevice device, int index) { 634 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 635 int connectionState = mStateMachine.getConnectionState(device); 636 if (connectionState != BluetoothProfile.STATE_CONNECTED && 637 connectionState != BluetoothProfile.STATE_CONNECTING) { 638 return false; 639 } 640 641 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.TERMINATE_CALL); 642 msg.arg1 = index; 643 mStateMachine.sendMessage(msg); 644 return true; 645 } 646 647 boolean enterPrivateMode(BluetoothDevice device, int index) { 648 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 649 int connectionState = mStateMachine.getConnectionState(device); 650 if (connectionState != BluetoothProfile.STATE_CONNECTED && 651 connectionState != BluetoothProfile.STATE_CONNECTING) { 652 return false; 653 } 654 655 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ENTER_PRIVATE_MODE); 656 msg.arg1 = index; 657 mStateMachine.sendMessage(msg); 658 return true; 659 } 660 661 boolean redial(BluetoothDevice device) { 662 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 663 int connectionState = mStateMachine.getConnectionState(device); 664 if (connectionState != BluetoothProfile.STATE_CONNECTED && 665 connectionState != BluetoothProfile.STATE_CONNECTING) { 666 return false; 667 } 668 669 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REDIAL); 670 mStateMachine.sendMessage(msg); 671 return true; 672 } 673 674 boolean dial(BluetoothDevice device, String number) { 675 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 676 int connectionState = mStateMachine.getConnectionState(device); 677 if (connectionState != BluetoothProfile.STATE_CONNECTED && 678 connectionState != BluetoothProfile.STATE_CONNECTING) { 679 return false; 680 } 681 682 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_NUMBER); 683 msg.obj = number; 684 mStateMachine.sendMessage(msg); 685 return true; 686 } 687 688 boolean dialMemory(BluetoothDevice device, int location) { 689 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 690 int connectionState = mStateMachine.getConnectionState(device); 691 if (connectionState != BluetoothProfile.STATE_CONNECTED && 692 connectionState != BluetoothProfile.STATE_CONNECTING) { 693 return false; 694 } 695 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_MEMORY); 696 msg.arg1 = location; 697 mStateMachine.sendMessage(msg); 698 return true; 699 } 700 701 public boolean sendDTMF(BluetoothDevice device, byte code) { 702 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 703 int connectionState = mStateMachine.getConnectionState(device); 704 if (connectionState != BluetoothProfile.STATE_CONNECTED && 705 connectionState != BluetoothProfile.STATE_CONNECTING) { 706 return false; 707 } 708 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.SEND_DTMF); 709 msg.arg1 = code; 710 mStateMachine.sendMessage(msg); 711 return true; 712 } 713 714 public boolean getLastVoiceTagNumber(BluetoothDevice device) { 715 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 716 int connectionState = mStateMachine.getConnectionState(device); 717 if (connectionState != BluetoothProfile.STATE_CONNECTED && 718 connectionState != BluetoothProfile.STATE_CONNECTING) { 719 return false; 720 } 721 Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.LAST_VTAG_NUMBER); 722 mStateMachine.sendMessage(msg); 723 return true; 724 } 725 726 public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) { 727 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 728 int connectionState = mStateMachine.getConnectionState(device); 729 if (connectionState != BluetoothProfile.STATE_CONNECTED) { 730 return null; 731 } 732 return mStateMachine.getCurrentCalls(); 733 } 734 735 public boolean explicitCallTransfer(BluetoothDevice device) { 736 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 737 int connectionState = mStateMachine.getConnectionState(device); 738 if (connectionState != BluetoothProfile.STATE_CONNECTED && 739 connectionState != BluetoothProfile.STATE_CONNECTING) { 740 return false; 741 } 742 Message msg = mStateMachine 743 .obtainMessage(HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER); 744 mStateMachine.sendMessage(msg); 745 return true; 746 } 747 748 public Bundle getCurrentAgEvents(BluetoothDevice device) { 749 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 750 int connectionState = mStateMachine.getConnectionState(device); 751 if (connectionState != BluetoothProfile.STATE_CONNECTED) { 752 return null; 753 } 754 return mStateMachine.getCurrentAgEvents(); 755 } 756 757 public Bundle getCurrentAgFeatures(BluetoothDevice device) { 758 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 759 int connectionState = mStateMachine.getConnectionState(device); 760 if (connectionState != BluetoothProfile.STATE_CONNECTED) { 761 return null; 762 } 763 return mStateMachine.getCurrentAgFeatures(); 764 } 765 766 @Override 767 public void dump(StringBuilder sb) { 768 super.dump(sb); 769 if (mStateMachine != null) { 770 mStateMachine.dump(sb); 771 } 772 } 773} 774