• 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 "BluetoothServiceJni"
18 #include "com_android_bluetooth.h"
19 #include "hardware/bt_sock.h"
20 #include "utils/Log.h"
21 #include "utils/misc.h"
22 #include "cutils/properties.h"
23 #include "android_runtime/AndroidRuntime.h"
24 #include "android_runtime/Log.h"
25 
26 #include <string.h>
27 #include <pthread.h>
28 
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 
32 namespace android {
33 
34 #define ADDITIONAL_NREFS 50
35 static jmethodID method_stateChangeCallback;
36 static jmethodID method_adapterPropertyChangedCallback;
37 static jmethodID method_devicePropertyChangedCallback;
38 static jmethodID method_deviceFoundCallback;
39 static jmethodID method_pinRequestCallback;
40 static jmethodID method_sspRequestCallback;
41 static jmethodID method_bondStateChangeCallback;
42 static jmethodID method_aclStateChangeCallback;
43 static jmethodID method_discoveryStateChangeCallback;
44 
45 static const bt_interface_t *sBluetoothInterface = NULL;
46 static const btsock_interface_t *sBluetoothSocketInterface = NULL;
47 static JNIEnv *callbackEnv = NULL;
48 
49 static jobject sJniCallbacksObj;
50 static jfieldID sJniCallbacksField;
51 
52 
getBluetoothInterface()53 const bt_interface_t* getBluetoothInterface() {
54     return sBluetoothInterface;
55 }
56 
getCallbackEnv()57 JNIEnv* getCallbackEnv() {
58     return callbackEnv;
59 }
60 
checkAndClearExceptionFromCallback(JNIEnv * env,const char * methodName)61 void checkAndClearExceptionFromCallback(JNIEnv* env,
62                                                const char* methodName) {
63     if (env->ExceptionCheck()) {
64         ALOGE("An exception was thrown by callback '%s'.", methodName);
65         LOGE_EX(env);
66         env->ExceptionClear();
67     }
68 }
69 
checkCallbackThread()70 static bool checkCallbackThread() {
71     JNIEnv* env = AndroidRuntime::getJNIEnv();
72     if (callbackEnv != env || callbackEnv == NULL) {
73         ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
74         return false;
75     }
76     return true;
77 }
78 
adapter_state_change_callback(bt_state_t status)79 static void adapter_state_change_callback(bt_state_t status) {
80     if (!checkCallbackThread()) {
81        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
82        return;
83     }
84     ALOGV("%s: Status is: %d", __FUNCTION__, status);
85 
86     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
87 
88     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
89 }
90 
get_properties(int num_properties,bt_property_t * properties,jintArray * types,jobjectArray * props)91 static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
92                         jobjectArray *props) {
93     jbyteArray propVal;
94     for (int i = 0; i < num_properties; i++) {
95         propVal = callbackEnv->NewByteArray(properties[i].len);
96         if (propVal == NULL) goto Fail;
97 
98         callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
99                                              (jbyte*)properties[i].val);
100         callbackEnv->SetObjectArrayElement(*props, i, propVal);
101         // Delete reference to propVal
102         callbackEnv->DeleteLocalRef(propVal);
103         callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
104     }
105     return 0;
106 Fail:
107     if (propVal) callbackEnv->DeleteLocalRef(propVal);
108     ALOGE("Error while allocation of array in %s", __FUNCTION__);
109     return -1;
110 }
111 
adapter_properties_callback(bt_status_t status,int num_properties,bt_property_t * properties)112 static void adapter_properties_callback(bt_status_t status, int num_properties,
113                                         bt_property_t *properties) {
114     jobjectArray props;
115     jintArray types;
116     jbyteArray val;
117     jclass mclass;
118 
119     if (!checkCallbackThread()) {
120        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
121        return;
122     }
123 
124     ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
125 
126     if (status != BT_STATUS_SUCCESS) {
127         ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
128         return;
129     }
130 
131     val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
132     if (val == NULL) {
133         ALOGE("%s: Error allocating byteArray", __FUNCTION__);
134         return;
135     }
136 
137     mclass = callbackEnv->GetObjectClass(val);
138 
139     /* (BT) Initialize the jobjectArray and jintArray here itself and send the
140      initialized array pointers alone to get_properties */
141 
142     props = callbackEnv->NewObjectArray(num_properties, mclass,
143                                              NULL);
144     if (props == NULL) {
145         ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
146         return;
147     }
148 
149     types = (jintArray)callbackEnv->NewIntArray(num_properties);
150 
151     if (types == NULL) {
152         ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
153         return;
154     }
155     // Delete the reference to val and mclass
156     callbackEnv->DeleteLocalRef(mclass);
157     callbackEnv->DeleteLocalRef(val);
158 
159     if (get_properties(num_properties, properties, &types, &props) < 0) {
160         if (props) callbackEnv->DeleteLocalRef(props);
161         if (types) callbackEnv->DeleteLocalRef(types);
162         return;
163     }
164 
165     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
166                                 props);
167     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
168     callbackEnv->DeleteLocalRef(props);
169     callbackEnv->DeleteLocalRef(types);
170     return;
171 
172 }
173 
remote_device_properties_callback(bt_status_t status,bt_bdaddr_t * bd_addr,int num_properties,bt_property_t * properties)174 static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
175                                               int num_properties, bt_property_t *properties) {
176     if (!checkCallbackThread()) {
177        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
178        return;
179     }
180 
181     ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
182 
183     if (status != BT_STATUS_SUCCESS) {
184         ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
185         return;
186     }
187 
188     callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
189 
190     jobjectArray props;
191     jbyteArray addr;
192     jintArray types;
193     jbyteArray val;
194     jclass mclass;
195 
196     val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
197     if (val == NULL) {
198         ALOGE("%s: Error allocating byteArray", __FUNCTION__);
199         return;
200     }
201 
202     mclass = callbackEnv->GetObjectClass(val);
203 
204     /* Initialize the jobjectArray and jintArray here itself and send the
205      initialized array pointers alone to get_properties */
206 
207     props = callbackEnv->NewObjectArray(num_properties, mclass,
208                                              NULL);
209     if (props == NULL) {
210         ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
211         return;
212     }
213 
214     types = (jintArray)callbackEnv->NewIntArray(num_properties);
215 
216     if (types == NULL) {
217         ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
218         return;
219     }
220     // Delete the reference to val and mclass
221     callbackEnv->DeleteLocalRef(mclass);
222     callbackEnv->DeleteLocalRef(val);
223 
224     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
225     if (addr == NULL) goto Fail;
226     if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
227 
228     if (get_properties(num_properties, properties, &types, &props) < 0) {
229         if (props) callbackEnv->DeleteLocalRef(props);
230         if (types) callbackEnv->DeleteLocalRef(types);
231         callbackEnv->PopLocalFrame(NULL);
232         return;
233     }
234 
235     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
236                                 types, props);
237     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
238     callbackEnv->DeleteLocalRef(props);
239     callbackEnv->DeleteLocalRef(types);
240     callbackEnv->DeleteLocalRef(addr);
241     callbackEnv->PopLocalFrame(NULL);
242     return;
243 
244 Fail:
245     ALOGE("Error while allocation byte array in %s", __FUNCTION__);
246 }
247 
248 
device_found_callback(int num_properties,bt_property_t * properties)249 static void device_found_callback(int num_properties, bt_property_t *properties) {
250     jbyteArray addr = NULL;
251     int addr_index;
252 
253     for (int i = 0; i < num_properties; i++) {
254         if (properties[i].type == BT_PROPERTY_BDADDR) {
255             addr = callbackEnv->NewByteArray(properties[i].len);
256             if (addr) {
257                 callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
258                                                 (jbyte*)properties[i].val);
259                 addr_index = i;
260             } else {
261                 ALOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
262                 return;
263             }
264         }
265     }
266     if (addr == NULL) {
267         ALOGE("Address is NULL in %s", __FUNCTION__);
268         return;
269     }
270 
271     ALOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
272         (const char *)properties[addr_index].val);
273 
274     remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
275                                       num_properties, properties);
276 
277     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
278     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
279     callbackEnv->DeleteLocalRef(addr);
280 }
281 
bond_state_changed_callback(bt_status_t status,bt_bdaddr_t * bd_addr,bt_bond_state_t state)282 static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
283                                         bt_bond_state_t state) {
284     jbyteArray addr;
285     int i;
286     if (!checkCallbackThread()) {
287        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
288        return;
289     }
290     if (!bd_addr) {
291         ALOGE("Address is null in %s", __FUNCTION__);
292         return;
293     }
294     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
295     if (addr == NULL) {
296        ALOGE("Address allocation failed in %s", __FUNCTION__);
297        return;
298     }
299     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
300 
301     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
302                                 addr, (jint)state);
303     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
304     callbackEnv->DeleteLocalRef(addr);
305 }
306 
acl_state_changed_callback(bt_status_t status,bt_bdaddr_t * bd_addr,bt_acl_state_t state)307 static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
308                                        bt_acl_state_t state)
309 {
310     jbyteArray addr;
311     int i;
312     if (!checkCallbackThread()) {
313        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
314        return;
315     }
316     if (!bd_addr) {
317         ALOGE("Address is null in %s", __FUNCTION__);
318         return;
319     }
320     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
321     if (addr == NULL) {
322        ALOGE("Address allocation failed in %s", __FUNCTION__);
323        return;
324     }
325     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
326 
327     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
328                                 addr, (jint)state);
329     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
330     callbackEnv->DeleteLocalRef(addr);
331 }
332 
discovery_state_changed_callback(bt_discovery_state_t state)333 static void discovery_state_changed_callback(bt_discovery_state_t state) {
334     jbyteArray addr;
335     if (!checkCallbackThread()) {
336        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
337        return;
338     }
339 
340     ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
341 
342     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
343                                 (jint)state);
344 
345     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
346 }
347 
pin_request_callback(bt_bdaddr_t * bd_addr,bt_bdname_t * bdname,uint32_t cod)348 static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) {
349     jbyteArray addr, devname;
350     if (!checkCallbackThread()) {
351        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
352        return;
353     }
354     if (!bd_addr) {
355         ALOGE("Address is null in %s", __FUNCTION__);
356         return;
357     }
358 
359     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
360     if (addr == NULL) goto Fail;
361     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
362 
363     devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
364     if (devname == NULL) goto Fail;
365 
366     callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
367 
368     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod);
369 
370     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
371     callbackEnv->DeleteLocalRef(addr);
372     callbackEnv->DeleteLocalRef(devname);
373     return;
374 
375 Fail:
376     if (addr) callbackEnv->DeleteLocalRef(addr);
377     if (devname) callbackEnv->DeleteLocalRef(devname);
378     ALOGE("Error while allocating in: %s", __FUNCTION__);
379 }
380 
ssp_request_callback(bt_bdaddr_t * bd_addr,bt_bdname_t * bdname,uint32_t cod,bt_ssp_variant_t pairing_variant,uint32_t pass_key)381 static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
382                                  bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
383     jbyteArray addr, devname;
384     if (!checkCallbackThread()) {
385        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
386        return;
387     }
388     if (!bd_addr) {
389         ALOGE("Address is null in %s", __FUNCTION__);
390         return;
391     }
392 
393     addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
394     if (addr == NULL) goto Fail;
395     callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
396 
397     devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
398     if (devname == NULL) goto Fail;
399     callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
400 
401     callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
402                                 (jint) pairing_variant, pass_key);
403 
404     checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
405     callbackEnv->DeleteLocalRef(addr);
406     callbackEnv->DeleteLocalRef(devname);
407     return;
408 
409 Fail:
410     if (addr) callbackEnv->DeleteLocalRef(addr);
411     if (devname) callbackEnv->DeleteLocalRef(devname);
412 
413     ALOGE("Error while allocating in: %s", __FUNCTION__);
414 }
415 
callback_thread_event(bt_cb_thread_evt event)416 static void callback_thread_event(bt_cb_thread_evt event) {
417     JavaVM* vm = AndroidRuntime::getJavaVM();
418     if (event  == ASSOCIATE_JVM) {
419         JavaVMAttachArgs args;
420         char name[] = "BT Service Callback Thread";
421         args.version = JNI_VERSION_1_6;
422         args.name = name;
423         args.group = NULL;
424         vm->AttachCurrentThread(&callbackEnv, &args);
425         ALOGV("Callback thread attached: %p", callbackEnv);
426     } else if (event == DISASSOCIATE_JVM) {
427         if (!checkCallbackThread()) {
428             ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
429             return;
430         }
431         vm->DetachCurrentThread();
432     }
433 }
434 
dut_mode_recv_callback(uint16_t opcode,uint8_t * buf,uint8_t len)435 static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) {
436 
437 }
le_test_mode_recv_callback(bt_status_t status,uint16_t packet_count)438 static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) {
439 
440     ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
441 }
442 bt_callbacks_t sBluetoothCallbacks = {
443     sizeof(sBluetoothCallbacks),
444     adapter_state_change_callback,
445     adapter_properties_callback,
446     remote_device_properties_callback,
447     device_found_callback,
448     discovery_state_changed_callback,
449     pin_request_callback,
450     ssp_request_callback,
451     bond_state_changed_callback,
452     acl_state_changed_callback,
453     callback_thread_event,
454     dut_mode_recv_callback,
455 
456     le_test_mode_recv_callback
457 };
458 
classInitNative(JNIEnv * env,jclass clazz)459 static void classInitNative(JNIEnv* env, jclass clazz) {
460     int err;
461     hw_module_t* module;
462 
463     jclass jniCallbackClass =
464         env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
465     sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
466         "Lcom/android/bluetooth/btservice/JniCallbacks;");
467 
468     method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
469 
470     method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
471                                                              "adapterPropertyChangedCallback",
472                                                              "([I[[B)V");
473     method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
474                                                            "discoveryStateChangeCallback", "(I)V");
475 
476     method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
477                                                             "devicePropertyChangedCallback",
478                                                             "([B[I[[B)V");
479     method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
480     method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
481                                                  "([B[BI)V");
482     method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
483                                                  "([B[BIII)V");
484 
485     method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
486                                                      "bondStateChangeCallback", "(I[BI)V");
487 
488     method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
489                                                     "aclStateChangeCallback", "(I[BI)V");
490     char value[PROPERTY_VALUE_MAX];
491     property_get("bluetooth.mock_stack", value, "");
492 
493     const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
494 
495     err = hw_get_module(id, (hw_module_t const**)&module);
496 
497     if (err == 0) {
498         hw_device_t* abstraction;
499         err = module->methods->open(module, id, &abstraction);
500         if (err == 0) {
501             bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
502             sBluetoothInterface = btStack->get_bluetooth_interface();
503         } else {
504            ALOGE("Error while opening Bluetooth library");
505         }
506     } else {
507         ALOGE("No Bluetooth Library found");
508     }
509 }
510 
initNative(JNIEnv * env,jobject obj)511 static bool initNative(JNIEnv* env, jobject obj) {
512     ALOGV("%s:",__FUNCTION__);
513 
514     sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
515 
516     if (sBluetoothInterface) {
517         int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
518         if (ret != BT_STATUS_SUCCESS) {
519             ALOGE("Error while setting the callbacks \n");
520             sBluetoothInterface = NULL;
521             return JNI_FALSE;
522         }
523         if ( (sBluetoothSocketInterface = (btsock_interface_t *)
524                   sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
525                 ALOGE("Error getting socket interface");
526         }
527         return JNI_TRUE;
528     }
529     return JNI_FALSE;
530 }
531 
cleanupNative(JNIEnv * env,jobject obj)532 static bool cleanupNative(JNIEnv *env, jobject obj) {
533     ALOGV("%s:",__FUNCTION__);
534 
535     jboolean result = JNI_FALSE;
536     if (!sBluetoothInterface) return result;
537 
538     sBluetoothInterface->cleanup();
539     ALOGI("%s: return from cleanup",__FUNCTION__);
540 
541     env->DeleteGlobalRef(sJniCallbacksObj);
542     return JNI_TRUE;
543 }
544 
enableNative(JNIEnv * env,jobject obj)545 static jboolean enableNative(JNIEnv* env, jobject obj) {
546     ALOGV("%s:",__FUNCTION__);
547 
548     jboolean result = JNI_FALSE;
549     if (!sBluetoothInterface) return result;
550 
551     int ret = sBluetoothInterface->enable();
552     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
553     return result;
554 }
555 
disableNative(JNIEnv * env,jobject obj)556 static jboolean disableNative(JNIEnv* env, jobject obj) {
557     ALOGV("%s:",__FUNCTION__);
558 
559     jboolean result = JNI_FALSE;
560     if (!sBluetoothInterface) return result;
561 
562     int ret = sBluetoothInterface->disable();
563     /* Retrun JNI_FALSE only when BTIF explicitly reports
564        BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY
565        case which indicates that stack had not been enabled.
566     */
567     result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE;
568     return result;
569 }
570 
startDiscoveryNative(JNIEnv * env,jobject obj)571 static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
572     ALOGV("%s:",__FUNCTION__);
573 
574     jboolean result = JNI_FALSE;
575     if (!sBluetoothInterface) return result;
576 
577     int ret = sBluetoothInterface->start_discovery();
578     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
579     return result;
580 }
581 
cancelDiscoveryNative(JNIEnv * env,jobject obj)582 static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
583     ALOGV("%s:",__FUNCTION__);
584 
585     jboolean result = JNI_FALSE;
586     if (!sBluetoothInterface) return result;
587 
588     int ret = sBluetoothInterface->cancel_discovery();
589     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
590     return result;
591 }
592 
createBondNative(JNIEnv * env,jobject obj,jbyteArray address)593 static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
594     ALOGV("%s:",__FUNCTION__);
595 
596     jbyte *addr;
597     jboolean result = JNI_FALSE;
598 
599     if (!sBluetoothInterface) return result;
600 
601     addr = env->GetByteArrayElements(address, NULL);
602     if (addr == NULL) {
603         jniThrowIOException(env, EINVAL);
604         return result;
605     }
606 
607     int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
608     env->ReleaseByteArrayElements(address, addr, 0);
609     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
610 
611     return result;
612 }
613 
removeBondNative(JNIEnv * env,jobject obj,jbyteArray address)614 static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
615     ALOGV("%s:",__FUNCTION__);
616 
617     jbyte *addr;
618     jboolean result;
619     if (!sBluetoothInterface) return JNI_FALSE;
620 
621     addr = env->GetByteArrayElements(address, NULL);
622     if (addr == NULL) {
623         jniThrowIOException(env, EINVAL);
624         return JNI_FALSE;
625     }
626 
627     int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
628     env->ReleaseByteArrayElements(address, addr, 0);
629     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
630 
631     return result;
632 }
633 
cancelBondNative(JNIEnv * env,jobject obj,jbyteArray address)634 static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
635     ALOGV("%s:",__FUNCTION__);
636 
637     jbyte *addr;
638     jboolean result;
639     if (!sBluetoothInterface) return JNI_FALSE;
640 
641     addr = env->GetByteArrayElements(address, NULL);
642     if (addr == NULL) {
643         jniThrowIOException(env, EINVAL);
644         return JNI_FALSE;
645     }
646 
647     int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
648     env->ReleaseByteArrayElements(address, addr, 0);
649     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
650 
651     return result;
652 }
653 
pinReplyNative(JNIEnv * env,jobject obj,jbyteArray address,jboolean accept,jint len,jbyteArray pinArray)654 static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
655                                jint len, jbyteArray pinArray) {
656     ALOGV("%s:",__FUNCTION__);
657 
658     jbyte *addr, *pinPtr = NULL;
659     jboolean result = JNI_FALSE;
660     if (!sBluetoothInterface) return result;
661 
662     addr = env->GetByteArrayElements(address, NULL);
663     if (addr == NULL) {
664         jniThrowIOException(env, EINVAL);
665         return result;
666     }
667 
668     if (accept) {
669         pinPtr = env->GetByteArrayElements(pinArray, NULL);
670         if (pinPtr == NULL) {
671            jniThrowIOException(env, EINVAL);
672            env->ReleaseByteArrayElements(address, addr, 0);
673            return result;
674         }
675     }
676 
677     int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
678                                               (bt_pin_code_t *) pinPtr);
679     env->ReleaseByteArrayElements(address, addr, 0);
680     env->ReleaseByteArrayElements(pinArray, pinPtr, 0);
681     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
682 
683     return result;
684 }
685 
sspReplyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type,jboolean accept,jint passkey)686 static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
687                                jint type, jboolean accept, jint passkey) {
688     ALOGV("%s:",__FUNCTION__);
689 
690     jbyte *addr;
691     jboolean result = JNI_FALSE;
692     if (!sBluetoothInterface) return result;
693 
694     addr = env->GetByteArrayElements(address, NULL);
695     if (addr == NULL) {
696         jniThrowIOException(env, EINVAL);
697         return result;
698     }
699 
700     int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
701          (bt_ssp_variant_t) type, accept, passkey);
702     env->ReleaseByteArrayElements(address, addr, 0);
703     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
704 
705     return result;
706 }
707 
setAdapterPropertyNative(JNIEnv * env,jobject obj,jint type,jbyteArray value)708 static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
709     ALOGV("%s:",__FUNCTION__);
710 
711     jbyte *val;
712     jboolean result = JNI_FALSE;
713     if (!sBluetoothInterface) return result;
714 
715     val = env->GetByteArrayElements(value, NULL);
716     bt_property_t prop;
717     prop.type = (bt_property_type_t) type;
718     prop.len = env->GetArrayLength(value);
719     prop.val = val;
720 
721     int ret = sBluetoothInterface->set_adapter_property(&prop);
722     env->ReleaseByteArrayElements(value, val, 0);
723     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
724 
725     return result;
726 }
727 
getAdapterPropertiesNative(JNIEnv * env,jobject obj)728 static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
729     ALOGV("%s:",__FUNCTION__);
730 
731     jboolean result = JNI_FALSE;
732     if (!sBluetoothInterface) return result;
733 
734     int ret = sBluetoothInterface->get_adapter_properties();
735     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
736 
737     return result;
738 }
739 
getAdapterPropertyNative(JNIEnv * env,jobject obj,jint type)740 static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
741     ALOGV("%s:",__FUNCTION__);
742 
743     jboolean result = JNI_FALSE;
744     if (!sBluetoothInterface) return result;
745 
746     int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
747     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
748 
749     return result;
750 }
751 
getDevicePropertyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type)752 static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
753     ALOGV("%s:",__FUNCTION__);
754 
755     jbyte *addr = NULL;
756     jboolean result = JNI_FALSE;
757     if (!sBluetoothInterface) return result;
758 
759     addr = env->GetByteArrayElements(address, NULL);
760     if (addr == NULL) {
761         jniThrowIOException(env, EINVAL);
762         return result;
763     }
764 
765     int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
766                                                               (bt_property_type_t) type);
767     env->ReleaseByteArrayElements(address, addr, 0);
768     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
769 
770     return result;
771 }
772 
setDevicePropertyNative(JNIEnv * env,jobject obj,jbyteArray address,jint type,jbyteArray value)773 static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
774                                         jint type, jbyteArray value) {
775     ALOGV("%s:",__FUNCTION__);
776 
777     jbyte *val, *addr;
778     jboolean result = JNI_FALSE;
779     if (!sBluetoothInterface) return result;
780 
781     val = env->GetByteArrayElements(value, NULL);
782     if (val == NULL) {
783         jniThrowIOException(env, EINVAL);
784         return result;
785     }
786 
787     addr = env->GetByteArrayElements(address, NULL);
788     if (addr == NULL) {
789         env->ReleaseByteArrayElements(value, val, 0);
790         jniThrowIOException(env, EINVAL);
791         return result;
792     }
793 
794 
795     bt_property_t prop;
796     prop.type = (bt_property_type_t) type;
797     prop.len = env->GetArrayLength(value);
798     prop.val = val;
799 
800     int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
801     env->ReleaseByteArrayElements(value, val, 0);
802     env->ReleaseByteArrayElements(address, addr, 0);
803 
804     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
805 
806     return result;
807 }
808 
getRemoteServicesNative(JNIEnv * env,jobject obj,jbyteArray address)809 static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
810     ALOGV("%s:",__FUNCTION__);
811 
812     jbyte *addr = NULL;
813     jboolean result = JNI_FALSE;
814     if (!sBluetoothInterface) return result;
815 
816     addr = env->GetByteArrayElements(address, NULL);
817     if (addr == NULL) {
818         jniThrowIOException(env, EINVAL);
819         return result;
820     }
821 
822     int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
823     env->ReleaseByteArrayElements(address, addr, 0);
824     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
825     return result;
826 }
827 
connectSocketNative(JNIEnv * env,jobject object,jbyteArray address,jint type,jbyteArray uuidObj,jint channel,jint flag)828 static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
829                                    jbyteArray uuidObj, jint channel, jint flag) {
830     jbyte *addr = NULL, *uuid = NULL;
831     int socket_fd;
832     bt_status_t status;
833 
834     if (!sBluetoothSocketInterface) return -1;
835 
836     addr = env->GetByteArrayElements(address, NULL);
837     if (!addr) {
838         ALOGE("failed to get Bluetooth device address");
839         goto Fail;
840     }
841 
842     uuid = env->GetByteArrayElements(uuidObj, NULL);
843     if (!uuid) {
844         ALOGE("failed to get uuid");
845         goto Fail;
846     }
847 
848     if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
849                        (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
850         ALOGE("Socket connection failed: %d", status);
851         goto Fail;
852     }
853 
854 
855     if (socket_fd < 0) {
856         ALOGE("Fail to creat file descriptor on socket fd");
857         goto Fail;
858     }
859     env->ReleaseByteArrayElements(address, addr, 0);
860     env->ReleaseByteArrayElements(uuidObj, uuid, 0);
861     return socket_fd;
862 
863 Fail:
864     if (addr) env->ReleaseByteArrayElements(address, addr, 0);
865     if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
866 
867     return -1;
868 }
869 
createSocketChannelNative(JNIEnv * env,jobject object,jint type,jstring name_str,jbyteArray uuidObj,jint channel,jint flag)870 static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
871                                      jstring name_str, jbyteArray uuidObj, jint channel, jint flag) {
872     const char *service_name;
873     jbyte *uuid = NULL;
874     int socket_fd;
875     bt_status_t status;
876 
877     if (!sBluetoothSocketInterface) return -1;
878 
879     service_name = env->GetStringUTFChars(name_str, NULL);
880 
881     uuid = env->GetByteArrayElements(uuidObj, NULL);
882     if (!uuid) {
883         ALOGE("failed to get uuid");
884         goto Fail;
885     }
886     ALOGE("SOCK FLAG = %x ***********************",flag);
887     if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
888                        (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
889         ALOGE("Socket listen failed: %d", status);
890         goto Fail;
891     }
892 
893     if (socket_fd < 0) {
894         ALOGE("Fail to creat file descriptor on socket fd");
895         goto Fail;
896     }
897     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
898     if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
899     return socket_fd;
900 
901 Fail:
902     if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
903     if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
904 
905     return -1;
906 }
907 
configHciSnoopLogNative(JNIEnv * env,jobject obj,jboolean enable)908 static jboolean configHciSnoopLogNative(JNIEnv* env, jobject obj, jboolean enable) {
909     ALOGV("%s:",__FUNCTION__);
910 
911     jboolean result = JNI_FALSE;
912 
913     if (!sBluetoothInterface) return result;
914 
915     int ret = sBluetoothInterface->config_hci_snoop_log(enable);
916 
917     result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
918 
919     return result;
920 }
921 
922 static JNINativeMethod sMethods[] = {
923     /* name, signature, funcPtr */
924     {"classInitNative", "()V", (void *) classInitNative},
925     {"initNative", "()Z", (void *) initNative},
926     {"cleanupNative", "()V", (void*) cleanupNative},
927     {"enableNative", "()Z",  (void*) enableNative},
928     {"disableNative", "()Z",  (void*) disableNative},
929     {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
930     {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
931     {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
932     {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
933     {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
934     {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
935     {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
936     {"createBondNative", "([B)Z", (void*) createBondNative},
937     {"removeBondNative", "([B)Z", (void*) removeBondNative},
938     {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
939     {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
940     {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
941     {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
942     {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
943     {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
944      (void*) createSocketChannelNative},
945     {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative}
946 };
947 
register_com_android_bluetooth_btservice_AdapterService(JNIEnv * env)948 int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
949 {
950     return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
951                                     sMethods, NELEM(sMethods));
952 }
953 
954 } /* namespace android */
955 
956 
957 /*
958  * JNI Initialization
959  */
JNI_OnLoad(JavaVM * jvm,void * reserved)960 jint JNI_OnLoad(JavaVM *jvm, void *reserved)
961 {
962     JNIEnv *e;
963     int status;
964 
965     ALOGV("Bluetooth Adapter Service : loading JNI\n");
966 
967     // Check JNI version
968     if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
969         ALOGE("JNI version mismatch error");
970         return JNI_ERR;
971     }
972 
973     if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
974         ALOGE("jni adapter service registration failure, status: %d", status);
975         return JNI_ERR;
976     }
977 
978     if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
979         ALOGE("jni hfp registration failure, status: %d", status);
980         return JNI_ERR;
981     }
982 
983     if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
984         ALOGE("jni a2dp registration failure: %d", status);
985         return JNI_ERR;
986     }
987 
988     if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
989         ALOGE("jni avrcp registration failure: %d", status);
990         return JNI_ERR;
991     }
992 
993     if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
994         ALOGE("jni hid registration failure: %d", status);
995         return JNI_ERR;
996     }
997 
998     if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
999         ALOGE("jni hdp registration failure: %d", status);
1000         return JNI_ERR;
1001     }
1002 
1003     if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
1004         ALOGE("jni pan registration failure: %d", status);
1005         return JNI_ERR;
1006     }
1007 
1008     if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
1009         ALOGE("jni gatt registration failure: %d", status);
1010         return JNI_ERR;
1011     }
1012     return JNI_VERSION_1_6;
1013 }
1014