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