• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 namespace android {
31 
32 static jmethodID method_onConnectionStateChanged;
33 static jmethodID method_onAudioStateChanged;
34 static jmethodID method_onVrStateChanged;
35 static jmethodID method_onAnswerCall;
36 static jmethodID method_onHangupCall;
37 static jmethodID method_onVolumeChanged;
38 static jmethodID method_onDialCall;
39 static jmethodID method_onSendDtmf;
40 static jmethodID method_onNoiceReductionEnable;
41 static jmethodID method_onWBS;
42 static jmethodID method_onAtChld;
43 static jmethodID method_onAtCnum;
44 static jmethodID method_onAtCind;
45 static jmethodID method_onAtCops;
46 static jmethodID method_onAtClcc;
47 static jmethodID method_onUnknownAt;
48 static jmethodID method_onKeyPressed;
49 static jmethodID method_onAtBind;
50 static jmethodID method_onAtBiev;
51 
52 static const bthf_interface_t* sBluetoothHfpInterface = NULL;
53 static std::shared_timed_mutex interface_mutex;
54 
55 static jobject mCallbacksObj = NULL;
56 static std::shared_timed_mutex callbacks_mutex;
57 
marshall_bda(bt_bdaddr_t * bd_addr)58 static 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 
connection_state_callback(bthf_connection_state_t state,bt_bdaddr_t * bd_addr)72 static 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 
audio_state_callback(bthf_audio_state_t state,bt_bdaddr_t * bd_addr)87 static 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 
voice_recognition_callback(bthf_vr_state_t state,bt_bdaddr_t * bd_addr)100 static 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 
answer_call_callback(bt_bdaddr_t * bd_addr)116 static 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 
hangup_call_callback(bt_bdaddr_t * bd_addr)130 static 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 
volume_control_callback(bthf_volume_type_t type,int volume,bt_bdaddr_t * bd_addr)144 static 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 
dial_call_callback(char * number,bt_bdaddr_t * bd_addr)160 static 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 
dtmf_cmd_callback(char dtmf,bt_bdaddr_t * bd_addr)177 static 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 
noice_reduction_callback(bthf_nrec_t nrec,bt_bdaddr_t * bd_addr)193 static 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 
wbs_callback(bthf_wbs_config_t wbs_config,bt_bdaddr_t * bd_addr)207 static 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 
at_chld_callback(bthf_chld_type_t chld,bt_bdaddr_t * bd_addr)219 static 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 
at_cnum_callback(bt_bdaddr_t * bd_addr)237 static 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 
at_cind_callback(bt_bdaddr_t * bd_addr)251 static 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 
at_cops_callback(bt_bdaddr_t * bd_addr)265 static 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 
at_clcc_callback(bt_bdaddr_t * bd_addr)279 static 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 
unknown_at_callback(char * at_string,bt_bdaddr_t * bd_addr)293 static 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 
key_pressed_callback(bt_bdaddr_t * bd_addr)310 static 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 
at_bind_callback(char * at_string,bt_bdaddr_t * bd_addr)324 static 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 
at_biev_callback(bthf_hf_ind_type_t ind_id,int ind_value,bt_bdaddr_t * bd_addr)339 static 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 
352 static 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 
classInitNative(JNIEnv * env,jclass clazz)374 static 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 
initializeNative(JNIEnv * env,jobject object,jint max_hf_clients,jboolean inband_ringing_support)406 static 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 
cleanupNative(JNIEnv * env,jobject object)447 static 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 
connectHfpNative(JNIEnv * env,jobject object,jbyteArray address)470 static 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 
disconnectHfpNative(JNIEnv * env,jobject object,jbyteArray address)490 static 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 
connectAudioNative(JNIEnv * env,jobject object,jbyteArray address)509 static 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 
disconnectAudioNative(JNIEnv * env,jobject object,jbyteArray address)529 static 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 
startVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)549 static 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 
stopVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)569 static 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 
setVolumeNative(JNIEnv * env,jobject object,jint volume_type,jint volume,jbyteArray address)589 static 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 
notifyDeviceStatusNative(JNIEnv * env,jobject object,jint network_state,jint service_type,jint signal,jint battery_charge)609 static 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 
copsResponseNative(JNIEnv * env,jobject object,jstring operator_str,jbyteArray address)624 static 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 
cindResponseNative(JNIEnv * env,jobject object,jint service,jint num_active,jint num_held,jint call_state,jint signal,jint roam,jint battery_charge,jbyteArray address)647 static 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 
bindResponseNative(JNIEnv * env,jobject object,jint ind_id,jboolean ind_status,jbyteArray address)672 static 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 
atResponseStringNative(JNIEnv * env,jobject object,jstring response_str,jbyteArray address)697 static 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 
atResponseCodeNative(JNIEnv * env,jobject object,jint response_code,jint cmee_code,jbyteArray address)721 static 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 
clccResponseNative(JNIEnv * env,jobject object,jint index,jint dir,jint callStatus,jint mode,jboolean mpty,jstring number_str,jint type,jbyteArray address)742 static 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 
phoneStateChangeNative(JNIEnv * env,jobject object,jint num_active,jint num_held,jint call_state,jstring number_str,jint type)771 static 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 
configureWBSNative(JNIEnv * env,jobject object,jbyteArray address,jint codec_config)790 static 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 
810 static 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 
register_com_android_bluetooth_hfp(JNIEnv * env)837 int 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