com_android_bluetooth_btservice_AdapterService.cpp revision 676cb1bdd1c14c7af56562bab51f168e7f8f6d62
1/*
2 * Copyright (C) 2012 Google Inc.
3 */
4
5#define LOG_TAG "BluetoothServiceJni"
6
7#include "com_android_bluetooth.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 JNIEnv *callbackEnv = NULL;
34
35static jobject sJniCallbacksObj;
36static jfieldID sJniCallbacksField;
37
38const bt_interface_t* getBluetoothInterface() {
39    return sBluetoothInterface;
40}
41
42JNIEnv* getCallbackEnv() {
43   return callbackEnv;
44}
45
46void checkAndClearExceptionFromCallback(JNIEnv* env,
47                                               const char* methodName) {
48    if (env->ExceptionCheck()) {
49        LOGE("An exception was thrown by callback '%s'.", methodName);
50        LOGE_EX(env);
51        env->ExceptionClear();
52    }
53}
54
55static bool checkCallbackThread() {
56    JNIEnv* env = AndroidRuntime::getJNIEnv();
57    if (callbackEnv != env || callbackEnv == NULL) {
58        LOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
59        return false;
60    }
61    return true;
62}
63
64static void adapter_state_change_callback(bt_state_t status) {
65    if (!checkCallbackThread()) {
66       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
67       return;
68    }
69    LOGV("%s: Status is: %d", __FUNCTION__, status);
70
71    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
72
73    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
74}
75
76static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
77                        jobjectArray *props) {
78    jbyteArray propVal, val;
79    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
80    if (val == NULL) goto Fail;
81
82    //TODO(BT) Is this the best way to do it ?
83    *props = callbackEnv->NewObjectArray(num_properties, callbackEnv->GetObjectClass(val),
84                                             NULL);
85    if (*props == NULL) goto Fail;
86
87    *types = callbackEnv->NewIntArray(num_properties);
88    if (*types == NULL) goto Fail;
89
90    for (int i = 0; i < num_properties; i++) {
91
92       /* The higher layers expect rssi as a short int value, while the value is sent as a byte
93        * to jni. Converting rssi value to the expected format.*/
94       if (properties[i].type == BT_PROPERTY_REMOTE_RSSI)
95       {
96           jbyte rssi = *((jbyte *) properties[i].val);
97           short rssiValue = rssi;
98           properties[i].len = sizeof(rssiValue);
99           properties[i].val = &rssiValue;
100       }
101
102       propVal = callbackEnv->NewByteArray(properties[i].len);
103       if (propVal == NULL) goto Fail;
104
105       callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
106                                            (jbyte*)properties[i].val);
107       callbackEnv->SetObjectArrayElement(*props, i, propVal);
108
109       callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
110    }
111    return 0;
112Fail:
113    if (val) callbackEnv->DeleteLocalRef(val);
114    if (propVal) callbackEnv->DeleteLocalRef(propVal);
115    LOGE("Error while allocation of array in %s", __FUNCTION__);
116    return -1;
117}
118
119static void adapter_properties_callback(bt_status_t status, int num_properties,
120                                        bt_property_t *properties) {
121    jobjectArray props;
122    jintArray types;
123    if (!checkCallbackThread()) {
124       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
125       return;
126    }
127
128    LOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
129
130    if (status != BT_STATUS_SUCCESS) {
131        LOGE("%s: Status %d is incorrect", __FUNCTION__, status);
132        return;
133    }
134
135    if (get_properties(num_properties, properties, &types, &props) < 0) {
136        if (props) callbackEnv->DeleteLocalRef(props);
137        if (types) callbackEnv->DeleteLocalRef(types);
138        return;
139    }
140
141    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
142                                props);
143    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
144    callbackEnv->DeleteLocalRef(props);
145    callbackEnv->DeleteLocalRef(types);
146    return;
147
148}
149
150static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
151                                              int num_properties, bt_property_t *properties) {
152    if (!checkCallbackThread()) {
153       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
154       return;
155    }
156
157    LOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
158
159    if (status != BT_STATUS_SUCCESS) {
160        LOGE("%s: Status %d is incorrect", __FUNCTION__, status);
161        return;
162    }
163
164    callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
165
166    jobjectArray props;
167    jbyteArray addr;
168    jintArray types;
169
170    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
171    if (addr == NULL) goto Fail;
172    if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
173
174    if (get_properties(num_properties, properties, &types, &props) < 0) {
175        if (props) callbackEnv->DeleteLocalRef(props);
176        if (types) callbackEnv->DeleteLocalRef(types);
177        callbackEnv->PopLocalFrame(NULL);
178        return;
179    }
180
181    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
182                                types, props);
183    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
184    callbackEnv->DeleteLocalRef(props);
185    callbackEnv->DeleteLocalRef(types);
186    callbackEnv->PopLocalFrame(NULL);
187    return;
188
189Fail:
190    LOGE("Error while allocation byte array in %s", __FUNCTION__);
191}
192
193
194static void device_found_callback(int num_properties, bt_property_t *properties) {
195    jbyteArray addr = NULL;
196    int addr_index;
197
198    for (int i = 0; i < num_properties; i++) {
199        if (properties[i].type == BT_PROPERTY_BDADDR) {
200            addr = callbackEnv->NewByteArray(properties[i].len);
201            if (addr) {
202                callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
203                                                (jbyte*)properties[i].val);
204                addr_index = i;
205            } else {
206                LOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
207                return;
208            }
209        }
210    }
211    if (addr == NULL) {
212        LOGE("Address is NULL in %s", __FUNCTION__);
213        return;
214    }
215
216    LOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
217        (const char *)properties[addr_index].val);
218
219    remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
220                                      num_properties, properties);
221
222    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
223    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
224    callbackEnv->DeleteLocalRef(addr);
225}
226
227static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
228                                        bt_bond_state_t state) {
229    jbyteArray addr;
230    int i;
231    if (!checkCallbackThread()) {
232       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
233       return;
234    }
235    if (!bd_addr) {
236        LOGE("Address is null in %s", __FUNCTION__);
237        return;
238    }
239    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
240    if (addr == NULL) {
241       LOGE("Address allocation failed in %s", __FUNCTION__);
242       return;
243    }
244    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
245
246    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
247                                addr, (jint)state);
248    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
249    callbackEnv->DeleteLocalRef(addr);
250}
251
252static void discovery_state_changed_callback(bt_discovery_state_t state) {
253    jbyteArray addr;
254    if (!checkCallbackThread()) {
255       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
256       return;
257    }
258
259    LOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
260
261    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
262                                (jint)state);
263
264    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
265}
266
267static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) {
268    jbyteArray addr, devname;
269    if (!checkCallbackThread()) {
270       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
271       return;
272    }
273    if (!bd_addr) {
274        LOGE("Address is null in %s", __FUNCTION__);
275        return;
276    }
277
278    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
279    if (addr == NULL) goto Fail;
280    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
281
282    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
283    if (devname == NULL) goto Fail;
284
285    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
286
287    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod);
288
289    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
290    callbackEnv->DeleteLocalRef(addr);
291    callbackEnv->DeleteLocalRef(devname);
292    return;
293
294Fail:
295    if (addr) callbackEnv->DeleteLocalRef(addr);
296    if (devname) callbackEnv->DeleteLocalRef(devname);
297    LOGE("Error while allocating in: %s", __FUNCTION__);
298}
299
300static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
301                                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
302    jbyteArray addr, devname;
303    if (!checkCallbackThread()) {
304       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
305       return;
306    }
307    if (!bd_addr) {
308        LOGE("Address is null in %s", __FUNCTION__);
309        return;
310    }
311
312    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
313    if (addr == NULL) goto Fail;
314    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
315
316    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
317    if (devname == NULL) goto Fail;
318    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
319
320    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
321                                (jint) pairing_variant, pass_key);
322
323    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
324    callbackEnv->DeleteLocalRef(addr);
325    callbackEnv->DeleteLocalRef(devname);
326    return;
327
328Fail:
329    if (addr) callbackEnv->DeleteLocalRef(addr);
330    if (devname) callbackEnv->DeleteLocalRef(devname);
331
332    LOGE("Error while allocating in: %s", __FUNCTION__);
333}
334
335static void callback_thread_event(bt_cb_thread_evt event) {
336    JavaVM* vm = AndroidRuntime::getJavaVM();
337    if (event  == ASSOCIATE_JVM) {
338        JavaVMAttachArgs args;
339        char name[] = "BT Service Callback Thread";
340        //TODO(BT)
341        //args.version = nat->envVer;
342        args.name = name;
343        args.group = NULL;
344        vm->AttachCurrentThread(&callbackEnv, &args);
345        LOGV("Callback thread attached: %p", callbackEnv);
346    } else if (event == DISASSOCIATE_JVM) {
347        if (!checkCallbackThread()) {
348            LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
349            return;
350        }
351        vm->DetachCurrentThread();
352    }
353}
354
355bt_callbacks_t sBluetoothCallbacks = {
356    sizeof(sBluetoothCallbacks),
357    adapter_state_change_callback,
358    adapter_properties_callback,
359    remote_device_properties_callback,
360    device_found_callback,
361    discovery_state_changed_callback,
362    pin_request_callback,
363    ssp_request_callback,
364    bond_state_changed_callback,
365    callback_thread_event,
366};
367
368static void classInitNative(JNIEnv* env, jclass clazz) {
369    int err;
370    hw_module_t* module;
371
372    jclass jniCallbackClass =
373        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
374    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
375        "Lcom/android/bluetooth/btservice/JniCallbacks;");
376
377    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
378
379    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
380                                                             "adapterPropertyChangedCallback",
381                                                             "([I[[B)V");
382    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
383                                                           "discoveryStateChangeCallback", "(I)V");
384
385    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
386                                                            "devicePropertyChangedCallback",
387                                                            "([B[I[[B)V");
388    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
389    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
390                                                 "([B[BI)V");
391    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
392                                                 "([B[BIII)V");
393
394    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
395                                                     "bondStateChangeCallback", "(I[BI)V");
396
397    char value[PROPERTY_VALUE_MAX];
398    property_get("bluetooth.mock_stack", value, "");
399
400    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
401
402    err = hw_get_module(id, (hw_module_t const**)&module);
403
404    if (err == 0) {
405        hw_device_t* abstraction;
406        err = module->methods->open(module, id, &abstraction);
407        if (err == 0) {
408            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
409            sBluetoothInterface = btStack->get_bluetooth_interface();
410        } else {
411           LOGE("Error while opening Bluetooth library");
412        }
413    } else {
414        LOGE("No Bluetooth Library found");
415    }
416}
417
418static bool initNative(JNIEnv* env, jobject obj) {
419    LOGV("%s:",__FUNCTION__);
420
421    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
422
423    if (sBluetoothInterface) {
424        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
425        if (ret != BT_STATUS_SUCCESS) {
426            LOGE("Error while setting the callbacks \n");
427            sBluetoothInterface = NULL;
428            return JNI_FALSE;
429        }
430        return JNI_TRUE;
431    }
432    return JNI_FALSE;
433}
434
435static bool cleanupNative(JNIEnv *env, jobject obj) {
436    LOGV("%s:",__FUNCTION__);
437
438    jboolean result = JNI_FALSE;
439    if (!sBluetoothInterface) return result;
440
441    sBluetoothInterface->cleanup();
442    env->DeleteGlobalRef(sJniCallbacksObj);
443    return JNI_TRUE;
444}
445
446static jboolean enableNative(JNIEnv* env, jobject obj) {
447    LOGV("%s:",__FUNCTION__);
448
449    jboolean result = JNI_FALSE;
450    if (!sBluetoothInterface) return result;
451
452    int ret = sBluetoothInterface->enable();
453    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
454    return result;
455}
456
457static jboolean disableNative(JNIEnv* env, jobject obj) {
458    LOGV("%s:",__FUNCTION__);
459
460    jboolean result = JNI_FALSE;
461    if (!sBluetoothInterface) return result;
462
463    int ret = sBluetoothInterface->disable();
464    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
465    return result;
466}
467
468static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
469    LOGV("%s:",__FUNCTION__);
470
471    jboolean result = JNI_FALSE;
472    if (!sBluetoothInterface) return result;
473
474    int ret = sBluetoothInterface->start_discovery();
475    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
476    return result;
477}
478
479static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
480    LOGV("%s:",__FUNCTION__);
481
482    jboolean result = JNI_FALSE;
483    if (!sBluetoothInterface) return result;
484
485    int ret = sBluetoothInterface->cancel_discovery();
486    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
487    return result;
488}
489
490static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
491    LOGV("%s:",__FUNCTION__);
492
493    jbyte *addr;
494    jboolean result = JNI_FALSE;
495
496    if (!sBluetoothInterface) return result;
497
498    addr = env->GetByteArrayElements(address, NULL);
499    if (addr == NULL) {
500        jniThrowIOException(env, EINVAL);
501        return result;
502    }
503
504    int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
505    env->ReleaseByteArrayElements(address, addr, NULL);
506    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
507
508    return result;
509}
510
511static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
512    LOGV("%s:",__FUNCTION__);
513
514    jbyte *addr;
515    jboolean result;
516    if (!sBluetoothInterface) return JNI_FALSE;
517
518    addr = env->GetByteArrayElements(address, NULL);
519    if (addr == NULL) {
520        jniThrowIOException(env, EINVAL);
521        return JNI_FALSE;
522    }
523
524    int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
525    env->ReleaseByteArrayElements(address, addr, NULL);
526    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
527
528    return result;
529}
530
531static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
532    LOGV("%s:",__FUNCTION__);
533
534    jbyte *addr;
535    jboolean result;
536    if (!sBluetoothInterface) return JNI_FALSE;
537
538    addr = env->GetByteArrayElements(address, NULL);
539    if (addr == NULL) {
540        jniThrowIOException(env, EINVAL);
541        return JNI_FALSE;
542    }
543
544    int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
545    env->ReleaseByteArrayElements(address, addr, NULL);
546    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
547
548    return result;
549}
550
551static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
552                               jint len, jbyteArray pinArray) {
553    LOGV("%s:",__FUNCTION__);
554
555    jbyte *addr, *pinPtr = NULL;
556    jboolean result = JNI_FALSE;
557    if (!sBluetoothInterface) return result;
558
559    addr = env->GetByteArrayElements(address, NULL);
560    if (addr == NULL) {
561        jniThrowIOException(env, EINVAL);
562        return result;
563    }
564
565    if (accept) {
566        pinPtr = env->GetByteArrayElements(pinArray, NULL);
567        if (pinPtr == NULL) {
568           jniThrowIOException(env, EINVAL);
569           env->ReleaseByteArrayElements(address, addr, NULL);
570           return result;
571        }
572    }
573
574    int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
575                                              (bt_pin_code_t *) pinPtr);
576    env->ReleaseByteArrayElements(address, addr, NULL);
577    env->ReleaseByteArrayElements(pinArray, pinPtr, NULL);
578    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
579
580    return result;
581}
582
583static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
584                               jint type, jboolean accept, jint passkey) {
585    LOGV("%s:",__FUNCTION__);
586
587    jbyte *addr;
588    jboolean result = JNI_FALSE;
589    if (!sBluetoothInterface) return result;
590
591    addr = env->GetByteArrayElements(address, NULL);
592    if (addr == NULL) {
593        jniThrowIOException(env, EINVAL);
594        return result;
595    }
596
597    int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
598         (bt_ssp_variant_t) type, accept, passkey);
599    env->ReleaseByteArrayElements(address, addr, NULL);
600    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
601
602    return result;
603}
604
605static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
606    LOGV("%s:",__FUNCTION__);
607
608    jbyte *val;
609    jboolean result = JNI_FALSE;
610    if (!sBluetoothInterface) return result;
611
612    val = env->GetByteArrayElements(value, NULL);
613    bt_property_t prop;
614    prop.type = (bt_property_type_t) type;
615    prop.len = env->GetArrayLength(value);
616    prop.val = val;
617
618    int ret = sBluetoothInterface->set_adapter_property(&prop);
619    env->ReleaseByteArrayElements(value, val, NULL);
620    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
621
622    return result;
623}
624
625static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
626    LOGV("%s:",__FUNCTION__);
627
628    jboolean result = JNI_FALSE;
629    if (!sBluetoothInterface) return result;
630
631    int ret = sBluetoothInterface->get_adapter_properties();
632    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
633
634    return result;
635}
636
637static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
638    LOGV("%s:",__FUNCTION__);
639
640    jboolean result = JNI_FALSE;
641    if (!sBluetoothInterface) return result;
642
643    int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
644    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
645
646    return result;
647}
648
649static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
650    LOGV("%s:",__FUNCTION__);
651
652    jbyte *addr = NULL;
653    jboolean result = JNI_FALSE;
654    if (!sBluetoothInterface) return result;
655
656    addr = env->GetByteArrayElements(address, NULL);
657    if (addr == NULL) {
658        jniThrowIOException(env, EINVAL);
659        return result;
660    }
661
662    int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
663                                                              (bt_property_type_t) type);
664    env->ReleaseByteArrayElements(address, addr, NULL);
665    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
666
667    return result;
668}
669
670static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
671                                        jint type, jbyteArray value) {
672    LOGV("%s:",__FUNCTION__);
673
674    jbyte *val, *addr;
675    jboolean result = JNI_FALSE;
676    if (!sBluetoothInterface) return result;
677
678    val = env->GetByteArrayElements(value, NULL);
679    if (val == NULL) {
680        jniThrowIOException(env, EINVAL);
681        return result;
682    }
683
684    addr = env->GetByteArrayElements(address, NULL);
685    if (addr == NULL) {
686        env->ReleaseByteArrayElements(value, val, NULL);
687        jniThrowIOException(env, EINVAL);
688        return result;
689    }
690
691
692    bt_property_t prop;
693    prop.type = (bt_property_type_t) type;
694    prop.len = env->GetArrayLength(value);
695    prop.val = val;
696
697    int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
698    env->ReleaseByteArrayElements(value, val, NULL);
699    env->ReleaseByteArrayElements(address, addr, NULL);
700
701    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
702
703    return result;
704}
705
706static JNINativeMethod sMethods[] = {
707     /* name, signature, funcPtr */
708    {"classInitNative", "()V", (void *) classInitNative},
709    {"initNative", "()Z", (void *) initNative},
710    {"cleanupNative", "()V", (void*) cleanupNative},
711    {"enableNative", "()Z",  (void*) enableNative},
712    {"disableNative", "()Z",  (void*) disableNative},
713    {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
714    {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
715    {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
716    {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
717    {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
718    {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
719    {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
720    {"createBondNative", "([B)Z", (void*) createBondNative},
721    {"removeBondNative", "([B)Z", (void*) removeBondNative},
722    {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
723    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
724    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
725};
726
727int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
728{
729    return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
730                                    sMethods, NELEM(sMethods));
731}
732
733} /* namespace android */
734
735
736/*
737 * JNI Initialization
738 */
739jint JNI_OnLoad(JavaVM *jvm, void *reserved)
740{
741   JNIEnv *e;
742   int status;
743
744   LOGV("Bluetooth Adapter Service : loading JNI\n");
745
746   // Check JNI version
747   if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
748       LOGE("JNI version mismatch error");
749      return JNI_ERR;
750   }
751
752   if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
753       LOGE("jni adapter service registration failure, status: %d", status);
754      return JNI_ERR;
755   }
756
757   if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
758       LOGE("jni hfp registration failure, status: %d", status);
759      return JNI_ERR;
760   }
761
762   if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
763       LOGE("jni a2dp registration failure: %d", status);
764      return JNI_ERR;
765   }
766
767   if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
768       LOGE("jni hid registration failure: %d", status);
769       return JNI_ERR;
770   }
771
772   if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
773       LOGE("jni hdp registration failure: %d", status);
774      return JNI_ERR;
775   }
776
777   return JNI_VERSION_1_6;
778}
779