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