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