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