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