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