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