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