• 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 #define CHECK_CALLBACK_ENV                                                      \
22    if (!checkCallbackThread()) {                                                \
23        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
24        return;                                                                  \
25    }
26 
27 #include "com_android_bluetooth.h"
28 #include "hardware/bt_hf.h"
29 #include "utils/Log.h"
30 #include "android_runtime/AndroidRuntime.h"
31 
32 #include <string.h>
33 
34 namespace android {
35 
36 static jmethodID method_onConnectionStateChanged;
37 static jmethodID method_onAudioStateChanged;
38 static jmethodID method_onVrStateChanged;
39 static jmethodID method_onAnswerCall;
40 static jmethodID method_onHangupCall;
41 static jmethodID method_onVolumeChanged;
42 static jmethodID method_onDialCall;
43 static jmethodID method_onSendDtmf;
44 static jmethodID method_onNoiceReductionEnable;
45 static jmethodID method_onWBS;
46 static jmethodID method_onAtChld;
47 static jmethodID method_onAtCnum;
48 static jmethodID method_onAtCind;
49 static jmethodID method_onAtCops;
50 static jmethodID method_onAtClcc;
51 static jmethodID method_onUnknownAt;
52 static jmethodID method_onKeyPressed;
53 static jmethodID method_onAtBind;
54 static jmethodID method_onAtBiev;
55 
56 static const bthf_interface_t *sBluetoothHfpInterface = NULL;
57 static jobject mCallbacksObj = NULL;
58 static JNIEnv *sCallbackEnv = NULL;
59 
checkCallbackThread()60 static bool checkCallbackThread() {
61     // Always fetch the latest callbackEnv from AdapterService.
62     // Caching this could cause this sCallbackEnv to go out-of-sync
63     // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event
64     // is received
65     //if (sCallbackEnv == NULL) {
66     sCallbackEnv = getCallbackEnv();
67     //}
68     JNIEnv* env = AndroidRuntime::getJNIEnv();
69     if (sCallbackEnv != env || sCallbackEnv == NULL) return false;
70     return true;
71 }
72 
marshall_bda(bt_bdaddr_t * bd_addr)73 static jbyteArray marshall_bda(bt_bdaddr_t* bd_addr)
74 {
75     jbyteArray addr;
76     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
77     if (!addr) {
78         ALOGE("Fail to new jbyteArray bd addr");
79         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
80         return NULL;
81     }
82     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
83     return addr;
84 }
85 
connection_state_callback(bthf_connection_state_t state,bt_bdaddr_t * bd_addr)86 static void connection_state_callback(bthf_connection_state_t state, bt_bdaddr_t* bd_addr) {
87     jbyteArray addr;
88 
89     ALOGI("%s", __FUNCTION__);
90 
91     CHECK_CALLBACK_ENV
92     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
93     if (!addr) {
94         ALOGE("Fail to new jbyteArray bd addr for connection state");
95         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
96         return;
97     }
98 
99     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*) bd_addr);
100     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged,
101                                  (jint) state, addr);
102     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
103     sCallbackEnv->DeleteLocalRef(addr);
104 }
105 
audio_state_callback(bthf_audio_state_t state,bt_bdaddr_t * bd_addr)106 static void audio_state_callback(bthf_audio_state_t state, bt_bdaddr_t* bd_addr) {
107     jbyteArray addr;
108 
109     CHECK_CALLBACK_ENV
110     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
111     if (!addr) {
112         ALOGE("Fail to new jbyteArray bd addr for audio state");
113         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
114         return;
115     }
116 
117     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
118     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, (jint) state, addr);
119     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
120     sCallbackEnv->DeleteLocalRef(addr);
121 }
122 
voice_recognition_callback(bthf_vr_state_t state,bt_bdaddr_t * bd_addr)123 static void voice_recognition_callback(bthf_vr_state_t state, bt_bdaddr_t* bd_addr) {
124     jbyteArray addr;
125 
126     CHECK_CALLBACK_ENV
127     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
128     if (!addr) {
129         ALOGE("Fail to new jbyteArray bd addr for audio state");
130         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
131         return;
132     }
133 
134     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
135     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVrStateChanged, (jint) state, addr);
136     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
137     sCallbackEnv->DeleteLocalRef(addr);
138 }
139 
answer_call_callback(bt_bdaddr_t * bd_addr)140 static void answer_call_callback(bt_bdaddr_t* bd_addr) {
141     jbyteArray addr;
142 
143     CHECK_CALLBACK_ENV
144     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
145     if (!addr) {
146         ALOGE("Fail to new jbyteArray bd addr for audio state");
147         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
148         return;
149     }
150 
151     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
152     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAnswerCall, addr);
153     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
154     sCallbackEnv->DeleteLocalRef(addr);
155 }
156 
hangup_call_callback(bt_bdaddr_t * bd_addr)157 static void hangup_call_callback(bt_bdaddr_t* bd_addr) {
158     jbyteArray addr;
159 
160     CHECK_CALLBACK_ENV
161     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
162     if (!addr) {
163         ALOGE("Fail to new jbyteArray bd addr for audio state");
164         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
165         return;
166     }
167 
168     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
169     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onHangupCall, addr);
170     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
171     sCallbackEnv->DeleteLocalRef(addr);
172 }
173 
volume_control_callback(bthf_volume_type_t type,int volume,bt_bdaddr_t * bd_addr)174 static void volume_control_callback(bthf_volume_type_t type, int volume, bt_bdaddr_t* bd_addr) {
175     jbyteArray addr;
176 
177     CHECK_CALLBACK_ENV
178     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
179     if (!addr) {
180         ALOGE("Fail to new jbyteArray bd addr for audio state");
181         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
182         return;
183     }
184 
185     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
186     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeChanged, (jint) type,
187                                                   (jint) volume, addr);
188     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
189     sCallbackEnv->DeleteLocalRef(addr);
190 }
191 
dial_call_callback(char * number,bt_bdaddr_t * bd_addr)192 static void dial_call_callback(char *number, bt_bdaddr_t* bd_addr) {
193     jbyteArray addr;
194 
195     CHECK_CALLBACK_ENV
196     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
197     if (!addr) {
198         ALOGE("Fail to new jbyteArray bd addr for audio state");
199         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
200         return;
201     }
202 
203     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
204     jstring js_number = sCallbackEnv->NewStringUTF(number);
205     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onDialCall,
206                                  js_number, addr);
207     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
208     sCallbackEnv->DeleteLocalRef(js_number);
209     sCallbackEnv->DeleteLocalRef(addr);
210 }
211 
dtmf_cmd_callback(char dtmf,bt_bdaddr_t * bd_addr)212 static void dtmf_cmd_callback(char dtmf, bt_bdaddr_t* bd_addr) {
213     jbyteArray addr;
214 
215     CHECK_CALLBACK_ENV
216     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
217     if (!addr) {
218         ALOGE("Fail to new jbyteArray bd addr for audio state");
219         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
220         return;
221     }
222 
223     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
224     // TBD dtmf has changed from int to char
225     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSendDtmf, dtmf, addr);
226     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
227     sCallbackEnv->DeleteLocalRef(addr);
228 }
229 
noice_reduction_callback(bthf_nrec_t nrec,bt_bdaddr_t * bd_addr)230 static void noice_reduction_callback(bthf_nrec_t nrec, bt_bdaddr_t* bd_addr) {
231     jbyteArray addr;
232 
233     CHECK_CALLBACK_ENV
234     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
235     if (!addr) {
236         ALOGE("Fail to new jbyteArray bd addr for audio state");
237         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
238         return;
239     }
240     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
241     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNoiceReductionEnable,
242                                  nrec == BTHF_NREC_START, addr);
243     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
244     sCallbackEnv->DeleteLocalRef(addr);
245 }
246 
wbs_callback(bthf_wbs_config_t wbs_config,bt_bdaddr_t * bd_addr)247 static void wbs_callback(bthf_wbs_config_t wbs_config, bt_bdaddr_t* bd_addr) {
248     jbyteArray addr;
249 
250     CHECK_CALLBACK_ENV
251 
252     if ((addr = marshall_bda(bd_addr)) == NULL)
253         return;
254 
255     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWBS, wbs_config, addr);
256     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
257     sCallbackEnv->DeleteLocalRef(addr);
258 }
259 
at_chld_callback(bthf_chld_type_t chld,bt_bdaddr_t * bd_addr)260 static void at_chld_callback(bthf_chld_type_t chld, bt_bdaddr_t* bd_addr) {
261     jbyteArray addr;
262 
263     CHECK_CALLBACK_ENV
264     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
265     if (!addr) {
266         ALOGE("Fail to new jbyteArray bd addr for audio state");
267         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
268         return;
269     }
270 
271     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
272     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtChld, chld, addr);
273     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
274     sCallbackEnv->DeleteLocalRef(addr);
275 }
276 
at_cnum_callback(bt_bdaddr_t * bd_addr)277 static void at_cnum_callback(bt_bdaddr_t* bd_addr) {
278     jbyteArray addr;
279 
280     CHECK_CALLBACK_ENV
281     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
282     if (!addr) {
283         ALOGE("Fail to new jbyteArray bd addr for audio state");
284         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
285         return;
286     }
287 
288     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
289     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCnum, addr);
290     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
291     sCallbackEnv->DeleteLocalRef(addr);
292 }
293 
at_cind_callback(bt_bdaddr_t * bd_addr)294 static void at_cind_callback(bt_bdaddr_t* bd_addr) {
295     jbyteArray addr;
296 
297     CHECK_CALLBACK_ENV
298     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
299     if (!addr) {
300         ALOGE("Fail to new jbyteArray bd addr for audio state");
301         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
302         return;
303     }
304 
305     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
306     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCind, addr);
307     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
308     sCallbackEnv->DeleteLocalRef(addr);
309 }
310 
at_cops_callback(bt_bdaddr_t * bd_addr)311 static void at_cops_callback(bt_bdaddr_t* bd_addr) {
312     jbyteArray addr;
313 
314     CHECK_CALLBACK_ENV
315     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
316     if (!addr) {
317         ALOGE("Fail to new jbyteArray bd addr for audio state");
318         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
319         return;
320     }
321 
322     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
323     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtCops, addr);
324     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
325     sCallbackEnv->DeleteLocalRef(addr);
326 }
327 
at_clcc_callback(bt_bdaddr_t * bd_addr)328 static void at_clcc_callback(bt_bdaddr_t* bd_addr) {
329     jbyteArray addr;
330 
331     CHECK_CALLBACK_ENV
332     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
333     if (!addr) {
334         ALOGE("Fail to new jbyteArray bd addr for audio state");
335         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
336         return;
337     }
338 
339     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
340     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtClcc, addr);
341     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
342     sCallbackEnv->DeleteLocalRef(addr);
343 }
344 
unknown_at_callback(char * at_string,bt_bdaddr_t * bd_addr)345 static void unknown_at_callback(char *at_string, bt_bdaddr_t* bd_addr) {
346     jbyteArray addr;
347 
348     CHECK_CALLBACK_ENV
349     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
350     if (!addr) {
351         ALOGE("Fail to new jbyteArray bd addr for audio state");
352         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
353         return;
354     }
355 
356     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
357     jstring js_at_string = sCallbackEnv->NewStringUTF(at_string);
358     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onUnknownAt,
359                                  js_at_string, addr);
360     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
361     sCallbackEnv->DeleteLocalRef(js_at_string);
362     sCallbackEnv->DeleteLocalRef(addr);
363 }
364 
key_pressed_callback(bt_bdaddr_t * bd_addr)365 static void key_pressed_callback(bt_bdaddr_t* bd_addr) {
366     jbyteArray addr;
367 
368     CHECK_CALLBACK_ENV
369     addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
370     if (!addr) {
371         ALOGE("Fail to new jbyteArray bd addr for audio state");
372         checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
373         return;
374     }
375 
376     sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr);
377     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onKeyPressed, addr);
378     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
379     sCallbackEnv->DeleteLocalRef(addr);
380 }
381 
at_bind_callback(char * at_string,bt_bdaddr_t * bd_addr)382 static void at_bind_callback(char *at_string, bt_bdaddr_t *bd_addr) {
383     CHECK_CALLBACK_ENV
384 
385     jbyteArray addr = marshall_bda(bd_addr);
386     if (addr == NULL)
387         return;
388 
389     jstring js_at_string = sCallbackEnv->NewStringUTF(at_string);
390 
391     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBind, js_at_string, addr);
392     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
393 
394     sCallbackEnv->DeleteLocalRef(js_at_string);
395     sCallbackEnv->DeleteLocalRef(addr);
396 }
397 
at_biev_callback(bthf_hf_ind_type_t ind_id,int ind_value,bt_bdaddr_t * bd_addr)398 static void at_biev_callback(bthf_hf_ind_type_t ind_id, int ind_value, bt_bdaddr_t *bd_addr) {
399     CHECK_CALLBACK_ENV
400 
401     jbyteArray addr = marshall_bda(bd_addr);
402     if (addr == NULL)
403         return;
404 
405     sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAtBiev, ind_id, (jint)ind_value, addr);
406     checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
407     sCallbackEnv->DeleteLocalRef(addr);
408 }
409 
410 static bthf_callbacks_t sBluetoothHfpCallbacks = {
411     sizeof(sBluetoothHfpCallbacks),
412     connection_state_callback,
413     audio_state_callback,
414     voice_recognition_callback,
415     answer_call_callback,
416     hangup_call_callback,
417     volume_control_callback,
418     dial_call_callback,
419     dtmf_cmd_callback,
420     noice_reduction_callback,
421     wbs_callback,
422     at_chld_callback,
423     at_cnum_callback,
424     at_cind_callback,
425     at_cops_callback,
426     at_clcc_callback,
427     unknown_at_callback,
428     at_bind_callback,
429     at_biev_callback,
430     key_pressed_callback
431 };
432 
classInitNative(JNIEnv * env,jclass clazz)433 static void classInitNative(JNIEnv* env, jclass clazz) {
434     method_onConnectionStateChanged =
435         env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");
436     method_onAudioStateChanged = env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");
437     method_onVrStateChanged = env->GetMethodID(clazz, "onVrStateChanged", "(I[B)V");
438     method_onAnswerCall = env->GetMethodID(clazz, "onAnswerCall", "([B)V");
439     method_onHangupCall = env->GetMethodID(clazz, "onHangupCall", "([B)V");
440     method_onVolumeChanged = env->GetMethodID(clazz, "onVolumeChanged", "(II[B)V");
441     method_onDialCall = env->GetMethodID(clazz, "onDialCall", "(Ljava/lang/String;[B)V");
442     method_onSendDtmf = env->GetMethodID(clazz, "onSendDtmf", "(I[B)V");
443     method_onNoiceReductionEnable = env->GetMethodID(clazz, "onNoiceReductionEnable", "(Z[B)V");
444     method_onWBS = env->GetMethodID(clazz,"onWBS","(I[B)V");
445     method_onAtChld = env->GetMethodID(clazz, "onAtChld", "(I[B)V");
446     method_onAtCnum = env->GetMethodID(clazz, "onAtCnum", "([B)V");
447     method_onAtCind = env->GetMethodID(clazz, "onAtCind", "([B)V");
448     method_onAtCops = env->GetMethodID(clazz, "onAtCops", "([B)V");
449     method_onAtClcc = env->GetMethodID(clazz, "onAtClcc", "([B)V");
450     method_onUnknownAt = env->GetMethodID(clazz, "onUnknownAt", "(Ljava/lang/String;[B)V");
451     method_onKeyPressed = env->GetMethodID(clazz, "onKeyPressed", "([B)V");
452     method_onAtBind = env->GetMethodID(clazz, "onATBind", "(Ljava/lang/String;[B)V");
453     method_onAtBiev = env->GetMethodID(clazz, "onATBiev", "(II[B)V");
454 
455     ALOGI("%s: succeeds", __FUNCTION__);
456 }
457 
initializeNative(JNIEnv * env,jobject object,jint max_hf_clients)458 static void initializeNative(JNIEnv *env, jobject object, jint max_hf_clients) {
459     const bt_interface_t* btInf;
460     bt_status_t status;
461 
462     if ( (btInf = getBluetoothInterface()) == NULL) {
463         ALOGE("Bluetooth module is not loaded");
464         return;
465     }
466 
467     if (sBluetoothHfpInterface !=NULL) {
468         ALOGW("Cleaning up Bluetooth Handsfree Interface before initializing...");
469         sBluetoothHfpInterface->cleanup();
470         sBluetoothHfpInterface = NULL;
471     }
472 
473     if (mCallbacksObj != NULL) {
474         ALOGW("Cleaning up Bluetooth Handsfree callback object");
475         env->DeleteGlobalRef(mCallbacksObj);
476         mCallbacksObj = NULL;
477     }
478 
479     if ( (sBluetoothHfpInterface = (bthf_interface_t *)
480           btInf->get_profile_interface(BT_PROFILE_HANDSFREE_ID)) == NULL) {
481         ALOGE("Failed to get Bluetooth Handsfree Interface");
482         return;
483     }
484 
485     if ( (status = sBluetoothHfpInterface->init(&sBluetoothHfpCallbacks,
486           max_hf_clients)) != BT_STATUS_SUCCESS) {
487         ALOGE("Failed to initialize Bluetooth HFP, status: %d", status);
488         sBluetoothHfpInterface = NULL;
489         return;
490     }
491 
492     mCallbacksObj = env->NewGlobalRef(object);
493 }
494 
cleanupNative(JNIEnv * env,jobject object)495 static void cleanupNative(JNIEnv *env, jobject object) {
496     const bt_interface_t* btInf;
497 
498     if ( (btInf = getBluetoothInterface()) == NULL) {
499         ALOGE("Bluetooth module is not loaded");
500         return;
501     }
502 
503     if (sBluetoothHfpInterface !=NULL) {
504         ALOGW("Cleaning up Bluetooth Handsfree Interface...");
505         sBluetoothHfpInterface->cleanup();
506         sBluetoothHfpInterface = NULL;
507     }
508 
509     if (mCallbacksObj != NULL) {
510         ALOGW("Cleaning up Bluetooth Handsfree callback object");
511         env->DeleteGlobalRef(mCallbacksObj);
512         mCallbacksObj = NULL;
513     }
514 }
515 
connectHfpNative(JNIEnv * env,jobject object,jbyteArray address)516 static jboolean connectHfpNative(JNIEnv *env, jobject object, jbyteArray address) {
517     jbyte *addr;
518     bt_status_t status;
519 
520     ALOGI("%s: sBluetoothHfpInterface: %p", __FUNCTION__, sBluetoothHfpInterface);
521     if (!sBluetoothHfpInterface) return JNI_FALSE;
522 
523     addr = env->GetByteArrayElements(address, NULL);
524     if (!addr) {
525         jniThrowIOException(env, EINVAL);
526         return JNI_FALSE;
527     }
528 
529     if ((status = sBluetoothHfpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
530         ALOGE("Failed HF connection, status: %d", status);
531     }
532     env->ReleaseByteArrayElements(address, addr, 0);
533     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
534 }
535 
disconnectHfpNative(JNIEnv * env,jobject object,jbyteArray address)536 static jboolean disconnectHfpNative(JNIEnv *env, jobject object, jbyteArray address) {
537     jbyte *addr;
538     bt_status_t status;
539 
540     if (!sBluetoothHfpInterface) return JNI_FALSE;
541 
542     addr = env->GetByteArrayElements(address, NULL);
543     if (!addr) {
544         jniThrowIOException(env, EINVAL);
545         return JNI_FALSE;
546     }
547 
548     if ( (status = sBluetoothHfpInterface->disconnect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
549         ALOGE("Failed HF disconnection, status: %d", status);
550     }
551     env->ReleaseByteArrayElements(address, addr, 0);
552     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
553 }
554 
connectAudioNative(JNIEnv * env,jobject object,jbyteArray address)555 static jboolean connectAudioNative(JNIEnv *env, jobject object, jbyteArray address) {
556     jbyte *addr;
557     bt_status_t status;
558 
559     if (!sBluetoothHfpInterface) return JNI_FALSE;
560 
561     addr = env->GetByteArrayElements(address, NULL);
562     if (!addr) {
563         jniThrowIOException(env, EINVAL);
564         return JNI_FALSE;
565     }
566 
567     if ( (status = sBluetoothHfpInterface->connect_audio((bt_bdaddr_t *)addr)) !=
568          BT_STATUS_SUCCESS) {
569         ALOGE("Failed HF audio connection, status: %d", status);
570     }
571     env->ReleaseByteArrayElements(address, addr, 0);
572     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
573 }
574 
disconnectAudioNative(JNIEnv * env,jobject object,jbyteArray address)575 static jboolean disconnectAudioNative(JNIEnv *env, jobject object, jbyteArray address) {
576     jbyte *addr;
577     bt_status_t status;
578 
579     if (!sBluetoothHfpInterface) return JNI_FALSE;
580 
581     addr = env->GetByteArrayElements(address, NULL);
582     if (!addr) {
583         jniThrowIOException(env, EINVAL);
584         return JNI_FALSE;
585     }
586 
587     if ( (status = sBluetoothHfpInterface->disconnect_audio((bt_bdaddr_t *) addr)) !=
588          BT_STATUS_SUCCESS) {
589         ALOGE("Failed HF audio disconnection, status: %d", status);
590     }
591     env->ReleaseByteArrayElements(address, addr, 0);
592     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
593 }
594 
startVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)595 static jboolean startVoiceRecognitionNative(JNIEnv *env, jobject object, jbyteArray address) {
596     jbyte *addr;
597     bt_status_t status;
598     if (!sBluetoothHfpInterface) return JNI_FALSE;
599 
600     addr = env->GetByteArrayElements(address, NULL);
601     if (!addr) {
602         jniThrowIOException(env, EINVAL);
603         return JNI_FALSE;
604     }
605 
606     if ( (status = sBluetoothHfpInterface->start_voice_recognition((bt_bdaddr_t *) addr))
607                                           != BT_STATUS_SUCCESS) {
608         ALOGE("Failed to start voice recognition, status: %d", status);
609     }
610     env->ReleaseByteArrayElements(address, addr, 0);
611     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
612 }
613 
stopVoiceRecognitionNative(JNIEnv * env,jobject object,jbyteArray address)614 static jboolean stopVoiceRecognitionNative(JNIEnv *env, jobject object, jbyteArray address) {
615     jbyte *addr;
616     bt_status_t status;
617     if (!sBluetoothHfpInterface) return JNI_FALSE;
618 
619     addr = env->GetByteArrayElements(address, NULL);
620     if (!addr) {
621         jniThrowIOException(env, EINVAL);
622         return JNI_FALSE;
623     }
624 
625     if ( (status = sBluetoothHfpInterface->stop_voice_recognition((bt_bdaddr_t *) addr))
626                                      != BT_STATUS_SUCCESS) {
627         ALOGE("Failed to stop voice recognition, status: %d", status);
628     }
629     env->ReleaseByteArrayElements(address, addr, 0);
630     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
631 }
632 
setVolumeNative(JNIEnv * env,jobject object,jint volume_type,jint volume,jbyteArray address)633 static jboolean setVolumeNative(JNIEnv *env, jobject object, jint volume_type,
634                                      jint volume, jbyteArray address) {
635     jbyte *addr;
636     bt_status_t status;
637     if (!sBluetoothHfpInterface) return JNI_FALSE;
638 
639     addr = env->GetByteArrayElements(address, NULL);
640     if (!addr) {
641         jniThrowIOException(env, EINVAL);
642         return JNI_FALSE;
643     }
644 
645     if ( (status = sBluetoothHfpInterface->volume_control((bthf_volume_type_t) volume_type,
646                                 volume, (bt_bdaddr_t *) addr)) != BT_STATUS_SUCCESS) {
647         ALOGE("FAILED to control volume, status: %d", status);
648     }
649     env->ReleaseByteArrayElements(address, addr, 0);
650     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
651 }
652 
notifyDeviceStatusNative(JNIEnv * env,jobject object,jint network_state,jint service_type,jint signal,jint battery_charge)653 static jboolean notifyDeviceStatusNative(JNIEnv *env, jobject object,
654                                          jint network_state, jint service_type, jint signal,
655                                          jint battery_charge) {
656     bt_status_t status;
657     if (!sBluetoothHfpInterface) return JNI_FALSE;
658 
659     if ( (status = sBluetoothHfpInterface->device_status_notification
660           ((bthf_network_state_t) network_state, (bthf_service_type_t) service_type,
661            signal, battery_charge)) != BT_STATUS_SUCCESS) {
662         ALOGE("FAILED to notify device status, status: %d", status);
663     }
664     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
665 }
666 
copsResponseNative(JNIEnv * env,jobject object,jstring operator_str,jbyteArray address)667 static jboolean copsResponseNative(JNIEnv *env, jobject object, jstring operator_str,
668                                               jbyteArray address) {
669     jbyte *addr;
670     bt_status_t status;
671     const char *operator_name;
672     if (!sBluetoothHfpInterface) return JNI_FALSE;
673 
674     addr = env->GetByteArrayElements(address, NULL);
675     if (!addr) {
676         jniThrowIOException(env, EINVAL);
677         return JNI_FALSE;
678     }
679 
680     operator_name = env->GetStringUTFChars(operator_str, NULL);
681 
682     if ( (status = sBluetoothHfpInterface->cops_response(operator_name,(bt_bdaddr_t *) addr))
683                                                   != BT_STATUS_SUCCESS) {
684         ALOGE("Failed sending cops response, status: %d", status);
685     }
686     env->ReleaseByteArrayElements(address, addr, 0);
687     env->ReleaseStringUTFChars(operator_str, operator_name);
688     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
689 }
690 
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)691 static jboolean cindResponseNative(JNIEnv *env, jobject object,
692                                    jint service, jint num_active, jint num_held, jint call_state,
693                                    jint signal, jint roam, jint battery_charge, jbyteArray address) {
694     jbyte *addr;
695     bt_status_t status;
696 
697     ALOGI("%s: sBluetoothHfpInterface: %p", __FUNCTION__, sBluetoothHfpInterface);
698     if (!sBluetoothHfpInterface) return JNI_FALSE;
699 
700     addr = env->GetByteArrayElements(address, NULL);
701     if (!addr) {
702         jniThrowIOException(env, EINVAL);
703         return JNI_FALSE;
704     }
705 
706     if ( (status = sBluetoothHfpInterface->cind_response(service, num_active, num_held,
707                        (bthf_call_state_t) call_state,
708                        signal, roam, battery_charge, (bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
709         ALOGE("Failed cind_response, status: %d", status);
710     }
711     env->ReleaseByteArrayElements(address, addr, 0);
712     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
713 }
714 
bindResponseNative(JNIEnv * env,jobject object,jint ind_id,jboolean ind_status,jbyteArray address)715 static jboolean bindResponseNative(JNIEnv *env,jobject object,
716                                 jint ind_id, jboolean ind_status,
717                                 jbyteArray address) {
718     ALOGI("%s: sBluetoothHfpInterface: %p", __FUNCTION__, sBluetoothHfpInterface);
719 
720     if (!sBluetoothHfpInterface)
721         return JNI_FALSE;
722 
723     jbyte *addr = env->GetByteArrayElements(address, NULL);
724     if (!addr) {
725         jniThrowIOException(env, EINVAL);
726         return JNI_FALSE;
727     }
728 
729     bt_status_t status = sBluetoothHfpInterface->bind_response((bthf_hf_ind_type_t) ind_id,
730                    ind_status ? BTHF_HF_IND_ENABLED : BTHF_HF_IND_DISABLED,
731                    (bt_bdaddr_t *)addr);
732 
733     if (status != BT_STATUS_SUCCESS)
734         ALOGE("%s: Failed bind_response, status: %d", __FUNCTION__, 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, jstring response_str,
741                                                  jbyteArray address) {
742     jbyte *addr;
743     bt_status_t status;
744     const char *response;
745     if (!sBluetoothHfpInterface) return JNI_FALSE;
746 
747     addr = env->GetByteArrayElements(address, NULL);
748     if (!addr) {
749         jniThrowIOException(env, EINVAL);
750         return JNI_FALSE;
751     }
752 
753     response = env->GetStringUTFChars(response_str, NULL);
754 
755     if ( (status = sBluetoothHfpInterface->formatted_at_response(response,
756                             (bt_bdaddr_t *)addr))!= BT_STATUS_SUCCESS) {
757         ALOGE("Failed formatted AT response, status: %d", status);
758     }
759     env->ReleaseByteArrayElements(address, addr, 0);
760     env->ReleaseStringUTFChars(response_str, response);
761     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
762 }
763 
atResponseCodeNative(JNIEnv * env,jobject object,jint response_code,jint cmee_code,jbyteArray address)764 static jboolean atResponseCodeNative(JNIEnv *env, jobject object, jint response_code,
765                                              jint cmee_code, jbyteArray address) {
766     jbyte *addr;
767     bt_status_t status;
768     if (!sBluetoothHfpInterface) return JNI_FALSE;
769 
770     addr = env->GetByteArrayElements(address, NULL);
771     if (!addr) {
772         jniThrowIOException(env, EINVAL);
773         return JNI_FALSE;
774     }
775 
776     if ( (status = sBluetoothHfpInterface->at_response((bthf_at_response_t) response_code,
777               cmee_code, (bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
778         ALOGE("Failed AT response, status: %d", status);
779     }
780     env->ReleaseByteArrayElements(address, addr, 0);
781     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
782 }
783 
clccResponseNative(JNIEnv * env,jobject object,jint index,jint dir,jint callStatus,jint mode,jboolean mpty,jstring number_str,jint type,jbyteArray address)784 static jboolean clccResponseNative(JNIEnv *env, jobject object, jint index, jint dir,
785                                    jint callStatus, jint mode, jboolean mpty, jstring number_str,
786                                    jint type, jbyteArray address) {
787     jbyte *addr;
788     bt_status_t status;
789     const char *number = NULL;
790     if (!sBluetoothHfpInterface) return JNI_FALSE;
791 
792     addr = env->GetByteArrayElements(address, NULL);
793     if (!addr) {
794         jniThrowIOException(env, EINVAL);
795         return JNI_FALSE;
796     }
797 
798     if (number_str)
799         number = env->GetStringUTFChars(number_str, NULL);
800 
801     if ( (status = sBluetoothHfpInterface->clcc_response(index, (bthf_call_direction_t) dir,
802                 (bthf_call_state_t) callStatus,  (bthf_call_mode_t) mode,
803                 mpty ? BTHF_CALL_MPTY_TYPE_MULTI : BTHF_CALL_MPTY_TYPE_SINGLE,
804                 number, (bthf_call_addrtype_t) type, (bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
805         ALOGE("Failed sending CLCC response, status: %d", status);
806     }
807     env->ReleaseByteArrayElements(address, addr, 0);
808     if (number)
809         env->ReleaseStringUTFChars(number_str, number);
810     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
811 }
812 
phoneStateChangeNative(JNIEnv * env,jobject object,jint num_active,jint num_held,jint call_state,jstring number_str,jint type)813 static jboolean phoneStateChangeNative(JNIEnv *env, jobject object, jint num_active, jint num_held,
814                                        jint call_state, jstring number_str, jint type) {
815     bt_status_t status;
816     const char *number;
817     if (!sBluetoothHfpInterface) return JNI_FALSE;
818 
819     number = env->GetStringUTFChars(number_str, NULL);
820 
821     if ( (status = sBluetoothHfpInterface->phone_state_change(num_active, num_held,
822                        (bthf_call_state_t) call_state, number,
823                        (bthf_call_addrtype_t) type)) != BT_STATUS_SUCCESS) {
824         ALOGE("Failed report phone state change, status: %d", status);
825     }
826     env->ReleaseStringUTFChars(number_str, number);
827     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
828 }
829 
830 
configureWBSNative(JNIEnv * env,jobject object,jbyteArray address,jint codec_config)831 static jboolean configureWBSNative(JNIEnv *env, jobject object, jbyteArray address,
832                                    jint codec_config) {
833     jbyte *addr;
834     bt_status_t status;
835 
836     if (!sBluetoothHfpInterface) return JNI_FALSE;
837 
838     addr = env->GetByteArrayElements(address, NULL);
839     if (!addr) {
840         jniThrowIOException(env, EINVAL);
841         return JNI_FALSE;
842     }
843 
844     if ((status = sBluetoothHfpInterface->configure_wbs((bt_bdaddr_t *)addr,
845                    (bthf_wbs_config_t)codec_config)) != BT_STATUS_SUCCESS){
846         ALOGE("Failed HF WBS codec config, status: %d", status);
847     }
848     env->ReleaseByteArrayElements(address, addr, 0);
849     return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
850 }
851 
852 
853 static JNINativeMethod sMethods[] = {
854     {"classInitNative", "()V", (void *) classInitNative},
855     {"initializeNative", "(I)V", (void *) initializeNative},
856     {"cleanupNative", "()V", (void *) cleanupNative},
857     {"connectHfpNative", "([B)Z", (void *) connectHfpNative},
858     {"disconnectHfpNative", "([B)Z", (void *) disconnectHfpNative},
859     {"connectAudioNative", "([B)Z", (void *) connectAudioNative},
860     {"disconnectAudioNative", "([B)Z", (void *) disconnectAudioNative},
861     {"startVoiceRecognitionNative", "([B)Z", (void *) startVoiceRecognitionNative},
862     {"stopVoiceRecognitionNative", "([B)Z", (void *) stopVoiceRecognitionNative},
863     {"setVolumeNative", "(II[B)Z", (void *) setVolumeNative},
864     {"notifyDeviceStatusNative", "(IIII)Z", (void *) notifyDeviceStatusNative},
865     {"copsResponseNative", "(Ljava/lang/String;[B)Z", (void *) copsResponseNative},
866     {"cindResponseNative", "(IIIIIII[B)Z", (void *) cindResponseNative},
867     {"bindResponseNative", "(IZ[B)Z", (void *)bindResponseNative},
868     {"atResponseStringNative", "(Ljava/lang/String;[B)Z", (void *) atResponseStringNative},
869     {"atResponseCodeNative", "(II[B)Z", (void *)atResponseCodeNative},
870     {"clccResponseNative", "(IIIIZLjava/lang/String;I[B)Z", (void *) clccResponseNative},
871     {"phoneStateChangeNative", "(IIILjava/lang/String;I)Z", (void *) phoneStateChangeNative},
872     {"configureWBSNative", "([BI)Z", (void *) configureWBSNative},
873 };
874 
register_com_android_bluetooth_hfp(JNIEnv * env)875 int register_com_android_bluetooth_hfp(JNIEnv* env)
876 {
877     return jniRegisterNativeMethods(env, "com/android/bluetooth/hfp/HeadsetStateMachine",
878                                     sMethods, NELEM(sMethods));
879 }
880 
881 } /* namespace android */
882