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