• 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 #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