1 /*
2  * Copyright (c) 2014 The Android Open Source Project
3  * Copyright (C) 2012 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #define LOG_TAG "BluetoothHeadsetClientServiceJni"
19 #define LOG_NDEBUG 0
20 
21 #include "com_android_bluetooth.h"
22 #include "hardware/bt_hf_client.h"
23 #include "utils/Log.h"
24 
25 namespace android {
26 
27 static bthf_client_interface_t* sBluetoothHfpClientInterface = NULL;
28 static jobject mCallbacksObj = NULL;
29 
30 static jmethodID method_onConnectionStateChanged;
31 static jmethodID method_onAudioStateChanged;
32 static jmethodID method_onVrStateChanged;
33 static jmethodID method_onNetworkState;
34 static jmethodID method_onNetworkRoaming;
35 static jmethodID method_onNetworkSignal;
36 static jmethodID method_onBatteryLevel;
37 static jmethodID method_onCurrentOperator;
38 static jmethodID method_onCall;
39 static jmethodID method_onCallSetup;
40 static jmethodID method_onCallHeld;
41 static jmethodID method_onRespAndHold;
42 static jmethodID method_onClip;
43 static jmethodID method_onCallWaiting;
44 static jmethodID method_onCurrentCalls;
45 static jmethodID method_onVolumeChange;
46 static jmethodID method_onCmdResult;
47 static jmethodID method_onSubscriberInfo;
48 static jmethodID method_onInBandRing;
49 static jmethodID method_onLastVoiceTagNumber;
50 static jmethodID method_onRingIndication;
51 static jmethodID method_onUnknownEvent;
52 
marshall_bda(const RawAddress * bd_addr)53 static jbyteArray marshall_bda(const RawAddress* bd_addr) {
54   CallbackEnv sCallbackEnv(__func__);
55   if (!sCallbackEnv.valid()) return NULL;
56 
57   jbyteArray addr = sCallbackEnv->NewByteArray(sizeof(RawAddress));
58   if (!addr) {
59     ALOGE("Fail to new jbyteArray bd addr");
60     return NULL;
61   }
62   sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(RawAddress),
63                                    (jbyte*)bd_addr);
64   return addr;
65 }
66 
connection_state_cb(const RawAddress * bd_addr,bthf_client_connection_state_t state,unsigned int peer_feat,unsigned int chld_feat)67 static void connection_state_cb(const RawAddress* bd_addr,
68                                 bthf_client_connection_state_t state,
69                                 unsigned int peer_feat,
70                                 unsigned int chld_feat) {
71   CallbackEnv sCallbackEnv(__func__);
72   if (!sCallbackEnv.valid()) return;
73 
74   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
75   if (!addr.get()) return;
76 
77   ALOGD("%s: state %d peer_feat %d chld_feat %d", __func__, state, peer_feat, chld_feat);
78   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
79                                (jint)state, (jint)peer_feat, (jint)chld_feat,
80                                addr.get());
81 }
82 
audio_state_cb(const RawAddress * bd_addr,bthf_client_audio_state_t state)83 static void audio_state_cb(const RawAddress* bd_addr,
84                            bthf_client_audio_state_t state) {
85   CallbackEnv sCallbackEnv(__func__);
86   if (!sCallbackEnv.valid()) return;
87 
88   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
89   if (!addr.get()) return;
90 
91   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged,
92                                (jint)state, addr.get());
93 }
94 
vr_cmd_cb(const RawAddress * bd_addr,bthf_client_vr_state_t state)95 static void vr_cmd_cb(const RawAddress* bd_addr, bthf_client_vr_state_t state) {
96   CallbackEnv sCallbackEnv(__func__);
97   if (!sCallbackEnv.valid()) return;
98 
99   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
100   if (!addr.get()) return;
101 
102   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged,
103                                (jint)state, addr.get());
104 }
105 
network_state_cb(const RawAddress * bd_addr,bthf_client_network_state_t state)106 static void network_state_cb(const RawAddress* bd_addr,
107                              bthf_client_network_state_t state) {
108   CallbackEnv sCallbackEnv(__func__);
109   if (!sCallbackEnv.valid()) return;
110 
111   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
112   if (!addr.get()) return;
113 
114   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkState,
115                                (jint)state, addr.get());
116 }
117 
network_roaming_cb(const RawAddress * bd_addr,bthf_client_service_type_t type)118 static void network_roaming_cb(const RawAddress* bd_addr,
119                                bthf_client_service_type_t type) {
120   CallbackEnv sCallbackEnv(__func__);
121 
122   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
123   if (!addr.get()) return;
124 
125   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkRoaming,
126                                (jint)type, addr.get());
127 }
128 
network_signal_cb(const RawAddress * bd_addr,int signal)129 static void network_signal_cb(const RawAddress* bd_addr, int signal) {
130   CallbackEnv sCallbackEnv(__func__);
131   if (!sCallbackEnv.valid()) return;
132 
133   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
134   if (!addr.get()) return;
135 
136   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNetworkSignal,
137                                (jint)signal, addr.get());
138 }
139 
battery_level_cb(const RawAddress * bd_addr,int level)140 static void battery_level_cb(const RawAddress* bd_addr, int level) {
141   CallbackEnv sCallbackEnv(__func__);
142   if (!sCallbackEnv.valid()) return;
143 
144   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
145   if (!addr.get()) return;
146 
147   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBatteryLevel,
148                                (jint)level, addr.get());
149 }
150 
current_operator_cb(const RawAddress * bd_addr,const char * name)151 static void current_operator_cb(const RawAddress* bd_addr, const char* name) {
152   CallbackEnv sCallbackEnv(__func__);
153   if (!sCallbackEnv.valid()) return;
154 
155   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
156   if (!addr.get()) return;
157 
158   const char null_str[] = "";
159   if (!sCallbackEnv.isValidUtf(name)) {
160     android_errorWriteLog(0x534e4554, "109838537");
161     ALOGE("%s: name is not a valid UTF string.", __func__);
162     name = null_str;
163   }
164 
165   ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
166                                   sCallbackEnv->NewStringUTF(name));
167   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentOperator,
168                                js_name.get(), addr.get());
169 }
170 
call_cb(const RawAddress * bd_addr,bthf_client_call_t call)171 static void call_cb(const RawAddress* bd_addr, bthf_client_call_t call) {
172   CallbackEnv sCallbackEnv(__func__);
173   if (!sCallbackEnv.valid()) return;
174 
175   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
176   if (!addr.get()) return;
177 
178   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCall, (jint)call,
179                                addr.get());
180 }
181 
callsetup_cb(const RawAddress * bd_addr,bthf_client_callsetup_t callsetup)182 static void callsetup_cb(const RawAddress* bd_addr,
183                          bthf_client_callsetup_t callsetup) {
184   CallbackEnv sCallbackEnv(__func__);
185   if (!sCallbackEnv.valid()) return;
186 
187   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
188   if (!addr.get()) return;
189 
190   ALOGD("callsetup_cb bdaddr %02x:%02x:%02x:%02x:%02x:%02x",
191         bd_addr->address[0], bd_addr->address[1], bd_addr->address[2],
192         bd_addr->address[3], bd_addr->address[4], bd_addr->address[5]);
193 
194   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallSetup,
195                                (jint)callsetup, addr.get());
196 }
197 
callheld_cb(const RawAddress * bd_addr,bthf_client_callheld_t callheld)198 static void callheld_cb(const RawAddress* bd_addr,
199                         bthf_client_callheld_t callheld) {
200   CallbackEnv sCallbackEnv(__func__);
201   if (!sCallbackEnv.valid()) return;
202 
203   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
204   if (!addr.get()) return;
205 
206   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallHeld, (jint)callheld,
207                                addr.get());
208 }
209 
resp_and_hold_cb(const RawAddress * bd_addr,bthf_client_resp_and_hold_t resp_and_hold)210 static void resp_and_hold_cb(const RawAddress* bd_addr,
211                              bthf_client_resp_and_hold_t resp_and_hold) {
212   CallbackEnv sCallbackEnv(__func__);
213   if (!sCallbackEnv.valid()) return;
214 
215   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
216   if (!addr.get()) return;
217 
218   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRespAndHold,
219                                (jint)resp_and_hold, addr.get());
220 }
221 
clip_cb(const RawAddress * bd_addr,const char * number)222 static void clip_cb(const RawAddress* bd_addr, const char* number) {
223   CallbackEnv sCallbackEnv(__func__);
224   if (!sCallbackEnv.valid()) return;
225 
226   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
227   if (!addr.get()) return;
228 
229   const char null_str[] = "";
230   if (!sCallbackEnv.isValidUtf(number)) {
231     android_errorWriteLog(0x534e4554, "109838537");
232     ALOGE("%s: number is not a valid UTF string.", __func__);
233     number = null_str;
234   }
235 
236   ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
237                                     sCallbackEnv->NewStringUTF(number));
238   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClip, js_number.get(),
239                                addr.get());
240 }
241 
call_waiting_cb(const RawAddress * bd_addr,const char * number)242 static void call_waiting_cb(const RawAddress* bd_addr, const char* number) {
243   CallbackEnv sCallbackEnv(__func__);
244   if (!sCallbackEnv.valid()) return;
245 
246   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
247   if (!addr.get()) return;
248 
249   const char null_str[] = "";
250   if (!sCallbackEnv.isValidUtf(number)) {
251     android_errorWriteLog(0x534e4554, "109838537");
252     ALOGE("%s: number is not a valid UTF string.", __func__);
253     number = null_str;
254   }
255 
256   ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
257                                     sCallbackEnv->NewStringUTF(number));
258   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCallWaiting,
259                                js_number.get(), addr.get());
260 }
261 
current_calls_cb(const RawAddress * bd_addr,int index,bthf_client_call_direction_t dir,bthf_client_call_state_t state,bthf_client_call_mpty_type_t mpty,const char * number)262 static void current_calls_cb(const RawAddress* bd_addr, int index,
263                              bthf_client_call_direction_t dir,
264                              bthf_client_call_state_t state,
265                              bthf_client_call_mpty_type_t mpty,
266                              const char* number) {
267   CallbackEnv sCallbackEnv(__func__);
268   if (!sCallbackEnv.valid()) return;
269 
270   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
271   if (!addr.get()) return;
272 
273   const char null_str[] = "";
274   if (!sCallbackEnv.isValidUtf(number)) {
275     android_errorWriteLog(0x534e4554, "109838537");
276     ALOGE("%s: number is not a valid UTF string.", __func__);
277     number = null_str;
278   }
279 
280   ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
281                                     sCallbackEnv->NewStringUTF(number));
282   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCurrentCalls, index, dir,
283                                state, mpty, js_number.get(), addr.get());
284 }
285 
volume_change_cb(const RawAddress * bd_addr,bthf_client_volume_type_t type,int volume)286 static void volume_change_cb(const RawAddress* bd_addr,
287                              bthf_client_volume_type_t type, int volume) {
288   CallbackEnv sCallbackEnv(__func__);
289   if (!sCallbackEnv.valid()) return;
290 
291   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
292   if (!addr.get()) return;
293   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChange, (jint)type,
294                                (jint)volume, addr.get());
295 }
296 
cmd_complete_cb(const RawAddress * bd_addr,bthf_client_cmd_complete_t type,int cme)297 static void cmd_complete_cb(const RawAddress* bd_addr,
298                             bthf_client_cmd_complete_t type, int cme) {
299   CallbackEnv sCallbackEnv(__func__);
300   if (!sCallbackEnv.valid()) return;
301 
302   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
303   if (!addr.get()) return;
304   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCmdResult, (jint)type,
305                                (jint)cme, addr.get());
306 }
307 
subscriber_info_cb(const RawAddress * bd_addr,const char * name,bthf_client_subscriber_service_type_t type)308 static void subscriber_info_cb(const RawAddress* bd_addr, const char* name,
309                                bthf_client_subscriber_service_type_t type) {
310   CallbackEnv sCallbackEnv(__func__);
311   if (!sCallbackEnv.valid()) return;
312 
313   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
314   if (!addr.get()) return;
315 
316   const char null_str[] = "";
317   if (!sCallbackEnv.isValidUtf(name)) {
318     android_errorWriteLog(0x534e4554, "109838537");
319     ALOGE("%s: name is not a valid UTF string.", __func__);
320     name = null_str;
321   }
322 
323   ScopedLocalRef<jstring> js_name(sCallbackEnv.get(),
324                                   sCallbackEnv->NewStringUTF(name));
325   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSubscriberInfo,
326                                js_name.get(), (jint)type, addr.get());
327 }
328 
in_band_ring_cb(const RawAddress * bd_addr,bthf_client_in_band_ring_state_t in_band)329 static void in_band_ring_cb(const RawAddress* bd_addr,
330                             bthf_client_in_band_ring_state_t in_band) {
331   CallbackEnv sCallbackEnv(__func__);
332   if (!sCallbackEnv.valid()) return;
333 
334   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
335   if (!addr.get()) return;
336   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onInBandRing,
337                                (jint)in_band, addr.get());
338 }
339 
last_voice_tag_number_cb(const RawAddress * bd_addr,const char * number)340 static void last_voice_tag_number_cb(const RawAddress* bd_addr,
341                                      const char* number) {
342   CallbackEnv sCallbackEnv(__func__);
343   if (!sCallbackEnv.valid()) return;
344 
345   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
346   if (!addr.get()) return;
347 
348   const char null_str[] = "";
349   if (!sCallbackEnv.isValidUtf(number)) {
350     android_errorWriteLog(0x534e4554, "109838537");
351     ALOGE("%s: number is not a valid UTF string.", __func__);
352     number = null_str;
353   }
354 
355   ScopedLocalRef<jstring> js_number(sCallbackEnv.get(),
356                                     sCallbackEnv->NewStringUTF(number));
357   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLastVoiceTagNumber,
358                                js_number.get(), addr.get());
359 }
360 
ring_indication_cb(const RawAddress * bd_addr)361 static void ring_indication_cb(const RawAddress* bd_addr) {
362   CallbackEnv sCallbackEnv(__func__);
363   if (!sCallbackEnv.valid()) return;
364 
365   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
366   if (!addr.get()) return;
367   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onRingIndication,
368                                addr.get());
369 }
370 
unknown_event_cb(const RawAddress * bd_addr,const char * eventString)371 static void unknown_event_cb(const RawAddress* bd_addr,
372                              const char* eventString) {
373   CallbackEnv sCallbackEnv(__func__);
374   if (!sCallbackEnv.valid()) return;
375 
376   ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
377   if (!addr.get()) return;
378 
379   ScopedLocalRef<jstring> js_event(sCallbackEnv.get(),
380                                    sCallbackEnv->NewStringUTF(eventString));
381   sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownEvent,
382                                js_event.get(), addr.get());
383 }
384 
385 static bthf_client_callbacks_t sBluetoothHfpClientCallbacks = {
386     sizeof(sBluetoothHfpClientCallbacks),
387     connection_state_cb,
388     audio_state_cb,
389     vr_cmd_cb,
390     network_state_cb,
391     network_roaming_cb,
392     network_signal_cb,
393     battery_level_cb,
394     current_operator_cb,
395     call_cb,
396     callsetup_cb,
397     callheld_cb,
398     resp_and_hold_cb,
399     clip_cb,
400     call_waiting_cb,
401     current_calls_cb,
402     volume_change_cb,
403     cmd_complete_cb,
404     subscriber_info_cb,
405     in_band_ring_cb,
406     last_voice_tag_number_cb,
407     ring_indication_cb,
408     unknown_event_cb,
409 };
410 
classInitNative(JNIEnv * env,jclass clazz)411 static void classInitNative(JNIEnv* env, jclass clazz) {
412   method_onConnectionStateChanged =
413       env->GetMethodID(clazz, "onConnectionStateChanged", "(III[B)V");
414   method_onAudioStateChanged =
415       env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");
416   method_onVrStateChanged =
417       env->GetMethodID(clazz, "onVrStateChanged", "(I[B)V");
418   method_onNetworkState = env->GetMethodID(clazz, "onNetworkState", "(I[B)V");
419   method_onNetworkRoaming = env->GetMethodID(clazz, "onNetworkRoaming", "(I[B)V");
420   method_onNetworkSignal = env->GetMethodID(clazz, "onNetworkSignal", "(I[B)V");
421   method_onBatteryLevel = env->GetMethodID(clazz, "onBatteryLevel", "(I[B)V");
422   method_onCurrentOperator =
423       env->GetMethodID(clazz, "onCurrentOperator", "(Ljava/lang/String;[B)V");
424   method_onCall = env->GetMethodID(clazz, "onCall", "(I[B)V");
425   method_onCallSetup = env->GetMethodID(clazz, "onCallSetup", "(I[B)V");
426   method_onCallHeld = env->GetMethodID(clazz, "onCallHeld", "(I[B)V");
427   method_onRespAndHold = env->GetMethodID(clazz, "onRespAndHold", "(I[B)V");
428   method_onClip = env->GetMethodID(clazz, "onClip", "(Ljava/lang/String;[B)V");
429   method_onCallWaiting =
430       env->GetMethodID(clazz, "onCallWaiting", "(Ljava/lang/String;[B)V");
431   method_onCurrentCalls =
432       env->GetMethodID(clazz, "onCurrentCalls", "(IIIILjava/lang/String;[B)V");
433   method_onVolumeChange = env->GetMethodID(clazz, "onVolumeChange", "(II[B)V");
434   method_onCmdResult = env->GetMethodID(clazz, "onCmdResult", "(II[B)V");
435   method_onSubscriberInfo =
436       env->GetMethodID(clazz, "onSubscriberInfo", "(Ljava/lang/String;I[B)V");
437   method_onInBandRing = env->GetMethodID(clazz, "onInBandRing", "(I[B)V");
438   method_onLastVoiceTagNumber =
439       env->GetMethodID(clazz, "onLastVoiceTagNumber", "(Ljava/lang/String;[B)V");
440   method_onRingIndication = env->GetMethodID(clazz, "onRingIndication", "([B)V");
441   method_onUnknownEvent =
442       env->GetMethodID(clazz, "onUnknownEvent", "(Ljava/lang/String;[B)V");
443 
444   ALOGI("%s succeeds", __func__);
445 }
446 
initializeNative(JNIEnv * env,jobject object)447 static void initializeNative(JNIEnv* env, jobject object) {
448   ALOGD("%s: HfpClient", __func__);
449   const bt_interface_t* btInf = getBluetoothInterface();
450   if (btInf == NULL) {
451     ALOGE("Bluetooth module is not loaded");
452     return;
453   }
454 
455   if (sBluetoothHfpClientInterface != NULL) {
456     ALOGW("Cleaning up Bluetooth HFP Client Interface before initializing");
457     sBluetoothHfpClientInterface->cleanup();
458     sBluetoothHfpClientInterface = NULL;
459   }
460 
461   if (mCallbacksObj != NULL) {
462     ALOGW("Cleaning up Bluetooth HFP Client callback object");
463     env->DeleteGlobalRef(mCallbacksObj);
464     mCallbacksObj = NULL;
465   }
466 
467   sBluetoothHfpClientInterface =
468       (bthf_client_interface_t*)btInf->get_profile_interface(
469           BT_PROFILE_HANDSFREE_CLIENT_ID);
470   if (sBluetoothHfpClientInterface == NULL) {
471     ALOGE("Failed to get Bluetooth HFP Client Interface");
472     return;
473   }
474 
475   bt_status_t status =
476       sBluetoothHfpClientInterface->init(&sBluetoothHfpClientCallbacks);
477   if (status != BT_STATUS_SUCCESS) {
478     ALOGE("Failed to initialize Bluetooth HFP Client, status: %d", status);
479     sBluetoothHfpClientInterface = NULL;
480     return;
481   }
482 
483   mCallbacksObj = env->NewGlobalRef(object);
484 }
485 
cleanupNative(JNIEnv * env,jobject object)486 static void cleanupNative(JNIEnv* env, jobject object) {
487   const bt_interface_t* btInf = getBluetoothInterface();
488   if (btInf == NULL) {
489     ALOGE("Bluetooth module is not loaded");
490     return;
491   }
492 
493   if (sBluetoothHfpClientInterface != NULL) {
494     ALOGW("Cleaning up Bluetooth HFP Client Interface...");
495     sBluetoothHfpClientInterface->cleanup();
496     sBluetoothHfpClientInterface = NULL;
497   }
498 
499   if (mCallbacksObj != NULL) {
500     ALOGW("Cleaning up Bluetooth HFP Client callback object");
501     env->DeleteGlobalRef(mCallbacksObj);
502     mCallbacksObj = NULL;
503   }
504 }
505 
connectNative(JNIEnv * env,jobject object,jbyteArray address)506 static jboolean connectNative(JNIEnv* env, jobject object, jbyteArray address) {
507   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
508 
509   jbyte* addr = env->GetByteArrayElements(address, NULL);
510   if (!addr) {
511     jniThrowIOException(env, EINVAL);
512     return JNI_FALSE;
513   }
514 
515   bt_status_t status = sBluetoothHfpClientInterface->connect((RawAddress*)addr);
516   if (status != BT_STATUS_SUCCESS) {
517     ALOGE("Failed AG connection, status: %d", status);
518   }
519   env->ReleaseByteArrayElements(address, addr, 0);
520   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
521 }
522 
disconnectNative(JNIEnv * env,jobject object,jbyteArray address)523 static jboolean disconnectNative(JNIEnv* env, jobject object,
524                                  jbyteArray address) {
525   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
526 
527   jbyte* addr = env->GetByteArrayElements(address, NULL);
528   if (!addr) {
529     jniThrowIOException(env, EINVAL);
530     return JNI_FALSE;
531   }
532 
533   bt_status_t status =
534       sBluetoothHfpClientInterface->disconnect((const RawAddress*)addr);
535   if (status != BT_STATUS_SUCCESS) {
536     ALOGE("Failed AG disconnection, status: %d", status);
537   }
538   env->ReleaseByteArrayElements(address, addr, 0);
539   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
540 }
541 
connectAudioNative(JNIEnv * env,jobject object,jbyteArray address)542 static jboolean connectAudioNative(JNIEnv* env, jobject object,
543                                    jbyteArray address) {
544   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
545 
546   jbyte* addr = env->GetByteArrayElements(address, NULL);
547   if (!addr) {
548     jniThrowIOException(env, EINVAL);
549     return JNI_FALSE;
550   }
551 
552   bt_status_t status =
553       sBluetoothHfpClientInterface->connect_audio((const RawAddress*)addr);
554   if (status != BT_STATUS_SUCCESS) {
555     ALOGE("Failed AG audio connection, status: %d", status);
556   }
557   env->ReleaseByteArrayElements(address, addr, 0);
558   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
559 }
560 
disconnectAudioNative(JNIEnv * env,jobject object,jbyteArray address)561 static jboolean disconnectAudioNative(JNIEnv* env, jobject object,
562                                       jbyteArray address) {
563   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
564 
565   jbyte* addr = env->GetByteArrayElements(address, NULL);
566   if (!addr) {
567     jniThrowIOException(env, EINVAL);
568     return JNI_FALSE;
569   }
570 
571   bt_status_t status =
572       sBluetoothHfpClientInterface->disconnect_audio((const RawAddress*)addr);
573   if (status != BT_STATUS_SUCCESS) {
574     ALOGE("Failed AG audio disconnection, status: %d", status);
575   }
576   env->ReleaseByteArrayElements(address, addr, 0);
577   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
578 }
579 
startVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)580 static jboolean startVoiceRecognitionNative(JNIEnv* env, jobject object,
581                                             jbyteArray address) {
582   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
583 
584   jbyte* addr = env->GetByteArrayElements(address, NULL);
585   if (!addr) {
586     jniThrowIOException(env, EINVAL);
587     return JNI_FALSE;
588   }
589 
590   bt_status_t status = sBluetoothHfpClientInterface->start_voice_recognition(
591       (const RawAddress*)addr);
592   if (status != BT_STATUS_SUCCESS) {
593     ALOGE("Failed to start voice recognition, status: %d", status);
594   }
595   env->ReleaseByteArrayElements(address, addr, 0);
596   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
597 }
598 
stopVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)599 static jboolean stopVoiceRecognitionNative(JNIEnv* env, jobject object,
600                                            jbyteArray address) {
601   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
602 
603   jbyte* addr = env->GetByteArrayElements(address, NULL);
604   if (!addr) {
605     jniThrowIOException(env, EINVAL);
606     return JNI_FALSE;
607   }
608 
609   bt_status_t status = sBluetoothHfpClientInterface->stop_voice_recognition(
610       (const RawAddress*)addr);
611   if (status != BT_STATUS_SUCCESS) {
612     ALOGE("Failed to stop voice recognition, status: %d", status);
613   }
614   env->ReleaseByteArrayElements(address, addr, 0);
615   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
616 }
617 
setVolumeNative(JNIEnv * env,jobject object,jbyteArray address,jint volume_type,jint volume)618 static jboolean setVolumeNative(JNIEnv* env, jobject object, jbyteArray address,
619                                 jint volume_type, jint volume) {
620   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
621 
622   jbyte* addr = env->GetByteArrayElements(address, NULL);
623   if (!addr) {
624     jniThrowIOException(env, EINVAL);
625     return JNI_FALSE;
626   }
627 
628   bt_status_t status = sBluetoothHfpClientInterface->volume_control(
629       (const RawAddress*)addr, (bthf_client_volume_type_t)volume_type, volume);
630   if (status != BT_STATUS_SUCCESS) {
631     ALOGE("FAILED to control volume, status: %d", status);
632   }
633   env->ReleaseByteArrayElements(address, addr, 0);
634   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
635 }
636 
dialNative(JNIEnv * env,jobject object,jbyteArray address,jstring number_str)637 static jboolean dialNative(JNIEnv* env, jobject object, jbyteArray address,
638                            jstring number_str) {
639   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
640 
641   jbyte* addr = env->GetByteArrayElements(address, NULL);
642   if (!addr) {
643     jniThrowIOException(env, EINVAL);
644     return JNI_FALSE;
645   }
646 
647   const char* number = nullptr;
648   if (number_str != nullptr) {
649     number = env->GetStringUTFChars(number_str, nullptr);
650   }
651   bt_status_t status =
652     sBluetoothHfpClientInterface->dial((const RawAddress*)addr,
653                                        number == nullptr ? "" : number);
654 
655   if (status != BT_STATUS_SUCCESS) {
656     ALOGE("Failed to dial, status: %d", status);
657   }
658   if (number != nullptr) {
659     env->ReleaseStringUTFChars(number_str, number);
660   }
661   env->ReleaseByteArrayElements(address, addr, 0);
662   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
663 }
664 
dialMemoryNative(JNIEnv * env,jobject object,jbyteArray address,jint location)665 static jboolean dialMemoryNative(JNIEnv* env, jobject object,
666                                  jbyteArray address, jint location) {
667   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
668 
669   jbyte* addr = env->GetByteArrayElements(address, NULL);
670   if (!addr) {
671     jniThrowIOException(env, EINVAL);
672     return JNI_FALSE;
673   }
674 
675   bt_status_t status = sBluetoothHfpClientInterface->dial_memory(
676       (const RawAddress*)addr, (int)location);
677   if (status != BT_STATUS_SUCCESS) {
678     ALOGE("Failed to dial from memory, status: %d", status);
679   }
680 
681   env->ReleaseByteArrayElements(address, addr, 0);
682   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
683 }
684 
handleCallActionNative(JNIEnv * env,jobject object,jbyteArray address,jint action,jint index)685 static jboolean handleCallActionNative(JNIEnv* env, jobject object,
686                                        jbyteArray address, jint action,
687                                        jint index) {
688   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
689 
690   jbyte* addr = env->GetByteArrayElements(address, NULL);
691   if (!addr) {
692     jniThrowIOException(env, EINVAL);
693     return JNI_FALSE;
694   }
695 
696   bt_status_t status = sBluetoothHfpClientInterface->handle_call_action(
697       (const RawAddress*)addr, (bthf_client_call_action_t)action, (int)index);
698 
699   if (status != BT_STATUS_SUCCESS) {
700     ALOGE("Failed to enter private mode, status: %d", status);
701   }
702   env->ReleaseByteArrayElements(address, addr, 0);
703   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
704 }
705 
queryCurrentCallsNative(JNIEnv * env,jobject object,jbyteArray address)706 static jboolean queryCurrentCallsNative(JNIEnv* env, jobject object,
707                                         jbyteArray address) {
708   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
709 
710   jbyte* addr = env->GetByteArrayElements(address, NULL);
711   if (!addr) {
712     jniThrowIOException(env, EINVAL);
713     return JNI_FALSE;
714   }
715 
716   bt_status_t status = sBluetoothHfpClientInterface->query_current_calls(
717       (const RawAddress*)addr);
718 
719   if (status != BT_STATUS_SUCCESS) {
720     ALOGE("Failed to query current calls, status: %d", status);
721   }
722   env->ReleaseByteArrayElements(address, addr, 0);
723   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
724 }
725 
queryCurrentOperatorNameNative(JNIEnv * env,jobject object,jbyteArray address)726 static jboolean queryCurrentOperatorNameNative(JNIEnv* env, jobject object,
727                                                jbyteArray address) {
728   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
729 
730   jbyte* addr = env->GetByteArrayElements(address, NULL);
731   if (!addr) {
732     jniThrowIOException(env, EINVAL);
733     return JNI_FALSE;
734   }
735 
736   bt_status_t status =
737       sBluetoothHfpClientInterface->query_current_operator_name(
738           (const RawAddress*)addr);
739   if (status != BT_STATUS_SUCCESS) {
740     ALOGE("Failed to query current operator name, status: %d", status);
741   }
742 
743   env->ReleaseByteArrayElements(address, addr, 0);
744   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
745 }
746 
retrieveSubscriberInfoNative(JNIEnv * env,jobject object,jbyteArray address)747 static jboolean retrieveSubscriberInfoNative(JNIEnv* env, jobject object,
748                                              jbyteArray address) {
749   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
750 
751   jbyte* addr = env->GetByteArrayElements(address, NULL);
752   if (!addr) {
753     jniThrowIOException(env, EINVAL);
754     return JNI_FALSE;
755   }
756 
757   bt_status_t status = sBluetoothHfpClientInterface->retrieve_subscriber_info(
758       (const RawAddress*)addr);
759   if (status != BT_STATUS_SUCCESS) {
760     ALOGE("Failed to retrieve subscriber info, status: %d", status);
761   }
762 
763   env->ReleaseByteArrayElements(address, addr, 0);
764   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
765 }
766 
sendDtmfNative(JNIEnv * env,jobject object,jbyteArray address,jbyte code)767 static jboolean sendDtmfNative(JNIEnv* env, jobject object, jbyteArray address,
768                                jbyte code) {
769   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
770 
771   jbyte* addr = env->GetByteArrayElements(address, NULL);
772   if (!addr) {
773     jniThrowIOException(env, EINVAL);
774     return JNI_FALSE;
775   }
776 
777   bt_status_t status = sBluetoothHfpClientInterface->send_dtmf(
778       (const RawAddress*)addr, (char)code);
779   if (status != BT_STATUS_SUCCESS) {
780     ALOGE("Failed to send DTMF, status: %d", status);
781   }
782 
783   env->ReleaseByteArrayElements(address, addr, 0);
784   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
785 }
786 
requestLastVoiceTagNumberNative(JNIEnv * env,jobject object,jbyteArray address)787 static jboolean requestLastVoiceTagNumberNative(JNIEnv* env, jobject object,
788                                                 jbyteArray address) {
789   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
790 
791   jbyte* addr = env->GetByteArrayElements(address, NULL);
792   if (!addr) {
793     jniThrowIOException(env, EINVAL);
794     return JNI_FALSE;
795   }
796 
797   bt_status_t status =
798       sBluetoothHfpClientInterface->request_last_voice_tag_number(
799           (const RawAddress*)addr);
800 
801   if (status != BT_STATUS_SUCCESS) {
802     ALOGE("Failed to request last Voice Tag number, status: %d", status);
803   }
804 
805   env->ReleaseByteArrayElements(address, addr, 0);
806   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
807 }
808 
sendATCmdNative(JNIEnv * env,jobject object,jbyteArray address,jint cmd,jint val1,jint val2,jstring arg_str)809 static jboolean sendATCmdNative(JNIEnv* env, jobject object, jbyteArray address,
810                                 jint cmd, jint val1, jint val2,
811                                 jstring arg_str) {
812   if (!sBluetoothHfpClientInterface) return JNI_FALSE;
813 
814   jbyte* addr = env->GetByteArrayElements(address, NULL);
815   if (!addr) {
816     jniThrowIOException(env, EINVAL);
817     return JNI_FALSE;
818   }
819   const char* arg = NULL;
820   if (arg_str != NULL) {
821     arg = env->GetStringUTFChars(arg_str, NULL);
822   }
823 
824   bt_status_t status = sBluetoothHfpClientInterface->send_at_cmd(
825       (const RawAddress*)addr, cmd, val1, val2, arg);
826 
827   if (status != BT_STATUS_SUCCESS) {
828     ALOGE("Failed to send cmd, status: %d", status);
829   }
830 
831   if (arg != NULL) {
832     env->ReleaseStringUTFChars(arg_str, arg);
833   }
834 
835   env->ReleaseByteArrayElements(address, addr, 0);
836   return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
837 }
838 
839 static JNINativeMethod sMethods[] = {
840     {"classInitNative", "()V", (void*)classInitNative},
841     {"initializeNative", "()V", (void*)initializeNative},
842     {"cleanupNative", "()V", (void*)cleanupNative},
843     {"connectNative", "([B)Z", (void*)connectNative},
844     {"disconnectNative", "([B)Z", (void*)disconnectNative},
845     {"connectAudioNative", "([B)Z", (void*)connectAudioNative},
846     {"disconnectAudioNative", "([B)Z", (void*)disconnectAudioNative},
847     {"startVoiceRecognitionNative", "([B)Z",
848      (void*)startVoiceRecognitionNative},
849     {"stopVoiceRecognitionNative", "([B)Z", (void*)stopVoiceRecognitionNative},
850     {"setVolumeNative", "([BII)Z", (void*)setVolumeNative},
851     {"dialNative", "([BLjava/lang/String;)Z", (void*)dialNative},
852     {"dialMemoryNative", "([BI)Z", (void*)dialMemoryNative},
853     {"handleCallActionNative", "([BII)Z", (void*)handleCallActionNative},
854     {"queryCurrentCallsNative", "([B)Z", (void*)queryCurrentCallsNative},
855     {"queryCurrentOperatorNameNative", "([B)Z",
856      (void*)queryCurrentOperatorNameNative},
857     {"retrieveSubscriberInfoNative", "([B)Z",
858      (void*)retrieveSubscriberInfoNative},
859     {"sendDtmfNative", "([BB)Z", (void*)sendDtmfNative},
860     {"requestLastVoiceTagNumberNative", "([B)Z",
861      (void*)requestLastVoiceTagNumberNative},
862     {"sendATCmdNative", "([BIIILjava/lang/String;)Z", (void*)sendATCmdNative},
863 };
864 
register_com_android_bluetooth_hfpclient(JNIEnv * env)865 int register_com_android_bluetooth_hfpclient(JNIEnv* env) {
866   return jniRegisterNativeMethods(
867       env, "com/android/bluetooth/hfpclient/NativeInterface",
868       sMethods, NELEM(sMethods));
869 }
870 
871 } /* namespace android */
872