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