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