1 /* 2 * Copyright (c) 2017 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 17 /* 18 * Defines the native interface that is used by state machine/service to either or receive messages 19 * from the native stack. This file is registered for the native methods in corresponding CPP file. 20 */ 21 package com.android.bluetooth.hfpclient; 22 23 import static java.util.Objects.requireNonNull; 24 25 import android.bluetooth.BluetoothDevice; 26 import android.util.Log; 27 28 import com.android.bluetooth.Utils; 29 import com.android.bluetooth.btservice.AdapterService; 30 import com.android.internal.annotations.GuardedBy; 31 import com.android.internal.annotations.VisibleForTesting; 32 33 /** 34 * Defines native calls that are used by state machine/service to either send or receive messages 35 * to/from the native stack. This file is registered for the native methods in corresponding CPP 36 * file. 37 */ 38 public class NativeInterface { 39 private static final String TAG = NativeInterface.class.getSimpleName(); 40 41 private final AdapterService mAdapterService; 42 43 @GuardedBy("INSTANCE_LOCK") 44 private static NativeInterface sInstance; 45 46 private static final Object INSTANCE_LOCK = new Object(); 47 48 @VisibleForTesting NativeInterface(AdapterService adapterService)49 NativeInterface(AdapterService adapterService) { 50 mAdapterService = requireNonNull(adapterService); 51 } 52 53 /** 54 * This class is a singleton because native library should only be loaded once 55 * 56 * @return default instance 57 */ getInstance()58 public static NativeInterface getInstance() { 59 synchronized (INSTANCE_LOCK) { 60 if (sInstance == null) { 61 sInstance = new NativeInterface(AdapterService.getAdapterService()); 62 } 63 return sInstance; 64 } 65 } 66 67 /** Set singleton instance. */ 68 @VisibleForTesting setInstance(NativeInterface instance)69 public static void setInstance(NativeInterface instance) { 70 synchronized (INSTANCE_LOCK) { 71 sInstance = instance; 72 } 73 } 74 75 // Native wrappers to help unit testing 76 /** Initialize native stack */ 77 @VisibleForTesting initialize()78 public void initialize() { 79 initializeNative(); 80 } 81 82 /** Close and clean up native stack */ 83 @VisibleForTesting cleanup()84 public void cleanup() { 85 cleanupNative(); 86 } 87 88 /** 89 * Connect to the specified paired device 90 * 91 * @param device target device 92 * @return True on success, False on failure 93 */ 94 @VisibleForTesting connect(BluetoothDevice device)95 public boolean connect(BluetoothDevice device) { 96 return connectNative(getByteAddress(device)); 97 } 98 99 /** 100 * Disconnect from the specified paired device 101 * 102 * @param device target device 103 * @return True on success, False on failure 104 */ 105 @VisibleForTesting disconnect(BluetoothDevice device)106 public boolean disconnect(BluetoothDevice device) { 107 return disconnectNative(getByteAddress(device)); 108 } 109 110 /** 111 * Initiate audio connection to the specified paired device 112 * 113 * @param device target device 114 * @return True on success, False on failure 115 */ 116 @VisibleForTesting connectAudio(BluetoothDevice device)117 public boolean connectAudio(BluetoothDevice device) { 118 return connectAudioNative(getByteAddress(device)); 119 } 120 121 /** 122 * Close audio connection from the specified paired device 123 * 124 * @param device target device 125 * @return True on success, False on failure 126 */ disconnectAudio(BluetoothDevice device)127 public boolean disconnectAudio(BluetoothDevice device) { 128 return disconnectAudioNative(getByteAddress(device)); 129 } 130 131 /** 132 * Initiate voice recognition to the specified paired device 133 * 134 * @param device target device 135 * @return True on success, False on failure 136 */ 137 @VisibleForTesting startVoiceRecognition(BluetoothDevice device)138 public boolean startVoiceRecognition(BluetoothDevice device) { 139 return startVoiceRecognitionNative(getByteAddress(device)); 140 } 141 142 /** 143 * Close voice recognition to the specified paired device 144 * 145 * @param device target device 146 * @return True on success, False on failure 147 */ 148 @VisibleForTesting stopVoiceRecognition(BluetoothDevice device)149 public boolean stopVoiceRecognition(BluetoothDevice device) { 150 return stopVoiceRecognitionNative(getByteAddress(device)); 151 } 152 153 /** 154 * Set volume to the specified paired device 155 * 156 * @param device target device 157 * @param volumeType type of volume as in HeadsetClientHalConstants.VOLUME_TYPE_xxxx 158 * @param volume volume level 159 * @return True on success, False on failure 160 */ 161 @VisibleForTesting setVolume(BluetoothDevice device, int volumeType, int volume)162 public boolean setVolume(BluetoothDevice device, int volumeType, int volume) { 163 return setVolumeNative(getByteAddress(device), volumeType, volume); 164 } 165 166 /** 167 * dial number from the specified paired device 168 * 169 * @param device target device 170 * @param number phone number to be dialed 171 * @return True on success, False on failure 172 */ 173 @VisibleForTesting dial(BluetoothDevice device, String number)174 public boolean dial(BluetoothDevice device, String number) { 175 return dialNative(getByteAddress(device), number); 176 } 177 178 /** 179 * Memory dialing from the specified paired device 180 * 181 * @param device target device 182 * @param location memory location 183 * @return True on success, False on failure 184 */ 185 @VisibleForTesting dialMemory(BluetoothDevice device, int location)186 public boolean dialMemory(BluetoothDevice device, int location) { 187 return dialMemoryNative(getByteAddress(device), location); 188 } 189 190 /** 191 * Apply action to call 192 * 193 * @param device target device 194 * @param action action (e.g. hold, terminate etc) 195 * @param index call index 196 * @return True on success, False on failure 197 */ 198 @VisibleForTesting handleCallAction(BluetoothDevice device, int action, int index)199 public boolean handleCallAction(BluetoothDevice device, int action, int index) { 200 return handleCallActionNative(getByteAddress(device), action, index); 201 } 202 203 /** 204 * Query current call status from the specified paired device 205 * 206 * @param device target device 207 * @return True on success, False on failure 208 */ 209 @VisibleForTesting queryCurrentCalls(BluetoothDevice device)210 public boolean queryCurrentCalls(BluetoothDevice device) { 211 return queryCurrentCallsNative(getByteAddress(device)); 212 } 213 214 /** 215 * Query operator name from the specified paired device 216 * 217 * @param device target device 218 * @return True on success, False on failure 219 */ 220 @VisibleForTesting queryCurrentOperatorName(BluetoothDevice device)221 public boolean queryCurrentOperatorName(BluetoothDevice device) { 222 return queryCurrentOperatorNameNative(getByteAddress(device)); 223 } 224 225 /** 226 * Retrieve subscriber number from the specified paired device 227 * 228 * @param device target device 229 * @return True on success, False on failure 230 */ 231 @VisibleForTesting retrieveSubscriberInfo(BluetoothDevice device)232 public boolean retrieveSubscriberInfo(BluetoothDevice device) { 233 return retrieveSubscriberInfoNative(getByteAddress(device)); 234 } 235 236 /** 237 * Transmit DTMF code 238 * 239 * @param device target device 240 * @param code DTMF code 241 * @return True on success, False on failure 242 */ 243 @VisibleForTesting sendDtmf(BluetoothDevice device, byte code)244 public boolean sendDtmf(BluetoothDevice device, byte code) { 245 return sendDtmfNative(getByteAddress(device), code); 246 } 247 248 /** 249 * Request last voice tag 250 * 251 * @param device target device 252 * @return True on success, False on failure 253 */ 254 @VisibleForTesting requestLastVoiceTagNumber(BluetoothDevice device)255 public boolean requestLastVoiceTagNumber(BluetoothDevice device) { 256 return requestLastVoiceTagNumberNative(getByteAddress(device)); 257 } 258 259 /** 260 * Send an AT command 261 * 262 * @param device target device 263 * @param atCmd command code 264 * @param val1 command specific argument1 265 * @param val2 command specific argument2 266 * @param arg other command specific arguments 267 * @return True on success, False on failure 268 */ 269 @VisibleForTesting sendATCmd(BluetoothDevice device, int atCmd, int val1, int val2, String arg)270 public boolean sendATCmd(BluetoothDevice device, int atCmd, int val1, int val2, String arg) { 271 return sendATCmdNative(getByteAddress(device), atCmd, val1, val2, arg); 272 } 273 274 /** 275 * Set call audio policy to the specified paired device 276 * 277 * @param cmd Android specific command string 278 * @return True on success, False on failure 279 */ 280 @VisibleForTesting sendAndroidAt(BluetoothDevice device, String cmd)281 public boolean sendAndroidAt(BluetoothDevice device, String cmd) { 282 if (device == null) { 283 Log.w(TAG, "Don't need to send " + cmd + " because no remote device"); 284 return false; 285 } 286 return sendAndroidAtNative(getByteAddress(device), cmd); 287 } 288 289 /**********************************************************************************************/ 290 /******************************************* native *******************************************/ 291 /**********************************************************************************************/ 292 initializeNative()293 private native void initializeNative(); 294 cleanupNative()295 private native void cleanupNative(); 296 connectNative(byte[] address)297 private static native boolean connectNative(byte[] address); 298 disconnectNative(byte[] address)299 private static native boolean disconnectNative(byte[] address); 300 connectAudioNative(byte[] address)301 private static native boolean connectAudioNative(byte[] address); 302 disconnectAudioNative(byte[] address)303 private static native boolean disconnectAudioNative(byte[] address); 304 startVoiceRecognitionNative(byte[] address)305 private static native boolean startVoiceRecognitionNative(byte[] address); 306 stopVoiceRecognitionNative(byte[] address)307 private static native boolean stopVoiceRecognitionNative(byte[] address); 308 setVolumeNative(byte[] address, int volumeType, int volume)309 private static native boolean setVolumeNative(byte[] address, int volumeType, int volume); 310 dialNative(byte[] address, String number)311 private static native boolean dialNative(byte[] address, String number); 312 dialMemoryNative(byte[] address, int location)313 private static native boolean dialMemoryNative(byte[] address, int location); 314 handleCallActionNative(byte[] address, int action, int index)315 private static native boolean handleCallActionNative(byte[] address, int action, int index); 316 queryCurrentCallsNative(byte[] address)317 private static native boolean queryCurrentCallsNative(byte[] address); 318 queryCurrentOperatorNameNative(byte[] address)319 private static native boolean queryCurrentOperatorNameNative(byte[] address); 320 retrieveSubscriberInfoNative(byte[] address)321 private static native boolean retrieveSubscriberInfoNative(byte[] address); 322 sendDtmfNative(byte[] address, byte code)323 private static native boolean sendDtmfNative(byte[] address, byte code); 324 requestLastVoiceTagNumberNative(byte[] address)325 private static native boolean requestLastVoiceTagNumberNative(byte[] address); 326 sendATCmdNative( byte[] address, int atCmd, int val1, int val2, String arg)327 private static native boolean sendATCmdNative( 328 byte[] address, int atCmd, int val1, int val2, String arg); 329 sendAndroidAtNative(byte[] address, String cmd)330 private static native boolean sendAndroidAtNative(byte[] address, String cmd); 331 getDevice(byte[] address)332 private BluetoothDevice getDevice(byte[] address) { 333 return mAdapterService.getDeviceFromByte(address); 334 } 335 getByteAddress(BluetoothDevice device)336 private static byte[] getByteAddress(BluetoothDevice device) { 337 return Utils.getByteBrEdrAddress(device); 338 } 339 340 // Callbacks from the native back into the java framework. All callbacks are routed via the 341 // Service which will disambiguate which state machine the message should be routed through. 342 @VisibleForTesting onConnectionStateChanged(int state, int peerFeat, int chldFeat, byte[] address)343 void onConnectionStateChanged(int state, int peerFeat, int chldFeat, byte[] address) { 344 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); 345 event.valueInt = state; 346 event.valueInt2 = peerFeat; 347 event.valueInt3 = chldFeat; 348 event.device = getDevice(address); 349 // BluetoothAdapter.getDefaultAdapter().getRemoteDevice(Utils.getAddressStringFromByte 350 // (address)); 351 Log.d(TAG, "Device addr " + event.device + " State " + state); 352 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 353 if (service != null) { 354 service.messageFromNative(event); 355 } else { 356 Log.w(TAG, "Ignoring message because service not available: " + event); 357 } 358 } 359 360 @VisibleForTesting onAudioStateChanged(int state, byte[] address)361 void onAudioStateChanged(int state, byte[] address) { 362 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); 363 event.valueInt = state; 364 event.device = getDevice(address); 365 Log.d(TAG, "onAudioStateChanged: event " + event); 366 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 367 if (service != null) { 368 service.messageFromNative(event); 369 } else { 370 Log.w( 371 TAG, 372 "onAudioStateChanged: Ignoring message because service not available: " 373 + event); 374 } 375 } 376 377 @VisibleForTesting onVrStateChanged(int state, byte[] address)378 void onVrStateChanged(int state, byte[] address) { 379 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_VR_STATE_CHANGED); 380 event.valueInt = state; 381 event.device = getDevice(address); 382 Log.d(TAG, "onVrStateChanged: event " + event); 383 384 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 385 if (service != null) { 386 service.messageFromNative(event); 387 } else { 388 Log.w( 389 TAG, 390 "onVrStateChanged: Ignoring message because service not available: " + event); 391 } 392 } 393 394 @VisibleForTesting onNetworkState(int state, byte[] address)395 void onNetworkState(int state, byte[] address) { 396 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_STATE); 397 event.valueInt = state; 398 event.device = getDevice(address); 399 Log.d(TAG, "onNetworkStateChanged: event " + event); 400 401 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 402 if (service != null) { 403 service.messageFromNative(event); 404 } else { 405 Log.w( 406 TAG, 407 "onNetworkStateChanged: Ignoring message because service not available: " 408 + event); 409 } 410 } 411 412 @VisibleForTesting onNetworkRoaming(int state, byte[] address)413 void onNetworkRoaming(int state, byte[] address) { 414 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_ROAMING_STATE); 415 event.valueInt = state; 416 event.device = getDevice(address); 417 Log.d(TAG, "onNetworkRoaming: incoming: " + event); 418 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 419 if (service != null) { 420 service.messageFromNative(event); 421 } else { 422 Log.w( 423 TAG, 424 "onNetworkRoaming: Ignoring message because service not available: " + event); 425 } 426 } 427 428 @VisibleForTesting onNetworkSignal(int signal, byte[] address)429 void onNetworkSignal(int signal, byte[] address) { 430 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_NETWORK_SIGNAL); 431 event.valueInt = signal; 432 event.device = getDevice(address); 433 Log.d(TAG, "onNetworkSignal: event " + event); 434 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 435 if (service != null) { 436 service.messageFromNative(event); 437 } else { 438 Log.w(TAG, "onNetworkSignal: Ignoring message because service not available: " + event); 439 } 440 } 441 442 @VisibleForTesting onBatteryLevel(int level, byte[] address)443 void onBatteryLevel(int level, byte[] address) { 444 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_BATTERY_LEVEL); 445 event.valueInt = level; 446 event.device = getDevice(address); 447 Log.d(TAG, "onBatteryLevel: event " + event); 448 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 449 if (service != null) { 450 service.messageFromNative(event); 451 } else { 452 Log.w(TAG, "onBatteryLevel: Ignoring message because service not available: " + event); 453 } 454 } 455 456 @VisibleForTesting onCurrentOperator(String name, byte[] address)457 void onCurrentOperator(String name, byte[] address) { 458 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_OPERATOR_NAME); 459 event.valueString = name; 460 event.device = getDevice(address); 461 Log.d(TAG, "onCurrentOperator: event " + event); 462 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 463 if (service != null) { 464 service.messageFromNative(event); 465 } else { 466 Log.w( 467 TAG, 468 "onCurrentOperator: Ignoring message because service not available: " + event); 469 } 470 } 471 472 @VisibleForTesting onCall(int call, byte[] address)473 void onCall(int call, byte[] address) { 474 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL); 475 event.valueInt = call; 476 event.device = getDevice(address); 477 Log.d(TAG, "onCall: event " + event); 478 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 479 if (service != null) { 480 service.messageFromNative(event); 481 } else { 482 Log.w(TAG, "onCall: Ignoring message because service not available: " + event); 483 } 484 } 485 486 /** 487 * CIEV (Call indicators) notifying if call(s) are getting set up. 488 * 489 * <p>Values include: 0 - No current call is in setup 1 - Incoming call process ongoing 2 - 490 * Outgoing call process ongoing 3 - Remote party being alerted for outgoing call 491 */ 492 @VisibleForTesting onCallSetup(int callsetup, byte[] address)493 void onCallSetup(int callsetup, byte[] address) { 494 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLSETUP); 495 event.valueInt = callsetup; 496 event.device = getDevice(address); 497 Log.d(TAG, "onCallSetup: device" + event.device); 498 Log.d(TAG, "onCallSetup: event " + event); 499 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 500 if (service != null) { 501 service.messageFromNative(event); 502 } else { 503 Log.w(TAG, "onCallSetup: Ignoring message because service not available: " + event); 504 } 505 } 506 507 /** 508 * CIEV (Call indicators) notifying call held states. 509 * 510 * <p>Values include: 0 - No calls held 1 - Call is placed on hold or active/held calls swapped 511 * (The AG has both an ACTIVE and HELD call) 2 - Call on hold, no active call 512 */ 513 @VisibleForTesting onCallHeld(int callheld, byte[] address)514 void onCallHeld(int callheld, byte[] address) { 515 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALLHELD); 516 event.valueInt = callheld; 517 event.device = getDevice(address); 518 Log.d(TAG, "onCallHeld: event " + event); 519 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 520 if (service != null) { 521 service.messageFromNative(event); 522 } else { 523 Log.w(TAG, "onCallHeld: Ignoring message because service not available: " + event); 524 } 525 } 526 527 @VisibleForTesting onRespAndHold(int respAndHold, byte[] address)528 void onRespAndHold(int respAndHold, byte[] address) { 529 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RESP_AND_HOLD); 530 event.valueInt = respAndHold; 531 event.device = getDevice(address); 532 Log.d(TAG, "onRespAndHold: event " + event); 533 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 534 if (service != null) { 535 service.messageFromNative(event); 536 } else { 537 Log.w(TAG, "onRespAndHold: Ignoring message because service not available: " + event); 538 } 539 } 540 541 @VisibleForTesting onClip(String number, byte[] address)542 void onClip(String number, byte[] address) { 543 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CLIP); 544 event.valueString = number; 545 event.device = getDevice(address); 546 Log.d(TAG, "onClip: event " + event); 547 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 548 if (service != null) { 549 service.messageFromNative(event); 550 } else { 551 Log.w(TAG, "onClip: Ignoring message because service not available: " + event); 552 } 553 } 554 555 @VisibleForTesting onCallWaiting(String number, byte[] address)556 void onCallWaiting(String number, byte[] address) { 557 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CALL_WAITING); 558 event.valueString = number; 559 event.device = getDevice(address); 560 Log.d(TAG, "onCallWaiting: event " + event); 561 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 562 if (service != null) { 563 service.messageFromNative(event); 564 } else { 565 Log.w(TAG, "onCallWaiting: Ignoring message because service not available: " + event); 566 } 567 } 568 569 @VisibleForTesting onCurrentCalls(int index, int dir, int state, int mparty, String number, byte[] address)570 void onCurrentCalls(int index, int dir, int state, int mparty, String number, byte[] address) { 571 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CURRENT_CALLS); 572 event.valueInt = index; 573 event.valueInt2 = dir; 574 event.valueInt3 = state; 575 event.valueInt4 = mparty; 576 event.valueString = number; 577 event.device = getDevice(address); 578 Log.d(TAG, "onCurrentCalls: event " + event); 579 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 580 if (service != null) { 581 service.messageFromNative(event); 582 } else { 583 Log.w(TAG, "onCurrentCalls: Ignoring message because service not available: " + event); 584 } 585 } 586 587 @VisibleForTesting onVolumeChange(int type, int volume, byte[] address)588 void onVolumeChange(int type, int volume, byte[] address) { 589 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_VOLUME_CHANGED); 590 event.valueInt = type; 591 event.valueInt2 = volume; 592 event.device = getDevice(address); 593 Log.d(TAG, "onVolumeChange: event " + event); 594 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 595 if (service != null) { 596 service.messageFromNative(event); 597 } else { 598 Log.w(TAG, "onVolumeChange: Ignoring message because service not available: " + event); 599 } 600 } 601 602 @VisibleForTesting onCmdResult(int type, int cme, byte[] address)603 void onCmdResult(int type, int cme, byte[] address) { 604 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CMD_RESULT); 605 event.valueInt = type; 606 event.valueInt2 = cme; 607 event.device = getDevice(address); 608 Log.d(TAG, "onCmdResult: event " + event); 609 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 610 if (service != null) { 611 service.messageFromNative(event); 612 } else { 613 Log.w(TAG, "onCmdResult: Ignoring message because service not available: " + event); 614 } 615 } 616 617 @VisibleForTesting onSubscriberInfo(String number, int type, byte[] address)618 void onSubscriberInfo(String number, int type, byte[] address) { 619 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_SUBSCRIBER_INFO); 620 event.valueInt = type; 621 event.valueString = number; 622 event.device = getDevice(address); 623 Log.d(TAG, "onSubscriberInfo: event " + event); 624 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 625 if (service != null) { 626 service.messageFromNative(event); 627 } else { 628 Log.w( 629 TAG, 630 "onSubscriberInfo: Ignoring message because service not available: " + event); 631 } 632 } 633 634 @VisibleForTesting onInBandRing(int inBand, byte[] address)635 void onInBandRing(int inBand, byte[] address) { 636 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_IN_BAND_RINGTONE); 637 event.valueInt = inBand; 638 event.device = getDevice(address); 639 Log.d(TAG, "onInBandRing: event " + event); 640 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 641 if (service != null) { 642 service.messageFromNative(event); 643 } else { 644 Log.w(TAG, "onInBandRing: Ignoring message because service not available: " + event); 645 } 646 } 647 648 @VisibleForTesting onLastVoiceTagNumber(String number, byte[] address)649 void onLastVoiceTagNumber(String number, byte[] address) { 650 Log.w(TAG, "onLastVoiceTagNumber not supported"); 651 } 652 653 @VisibleForTesting onRingIndication(byte[] address)654 void onRingIndication(byte[] address) { 655 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_RING_INDICATION); 656 event.device = getDevice(address); 657 Log.d(TAG, "onRingIndication: event " + event); 658 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 659 if (service != null) { 660 service.messageFromNative(event); 661 } else { 662 Log.w( 663 TAG, 664 "onRingIndication: Ignoring message because service not available: " + event); 665 } 666 } 667 668 @VisibleForTesting onUnknownEvent(String eventString, byte[] address)669 void onUnknownEvent(String eventString, byte[] address) { 670 StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_UNKNOWN_EVENT); 671 event.device = getDevice(address); 672 event.valueString = eventString; 673 Log.d(TAG, "onUnknownEvent: event " + event); 674 HeadsetClientService service = HeadsetClientService.getHeadsetClientService(); 675 if (service != null) { 676 service.messageFromNative(event); 677 } else { 678 Log.w(TAG, "onUnknownEvent: Ignoring message because service not available: " + event); 679 } 680 } 681 } 682