com_android_bluetooth_btservice_AdapterService.cpp revision edb14a4944d66ca9255b2ab9b384c583b626fd94
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
22
23static jmethodID method_stateChangeCallback;
24static jmethodID method_adapterPropertyChangedCallback;
25static jmethodID method_devicePropertyChangedCallback;
26static jmethodID method_deviceFoundCallback;
27static jmethodID method_pinRequestCallback;
28static jmethodID method_sspRequestCallback;
29static jmethodID method_bondStateChangeCallback;
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        LOGE("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        LOGE("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       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
69       return;
70    }
71    LOGV("%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    LOGE("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       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
119       return;
120    }
121
122    LOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
123
124    if (status != BT_STATUS_SUCCESS) {
125        LOGE("%s: Status %d is incorrect", __FUNCTION__, status);
126        return;
127    }
128
129    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
130    if (val == NULL) {
131        LOGE("%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        LOGE("%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        LOGE("%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       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
176       return;
177    }
178
179    LOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
180
181    if (status != BT_STATUS_SUCCESS) {
182        LOGE("%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        LOGE("%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        LOGE("%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        LOGE("%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    LOGE("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                LOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
260                return;
261            }
262        }
263    }
264    if (addr == NULL) {
265        LOGE("Address is NULL in %s", __FUNCTION__);
266        return;
267    }
268
269    LOGV("%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       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
286       return;
287    }
288    if (!bd_addr) {
289        LOGE("Address is null in %s", __FUNCTION__);
290        return;
291    }
292    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
293    if (addr == NULL) {
294       LOGE("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 discovery_state_changed_callback(bt_discovery_state_t state) {
306    jbyteArray addr;
307    if (!checkCallbackThread()) {
308       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
309       return;
310    }
311
312    LOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
313
314    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
315                                (jint)state);
316
317    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
318}
319
320static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) {
321    jbyteArray addr, devname;
322    if (!checkCallbackThread()) {
323       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
324       return;
325    }
326    if (!bd_addr) {
327        LOGE("Address is null in %s", __FUNCTION__);
328        return;
329    }
330
331    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
332    if (addr == NULL) goto Fail;
333    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
334
335    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
336    if (devname == NULL) goto Fail;
337
338    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
339
340    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod);
341
342    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
343    callbackEnv->DeleteLocalRef(addr);
344    callbackEnv->DeleteLocalRef(devname);
345    return;
346
347Fail:
348    if (addr) callbackEnv->DeleteLocalRef(addr);
349    if (devname) callbackEnv->DeleteLocalRef(devname);
350    LOGE("Error while allocating in: %s", __FUNCTION__);
351}
352
353static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
354                                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
355    jbyteArray addr, devname;
356    if (!checkCallbackThread()) {
357       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
358       return;
359    }
360    if (!bd_addr) {
361        LOGE("Address is null in %s", __FUNCTION__);
362        return;
363    }
364
365    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
366    if (addr == NULL) goto Fail;
367    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
368
369    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
370    if (devname == NULL) goto Fail;
371    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
372
373    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
374                                (jint) pairing_variant, pass_key);
375
376    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
377    callbackEnv->DeleteLocalRef(addr);
378    callbackEnv->DeleteLocalRef(devname);
379    return;
380
381Fail:
382    if (addr) callbackEnv->DeleteLocalRef(addr);
383    if (devname) callbackEnv->DeleteLocalRef(devname);
384
385    LOGE("Error while allocating in: %s", __FUNCTION__);
386}
387
388static void callback_thread_event(bt_cb_thread_evt event) {
389    JavaVM* vm = AndroidRuntime::getJavaVM();
390    if (event  == ASSOCIATE_JVM) {
391        JavaVMAttachArgs args;
392        char name[] = "BT Service Callback Thread";
393        //TODO(BT)
394        //args.version = nat->envVer;
395        args.name = name;
396        args.group = NULL;
397        vm->AttachCurrentThread(&callbackEnv, &args);
398        LOGV("Callback thread attached: %p", callbackEnv);
399    } else if (event == DISASSOCIATE_JVM) {
400        if (!checkCallbackThread()) {
401            LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
402            return;
403        }
404        vm->DetachCurrentThread();
405    }
406}
407
408bt_callbacks_t sBluetoothCallbacks = {
409    sizeof(sBluetoothCallbacks),
410    adapter_state_change_callback,
411    adapter_properties_callback,
412    remote_device_properties_callback,
413    device_found_callback,
414    discovery_state_changed_callback,
415    pin_request_callback,
416    ssp_request_callback,
417    bond_state_changed_callback,
418    callback_thread_event,
419};
420
421static void classInitNative(JNIEnv* env, jclass clazz) {
422    int err;
423    hw_module_t* module;
424
425    jclass jniCallbackClass =
426        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
427    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
428        "Lcom/android/bluetooth/btservice/JniCallbacks;");
429
430    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
431
432    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
433                                                             "adapterPropertyChangedCallback",
434                                                             "([I[[B)V");
435    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
436                                                           "discoveryStateChangeCallback", "(I)V");
437
438    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
439                                                            "devicePropertyChangedCallback",
440                                                            "([B[I[[B)V");
441    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
442    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
443                                                 "([B[BI)V");
444    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
445                                                 "([B[BIII)V");
446
447    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
448                                                     "bondStateChangeCallback", "(I[BI)V");
449
450    char value[PROPERTY_VALUE_MAX];
451    property_get("bluetooth.mock_stack", value, "");
452
453    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
454
455    err = hw_get_module(id, (hw_module_t const**)&module);
456
457    if (err == 0) {
458        hw_device_t* abstraction;
459        err = module->methods->open(module, id, &abstraction);
460        if (err == 0) {
461            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
462            sBluetoothInterface = btStack->get_bluetooth_interface();
463        } else {
464           LOGE("Error while opening Bluetooth library");
465        }
466    } else {
467        LOGE("No Bluetooth Library found");
468    }
469}
470
471static bool initNative(JNIEnv* env, jobject obj) {
472    LOGV("%s:",__FUNCTION__);
473
474    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
475
476    if (sBluetoothInterface) {
477        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
478        if (ret != BT_STATUS_SUCCESS) {
479            LOGE("Error while setting the callbacks \n");
480            sBluetoothInterface = NULL;
481            return JNI_FALSE;
482        }
483        if ( (sBluetoothSocketInterface = (btsock_interface_t *)
484                  sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
485                LOGE("Error getting socket interface");
486        }
487        return JNI_TRUE;
488    }
489    return JNI_FALSE;
490}
491
492static bool cleanupNative(JNIEnv *env, jobject obj) {
493    LOGV("%s:",__FUNCTION__);
494
495    jboolean result = JNI_FALSE;
496    if (!sBluetoothInterface) return result;
497
498    sBluetoothInterface->cleanup();
499    env->DeleteGlobalRef(sJniCallbacksObj);
500    return JNI_TRUE;
501}
502
503static jboolean enableNative(JNIEnv* env, jobject obj) {
504    LOGV("%s:",__FUNCTION__);
505
506    jboolean result = JNI_FALSE;
507    if (!sBluetoothInterface) return result;
508
509    int ret = sBluetoothInterface->enable();
510    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
511    return result;
512}
513
514static jboolean disableNative(JNIEnv* env, jobject obj) {
515    LOGV("%s:",__FUNCTION__);
516
517    jboolean result = JNI_FALSE;
518    if (!sBluetoothInterface) return result;
519
520    int ret = sBluetoothInterface->disable();
521    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
522    return result;
523}
524
525static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
526    LOGV("%s:",__FUNCTION__);
527
528    jboolean result = JNI_FALSE;
529    if (!sBluetoothInterface) return result;
530
531    int ret = sBluetoothInterface->start_discovery();
532    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
533    return result;
534}
535
536static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
537    LOGV("%s:",__FUNCTION__);
538
539    jboolean result = JNI_FALSE;
540    if (!sBluetoothInterface) return result;
541
542    int ret = sBluetoothInterface->cancel_discovery();
543    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
544    return result;
545}
546
547static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
548    LOGV("%s:",__FUNCTION__);
549
550    jbyte *addr;
551    jboolean result = JNI_FALSE;
552
553    if (!sBluetoothInterface) return result;
554
555    addr = env->GetByteArrayElements(address, NULL);
556    if (addr == NULL) {
557        jniThrowIOException(env, EINVAL);
558        return result;
559    }
560
561    int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
562    env->ReleaseByteArrayElements(address, addr, NULL);
563    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
564
565    return result;
566}
567
568static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
569    LOGV("%s:",__FUNCTION__);
570
571    jbyte *addr;
572    jboolean result;
573    if (!sBluetoothInterface) return JNI_FALSE;
574
575    addr = env->GetByteArrayElements(address, NULL);
576    if (addr == NULL) {
577        jniThrowIOException(env, EINVAL);
578        return JNI_FALSE;
579    }
580
581    int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
582    env->ReleaseByteArrayElements(address, addr, NULL);
583    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
584
585    return result;
586}
587
588static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
589    LOGV("%s:",__FUNCTION__);
590
591    jbyte *addr;
592    jboolean result;
593    if (!sBluetoothInterface) return JNI_FALSE;
594
595    addr = env->GetByteArrayElements(address, NULL);
596    if (addr == NULL) {
597        jniThrowIOException(env, EINVAL);
598        return JNI_FALSE;
599    }
600
601    int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
602    env->ReleaseByteArrayElements(address, addr, NULL);
603    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
604
605    return result;
606}
607
608static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
609                               jint len, jbyteArray pinArray) {
610    LOGV("%s:",__FUNCTION__);
611
612    jbyte *addr, *pinPtr = NULL;
613    jboolean result = JNI_FALSE;
614    if (!sBluetoothInterface) return result;
615
616    addr = env->GetByteArrayElements(address, NULL);
617    if (addr == NULL) {
618        jniThrowIOException(env, EINVAL);
619        return result;
620    }
621
622    if (accept) {
623        pinPtr = env->GetByteArrayElements(pinArray, NULL);
624        if (pinPtr == NULL) {
625           jniThrowIOException(env, EINVAL);
626           env->ReleaseByteArrayElements(address, addr, NULL);
627           return result;
628        }
629    }
630
631    int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
632                                              (bt_pin_code_t *) pinPtr);
633    env->ReleaseByteArrayElements(address, addr, NULL);
634    env->ReleaseByteArrayElements(pinArray, pinPtr, NULL);
635    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
636
637    return result;
638}
639
640static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
641                               jint type, jboolean accept, jint passkey) {
642    LOGV("%s:",__FUNCTION__);
643
644    jbyte *addr;
645    jboolean result = JNI_FALSE;
646    if (!sBluetoothInterface) return result;
647
648    addr = env->GetByteArrayElements(address, NULL);
649    if (addr == NULL) {
650        jniThrowIOException(env, EINVAL);
651        return result;
652    }
653
654    int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
655         (bt_ssp_variant_t) type, accept, passkey);
656    env->ReleaseByteArrayElements(address, addr, NULL);
657    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
658
659    return result;
660}
661
662static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
663    LOGV("%s:",__FUNCTION__);
664
665    jbyte *val;
666    jboolean result = JNI_FALSE;
667    if (!sBluetoothInterface) return result;
668
669    val = env->GetByteArrayElements(value, NULL);
670    bt_property_t prop;
671    prop.type = (bt_property_type_t) type;
672    prop.len = env->GetArrayLength(value);
673    prop.val = val;
674
675    int ret = sBluetoothInterface->set_adapter_property(&prop);
676    env->ReleaseByteArrayElements(value, val, NULL);
677    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
678
679    return result;
680}
681
682static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
683    LOGV("%s:",__FUNCTION__);
684
685    jboolean result = JNI_FALSE;
686    if (!sBluetoothInterface) return result;
687
688    int ret = sBluetoothInterface->get_adapter_properties();
689    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
690
691    return result;
692}
693
694static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
695    LOGV("%s:",__FUNCTION__);
696
697    jboolean result = JNI_FALSE;
698    if (!sBluetoothInterface) return result;
699
700    int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
701    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
702
703    return result;
704}
705
706static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
707    LOGV("%s:",__FUNCTION__);
708
709    jbyte *addr = NULL;
710    jboolean result = JNI_FALSE;
711    if (!sBluetoothInterface) return result;
712
713    addr = env->GetByteArrayElements(address, NULL);
714    if (addr == NULL) {
715        jniThrowIOException(env, EINVAL);
716        return result;
717    }
718
719    int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
720                                                              (bt_property_type_t) type);
721    env->ReleaseByteArrayElements(address, addr, NULL);
722    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
723
724    return result;
725}
726
727static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
728                                        jint type, jbyteArray value) {
729    LOGV("%s:",__FUNCTION__);
730
731    jbyte *val, *addr;
732    jboolean result = JNI_FALSE;
733    if (!sBluetoothInterface) return result;
734
735    val = env->GetByteArrayElements(value, NULL);
736    if (val == NULL) {
737        jniThrowIOException(env, EINVAL);
738        return result;
739    }
740
741    addr = env->GetByteArrayElements(address, NULL);
742    if (addr == NULL) {
743        env->ReleaseByteArrayElements(value, val, NULL);
744        jniThrowIOException(env, EINVAL);
745        return result;
746    }
747
748
749    bt_property_t prop;
750    prop.type = (bt_property_type_t) type;
751    prop.len = env->GetArrayLength(value);
752    prop.val = val;
753
754    int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
755    env->ReleaseByteArrayElements(value, val, NULL);
756    env->ReleaseByteArrayElements(address, addr, NULL);
757
758    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
759
760    return result;
761}
762
763static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
764    LOGV("%s:",__FUNCTION__);
765
766    jbyte *addr = NULL;
767    jboolean result = JNI_FALSE;
768    if (!sBluetoothInterface) return result;
769
770    addr = env->GetByteArrayElements(address, NULL);
771    if (addr == NULL) {
772        jniThrowIOException(env, EINVAL);
773        return result;
774    }
775
776    int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
777    env->ReleaseByteArrayElements(address, addr, NULL);
778    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
779    return result;
780}
781
782static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
783                                   jbyteArray uuidObj, jint channel, jint flag) {
784    jbyte *addr = NULL, *uuid = NULL;
785    int socket_fd;
786    bt_status_t status;
787
788    if (!sBluetoothSocketInterface) return NULL;
789
790    addr = env->GetByteArrayElements(address, NULL);
791    if (!addr) {
792        LOGE("failed to get Bluetooth device address");
793        goto Fail;
794    }
795
796    uuid = env->GetByteArrayElements(uuidObj, NULL);
797    if (!uuid) {
798        LOGE("failed to get uuid");
799        goto Fail;
800    }
801
802    if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
803                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
804        LOGE("Socket connection failed: %d", status);
805        goto Fail;
806    }
807
808
809    if (socket_fd < 0) {
810        LOGE("Fail to creat file descriptor on socket fd");
811        goto Fail;
812    }
813    env->ReleaseByteArrayElements(address, addr, 0);
814    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
815    return socket_fd;
816
817Fail:
818    if (addr) env->ReleaseByteArrayElements(address, addr, 0);
819    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
820
821    return -1;
822}
823
824static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
825                                         jstring name_str, jbyteArray uuidObj, jint channel, jint flag) {
826    const char *service_name;
827    jbyte *uuid = NULL;
828    int socket_fd;
829    bt_status_t status;
830
831    if (!sBluetoothSocketInterface) return NULL;
832
833    service_name = env->GetStringUTFChars(name_str, NULL);
834
835    uuid = env->GetByteArrayElements(uuidObj, NULL);
836    if (!uuid) {
837        LOGE("failed to get uuid");
838        goto Fail;
839    }
840
841    if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
842                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
843        LOGE("Socket listen failed: %d", status);
844        goto Fail;
845    }
846
847    if (socket_fd < 0) {
848        LOGE("Fail to creat file descriptor on socket fd");
849        goto Fail;
850    }
851    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
852    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
853    return socket_fd;
854
855Fail:
856    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
857    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
858
859    return -1;
860}
861
862static JNINativeMethod sMethods[] = {
863     /* name, signature, funcPtr */
864    {"classInitNative", "()V", (void *) classInitNative},
865    {"initNative", "()Z", (void *) initNative},
866    {"cleanupNative", "()V", (void*) cleanupNative},
867    {"enableNative", "()Z",  (void*) enableNative},
868    {"disableNative", "()Z",  (void*) disableNative},
869    {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
870    {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
871    {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
872    {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
873    {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
874    {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
875    {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
876    {"createBondNative", "([B)Z", (void*) createBondNative},
877    {"removeBondNative", "([B)Z", (void*) removeBondNative},
878    {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
879    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
880    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
881    {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
882    {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
883    {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
884     (void*) createSocketChannelNative},
885};
886
887int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
888{
889    return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
890                                    sMethods, NELEM(sMethods));
891}
892
893} /* namespace android */
894
895
896/*
897 * JNI Initialization
898 */
899jint JNI_OnLoad(JavaVM *jvm, void *reserved)
900{
901   JNIEnv *e;
902   int status;
903
904   LOGV("Bluetooth Adapter Service : loading JNI\n");
905
906   // Check JNI version
907   if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
908       LOGE("JNI version mismatch error");
909      return JNI_ERR;
910   }
911
912   if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
913       LOGE("jni adapter service registration failure, status: %d", status);
914      return JNI_ERR;
915   }
916
917   if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
918       LOGE("jni hfp registration failure, status: %d", status);
919      return JNI_ERR;
920   }
921
922   if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
923       LOGE("jni a2dp registration failure: %d", status);
924      return JNI_ERR;
925   }
926
927   if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
928       LOGE("jni hid registration failure: %d", status);
929       return JNI_ERR;
930   }
931
932   if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
933       LOGE("jni hdp registration failure: %d", status);
934      return JNI_ERR;
935   }
936
937   return JNI_VERSION_1_6;
938}
939