com_android_bluetooth_btservice_AdapterService.cpp revision 6654f5c903de510a70f9e72cd5ad7837b615d93f
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    LOGV("%s: return from cleanup",__FUNCTION__);
500
501    env->DeleteGlobalRef(sJniCallbacksObj);
502    return JNI_TRUE;
503}
504
505static jboolean enableNative(JNIEnv* env, jobject obj) {
506    LOGV("%s:",__FUNCTION__);
507
508    jboolean result = JNI_FALSE;
509    if (!sBluetoothInterface) return result;
510
511    int ret = sBluetoothInterface->enable();
512    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
513    return result;
514}
515
516static jboolean disableNative(JNIEnv* env, jobject obj) {
517    LOGV("%s:",__FUNCTION__);
518
519    jboolean result = JNI_FALSE;
520    if (!sBluetoothInterface) return result;
521
522    int ret = sBluetoothInterface->disable();
523    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
524    return result;
525}
526
527static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
528    LOGV("%s:",__FUNCTION__);
529
530    jboolean result = JNI_FALSE;
531    if (!sBluetoothInterface) return result;
532
533    int ret = sBluetoothInterface->start_discovery();
534    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
535    return result;
536}
537
538static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
539    LOGV("%s:",__FUNCTION__);
540
541    jboolean result = JNI_FALSE;
542    if (!sBluetoothInterface) return result;
543
544    int ret = sBluetoothInterface->cancel_discovery();
545    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
546    return result;
547}
548
549static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
550    LOGV("%s:",__FUNCTION__);
551
552    jbyte *addr;
553    jboolean result = JNI_FALSE;
554
555    if (!sBluetoothInterface) return result;
556
557    addr = env->GetByteArrayElements(address, NULL);
558    if (addr == NULL) {
559        jniThrowIOException(env, EINVAL);
560        return result;
561    }
562
563    int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
564    env->ReleaseByteArrayElements(address, addr, NULL);
565    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
566
567    return result;
568}
569
570static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
571    LOGV("%s:",__FUNCTION__);
572
573    jbyte *addr;
574    jboolean result;
575    if (!sBluetoothInterface) return JNI_FALSE;
576
577    addr = env->GetByteArrayElements(address, NULL);
578    if (addr == NULL) {
579        jniThrowIOException(env, EINVAL);
580        return JNI_FALSE;
581    }
582
583    int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
584    env->ReleaseByteArrayElements(address, addr, NULL);
585    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
586
587    return result;
588}
589
590static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
591    LOGV("%s:",__FUNCTION__);
592
593    jbyte *addr;
594    jboolean result;
595    if (!sBluetoothInterface) return JNI_FALSE;
596
597    addr = env->GetByteArrayElements(address, NULL);
598    if (addr == NULL) {
599        jniThrowIOException(env, EINVAL);
600        return JNI_FALSE;
601    }
602
603    int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
604    env->ReleaseByteArrayElements(address, addr, NULL);
605    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
606
607    return result;
608}
609
610static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
611                               jint len, jbyteArray pinArray) {
612    LOGV("%s:",__FUNCTION__);
613
614    jbyte *addr, *pinPtr = NULL;
615    jboolean result = JNI_FALSE;
616    if (!sBluetoothInterface) return result;
617
618    addr = env->GetByteArrayElements(address, NULL);
619    if (addr == NULL) {
620        jniThrowIOException(env, EINVAL);
621        return result;
622    }
623
624    if (accept) {
625        pinPtr = env->GetByteArrayElements(pinArray, NULL);
626        if (pinPtr == NULL) {
627           jniThrowIOException(env, EINVAL);
628           env->ReleaseByteArrayElements(address, addr, NULL);
629           return result;
630        }
631    }
632
633    int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
634                                              (bt_pin_code_t *) pinPtr);
635    env->ReleaseByteArrayElements(address, addr, NULL);
636    env->ReleaseByteArrayElements(pinArray, pinPtr, NULL);
637    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
638
639    return result;
640}
641
642static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
643                               jint type, jboolean accept, jint passkey) {
644    LOGV("%s:",__FUNCTION__);
645
646    jbyte *addr;
647    jboolean result = JNI_FALSE;
648    if (!sBluetoothInterface) return result;
649
650    addr = env->GetByteArrayElements(address, NULL);
651    if (addr == NULL) {
652        jniThrowIOException(env, EINVAL);
653        return result;
654    }
655
656    int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
657         (bt_ssp_variant_t) type, accept, passkey);
658    env->ReleaseByteArrayElements(address, addr, NULL);
659    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
660
661    return result;
662}
663
664static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
665    LOGV("%s:",__FUNCTION__);
666
667    jbyte *val;
668    jboolean result = JNI_FALSE;
669    if (!sBluetoothInterface) return result;
670
671    val = env->GetByteArrayElements(value, NULL);
672    bt_property_t prop;
673    prop.type = (bt_property_type_t) type;
674    prop.len = env->GetArrayLength(value);
675    prop.val = val;
676
677    int ret = sBluetoothInterface->set_adapter_property(&prop);
678    env->ReleaseByteArrayElements(value, val, NULL);
679    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
680
681    return result;
682}
683
684static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
685    LOGV("%s:",__FUNCTION__);
686
687    jboolean result = JNI_FALSE;
688    if (!sBluetoothInterface) return result;
689
690    int ret = sBluetoothInterface->get_adapter_properties();
691    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
692
693    return result;
694}
695
696static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
697    LOGV("%s:",__FUNCTION__);
698
699    jboolean result = JNI_FALSE;
700    if (!sBluetoothInterface) return result;
701
702    int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
703    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
704
705    return result;
706}
707
708static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
709    LOGV("%s:",__FUNCTION__);
710
711    jbyte *addr = NULL;
712    jboolean result = JNI_FALSE;
713    if (!sBluetoothInterface) return result;
714
715    addr = env->GetByteArrayElements(address, NULL);
716    if (addr == NULL) {
717        jniThrowIOException(env, EINVAL);
718        return result;
719    }
720
721    int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
722                                                              (bt_property_type_t) type);
723    env->ReleaseByteArrayElements(address, addr, NULL);
724    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
725
726    return result;
727}
728
729static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
730                                        jint type, jbyteArray value) {
731    LOGV("%s:",__FUNCTION__);
732
733    jbyte *val, *addr;
734    jboolean result = JNI_FALSE;
735    if (!sBluetoothInterface) return result;
736
737    val = env->GetByteArrayElements(value, NULL);
738    if (val == NULL) {
739        jniThrowIOException(env, EINVAL);
740        return result;
741    }
742
743    addr = env->GetByteArrayElements(address, NULL);
744    if (addr == NULL) {
745        env->ReleaseByteArrayElements(value, val, NULL);
746        jniThrowIOException(env, EINVAL);
747        return result;
748    }
749
750
751    bt_property_t prop;
752    prop.type = (bt_property_type_t) type;
753    prop.len = env->GetArrayLength(value);
754    prop.val = val;
755
756    int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
757    env->ReleaseByteArrayElements(value, val, NULL);
758    env->ReleaseByteArrayElements(address, addr, NULL);
759
760    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
761
762    return result;
763}
764
765static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
766    LOGV("%s:",__FUNCTION__);
767
768    jbyte *addr = NULL;
769    jboolean result = JNI_FALSE;
770    if (!sBluetoothInterface) return result;
771
772    addr = env->GetByteArrayElements(address, NULL);
773    if (addr == NULL) {
774        jniThrowIOException(env, EINVAL);
775        return result;
776    }
777
778    int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
779    env->ReleaseByteArrayElements(address, addr, NULL);
780    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
781    return result;
782}
783
784static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
785                                   jbyteArray uuidObj, jint channel, jint flag) {
786    jbyte *addr = NULL, *uuid = NULL;
787    int socket_fd;
788    bt_status_t status;
789
790    if (!sBluetoothSocketInterface) return NULL;
791
792    addr = env->GetByteArrayElements(address, NULL);
793    if (!addr) {
794        LOGE("failed to get Bluetooth device address");
795        goto Fail;
796    }
797
798    uuid = env->GetByteArrayElements(uuidObj, NULL);
799    if (!uuid) {
800        LOGE("failed to get uuid");
801        goto Fail;
802    }
803
804    if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
805                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
806        LOGE("Socket connection failed: %d", status);
807        goto Fail;
808    }
809
810
811    if (socket_fd < 0) {
812        LOGE("Fail to creat file descriptor on socket fd");
813        goto Fail;
814    }
815    env->ReleaseByteArrayElements(address, addr, 0);
816    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
817    return socket_fd;
818
819Fail:
820    if (addr) env->ReleaseByteArrayElements(address, addr, 0);
821    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
822
823    return -1;
824}
825
826static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
827                                         jstring name_str, jbyteArray uuidObj, jint channel, jint flag) {
828    const char *service_name;
829    jbyte *uuid = NULL;
830    int socket_fd;
831    bt_status_t status;
832
833    if (!sBluetoothSocketInterface) return NULL;
834
835    service_name = env->GetStringUTFChars(name_str, NULL);
836
837    uuid = env->GetByteArrayElements(uuidObj, NULL);
838    if (!uuid) {
839        LOGE("failed to get uuid");
840        goto Fail;
841    }
842    LOGE("SOCK FLAG = %x ***********************",flag);
843    if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
844                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
845        LOGE("Socket listen failed: %d", status);
846        goto Fail;
847    }
848
849    if (socket_fd < 0) {
850        LOGE("Fail to creat file descriptor on socket fd");
851        goto Fail;
852    }
853    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
854    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
855    return socket_fd;
856
857Fail:
858    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
859    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
860
861    return -1;
862}
863
864static JNINativeMethod sMethods[] = {
865     /* name, signature, funcPtr */
866    {"classInitNative", "()V", (void *) classInitNative},
867    {"initNative", "()Z", (void *) initNative},
868    {"cleanupNative", "()V", (void*) cleanupNative},
869    {"enableNative", "()Z",  (void*) enableNative},
870    {"disableNative", "()Z",  (void*) disableNative},
871    {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
872    {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
873    {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
874    {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
875    {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
876    {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
877    {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
878    {"createBondNative", "([B)Z", (void*) createBondNative},
879    {"removeBondNative", "([B)Z", (void*) removeBondNative},
880    {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
881    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
882    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
883    {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
884    {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
885    {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
886     (void*) createSocketChannelNative},
887};
888
889int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
890{
891    return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
892                                    sMethods, NELEM(sMethods));
893}
894
895} /* namespace android */
896
897
898/*
899 * JNI Initialization
900 */
901jint JNI_OnLoad(JavaVM *jvm, void *reserved)
902{
903   JNIEnv *e;
904   int status;
905
906   LOGV("Bluetooth Adapter Service : loading JNI\n");
907
908   // Check JNI version
909   if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
910       LOGE("JNI version mismatch error");
911      return JNI_ERR;
912   }
913
914   if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
915       LOGE("jni adapter service registration failure, status: %d", status);
916      return JNI_ERR;
917   }
918
919   if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
920       LOGE("jni hfp registration failure, status: %d", status);
921      return JNI_ERR;
922   }
923
924   if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
925       LOGE("jni a2dp registration failure: %d", status);
926      return JNI_ERR;
927   }
928
929   if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
930       LOGE("jni hid registration failure: %d", status);
931       return JNI_ERR;
932   }
933
934   if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
935       LOGE("jni hdp registration failure: %d", status);
936      return JNI_ERR;
937   }
938
939   if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
940       LOGE("jni pan registration failure: %d", status);
941      return JNI_ERR;
942   }
943
944   return JNI_VERSION_1_6;
945}
946