1 /* 2 * Copyright (C) 2012 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 #define LOG_TAG "BluetoothHeadsetServiceJni" 18 19 #define LOG_NDEBUG 0 20 21 #define CHECK_CALLBACK_ENV \ 22 if (!checkCallbackThread()) { \ 23 ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\ 24 return; \ 25 } 26 27 #include "com_android_bluetooth.h" 28 #include "hardware/bt_hf.h" 29 #include "utils/Log.h" 30 #include "android_runtime/AndroidRuntime.h" 31 32 #include <string.h> 33 34 namespace android { 35 36 static jmethodID method_onConnectionStateChanged; 37 static jmethodID method_onAudioStateChanged; 38 static jmethodID method_onVrStateChanged; 39 static jmethodID method_onAnswerCall; 40 static jmethodID method_onHangupCall; 41 static jmethodID method_onVolumeChanged; 42 static jmethodID method_onDialCall; 43 static jmethodID method_onSendDtmf; 44 static jmethodID method_onNoiceReductionEnable; 45 static jmethodID method_onWBS; 46 static jmethodID method_onAtChld; 47 static jmethodID method_onAtCnum; 48 static jmethodID method_onAtCind; 49 static jmethodID method_onAtCops; 50 static jmethodID method_onAtClcc; 51 static jmethodID method_onUnknownAt; 52 static jmethodID method_onKeyPressed; 53 static jmethodID method_onAtBind; 54 static jmethodID method_onAtBiev; 55 56 static const bthf_interface_t *sBluetoothHfpInterface = NULL; 57 static jobject mCallbacksObj = NULL; 58 static JNIEnv *sCallbackEnv = NULL; 59 60 static bool checkCallbackThread() { 61 // Always fetch the latest callbackEnv from AdapterService. 62 // Caching this could cause this sCallbackEnv to go out-of-sync 63 // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event 64 // is received 65 //if (sCallbackEnv == NULL) { 66 sCallbackEnv = getCallbackEnv(); 67 //} 68 JNIEnv* env = AndroidRuntime::getJNIEnv(); 69 if (sCallbackEnv != env || sCallbackEnv == NULL) return false; 70 return true; 71 } 72 73 static jbyteArray marshall_bda(bt_bdaddr_t* bd_addr) 74 { 75 jbyteArray addr; 76 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 77 if (!addr) { 78 ALOGE("Fail to new jbyteArray bd addr"); 79 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 80 return NULL; 81 } 82 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 83 return addr; 84 } 85 86 static void connection_state_callback(bthf_connection_state_t state, bt_bdaddr_t* bd_addr) { 87 jbyteArray addr; 88 89 ALOGI("%s", __FUNCTION__); 90 91 CHECK_CALLBACK_ENV 92 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 93 if (!addr) { 94 ALOGE("Fail to new jbyteArray bd addr for connection state"); 95 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 96 return; 97 } 98 99 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr); 100 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, 101 (jint) state, addr); 102 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 103 sCallbackEnv->DeleteLocalRef(addr); 104 } 105 106 static void audio_state_callback(bthf_audio_state_t state, bt_bdaddr_t* bd_addr) { 107 jbyteArray addr; 108 109 CHECK_CALLBACK_ENV 110 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 111 if (!addr) { 112 ALOGE("Fail to new jbyteArray bd addr for audio state"); 113 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 114 return; 115 } 116 117 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 118 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state, addr); 119 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 120 sCallbackEnv->DeleteLocalRef(addr); 121 } 122 123 static void voice_recognition_callback(bthf_vr_state_t state, bt_bdaddr_t* bd_addr) { 124 jbyteArray addr; 125 126 CHECK_CALLBACK_ENV 127 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 128 if (!addr) { 129 ALOGE("Fail to new jbyteArray bd addr for audio state"); 130 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 131 return; 132 } 133 134 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 135 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged, (jint) state, addr); 136 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 137 sCallbackEnv->DeleteLocalRef(addr); 138 } 139 140 static void answer_call_callback(bt_bdaddr_t* bd_addr) { 141 jbyteArray addr; 142 143 CHECK_CALLBACK_ENV 144 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 145 if (!addr) { 146 ALOGE("Fail to new jbyteArray bd addr for audio state"); 147 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 148 return; 149 } 150 151 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 152 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAnswerCall, addr); 153 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 154 sCallbackEnv->DeleteLocalRef(addr); 155 } 156 157 static void hangup_call_callback(bt_bdaddr_t* bd_addr) { 158 jbyteArray addr; 159 160 CHECK_CALLBACK_ENV 161 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 162 if (!addr) { 163 ALOGE("Fail to new jbyteArray bd addr for audio state"); 164 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 165 return; 166 } 167 168 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 169 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onHangupCall, addr); 170 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 171 sCallbackEnv->DeleteLocalRef(addr); 172 } 173 174 static void volume_control_callback(bthf_volume_type_t type, int volume, bt_bdaddr_t* bd_addr) { 175 jbyteArray addr; 176 177 CHECK_CALLBACK_ENV 178 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 179 if (!addr) { 180 ALOGE("Fail to new jbyteArray bd addr for audio state"); 181 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 182 return; 183 } 184 185 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 186 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChanged, (jint) type, 187 (jint) volume, addr); 188 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 189 sCallbackEnv->DeleteLocalRef(addr); 190 } 191 192 static void dial_call_callback(char *number, bt_bdaddr_t* bd_addr) { 193 jbyteArray addr; 194 195 CHECK_CALLBACK_ENV 196 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 197 if (!addr) { 198 ALOGE("Fail to new jbyteArray bd addr for audio state"); 199 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 200 return; 201 } 202 203 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 204 jstring js_number = sCallbackEnv->NewStringUTF(number); 205 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDialCall, 206 js_number, addr); 207 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 208 sCallbackEnv->DeleteLocalRef(js_number); 209 sCallbackEnv->DeleteLocalRef(addr); 210 } 211 212 static void dtmf_cmd_callback(char dtmf, bt_bdaddr_t* bd_addr) { 213 jbyteArray addr; 214 215 CHECK_CALLBACK_ENV 216 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 217 if (!addr) { 218 ALOGE("Fail to new jbyteArray bd addr for audio state"); 219 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 220 return; 221 } 222 223 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 224 // TBD dtmf has changed from int to char 225 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSendDtmf, dtmf, addr); 226 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 227 sCallbackEnv->DeleteLocalRef(addr); 228 } 229 230 static void noice_reduction_callback(bthf_nrec_t nrec, bt_bdaddr_t* bd_addr) { 231 jbyteArray addr; 232 233 CHECK_CALLBACK_ENV 234 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 235 if (!addr) { 236 ALOGE("Fail to new jbyteArray bd addr for audio state"); 237 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 238 return; 239 } 240 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 241 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNoiceReductionEnable, 242 nrec == BTHF_NREC_START, addr); 243 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 244 sCallbackEnv->DeleteLocalRef(addr); 245 } 246 247 static void wbs_callback(bthf_wbs_config_t wbs_config, bt_bdaddr_t* bd_addr) { 248 jbyteArray addr; 249 250 CHECK_CALLBACK_ENV 251 252 if ((addr = marshall_bda(bd_addr)) == NULL) 253 return; 254 255 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWBS, wbs_config, addr); 256 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 257 sCallbackEnv->DeleteLocalRef(addr); 258 } 259 260 static void at_chld_callback(bthf_chld_type_t chld, bt_bdaddr_t* bd_addr) { 261 jbyteArray addr; 262 263 CHECK_CALLBACK_ENV 264 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 265 if (!addr) { 266 ALOGE("Fail to new jbyteArray bd addr for audio state"); 267 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 268 return; 269 } 270 271 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 272 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtChld, chld, addr); 273 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 274 sCallbackEnv->DeleteLocalRef(addr); 275 } 276 277 static void at_cnum_callback(bt_bdaddr_t* bd_addr) { 278 jbyteArray addr; 279 280 CHECK_CALLBACK_ENV 281 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 282 if (!addr) { 283 ALOGE("Fail to new jbyteArray bd addr for audio state"); 284 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 285 return; 286 } 287 288 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 289 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCnum, addr); 290 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 291 sCallbackEnv->DeleteLocalRef(addr); 292 } 293 294 static void at_cind_callback(bt_bdaddr_t* bd_addr) { 295 jbyteArray addr; 296 297 CHECK_CALLBACK_ENV 298 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 299 if (!addr) { 300 ALOGE("Fail to new jbyteArray bd addr for audio state"); 301 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 302 return; 303 } 304 305 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 306 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCind, addr); 307 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 308 sCallbackEnv->DeleteLocalRef(addr); 309 } 310 311 static void at_cops_callback(bt_bdaddr_t* bd_addr) { 312 jbyteArray addr; 313 314 CHECK_CALLBACK_ENV 315 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 316 if (!addr) { 317 ALOGE("Fail to new jbyteArray bd addr for audio state"); 318 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 319 return; 320 } 321 322 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 323 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCops, addr); 324 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 325 sCallbackEnv->DeleteLocalRef(addr); 326 } 327 328 static void at_clcc_callback(bt_bdaddr_t* bd_addr) { 329 jbyteArray addr; 330 331 CHECK_CALLBACK_ENV 332 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 333 if (!addr) { 334 ALOGE("Fail to new jbyteArray bd addr for audio state"); 335 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 336 return; 337 } 338 339 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 340 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtClcc, addr); 341 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 342 sCallbackEnv->DeleteLocalRef(addr); 343 } 344 345 static void unknown_at_callback(char *at_string, bt_bdaddr_t* bd_addr) { 346 jbyteArray addr; 347 348 CHECK_CALLBACK_ENV 349 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 350 if (!addr) { 351 ALOGE("Fail to new jbyteArray bd addr for audio state"); 352 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 353 return; 354 } 355 356 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 357 jstring js_at_string = sCallbackEnv->NewStringUTF(at_string); 358 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownAt, 359 js_at_string, addr); 360 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 361 sCallbackEnv->DeleteLocalRef(js_at_string); 362 sCallbackEnv->DeleteLocalRef(addr); 363 } 364 365 static void key_pressed_callback(bt_bdaddr_t* bd_addr) { 366 jbyteArray addr; 367 368 CHECK_CALLBACK_ENV 369 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 370 if (!addr) { 371 ALOGE("Fail to new jbyteArray bd addr for audio state"); 372 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 373 return; 374 } 375 376 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 377 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onKeyPressed, addr); 378 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 379 sCallbackEnv->DeleteLocalRef(addr); 380 } 381 382 static void at_bind_callback(char *at_string, bt_bdaddr_t *bd_addr) { 383 CHECK_CALLBACK_ENV 384 385 jbyteArray addr = marshall_bda(bd_addr); 386 if (addr == NULL) 387 return; 388 389 jstring js_at_string = sCallbackEnv->NewStringUTF(at_string); 390 391 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBind, js_at_string, addr); 392 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 393 394 sCallbackEnv->DeleteLocalRef(js_at_string); 395 sCallbackEnv->DeleteLocalRef(addr); 396 } 397 398 static void at_biev_callback(bthf_hf_ind_type_t ind_id, int ind_value, bt_bdaddr_t *bd_addr) { 399 CHECK_CALLBACK_ENV 400 401 jbyteArray addr = marshall_bda(bd_addr); 402 if (addr == NULL) 403 return; 404 405 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBiev, ind_id, (jint)ind_value, addr); 406 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 407 sCallbackEnv->DeleteLocalRef(addr); 408 } 409 410 static bthf_callbacks_t sBluetoothHfpCallbacks = { 411 sizeof(sBluetoothHfpCallbacks), 412 connection_state_callback, 413 audio_state_callback, 414 voice_recognition_callback, 415 answer_call_callback, 416 hangup_call_callback, 417 volume_control_callback, 418 dial_call_callback, 419 dtmf_cmd_callback, 420 noice_reduction_callback, 421 wbs_callback, 422 at_chld_callback, 423 at_cnum_callback, 424 at_cind_callback, 425 at_cops_callback, 426 at_clcc_callback, 427 unknown_at_callback, 428 at_bind_callback, 429 at_biev_callback, 430 key_pressed_callback 431 }; 432 433 static void classInitNative(JNIEnv* env, jclass clazz) { 434 method_onConnectionStateChanged = 435 env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); 436 method_onAudioStateChanged = env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V"); 437 method_onVrStateChanged = env->GetMethodID(clazz, "onVrStateChanged", "(I[B)V"); 438 method_onAnswerCall = env->GetMethodID(clazz, "onAnswerCall", "([B)V"); 439 method_onHangupCall = env->GetMethodID(clazz, "onHangupCall", "([B)V"); 440 method_onVolumeChanged = env->GetMethodID(clazz, "onVolumeChanged", "(II[B)V"); 441 method_onDialCall = env->GetMethodID(clazz, "onDialCall", "(Ljava/lang/String;[B)V"); 442 method_onSendDtmf = env->GetMethodID(clazz, "onSendDtmf", "(I[B)V"); 443 method_onNoiceReductionEnable = env->GetMethodID(clazz, "onNoiceReductionEnable", "(Z[B)V"); 444 method_onWBS = env->GetMethodID(clazz,"onWBS","(I[B)V"); 445 method_onAtChld = env->GetMethodID(clazz, "onAtChld", "(I[B)V"); 446 method_onAtCnum = env->GetMethodID(clazz, "onAtCnum", "([B)V"); 447 method_onAtCind = env->GetMethodID(clazz, "onAtCind", "([B)V"); 448 method_onAtCops = env->GetMethodID(clazz, "onAtCops", "([B)V"); 449 method_onAtClcc = env->GetMethodID(clazz, "onAtClcc", "([B)V"); 450 method_onUnknownAt = env->GetMethodID(clazz, "onUnknownAt", "(Ljava/lang/String;[B)V"); 451 method_onKeyPressed = env->GetMethodID(clazz, "onKeyPressed", "([B)V"); 452 method_onAtBind = env->GetMethodID(clazz, "onATBind", "(Ljava/lang/String;[B)V"); 453 method_onAtBiev = env->GetMethodID(clazz, "onATBiev", "(II[B)V"); 454 455 ALOGI("%s: succeeds", __FUNCTION__); 456 } 457 458 static void initializeNative(JNIEnv *env, jobject object, jint max_hf_clients) { 459 const bt_interface_t* btInf; 460 bt_status_t status; 461 462 if ( (btInf = getBluetoothInterface()) == NULL) { 463 ALOGE("Bluetooth module is not loaded"); 464 return; 465 } 466 467 if (sBluetoothHfpInterface !=NULL) { 468 ALOGW("Cleaning up Bluetooth Handsfree Interface before initializing..."); 469 sBluetoothHfpInterface->cleanup(); 470 sBluetoothHfpInterface = NULL; 471 } 472 473 if (mCallbacksObj != NULL) { 474 ALOGW("Cleaning up Bluetooth Handsfree callback object"); 475 env->DeleteGlobalRef(mCallbacksObj); 476 mCallbacksObj = NULL; 477 } 478 479 if ( (sBluetoothHfpInterface = (bthf_interface_t *) 480 btInf->get_profile_interface(BT_PROFILE_HANDSFREE_ID)) == NULL) { 481 ALOGE("Failed to get Bluetooth Handsfree Interface"); 482 return; 483 } 484 485 if ( (status = sBluetoothHfpInterface->init(&sBluetoothHfpCallbacks, 486 max_hf_clients)) != BT_STATUS_SUCCESS) { 487 ALOGE("Failed to initialize Bluetooth HFP, status: %d", status); 488 sBluetoothHfpInterface = NULL; 489 return; 490 } 491 492 mCallbacksObj = env->NewGlobalRef(object); 493 } 494 495 static void cleanupNative(JNIEnv *env, jobject object) { 496 const bt_interface_t* btInf; 497 498 if ( (btInf = getBluetoothInterface()) == NULL) { 499 ALOGE("Bluetooth module is not loaded"); 500 return; 501 } 502 503 if (sBluetoothHfpInterface !=NULL) { 504 ALOGW("Cleaning up Bluetooth Handsfree Interface..."); 505 sBluetoothHfpInterface->cleanup(); 506 sBluetoothHfpInterface = NULL; 507 } 508 509 if (mCallbacksObj != NULL) { 510 ALOGW("Cleaning up Bluetooth Handsfree callback object"); 511 env->DeleteGlobalRef(mCallbacksObj); 512 mCallbacksObj = NULL; 513 } 514 } 515 516 static jboolean connectHfpNative(JNIEnv *env, jobject object, jbyteArray address) { 517 jbyte *addr; 518 bt_status_t status; 519 520 ALOGI("%s: sBluetoothHfpInterface: %p", __FUNCTION__, sBluetoothHfpInterface); 521 if (!sBluetoothHfpInterface) return JNI_FALSE; 522 523 addr = env->GetByteArrayElements(address, NULL); 524 if (!addr) { 525 jniThrowIOException(env, EINVAL); 526 return JNI_FALSE; 527 } 528 529 if ((status = sBluetoothHfpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { 530 ALOGE("Failed HF connection, status: %d", status); 531 } 532 env->ReleaseByteArrayElements(address, addr, 0); 533 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 534 } 535 536 static jboolean disconnectHfpNative(JNIEnv *env, jobject object, jbyteArray address) { 537 jbyte *addr; 538 bt_status_t status; 539 540 if (!sBluetoothHfpInterface) return JNI_FALSE; 541 542 addr = env->GetByteArrayElements(address, NULL); 543 if (!addr) { 544 jniThrowIOException(env, EINVAL); 545 return JNI_FALSE; 546 } 547 548 if ( (status = sBluetoothHfpInterface->disconnect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { 549 ALOGE("Failed HF disconnection, status: %d", status); 550 } 551 env->ReleaseByteArrayElements(address, addr, 0); 552 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 553 } 554 555 static jboolean connectAudioNative(JNIEnv *env, jobject object, jbyteArray address) { 556 jbyte *addr; 557 bt_status_t status; 558 559 if (!sBluetoothHfpInterface) return JNI_FALSE; 560 561 addr = env->GetByteArrayElements(address, NULL); 562 if (!addr) { 563 jniThrowIOException(env, EINVAL); 564 return JNI_FALSE; 565 } 566 567 if ( (status = sBluetoothHfpInterface->connect_audio((bt_bdaddr_t *)addr)) != 568 BT_STATUS_SUCCESS) { 569 ALOGE("Failed HF audio connection, status: %d", status); 570 } 571 env->ReleaseByteArrayElements(address, addr, 0); 572 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 573 } 574 575 static jboolean disconnectAudioNative(JNIEnv *env, jobject object, jbyteArray address) { 576 jbyte *addr; 577 bt_status_t status; 578 579 if (!sBluetoothHfpInterface) return JNI_FALSE; 580 581 addr = env->GetByteArrayElements(address, NULL); 582 if (!addr) { 583 jniThrowIOException(env, EINVAL); 584 return JNI_FALSE; 585 } 586 587 if ( (status = sBluetoothHfpInterface->disconnect_audio((bt_bdaddr_t *) addr)) != 588 BT_STATUS_SUCCESS) { 589 ALOGE("Failed HF audio disconnection, status: %d", status); 590 } 591 env->ReleaseByteArrayElements(address, addr, 0); 592 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 593 } 594 595 static jboolean startVoiceRecognitionNative(JNIEnv *env, jobject object, jbyteArray address) { 596 jbyte *addr; 597 bt_status_t status; 598 if (!sBluetoothHfpInterface) return JNI_FALSE; 599 600 addr = env->GetByteArrayElements(address, NULL); 601 if (!addr) { 602 jniThrowIOException(env, EINVAL); 603 return JNI_FALSE; 604 } 605 606 if ( (status = sBluetoothHfpInterface->start_voice_recognition((bt_bdaddr_t *) addr)) 607 != BT_STATUS_SUCCESS) { 608 ALOGE("Failed to start voice recognition, status: %d", status); 609 } 610 env->ReleaseByteArrayElements(address, addr, 0); 611 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 612 } 613 614 static jboolean stopVoiceRecognitionNative(JNIEnv *env, jobject object, jbyteArray address) { 615 jbyte *addr; 616 bt_status_t status; 617 if (!sBluetoothHfpInterface) return JNI_FALSE; 618 619 addr = env->GetByteArrayElements(address, NULL); 620 if (!addr) { 621 jniThrowIOException(env, EINVAL); 622 return JNI_FALSE; 623 } 624 625 if ( (status = sBluetoothHfpInterface->stop_voice_recognition((bt_bdaddr_t *) addr)) 626 != BT_STATUS_SUCCESS) { 627 ALOGE("Failed to stop voice recognition, status: %d", status); 628 } 629 env->ReleaseByteArrayElements(address, addr, 0); 630 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 631 } 632 633 static jboolean setVolumeNative(JNIEnv *env, jobject object, jint volume_type, 634 jint volume, jbyteArray address) { 635 jbyte *addr; 636 bt_status_t status; 637 if (!sBluetoothHfpInterface) return JNI_FALSE; 638 639 addr = env->GetByteArrayElements(address, NULL); 640 if (!addr) { 641 jniThrowIOException(env, EINVAL); 642 return JNI_FALSE; 643 } 644 645 if ( (status = sBluetoothHfpInterface->volume_control((bthf_volume_type_t) volume_type, 646 volume, (bt_bdaddr_t *) addr)) != BT_STATUS_SUCCESS) { 647 ALOGE("FAILED to control volume, status: %d", status); 648 } 649 env->ReleaseByteArrayElements(address, addr, 0); 650 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 651 } 652 653 static jboolean notifyDeviceStatusNative(JNIEnv *env, jobject object, 654 jint network_state, jint service_type, jint signal, 655 jint battery_charge) { 656 bt_status_t status; 657 if (!sBluetoothHfpInterface) return JNI_FALSE; 658 659 if ( (status = sBluetoothHfpInterface->device_status_notification 660 ((bthf_network_state_t) network_state, (bthf_service_type_t) service_type, 661 signal, battery_charge)) != BT_STATUS_SUCCESS) { 662 ALOGE("FAILED to notify device status, status: %d", status); 663 } 664 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 665 } 666 667 static jboolean copsResponseNative(JNIEnv *env, jobject object, jstring operator_str, 668 jbyteArray address) { 669 jbyte *addr; 670 bt_status_t status; 671 const char *operator_name; 672 if (!sBluetoothHfpInterface) return JNI_FALSE; 673 674 addr = env->GetByteArrayElements(address, NULL); 675 if (!addr) { 676 jniThrowIOException(env, EINVAL); 677 return JNI_FALSE; 678 } 679 680 operator_name = env->GetStringUTFChars(operator_str, NULL); 681 682 if ( (status = sBluetoothHfpInterface->cops_response(operator_name,(bt_bdaddr_t *) addr)) 683 != BT_STATUS_SUCCESS) { 684 ALOGE("Failed sending cops response, status: %d", status); 685 } 686 env->ReleaseByteArrayElements(address, addr, 0); 687 env->ReleaseStringUTFChars(operator_str, operator_name); 688 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 689 } 690 691 static jboolean cindResponseNative(JNIEnv *env, jobject object, 692 jint service, jint num_active, jint num_held, jint call_state, 693 jint signal, jint roam, jint battery_charge, jbyteArray address) { 694 jbyte *addr; 695 bt_status_t status; 696 697 ALOGI("%s: sBluetoothHfpInterface: %p", __FUNCTION__, sBluetoothHfpInterface); 698 if (!sBluetoothHfpInterface) return JNI_FALSE; 699 700 addr = env->GetByteArrayElements(address, NULL); 701 if (!addr) { 702 jniThrowIOException(env, EINVAL); 703 return JNI_FALSE; 704 } 705 706 if ( (status = sBluetoothHfpInterface->cind_response(service, num_active, num_held, 707 (bthf_call_state_t) call_state, 708 signal, roam, battery_charge, (bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { 709 ALOGE("Failed cind_response, status: %d", status); 710 } 711 env->ReleaseByteArrayElements(address, addr, 0); 712 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 713 } 714 715 static jboolean bindResponseNative(JNIEnv *env,jobject object, 716 jint ind_id, jboolean ind_status, 717 jbyteArray address) { 718 ALOGI("%s: sBluetoothHfpInterface: %p", __FUNCTION__, sBluetoothHfpInterface); 719 720 if (!sBluetoothHfpInterface) 721 return JNI_FALSE; 722 723 jbyte *addr = env->GetByteArrayElements(address, NULL); 724 if (!addr) { 725 jniThrowIOException(env, EINVAL); 726 return JNI_FALSE; 727 } 728 729 bt_status_t status = sBluetoothHfpInterface->bind_response((bthf_hf_ind_type_t) ind_id, 730 ind_status ? BTHF_HF_IND_ENABLED : BTHF_HF_IND_DISABLED, 731 (bt_bdaddr_t *)addr); 732 733 if (status != BT_STATUS_SUCCESS) 734 ALOGE("%s: Failed bind_response, status: %d", __FUNCTION__, status); 735 736 env->ReleaseByteArrayElements(address, addr, 0); 737 return (status == BT_STATUS_SUCCESS ? JNI_TRUE : JNI_FALSE); 738 } 739 740 static jboolean atResponseStringNative(JNIEnv *env, jobject object, jstring response_str, 741 jbyteArray address) { 742 jbyte *addr; 743 bt_status_t status; 744 const char *response; 745 if (!sBluetoothHfpInterface) return JNI_FALSE; 746 747 addr = env->GetByteArrayElements(address, NULL); 748 if (!addr) { 749 jniThrowIOException(env, EINVAL); 750 return JNI_FALSE; 751 } 752 753 response = env->GetStringUTFChars(response_str, NULL); 754 755 if ( (status = sBluetoothHfpInterface->formatted_at_response(response, 756 (bt_bdaddr_t *)addr))!= BT_STATUS_SUCCESS) { 757 ALOGE("Failed formatted AT response, status: %d", status); 758 } 759 env->ReleaseByteArrayElements(address, addr, 0); 760 env->ReleaseStringUTFChars(response_str, response); 761 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 762 } 763 764 static jboolean atResponseCodeNative(JNIEnv *env, jobject object, jint response_code, 765 jint cmee_code, jbyteArray address) { 766 jbyte *addr; 767 bt_status_t status; 768 if (!sBluetoothHfpInterface) return JNI_FALSE; 769 770 addr = env->GetByteArrayElements(address, NULL); 771 if (!addr) { 772 jniThrowIOException(env, EINVAL); 773 return JNI_FALSE; 774 } 775 776 if ( (status = sBluetoothHfpInterface->at_response((bthf_at_response_t) response_code, 777 cmee_code, (bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { 778 ALOGE("Failed AT response, status: %d", status); 779 } 780 env->ReleaseByteArrayElements(address, addr, 0); 781 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 782 } 783 784 static jboolean clccResponseNative(JNIEnv *env, jobject object, jint index, jint dir, 785 jint callStatus, jint mode, jboolean mpty, jstring number_str, 786 jint type, jbyteArray address) { 787 jbyte *addr; 788 bt_status_t status; 789 const char *number = NULL; 790 if (!sBluetoothHfpInterface) return JNI_FALSE; 791 792 addr = env->GetByteArrayElements(address, NULL); 793 if (!addr) { 794 jniThrowIOException(env, EINVAL); 795 return JNI_FALSE; 796 } 797 798 if (number_str) 799 number = env->GetStringUTFChars(number_str, NULL); 800 801 if ( (status = sBluetoothHfpInterface->clcc_response(index, (bthf_call_direction_t) dir, 802 (bthf_call_state_t) callStatus, (bthf_call_mode_t) mode, 803 mpty ? BTHF_CALL_MPTY_TYPE_MULTI : BTHF_CALL_MPTY_TYPE_SINGLE, 804 number, (bthf_call_addrtype_t) type, (bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) { 805 ALOGE("Failed sending CLCC response, status: %d", status); 806 } 807 env->ReleaseByteArrayElements(address, addr, 0); 808 if (number) 809 env->ReleaseStringUTFChars(number_str, number); 810 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 811 } 812 813 static jboolean phoneStateChangeNative(JNIEnv *env, jobject object, jint num_active, jint num_held, 814 jint call_state, jstring number_str, jint type) { 815 bt_status_t status; 816 const char *number; 817 if (!sBluetoothHfpInterface) return JNI_FALSE; 818 819 number = env->GetStringUTFChars(number_str, NULL); 820 821 if ( (status = sBluetoothHfpInterface->phone_state_change(num_active, num_held, 822 (bthf_call_state_t) call_state, number, 823 (bthf_call_addrtype_t) type)) != BT_STATUS_SUCCESS) { 824 ALOGE("Failed report phone state change, status: %d", status); 825 } 826 env->ReleaseStringUTFChars(number_str, number); 827 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 828 } 829 830 831 static jboolean configureWBSNative(JNIEnv *env, jobject object, jbyteArray address, 832 jint codec_config) { 833 jbyte *addr; 834 bt_status_t status; 835 836 if (!sBluetoothHfpInterface) return JNI_FALSE; 837 838 addr = env->GetByteArrayElements(address, NULL); 839 if (!addr) { 840 jniThrowIOException(env, EINVAL); 841 return JNI_FALSE; 842 } 843 844 if ((status = sBluetoothHfpInterface->configure_wbs((bt_bdaddr_t *)addr, 845 (bthf_wbs_config_t)codec_config)) != BT_STATUS_SUCCESS){ 846 ALOGE("Failed HF WBS codec config, status: %d", status); 847 } 848 env->ReleaseByteArrayElements(address, addr, 0); 849 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; 850 } 851 852 853 static JNINativeMethod sMethods[] = { 854 {"classInitNative", "()V", (void *) classInitNative}, 855 {"initializeNative", "(I)V", (void *) initializeNative}, 856 {"cleanupNative", "()V", (void *) cleanupNative}, 857 {"connectHfpNative", "([B)Z", (void *) connectHfpNative}, 858 {"disconnectHfpNative", "([B)Z", (void *) disconnectHfpNative}, 859 {"connectAudioNative", "([B)Z", (void *) connectAudioNative}, 860 {"disconnectAudioNative", "([B)Z", (void *) disconnectAudioNative}, 861 {"startVoiceRecognitionNative", "([B)Z", (void *) startVoiceRecognitionNative}, 862 {"stopVoiceRecognitionNative", "([B)Z", (void *) stopVoiceRecognitionNative}, 863 {"setVolumeNative", "(II[B)Z", (void *) setVolumeNative}, 864 {"notifyDeviceStatusNative", "(IIII)Z", (void *) notifyDeviceStatusNative}, 865 {"copsResponseNative", "(Ljava/lang/String;[B)Z", (void *) copsResponseNative}, 866 {"cindResponseNative", "(IIIIIII[B)Z", (void *) cindResponseNative}, 867 {"bindResponseNative", "(IZ[B)Z", (void *)bindResponseNative}, 868 {"atResponseStringNative", "(Ljava/lang/String;[B)Z", (void *) atResponseStringNative}, 869 {"atResponseCodeNative", "(II[B)Z", (void *)atResponseCodeNative}, 870 {"clccResponseNative", "(IIIIZLjava/lang/String;I[B)Z", (void *) clccResponseNative}, 871 {"phoneStateChangeNative", "(IIILjava/lang/String;I)Z", (void *) phoneStateChangeNative}, 872 {"configureWBSNative", "([BI)Z", (void *) configureWBSNative}, 873 }; 874 875 int register_com_android_bluetooth_hfp(JNIEnv* env) 876 { 877 return jniRegisterNativeMethods(env, "com/android/bluetooth/hfp/HeadsetStateMachine", 878 sMethods, NELEM(sMethods)); 879 } 880 881 } /* namespace android */ 882