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