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