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 #include <bluetooth/log.h>
20 #include <jni.h>
21 #include <nativehelper/JNIHelp.h>
22 #include <nativehelper/scoped_local_ref.h>
23
24 #include <cerrno>
25 #include <cstdint>
26 #include <cstring>
27 #include <mutex>
28 #include <shared_mutex>
29
30 #include "com_android_bluetooth.h"
31 #include "hardware/bluetooth.h"
32 #include "hardware/bluetooth_headset_callbacks.h"
33 #include "hardware/bluetooth_headset_interface.h"
34 #include "hardware/bt_hf.h"
35 #include "types/raw_address.h"
36
37 namespace android {
38
39 static jmethodID method_onConnectionStateChanged;
40 static jmethodID method_onAudioStateChanged;
41 static jmethodID method_onVrStateChanged;
42 static jmethodID method_onAnswerCall;
43 static jmethodID method_onHangupCall;
44 static jmethodID method_onVolumeChanged;
45 static jmethodID method_onDialCall;
46 static jmethodID method_onSendDtmf;
47 static jmethodID method_onNoiseReductionEnable;
48 static jmethodID method_onWBS;
49 static jmethodID method_onSWB;
50 static jmethodID method_onAtChld;
51 static jmethodID method_onAtCnum;
52 static jmethodID method_onAtCind;
53 static jmethodID method_onAtCops;
54 static jmethodID method_onAtClcc;
55 static jmethodID method_onUnknownAt;
56 static jmethodID method_onKeyPressed;
57 static jmethodID method_onAtBind;
58 static jmethodID method_onAtBiev;
59 static jmethodID method_onAtBia;
60
61 static bluetooth::headset::Interface* sBluetoothHfpInterface = nullptr;
62 static std::shared_timed_mutex interface_mutex;
63
64 static jobject mCallbacksObj = nullptr;
65 static std::shared_timed_mutex callbacks_mutex;
66
marshall_bda(RawAddress * bd_addr)67 static jbyteArray marshall_bda(RawAddress* bd_addr) {
68 CallbackEnv sCallbackEnv(__func__);
69 if (!sCallbackEnv.valid()) {
70 return nullptr;
71 }
72
73 jbyteArray addr = sCallbackEnv->NewByteArray(sizeof(RawAddress));
74 if (!addr) {
75 log::error("Fail to new jbyteArray bd addr");
76 return nullptr;
77 }
78 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(RawAddress), (jbyte*)bd_addr);
79 return addr;
80 }
81
82 class JniHeadsetCallbacks : bluetooth::headset::Callbacks {
83 public:
GetInstance()84 static bluetooth::headset::Callbacks* GetInstance() {
85 static bluetooth::headset::Callbacks* instance = new JniHeadsetCallbacks();
86 return instance;
87 }
88
ConnectionStateCallback(bluetooth::headset::bthf_connection_state_t state,RawAddress * bd_addr)89 void ConnectionStateCallback(bluetooth::headset::bthf_connection_state_t state,
90 RawAddress* bd_addr) override {
91 log::info("{} for {}", state, *bd_addr);
92
93 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
94 CallbackEnv sCallbackEnv(__func__);
95 if (!sCallbackEnv.valid() || !mCallbacksObj) {
96 return;
97 }
98
99 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
100 if (!addr.get()) {
101 return;
102 }
103
104 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, (jint)state,
105 addr.get());
106 }
107
AudioStateCallback(bluetooth::headset::bthf_audio_state_t state,RawAddress * bd_addr)108 void AudioStateCallback(bluetooth::headset::bthf_audio_state_t state,
109 RawAddress* bd_addr) override {
110 log::info("{} for {}", state, *bd_addr);
111
112 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
113 CallbackEnv sCallbackEnv(__func__);
114 if (!sCallbackEnv.valid() || !mCallbacksObj) {
115 return;
116 }
117
118 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
119 if (!addr.get()) {
120 return;
121 }
122
123 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint)state,
124 addr.get());
125 }
126
VoiceRecognitionCallback(bluetooth::headset::bthf_vr_state_t state,RawAddress * bd_addr)127 void VoiceRecognitionCallback(bluetooth::headset::bthf_vr_state_t state,
128 RawAddress* bd_addr) override {
129 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
130 CallbackEnv sCallbackEnv(__func__);
131 if (!sCallbackEnv.valid() || !mCallbacksObj) {
132 return;
133 }
134
135 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
136 if (!addr.get()) {
137 log::error("Fail to new jbyteArray bd addr for audio state");
138 return;
139 }
140
141 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged, (jint)state, addr.get());
142 }
143
AnswerCallCallback(RawAddress * bd_addr)144 void AnswerCallCallback(RawAddress* bd_addr) override {
145 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
146 CallbackEnv sCallbackEnv(__func__);
147 if (!sCallbackEnv.valid() || !mCallbacksObj) {
148 return;
149 }
150
151 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
152 if (!addr.get()) {
153 log::error("Fail to new jbyteArray bd addr for audio state");
154 return;
155 }
156
157 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAnswerCall, addr.get());
158 }
159
HangupCallCallback(RawAddress * bd_addr)160 void HangupCallCallback(RawAddress* bd_addr) override {
161 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
162 CallbackEnv sCallbackEnv(__func__);
163 if (!sCallbackEnv.valid() || !mCallbacksObj) {
164 return;
165 }
166
167 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
168 if (!addr.get()) {
169 log::error("Fail to new jbyteArray bd addr for audio state");
170 return;
171 }
172
173 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onHangupCall, addr.get());
174 }
175
VolumeControlCallback(bluetooth::headset::bthf_volume_type_t type,int volume,RawAddress * bd_addr)176 void VolumeControlCallback(bluetooth::headset::bthf_volume_type_t type, int volume,
177 RawAddress* bd_addr) override {
178 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
179 CallbackEnv sCallbackEnv(__func__);
180 if (!sCallbackEnv.valid() || !mCallbacksObj) {
181 return;
182 }
183
184 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
185 if (!addr.get()) {
186 log::error("Fail to new jbyteArray bd addr for audio state");
187 return;
188 }
189
190 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChanged, (jint)type, (jint)volume,
191 addr.get());
192 }
193
DialCallCallback(char * number,RawAddress * bd_addr)194 void DialCallCallback(char* number, RawAddress* bd_addr) override {
195 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
196 CallbackEnv sCallbackEnv(__func__);
197 if (!sCallbackEnv.valid() || !mCallbacksObj) {
198 return;
199 }
200
201 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
202 if (!addr.get()) {
203 log::error("Fail to new jbyteArray bd addr for audio state");
204 return;
205 }
206
207 char null_str[] = "";
208 if (!sCallbackEnv.isValidUtf(number)) {
209 log::error("number is not a valid UTF string.");
210 number = null_str;
211 }
212
213 ScopedLocalRef<jstring> js_number(sCallbackEnv.get(), sCallbackEnv->NewStringUTF(number));
214 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDialCall, js_number.get(), addr.get());
215 }
216
DtmfCmdCallback(char dtmf,RawAddress * bd_addr)217 void DtmfCmdCallback(char dtmf, RawAddress* bd_addr) override {
218 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
219 CallbackEnv sCallbackEnv(__func__);
220 if (!sCallbackEnv.valid() || !mCallbacksObj) {
221 return;
222 }
223
224 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
225 if (!addr.get()) {
226 log::error("Fail to new jbyteArray bd addr for audio state");
227 return;
228 }
229
230 // TBD dtmf has changed from int to char
231 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSendDtmf, dtmf, addr.get());
232 }
233
NoiseReductionCallback(bluetooth::headset::bthf_nrec_t nrec,RawAddress * bd_addr)234 void NoiseReductionCallback(bluetooth::headset::bthf_nrec_t nrec, RawAddress* bd_addr) override {
235 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
236 CallbackEnv sCallbackEnv(__func__);
237 if (!sCallbackEnv.valid() || !mCallbacksObj) {
238 return;
239 }
240
241 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
242 if (!addr.get()) {
243 log::error("Fail to new jbyteArray bd addr for audio state");
244 return;
245 }
246 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNoiseReductionEnable,
247 nrec == bluetooth::headset::BTHF_NREC_START, addr.get());
248 }
249
WbsCallback(bluetooth::headset::bthf_wbs_config_t wbs_config,RawAddress * bd_addr)250 void WbsCallback(bluetooth::headset::bthf_wbs_config_t wbs_config, RawAddress* bd_addr) override {
251 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
252 CallbackEnv sCallbackEnv(__func__);
253 if (!sCallbackEnv.valid() || !mCallbacksObj) {
254 return;
255 }
256
257 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
258 if (addr.get() == nullptr) {
259 return;
260 }
261
262 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWBS, wbs_config, addr.get());
263 }
264
SwbCallback(bluetooth::headset::bthf_swb_codec_t swb_codec,bluetooth::headset::bthf_swb_config_t swb_config,RawAddress * bd_addr)265 void SwbCallback(bluetooth::headset::bthf_swb_codec_t swb_codec,
266 bluetooth::headset::bthf_swb_config_t swb_config, RawAddress* bd_addr) override {
267 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
268 CallbackEnv sCallbackEnv(__func__);
269 if (!sCallbackEnv.valid() || !mCallbacksObj) {
270 return;
271 }
272
273 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
274 if (addr.get() == nullptr) {
275 return;
276 }
277
278 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSWB, swb_codec, swb_config, addr.get());
279 }
280
AtChldCallback(bluetooth::headset::bthf_chld_type_t chld,RawAddress * bd_addr)281 void AtChldCallback(bluetooth::headset::bthf_chld_type_t chld, RawAddress* bd_addr) override {
282 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
283 CallbackEnv sCallbackEnv(__func__);
284 if (!sCallbackEnv.valid() || !mCallbacksObj) {
285 return;
286 }
287
288 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(),
289 sCallbackEnv->NewByteArray(sizeof(RawAddress)));
290 if (!addr.get()) {
291 log::error("Fail to new jbyteArray bd addr for audio state");
292 return;
293 }
294
295 sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)bd_addr);
296 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtChld, chld, addr.get());
297 }
298
AtCnumCallback(RawAddress * bd_addr)299 void AtCnumCallback(RawAddress* bd_addr) override {
300 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
301 CallbackEnv sCallbackEnv(__func__);
302 if (!sCallbackEnv.valid() || !mCallbacksObj) {
303 return;
304 }
305
306 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
307 if (!addr.get()) {
308 log::error("Fail to new jbyteArray bd addr for audio state");
309 return;
310 }
311
312 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCnum, addr.get());
313 }
314
AtCindCallback(RawAddress * bd_addr)315 void AtCindCallback(RawAddress* bd_addr) override {
316 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
317 CallbackEnv sCallbackEnv(__func__);
318 if (!sCallbackEnv.valid() || !mCallbacksObj) {
319 return;
320 }
321
322 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
323 if (!addr.get()) {
324 log::error("Fail to new jbyteArray bd addr for audio state");
325 return;
326 }
327
328 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCind, addr.get());
329 }
330
AtCopsCallback(RawAddress * bd_addr)331 void AtCopsCallback(RawAddress* bd_addr) override {
332 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
333 CallbackEnv sCallbackEnv(__func__);
334 if (!sCallbackEnv.valid() || !mCallbacksObj) {
335 return;
336 }
337
338 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
339 if (!addr.get()) {
340 log::error("Fail to new jbyteArray bd addr for audio state");
341 return;
342 }
343
344 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCops, addr.get());
345 }
346
AtClccCallback(RawAddress * bd_addr)347 void AtClccCallback(RawAddress* bd_addr) override {
348 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
349 CallbackEnv sCallbackEnv(__func__);
350 if (!sCallbackEnv.valid() || !mCallbacksObj) {
351 return;
352 }
353
354 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
355 if (!addr.get()) {
356 log::error("Fail to new jbyteArray bd addr for audio state");
357 return;
358 }
359
360 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtClcc, addr.get());
361 }
362
UnknownAtCallback(char * at_string,RawAddress * bd_addr)363 void UnknownAtCallback(char* at_string, RawAddress* bd_addr) override {
364 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
365 CallbackEnv sCallbackEnv(__func__);
366 if (!sCallbackEnv.valid() || !mCallbacksObj) {
367 return;
368 }
369
370 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
371 if (!addr.get()) {
372 log::error("Fail to new jbyteArray bd addr for audio state");
373 return;
374 }
375
376 char null_str[] = "";
377 if (!sCallbackEnv.isValidUtf(at_string)) {
378 log::error("at_string is not a valid UTF string.");
379 at_string = null_str;
380 }
381
382 ScopedLocalRef<jstring> js_at_string(sCallbackEnv.get(), sCallbackEnv->NewStringUTF(at_string));
383 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownAt, js_at_string.get(), addr.get());
384 }
385
KeyPressedCallback(RawAddress * bd_addr)386 void KeyPressedCallback(RawAddress* bd_addr) override {
387 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
388 CallbackEnv sCallbackEnv(__func__);
389 if (!sCallbackEnv.valid() || !mCallbacksObj) {
390 return;
391 }
392
393 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
394 if (!addr.get()) {
395 log::error("Fail to new jbyteArray bd addr for audio state");
396 return;
397 }
398
399 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onKeyPressed, addr.get());
400 }
401
AtBindCallback(char * at_string,RawAddress * bd_addr)402 void AtBindCallback(char* at_string, RawAddress* bd_addr) override {
403 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
404 CallbackEnv sCallbackEnv(__func__);
405 if (!sCallbackEnv.valid() || !mCallbacksObj) {
406 return;
407 }
408
409 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
410 if (addr.get() == nullptr) {
411 return;
412 }
413
414 char null_str[] = "";
415 if (!sCallbackEnv.isValidUtf(at_string)) {
416 log::error("at_string is not a valid UTF string.");
417 at_string = null_str;
418 }
419
420 ScopedLocalRef<jstring> js_at_string(sCallbackEnv.get(), sCallbackEnv->NewStringUTF(at_string));
421
422 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBind, js_at_string.get(), addr.get());
423 }
424
AtBievCallback(bluetooth::headset::bthf_hf_ind_type_t ind_id,int ind_value,RawAddress * bd_addr)425 void AtBievCallback(bluetooth::headset::bthf_hf_ind_type_t ind_id, int ind_value,
426 RawAddress* bd_addr) override {
427 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
428 CallbackEnv sCallbackEnv(__func__);
429 if (!sCallbackEnv.valid() || !mCallbacksObj) {
430 return;
431 }
432
433 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
434 if (addr.get() == nullptr) {
435 return;
436 }
437
438 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBiev, ind_id, (jint)ind_value,
439 addr.get());
440 }
441
AtBiaCallback(bool service,bool roam,bool signal,bool battery,RawAddress * bd_addr)442 void AtBiaCallback(bool service, bool roam, bool signal, bool battery,
443 RawAddress* bd_addr) override {
444 std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex);
445 CallbackEnv sCallbackEnv(__func__);
446 if (!sCallbackEnv.valid() || !mCallbacksObj) {
447 return;
448 }
449
450 ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
451 if (addr.get() == nullptr) {
452 return;
453 }
454
455 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBia, service, roam, signal, battery,
456 addr.get());
457 }
458
DebugDumpCallback(bool,uint16_t,int,double,uint64_t,uint64_t,const char *,const char *)459 void DebugDumpCallback(bool /* active */, uint16_t /* codec_id */,
460 int /* total_num_decoded_frames */, double /* pkt_loss_ratio */,
461 uint64_t /* begin_ts */, uint64_t /* end_ts */,
462 const char* /* pkt_status_in_hex */,
463 const char* /* pkt_status_in_binary */) override {
464 log::error("Not implemented and shouldn't be called");
465 }
466 };
467
initializeNative(JNIEnv * env,jobject object,jint max_hf_clients,jboolean inband_ringing_enabled)468 static void initializeNative(JNIEnv* env, jobject object, jint max_hf_clients,
469 jboolean inband_ringing_enabled) {
470 std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
471 std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
472
473 const bt_interface_t* btInf = getBluetoothInterface();
474 if (!btInf) {
475 log::error("Bluetooth module is not loaded");
476 jniThrowIOException(env, EINVAL);
477 return;
478 }
479
480 if (sBluetoothHfpInterface) {
481 log::info("Cleaning up Bluetooth Handsfree Interface before initializing");
482 sBluetoothHfpInterface->Cleanup();
483 sBluetoothHfpInterface = nullptr;
484 }
485
486 if (mCallbacksObj) {
487 log::info("Cleaning up Bluetooth Handsfree callback object");
488 env->DeleteGlobalRef(mCallbacksObj);
489 mCallbacksObj = nullptr;
490 }
491
492 sBluetoothHfpInterface =
493 (bluetooth::headset::Interface*)btInf->get_profile_interface(BT_PROFILE_HANDSFREE_ID);
494 if (!sBluetoothHfpInterface) {
495 log::warn("Failed to get Bluetooth Handsfree Interface");
496 jniThrowIOException(env, EINVAL);
497 return;
498 }
499 bt_status_t status = sBluetoothHfpInterface->Init(JniHeadsetCallbacks::GetInstance(),
500 max_hf_clients, inband_ringing_enabled);
501 if (status != BT_STATUS_SUCCESS) {
502 log::error("Failed to initialize Bluetooth Handsfree Interface, status: {}",
503 bt_status_text(status));
504 sBluetoothHfpInterface = nullptr;
505 return;
506 }
507
508 mCallbacksObj = env->NewGlobalRef(object);
509 }
510
cleanupNative(JNIEnv * env,jobject)511 static void cleanupNative(JNIEnv* env, jobject /* object */) {
512 std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex);
513 std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex);
514
515 const bt_interface_t* btInf = getBluetoothInterface();
516 if (!btInf) {
517 log::warn("Bluetooth module is not loaded");
518 return;
519 }
520
521 if (sBluetoothHfpInterface) {
522 log::info("Cleaning up Bluetooth Handsfree Interface");
523 sBluetoothHfpInterface->Cleanup();
524 sBluetoothHfpInterface = nullptr;
525 }
526
527 if (mCallbacksObj) {
528 log::info("Cleaning up Bluetooth Handsfree callback object");
529 env->DeleteGlobalRef(mCallbacksObj);
530 mCallbacksObj = nullptr;
531 }
532 }
533
connectHfpNative(JNIEnv * env,jobject,jbyteArray address)534 static jboolean connectHfpNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
535 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
536 if (!sBluetoothHfpInterface) {
537 log::warn("sBluetoothHfpInterface is null");
538 return JNI_FALSE;
539 }
540 jbyte* addr = env->GetByteArrayElements(address, nullptr);
541 if (!addr) {
542 log::error("failed to get device address");
543 jniThrowIOException(env, EINVAL);
544 return JNI_FALSE;
545 }
546 log::info("device {}", *((RawAddress*)addr));
547 bt_status_t status = sBluetoothHfpInterface->Connect((RawAddress*)addr);
548 if (status != BT_STATUS_SUCCESS) {
549 log::error("Failed HF connection, status: {}", bt_status_text(status));
550 }
551 env->ReleaseByteArrayElements(address, addr, 0);
552 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
553 }
554
disconnectHfpNative(JNIEnv * env,jobject,jbyteArray address)555 static jboolean disconnectHfpNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
556 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
557 if (!sBluetoothHfpInterface) {
558 log::warn("sBluetoothHfpInterface is null");
559 return JNI_FALSE;
560 }
561 jbyte* addr = env->GetByteArrayElements(address, nullptr);
562 if (!addr) {
563 log::error("failed to get device address");
564 jniThrowIOException(env, EINVAL);
565 return JNI_FALSE;
566 }
567 log::info("device {}", *((RawAddress*)addr));
568 bt_status_t status = sBluetoothHfpInterface->Disconnect((RawAddress*)addr);
569 if (status != BT_STATUS_SUCCESS) {
570 log::error("Failed HF disconnection, status: {}", bt_status_text(status));
571 }
572 env->ReleaseByteArrayElements(address, addr, 0);
573 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
574 }
575
connectAudioNative(JNIEnv * env,jobject,jbyteArray address)576 static jboolean connectAudioNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
577 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
578 if (!sBluetoothHfpInterface) {
579 log::warn("sBluetoothHfpInterface is null");
580 return JNI_FALSE;
581 }
582 jbyte* addr = env->GetByteArrayElements(address, nullptr);
583 if (!addr) {
584 log::error("failed to get device address");
585 jniThrowIOException(env, EINVAL);
586 return JNI_FALSE;
587 }
588 log::info("device {}", *((RawAddress*)addr));
589 bt_status_t status = sBluetoothHfpInterface->ConnectAudio((RawAddress*)addr, 0);
590 if (status != BT_STATUS_SUCCESS) {
591 log::error("Failed HF audio connection, status: {}", bt_status_text(status));
592 }
593 env->ReleaseByteArrayElements(address, addr, 0);
594 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
595 }
596
disconnectAudioNative(JNIEnv * env,jobject,jbyteArray address)597 static jboolean disconnectAudioNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
598 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
599 if (!sBluetoothHfpInterface) {
600 log::warn("sBluetoothHfpInterface is null");
601 return JNI_FALSE;
602 }
603 jbyte* addr = env->GetByteArrayElements(address, nullptr);
604 if (!addr) {
605 log::error("failed to get device address");
606 jniThrowIOException(env, EINVAL);
607 return JNI_FALSE;
608 }
609 log::info("device {}", *((RawAddress*)addr));
610 bt_status_t status = sBluetoothHfpInterface->DisconnectAudio((RawAddress*)addr);
611 if (status != BT_STATUS_SUCCESS) {
612 log::error("Failed HF audio disconnection, status: {}", bt_status_text(status));
613 }
614 env->ReleaseByteArrayElements(address, addr, 0);
615 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
616 }
617
isNoiseReductionSupportedNative(JNIEnv * env,jobject,jbyteArray address)618 static jboolean isNoiseReductionSupportedNative(JNIEnv* env, jobject /* object */,
619 jbyteArray address) {
620 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
621 if (!sBluetoothHfpInterface) {
622 log::warn("sBluetoothHfpInterface is null");
623 return JNI_FALSE;
624 }
625 jbyte* addr = env->GetByteArrayElements(address, nullptr);
626 if (!addr) {
627 log::error("failed to get device address");
628 jniThrowIOException(env, EINVAL);
629 return JNI_FALSE;
630 }
631 bt_status_t status = sBluetoothHfpInterface->isNoiseReductionSupported((RawAddress*)addr);
632 env->ReleaseByteArrayElements(address, addr, 0);
633 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
634 }
635
isVoiceRecognitionSupportedNative(JNIEnv * env,jobject,jbyteArray address)636 static jboolean isVoiceRecognitionSupportedNative(JNIEnv* env, jobject /* object */,
637 jbyteArray address) {
638 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
639 if (!sBluetoothHfpInterface) {
640 log::warn("sBluetoothHfpInterface is null");
641 return JNI_FALSE;
642 }
643 jbyte* addr = env->GetByteArrayElements(address, nullptr);
644 if (!addr) {
645 log::error("failed to get device address");
646 jniThrowIOException(env, EINVAL);
647 return JNI_FALSE;
648 }
649 bt_status_t status = sBluetoothHfpInterface->isVoiceRecognitionSupported((RawAddress*)addr);
650 env->ReleaseByteArrayElements(address, addr, 0);
651 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
652 }
653
startVoiceRecognitionNative(JNIEnv * env,jobject,jbyteArray address,jboolean sendResult)654 static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject /* object */, jbyteArray address,
655 jboolean sendResult) {
656 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
657 if (!sBluetoothHfpInterface) {
658 log::warn("sBluetoothHfpInterface is null");
659 return JNI_FALSE;
660 }
661 jbyte* addr = env->GetByteArrayElements(address, nullptr);
662 if (!addr) {
663 log::error("failed to get device address");
664 jniThrowIOException(env, EINVAL);
665 return JNI_FALSE;
666 }
667 bt_status_t status = sBluetoothHfpInterface->StartVoiceRecognition((RawAddress*)addr, sendResult);
668 if (status != BT_STATUS_SUCCESS) {
669 log::error("Failed to start voice recognition, status: {}", bt_status_text(status));
670 }
671 env->ReleaseByteArrayElements(address, addr, 0);
672 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
673 }
674
stopVoiceRecognitionNative(JNIEnv * env,jobject,jbyteArray address)675 static jboolean stopVoiceRecognitionNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
676 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
677 if (!sBluetoothHfpInterface) {
678 log::warn("sBluetoothHfpInterface is null");
679 return JNI_FALSE;
680 }
681 jbyte* addr = env->GetByteArrayElements(address, nullptr);
682 if (!addr) {
683 log::error("failed to get device address");
684 jniThrowIOException(env, EINVAL);
685 return JNI_FALSE;
686 }
687 bt_status_t status = sBluetoothHfpInterface->StopVoiceRecognition((RawAddress*)addr);
688 if (status != BT_STATUS_SUCCESS) {
689 log::error("Failed to stop voice recognition, status: {}", bt_status_text(status));
690 }
691 env->ReleaseByteArrayElements(address, addr, 0);
692 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
693 }
694
setVolumeNative(JNIEnv * env,jobject,jint volume_type,jint volume,jbyteArray address)695 static jboolean setVolumeNative(JNIEnv* env, jobject /* object */, jint volume_type, jint volume,
696 jbyteArray address) {
697 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
698 if (!sBluetoothHfpInterface) {
699 log::warn("sBluetoothHfpInterface is null");
700 return JNI_FALSE;
701 }
702 jbyte* addr = env->GetByteArrayElements(address, nullptr);
703 if (!addr) {
704 log::error("failed to get device address");
705 jniThrowIOException(env, EINVAL);
706 return JNI_FALSE;
707 }
708 bt_status_t status = sBluetoothHfpInterface->VolumeControl(
709 (bluetooth::headset::bthf_volume_type_t)volume_type, volume, (RawAddress*)addr);
710 if (status != BT_STATUS_SUCCESS) {
711 log::error("FAILED to control volume, status: {}", bt_status_text(status));
712 }
713 env->ReleaseByteArrayElements(address, addr, 0);
714 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
715 }
716
notifyDeviceStatusNative(JNIEnv * env,jobject,jint network_state,jint service_type,jint signal,jint battery_charge,jbyteArray address)717 static jboolean notifyDeviceStatusNative(JNIEnv* env, jobject /* object */, jint network_state,
718 jint service_type, jint signal, jint battery_charge,
719 jbyteArray address) {
720 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
721 if (!sBluetoothHfpInterface) {
722 log::warn("sBluetoothHfpInterface is null");
723 return JNI_FALSE;
724 }
725 jbyte* addr = env->GetByteArrayElements(address, nullptr);
726 if (!addr) {
727 log::error("failed to get device address");
728 jniThrowIOException(env, EINVAL);
729 return JNI_FALSE;
730 }
731 bt_status_t status = sBluetoothHfpInterface->DeviceStatusNotification(
732 (bluetooth::headset::bthf_network_state_t)network_state,
733 (bluetooth::headset::bthf_service_type_t)service_type, signal, battery_charge,
734 (RawAddress*)addr);
735 env->ReleaseByteArrayElements(address, addr, 0);
736 if (status != BT_STATUS_SUCCESS) {
737 log::error("FAILED to notify device status, status: {}", bt_status_text(status));
738 }
739 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
740 }
741
copsResponseNative(JNIEnv * env,jobject,jstring operator_str,jbyteArray address)742 static jboolean copsResponseNative(JNIEnv* env, jobject /* object */, jstring operator_str,
743 jbyteArray address) {
744 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
745 if (!sBluetoothHfpInterface) {
746 log::warn("sBluetoothHfpInterface is null");
747 return JNI_FALSE;
748 }
749 jbyte* addr = env->GetByteArrayElements(address, nullptr);
750 if (!addr) {
751 log::error("failed to get device address");
752 jniThrowIOException(env, EINVAL);
753 return JNI_FALSE;
754 }
755 const char* operator_name = env->GetStringUTFChars(operator_str, nullptr);
756 bt_status_t status = sBluetoothHfpInterface->CopsResponse(operator_name, (RawAddress*)addr);
757 if (status != BT_STATUS_SUCCESS) {
758 log::error("Failed sending cops response, status: {}", bt_status_text(status));
759 }
760 env->ReleaseByteArrayElements(address, addr, 0);
761 env->ReleaseStringUTFChars(operator_str, operator_name);
762 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
763 }
764
cindResponseNative(JNIEnv * env,jobject,jint service,jint num_active,jint num_held,jint call_state,jint signal,jint roam,jint battery_charge,jbyteArray address)765 static jboolean cindResponseNative(JNIEnv* env, jobject /* object */, jint service, jint num_active,
766 jint num_held, jint call_state, jint signal, jint roam,
767 jint battery_charge, jbyteArray address) {
768 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
769 if (!sBluetoothHfpInterface) {
770 log::warn("sBluetoothHfpInterface is null");
771 return JNI_FALSE;
772 }
773 jbyte* addr = env->GetByteArrayElements(address, nullptr);
774 if (!addr) {
775 log::error("failed to get device address");
776 jniThrowIOException(env, EINVAL);
777 return JNI_FALSE;
778 }
779 bt_status_t status = sBluetoothHfpInterface->CindResponse(
780 service, num_active, num_held, (bluetooth::headset::bthf_call_state_t)call_state, signal,
781 roam, battery_charge, (RawAddress*)addr);
782 if (status != BT_STATUS_SUCCESS) {
783 log::error("failed, status: {}", bt_status_text(status));
784 }
785 env->ReleaseByteArrayElements(address, addr, 0);
786 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
787 }
788
atResponseStringNative(JNIEnv * env,jobject,jstring response_str,jbyteArray address)789 static jboolean atResponseStringNative(JNIEnv* env, jobject /* object */, jstring response_str,
790 jbyteArray address) {
791 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
792 if (!sBluetoothHfpInterface) {
793 log::warn("sBluetoothHfpInterface is null");
794 return JNI_FALSE;
795 }
796 jbyte* addr = env->GetByteArrayElements(address, nullptr);
797 if (!addr) {
798 log::error("failed to get device address");
799 jniThrowIOException(env, EINVAL);
800 return JNI_FALSE;
801 }
802 const char* response = env->GetStringUTFChars(response_str, nullptr);
803 bt_status_t status = sBluetoothHfpInterface->FormattedAtResponse(response, (RawAddress*)addr);
804 if (status != BT_STATUS_SUCCESS) {
805 log::error("Failed formatted AT response, status: {}", bt_status_text(status));
806 }
807 env->ReleaseByteArrayElements(address, addr, 0);
808 env->ReleaseStringUTFChars(response_str, response);
809 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
810 }
811
atResponseCodeNative(JNIEnv * env,jobject,jint response_code,jint cmee_code,jbyteArray address)812 static jboolean atResponseCodeNative(JNIEnv* env, jobject /* object */, jint response_code,
813 jint cmee_code, jbyteArray address) {
814 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
815 if (!sBluetoothHfpInterface) {
816 log::warn("sBluetoothHfpInterface is null");
817 return JNI_FALSE;
818 }
819 jbyte* addr = env->GetByteArrayElements(address, nullptr);
820 if (!addr) {
821 log::error("failed to get device address");
822 jniThrowIOException(env, EINVAL);
823 return JNI_FALSE;
824 }
825 bt_status_t status = sBluetoothHfpInterface->AtResponse(
826 (bluetooth::headset::bthf_at_response_t)response_code, cmee_code, (RawAddress*)addr);
827 if (status != BT_STATUS_SUCCESS) {
828 log::error("Failed AT response, status: {}", bt_status_text(status));
829 }
830 env->ReleaseByteArrayElements(address, addr, 0);
831 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
832 }
833
clccResponseNative(JNIEnv * env,jobject,jint index,jint dir,jint callStatus,jint mode,jboolean mpty,jstring number_str,jint type,jbyteArray address)834 static jboolean clccResponseNative(JNIEnv* env, jobject /* object */, jint index, jint dir,
835 jint callStatus, jint mode, jboolean mpty, jstring number_str,
836 jint type, jbyteArray address) {
837 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
838 if (!sBluetoothHfpInterface) {
839 log::warn("sBluetoothHfpInterface is null");
840 return JNI_FALSE;
841 }
842 jbyte* addr = env->GetByteArrayElements(address, nullptr);
843 if (!addr) {
844 log::error("failed to get device address");
845 jniThrowIOException(env, EINVAL);
846 return JNI_FALSE;
847 }
848 const char* number = nullptr;
849 if (number_str) {
850 number = env->GetStringUTFChars(number_str, nullptr);
851 }
852 bt_status_t status = sBluetoothHfpInterface->ClccResponse(
853 index, (bluetooth::headset::bthf_call_direction_t)dir,
854 (bluetooth::headset::bthf_call_state_t)callStatus,
855 (bluetooth::headset::bthf_call_mode_t)mode,
856 mpty ? bluetooth::headset::BTHF_CALL_MPTY_TYPE_MULTI
857 : bluetooth::headset::BTHF_CALL_MPTY_TYPE_SINGLE,
858 number, (bluetooth::headset::bthf_call_addrtype_t)type, (RawAddress*)addr);
859 if (status != BT_STATUS_SUCCESS) {
860 log::error("Failed sending CLCC response, status: {}", bt_status_text(status));
861 }
862 env->ReleaseByteArrayElements(address, addr, 0);
863 if (number) {
864 env->ReleaseStringUTFChars(number_str, number);
865 }
866 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
867 }
868
phoneStateChangeNative(JNIEnv * env,jobject,jint num_active,jint num_held,jint call_state,jstring number_str,jint type,jstring name_str,jbyteArray address)869 static jboolean phoneStateChangeNative(JNIEnv* env, jobject /* object */, jint num_active,
870 jint num_held, jint call_state, jstring number_str,
871 jint type, jstring name_str, jbyteArray address) {
872 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
873 if (!sBluetoothHfpInterface) {
874 log::warn("sBluetoothHfpInterface is null");
875 return JNI_FALSE;
876 }
877 jbyte* addr = env->GetByteArrayElements(address, nullptr);
878 if (!addr) {
879 log::error("failed to get device address");
880 jniThrowIOException(env, EINVAL);
881 return JNI_FALSE;
882 }
883 const char* number = env->GetStringUTFChars(number_str, nullptr);
884 const char* name = nullptr;
885 if (name_str != nullptr) {
886 name = env->GetStringUTFChars(name_str, nullptr);
887 }
888 bt_status_t status = sBluetoothHfpInterface->PhoneStateChange(
889 num_active, num_held, (bluetooth::headset::bthf_call_state_t)call_state, number,
890 (bluetooth::headset::bthf_call_addrtype_t)type, name, (RawAddress*)addr);
891 if (status != BT_STATUS_SUCCESS) {
892 log::error("Failed report phone state change, status: {}", bt_status_text(status));
893 }
894 env->ReleaseStringUTFChars(number_str, number);
895 if (name != nullptr) {
896 env->ReleaseStringUTFChars(name_str, name);
897 }
898 env->ReleaseByteArrayElements(address, addr, 0);
899 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
900 }
901
setScoAllowedNative(JNIEnv *,jobject,jboolean value)902 static jboolean setScoAllowedNative(JNIEnv* /* env */, jobject /* object */, jboolean value) {
903 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
904 if (!sBluetoothHfpInterface) {
905 log::warn("sBluetoothHfpInterface is null");
906 return JNI_FALSE;
907 }
908 bt_status_t status = sBluetoothHfpInterface->SetScoAllowed(value == JNI_TRUE);
909 if (status != BT_STATUS_SUCCESS) {
910 log::error("Failed HF set sco allowed, status: {}", bt_status_text(status));
911 }
912 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
913 }
914
sendBsirNative(JNIEnv * env,jobject,jboolean value,jbyteArray address)915 static jboolean sendBsirNative(JNIEnv* env, jobject /* object */, jboolean value,
916 jbyteArray address) {
917 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
918 if (!sBluetoothHfpInterface) {
919 log::warn("sBluetoothHfpInterface is null");
920 return JNI_FALSE;
921 }
922 jbyte* addr = env->GetByteArrayElements(address, NULL);
923 if (!addr) {
924 log::error("failed to get device address");
925 jniThrowIOException(env, EINVAL);
926 return JNI_FALSE;
927 }
928 bt_status_t status = sBluetoothHfpInterface->SendBsir(value == JNI_TRUE, (RawAddress*)addr);
929 if (status != BT_STATUS_SUCCESS) {
930 log::error("Failed sending BSIR, value={}, status={}", value, bt_status_text(status));
931 }
932 env->ReleaseByteArrayElements(address, addr, 0);
933 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
934 }
935
setActiveDeviceNative(JNIEnv * env,jobject,jbyteArray address)936 static jboolean setActiveDeviceNative(JNIEnv* env, jobject /* object */, jbyteArray address) {
937 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
938 if (!sBluetoothHfpInterface) {
939 log::warn("sBluetoothHfpInterface is null");
940 return JNI_FALSE;
941 }
942 jbyte* addr = env->GetByteArrayElements(address, NULL);
943 if (!addr) {
944 log::error("failed to get device address");
945 jniThrowIOException(env, EINVAL);
946 return JNI_FALSE;
947 }
948 bt_status_t status = sBluetoothHfpInterface->SetActiveDevice((RawAddress*)addr);
949 if (status != BT_STATUS_SUCCESS) {
950 log::error("Failed to set active device, status: {}", bt_status_text(status));
951 }
952 env->ReleaseByteArrayElements(address, addr, 0);
953 return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
954 }
955
enableSwbNative(JNIEnv * env,jobject,jint swbCodec,jboolean enable,jbyteArray address)956 static jboolean enableSwbNative(JNIEnv* env, jobject /* object */, jint swbCodec, jboolean enable,
957 jbyteArray address) {
958 std::shared_lock<std::shared_timed_mutex> lock(interface_mutex);
959 if (!sBluetoothHfpInterface) {
960 log::warn("sBluetoothHfpInterface is null");
961 return JNI_FALSE;
962 }
963 jbyte* addr = env->GetByteArrayElements(address, NULL);
964 if (!addr) {
965 log::error("failed to get device address");
966 jniThrowIOException(env, EINVAL);
967 return JNI_FALSE;
968 }
969 bt_status_t ret = sBluetoothHfpInterface->EnableSwb(
970 (bluetooth::headset::bthf_swb_codec_t)swbCodec, (bool)enable, (RawAddress*)addr);
971 env->ReleaseByteArrayElements(address, addr, 0);
972 if (ret != BT_STATUS_SUCCESS) {
973 log::error("Failed to {}", (enable ? "enable" : "disable"));
974 return JNI_FALSE;
975 }
976 log::verbose("Successfully {}", (enable ? "enabled" : "disabled"));
977 return JNI_TRUE;
978 }
979
register_com_android_bluetooth_hfp(JNIEnv * env)980 int register_com_android_bluetooth_hfp(JNIEnv* env) {
981 const JNINativeMethod methods[] = {
982 {"initializeNative", "(IZ)V", (void*)initializeNative},
983 {"cleanupNative", "()V", (void*)cleanupNative},
984 {"connectHfpNative", "([B)Z", (void*)connectHfpNative},
985 {"disconnectHfpNative", "([B)Z", (void*)disconnectHfpNative},
986 {"connectAudioNative", "([B)Z", (void*)connectAudioNative},
987 {"disconnectAudioNative", "([B)Z", (void*)disconnectAudioNative},
988 {"isNoiseReductionSupportedNative", "([B)Z", (void*)isNoiseReductionSupportedNative},
989 {"isVoiceRecognitionSupportedNative", "([B)Z", (void*)isVoiceRecognitionSupportedNative},
990 {"startVoiceRecognitionNative", "([BZ)Z", (void*)startVoiceRecognitionNative},
991 {"stopVoiceRecognitionNative", "([B)Z", (void*)stopVoiceRecognitionNative},
992 {"setVolumeNative", "(II[B)Z", (void*)setVolumeNative},
993 {"notifyDeviceStatusNative", "(IIII[B)Z", (void*)notifyDeviceStatusNative},
994 {"copsResponseNative", "(Ljava/lang/String;[B)Z", (void*)copsResponseNative},
995 {"cindResponseNative", "(IIIIIII[B)Z", (void*)cindResponseNative},
996 {"atResponseStringNative", "(Ljava/lang/String;[B)Z", (void*)atResponseStringNative},
997 {"atResponseCodeNative", "(II[B)Z", (void*)atResponseCodeNative},
998 {"clccResponseNative", "(IIIIZLjava/lang/String;I[B)Z", (void*)clccResponseNative},
999 {"phoneStateChangeNative", "(IIILjava/lang/String;ILjava/lang/String;[B)Z",
1000 (void*)phoneStateChangeNative},
1001 {"setScoAllowedNative", "(Z)Z", (void*)setScoAllowedNative},
1002 {"sendBsirNative", "(Z[B)Z", (void*)sendBsirNative},
1003 {"setActiveDeviceNative", "([B)Z", (void*)setActiveDeviceNative},
1004 {"enableSwbNative", "(IZ[B)Z", (void*)enableSwbNative},
1005 };
1006 const int result =
1007 REGISTER_NATIVE_METHODS(env, "com/android/bluetooth/hfp/HeadsetNativeInterface", methods);
1008 if (result != 0) {
1009 return result;
1010 }
1011
1012 const JNIJavaMethod javaMethods[] = {
1013 {"onConnectionStateChanged", "(I[B)V", &method_onConnectionStateChanged},
1014 {"onAudioStateChanged", "(I[B)V", &method_onAudioStateChanged},
1015 {"onVrStateChanged", "(I[B)V", &method_onVrStateChanged},
1016 {"onAnswerCall", "([B)V", &method_onAnswerCall},
1017 {"onHangupCall", "([B)V", &method_onHangupCall},
1018 {"onVolumeChanged", "(II[B)V", &method_onVolumeChanged},
1019 {"onDialCall", "(Ljava/lang/String;[B)V", &method_onDialCall},
1020 {"onSendDtmf", "(I[B)V", &method_onSendDtmf},
1021 {"onNoiseReductionEnable", "(Z[B)V", &method_onNoiseReductionEnable},
1022 {"onWBS", "(I[B)V", &method_onWBS},
1023 {"onSWB", "(II[B)V", &method_onSWB},
1024 {"onAtChld", "(I[B)V", &method_onAtChld},
1025 {"onAtCnum", "([B)V", &method_onAtCnum},
1026 {"onAtCind", "([B)V", &method_onAtCind},
1027 {"onAtCops", "([B)V", &method_onAtCops},
1028 {"onAtClcc", "([B)V", &method_onAtClcc},
1029 {"onUnknownAt", "(Ljava/lang/String;[B)V", &method_onUnknownAt},
1030 {"onKeyPressed", "([B)V", &method_onKeyPressed},
1031 {"onATBind", "(Ljava/lang/String;[B)V", &method_onAtBind},
1032 {"onATBiev", "(II[B)V", &method_onAtBiev},
1033 {"onAtBia", "(ZZZZ[B)V", &method_onAtBia},
1034 };
1035 GET_JAVA_METHODS(env, "com/android/bluetooth/hfp/HeadsetNativeInterface", javaMethods);
1036
1037 return 0;
1038 }
1039
1040 } /* namespace android */
1041