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