com_android_bluetooth_btservice_AdapterService.cpp revision d4a64dd76ad2847a08db3258f0a81ad631f5db26
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 OOB_TK_SIZE 16
35
36#define ADDITIONAL_NREFS 50
37static jmethodID method_stateChangeCallback;
38static jmethodID method_adapterPropertyChangedCallback;
39static jmethodID method_devicePropertyChangedCallback;
40static jmethodID method_deviceFoundCallback;
41static jmethodID method_pinRequestCallback;
42static jmethodID method_sspRequestCallback;
43static jmethodID method_bondStateChangeCallback;
44static jmethodID method_aclStateChangeCallback;
45static jmethodID method_discoveryStateChangeCallback;
46static jmethodID method_setWakeAlarm;
47static jmethodID method_acquireWakeLock;
48static jmethodID method_releaseWakeLock;
49static jmethodID method_energyInfo;
50
51static struct {
52    jclass clazz;
53    jmethodID constructor;
54} android_bluetooth_UidTraffic;
55
56static const bt_interface_t *sBluetoothInterface = NULL;
57static const btsock_interface_t *sBluetoothSocketInterface = NULL;
58static JNIEnv *callbackEnv = NULL;
59
60static jobject sJniAdapterServiceObj;
61static jobject sJniCallbacksObj;
62static jfieldID sJniCallbacksField;
63
64
65const bt_interface_t* getBluetoothInterface() {
66    return sBluetoothInterface;
67}
68
69JNIEnv* getCallbackEnv() {
70    return callbackEnv;
71}
72
73void checkAndClearExceptionFromCallback(JNIEnv* env,
74                                               const char* methodName) {
75    if (env->ExceptionCheck()) {
76        ALOGE("An exception was thrown by callback '%s'.", methodName);
77        LOGE_EX(env);
78        env->ExceptionClear();
79    }
80}
81
82static bool checkCallbackThread() {
83    JNIEnv* env = AndroidRuntime::getJNIEnv();
84    if (callbackEnv != env || callbackEnv == NULL) {
85        ALOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
86        return false;
87    }
88    return true;
89}
90
91static void adapter_state_change_callback(bt_state_t status) {
92    if (!checkCallbackThread()) {
93       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
94       return;
95    }
96    ALOGV("%s: Status is: %d", __FUNCTION__, status);
97
98    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
99
100    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
101}
102
103static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
104                        jobjectArray *props) {
105    jbyteArray propVal;
106    for (int i = 0; i < num_properties; i++) {
107        propVal = callbackEnv->NewByteArray(properties[i].len);
108        if (propVal == NULL) goto Fail;
109
110        callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
111                                             (jbyte*)properties[i].val);
112        callbackEnv->SetObjectArrayElement(*props, i, propVal);
113        // Delete reference to propVal
114        callbackEnv->DeleteLocalRef(propVal);
115        callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
116    }
117    return 0;
118Fail:
119    if (propVal) callbackEnv->DeleteLocalRef(propVal);
120    ALOGE("Error while allocation of array in %s", __FUNCTION__);
121    return -1;
122}
123
124static void adapter_properties_callback(bt_status_t status, int num_properties,
125                                        bt_property_t *properties) {
126    jobjectArray props;
127    jintArray types;
128    jbyteArray val;
129    jclass mclass;
130
131    if (!checkCallbackThread()) {
132       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
133       return;
134    }
135
136    ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
137
138    if (status != BT_STATUS_SUCCESS) {
139        ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
140        return;
141    }
142
143    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
144    if (val == NULL) {
145        ALOGE("%s: Error allocating byteArray", __FUNCTION__);
146        return;
147    }
148
149    mclass = callbackEnv->GetObjectClass(val);
150
151    /* (BT) Initialize the jobjectArray and jintArray here itself and send the
152     initialized array pointers alone to get_properties */
153
154    props = callbackEnv->NewObjectArray(num_properties, mclass,
155                                             NULL);
156    if (props == NULL) {
157        ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
158        return;
159    }
160
161    types = (jintArray)callbackEnv->NewIntArray(num_properties);
162
163    if (types == NULL) {
164        ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
165        return;
166    }
167    // Delete the reference to val and mclass
168    callbackEnv->DeleteLocalRef(mclass);
169    callbackEnv->DeleteLocalRef(val);
170
171    if (get_properties(num_properties, properties, &types, &props) < 0) {
172        if (props) callbackEnv->DeleteLocalRef(props);
173        if (types) callbackEnv->DeleteLocalRef(types);
174        return;
175    }
176
177    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
178                                props);
179    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
180    callbackEnv->DeleteLocalRef(props);
181    callbackEnv->DeleteLocalRef(types);
182    return;
183
184}
185
186static void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
187                                              int num_properties, bt_property_t *properties) {
188    if (!checkCallbackThread()) {
189       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
190       return;
191    }
192
193    ALOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
194
195    if (status != BT_STATUS_SUCCESS) {
196        ALOGE("%s: Status %d is incorrect", __FUNCTION__, status);
197        return;
198    }
199
200    callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
201
202    jobjectArray props;
203    jbyteArray addr;
204    jintArray types;
205    jbyteArray val;
206    jclass mclass;
207
208    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
209    if (val == NULL) {
210        ALOGE("%s: Error allocating byteArray", __FUNCTION__);
211        return;
212    }
213
214    mclass = callbackEnv->GetObjectClass(val);
215
216    /* Initialize the jobjectArray and jintArray here itself and send the
217     initialized array pointers alone to get_properties */
218
219    props = callbackEnv->NewObjectArray(num_properties, mclass,
220                                             NULL);
221    if (props == NULL) {
222        ALOGE("%s: Error allocating object Array for properties", __FUNCTION__);
223        return;
224    }
225
226    types = (jintArray)callbackEnv->NewIntArray(num_properties);
227
228    if (types == NULL) {
229        ALOGE("%s: Error allocating int Array for values", __FUNCTION__);
230        return;
231    }
232    // Delete the reference to val and mclass
233    callbackEnv->DeleteLocalRef(mclass);
234    callbackEnv->DeleteLocalRef(val);
235
236    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
237    if (addr == NULL) goto Fail;
238    if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
239
240    if (get_properties(num_properties, properties, &types, &props) < 0) {
241        if (props) callbackEnv->DeleteLocalRef(props);
242        if (types) callbackEnv->DeleteLocalRef(types);
243        callbackEnv->PopLocalFrame(NULL);
244        return;
245    }
246
247    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
248                                types, props);
249    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
250    callbackEnv->DeleteLocalRef(props);
251    callbackEnv->DeleteLocalRef(types);
252    callbackEnv->DeleteLocalRef(addr);
253    callbackEnv->PopLocalFrame(NULL);
254    return;
255
256Fail:
257    ALOGE("Error while allocation byte array in %s", __FUNCTION__);
258}
259
260
261static void device_found_callback(int num_properties, bt_property_t *properties) {
262    jbyteArray addr = NULL;
263    int addr_index;
264
265    for (int i = 0; i < num_properties; i++) {
266        if (properties[i].type == BT_PROPERTY_BDADDR) {
267            addr = callbackEnv->NewByteArray(properties[i].len);
268            if (addr) {
269                callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
270                                                (jbyte*)properties[i].val);
271                addr_index = i;
272            } else {
273                ALOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
274                return;
275            }
276        }
277    }
278    if (addr == NULL) {
279        ALOGE("Address is NULL in %s", __FUNCTION__);
280        return;
281    }
282
283    ALOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
284        (const char *)properties[addr_index].val);
285
286    remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
287                                      num_properties, properties);
288
289    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
290    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
291    callbackEnv->DeleteLocalRef(addr);
292}
293
294static void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
295                                        bt_bond_state_t state) {
296    jbyteArray addr;
297    if (!checkCallbackThread()) {
298       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
299       return;
300    }
301    if (!bd_addr) {
302        ALOGE("Address is null in %s", __FUNCTION__);
303        return;
304    }
305    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
306    if (addr == NULL) {
307       ALOGE("Address allocation failed in %s", __FUNCTION__);
308       return;
309    }
310    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
311
312    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
313                                addr, (jint)state);
314    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
315    callbackEnv->DeleteLocalRef(addr);
316}
317
318static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
319                                       bt_acl_state_t state)
320{
321    jbyteArray addr;
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    if (!checkCallbackThread()) {
345       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
346       return;
347    }
348
349    ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
350
351    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
352                                (jint)state);
353
354    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
355}
356
357static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
358        bool min_16_digits) {
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            min_16_digits);
380
381    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
382    callbackEnv->DeleteLocalRef(addr);
383    callbackEnv->DeleteLocalRef(devname);
384    return;
385
386Fail:
387    if (addr) callbackEnv->DeleteLocalRef(addr);
388    if (devname) callbackEnv->DeleteLocalRef(devname);
389    ALOGE("Error while allocating in: %s", __FUNCTION__);
390}
391
392static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
393                                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
394    jbyteArray addr, devname;
395    if (!checkCallbackThread()) {
396       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
397       return;
398    }
399    if (!bd_addr) {
400        ALOGE("Address is null in %s", __FUNCTION__);
401        return;
402    }
403
404    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
405    if (addr == NULL) goto Fail;
406    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
407
408    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
409    if (devname == NULL) goto Fail;
410    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
411
412    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
413                                (jint) pairing_variant, pass_key);
414
415    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
416    callbackEnv->DeleteLocalRef(addr);
417    callbackEnv->DeleteLocalRef(devname);
418    return;
419
420Fail:
421    if (addr) callbackEnv->DeleteLocalRef(addr);
422    if (devname) callbackEnv->DeleteLocalRef(devname);
423
424    ALOGE("Error while allocating in: %s", __FUNCTION__);
425}
426
427static void callback_thread_event(bt_cb_thread_evt event) {
428    JavaVM* vm = AndroidRuntime::getJavaVM();
429    if (event  == ASSOCIATE_JVM) {
430        JavaVMAttachArgs args;
431        char name[] = "BT Service Callback Thread";
432        args.version = JNI_VERSION_1_6;
433        args.name = name;
434        args.group = NULL;
435        vm->AttachCurrentThread(&callbackEnv, &args);
436        ALOGV("Callback thread attached: %p", callbackEnv);
437    } else if (event == DISASSOCIATE_JVM) {
438        if (!checkCallbackThread()) {
439            ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
440            return;
441        }
442        vm->DetachCurrentThread();
443    }
444}
445
446static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) {
447
448}
449static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) {
450
451    ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
452}
453
454static void energy_info_recv_callback(bt_activity_energy_info *p_energy_info,
455                                      bt_uid_traffic_t* uid_data)
456{
457    if (!checkCallbackThread()) {
458       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
459       return;
460    }
461
462    jsize len = 0;
463    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
464        len++;
465    }
466
467    jobjectArray array = callbackEnv->NewObjectArray(len, android_bluetooth_UidTraffic.clazz, NULL);
468    jsize i = 0;
469    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
470        jobject uidObj = callbackEnv->NewObject(android_bluetooth_UidTraffic.clazz,
471                                                android_bluetooth_UidTraffic.constructor,
472                                                (jint) data->app_uid, (jlong) data->rx_bytes,
473                                                (jlong) data->tx_bytes);
474        callbackEnv->SetObjectArrayElement(array, i++, uidObj);
475        callbackEnv->DeleteLocalRef(uidObj);
476    }
477
478    callbackEnv->CallVoidMethod(sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
479        p_energy_info->ctrl_state, p_energy_info->tx_time, p_energy_info->rx_time,
480        p_energy_info->idle_time, p_energy_info->energy_used, array);
481
482    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
483    callbackEnv->DeleteLocalRef(array);
484}
485
486static bt_callbacks_t sBluetoothCallbacks = {
487    sizeof(sBluetoothCallbacks),
488    adapter_state_change_callback,
489    adapter_properties_callback,
490    remote_device_properties_callback,
491    device_found_callback,
492    discovery_state_changed_callback,
493    pin_request_callback,
494    ssp_request_callback,
495    bond_state_changed_callback,
496    acl_state_changed_callback,
497    callback_thread_event,
498    dut_mode_recv_callback,
499    le_test_mode_recv_callback,
500    energy_info_recv_callback
501};
502
503// The callback to call when the wake alarm fires.
504static alarm_cb sAlarmCallback;
505
506// The data to pass to the wake alarm callback.
507static void *sAlarmCallbackData;
508
509static JavaVMAttachArgs sAttachArgs = {
510  .version = JNI_VERSION_1_6,
511  .name = "bluedroid wake/alarm thread",
512  .group = NULL
513};
514
515static bool set_wake_alarm_callout(uint64_t delay_millis, bool should_wake,
516        alarm_cb cb, void *data) {
517    JNIEnv *env;
518    JavaVM *vm = AndroidRuntime::getJavaVM();
519    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
520
521    if (status != JNI_OK && status != JNI_EDETACHED) {
522        ALOGE("%s unable to get environment for JNI call", __func__);
523        return false;
524    }
525
526    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
527        ALOGE("%s unable to attach thread to VM", __func__);
528        return false;
529    }
530
531    sAlarmCallback = cb;
532    sAlarmCallbackData = data;
533
534    jboolean jshould_wake = should_wake ? JNI_TRUE : JNI_FALSE;
535    jboolean ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_setWakeAlarm,
536            (jlong)delay_millis, jshould_wake);
537    if (!ret) {
538        sAlarmCallback = NULL;
539        sAlarmCallbackData = NULL;
540    }
541
542    if (status == JNI_EDETACHED) {
543        vm->DetachCurrentThread();
544    }
545
546    return !!ret;
547}
548
549static int acquire_wake_lock_callout(const char *lock_name) {
550    JNIEnv *env;
551    JavaVM *vm = AndroidRuntime::getJavaVM();
552    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
553    if (status != JNI_OK && status != JNI_EDETACHED) {
554        ALOGE("%s unable to get environment for JNI call", __func__);
555        return BT_STATUS_FAIL;
556    }
557    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
558        ALOGE("%s unable to attach thread to VM", __func__);
559        return BT_STATUS_FAIL;
560    }
561
562    jboolean ret = JNI_FALSE;
563    jstring lock_name_jni = env->NewStringUTF(lock_name);
564    if (lock_name_jni) {
565        ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_acquireWakeLock, lock_name_jni);
566        env->DeleteLocalRef(lock_name_jni);
567    } else {
568        ALOGE("%s unable to allocate string: %s", __func__, lock_name);
569    }
570
571    if (status == JNI_EDETACHED) {
572        vm->DetachCurrentThread();
573    }
574
575    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
576}
577
578static int release_wake_lock_callout(const char *lock_name) {
579    JNIEnv *env;
580    JavaVM *vm = AndroidRuntime::getJavaVM();
581    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
582
583    if (status != JNI_OK && status != JNI_EDETACHED) {
584        ALOGE("%s unable to get environment for JNI call", __func__);
585        return BT_STATUS_FAIL;
586    }
587    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
588        ALOGE("%s unable to attach thread to VM", __func__);
589        return BT_STATUS_FAIL;
590    }
591    jboolean ret = JNI_FALSE;
592    jstring lock_name_jni = env->NewStringUTF(lock_name);
593    if (lock_name_jni) {
594        ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_releaseWakeLock, lock_name_jni);
595        env->DeleteLocalRef(lock_name_jni);
596    } else {
597        ALOGE("%s unable to allocate string: %s", __func__, lock_name);
598    }
599    if (status == JNI_EDETACHED) {
600        vm->DetachCurrentThread();
601    }
602    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
603}
604
605// Called by Java code when alarm is fired. A wake lock is held by the caller
606// over the duration of this callback.
607static void alarmFiredNative(JNIEnv *env, jobject obj) {
608    if (sAlarmCallback) {
609        sAlarmCallback(sAlarmCallbackData);
610    } else {
611        ALOGE("%s() - Alarm fired with callback not set!", __FUNCTION__);
612    }
613}
614
615static bt_os_callouts_t sBluetoothOsCallouts = {
616    sizeof(sBluetoothOsCallouts),
617    set_wake_alarm_callout,
618    acquire_wake_lock_callout,
619    release_wake_lock_callout,
620};
621
622
623
624static void classInitNative(JNIEnv* env, jclass clazz) {
625    int err;
626    hw_module_t* module;
627
628
629    jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
630    android_bluetooth_UidTraffic.constructor = env->GetMethodID(jniUidTrafficClass,
631                                                                "<init>", "(IJJ)V");
632
633    jclass jniCallbackClass =
634        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
635    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
636        "Lcom/android/bluetooth/btservice/JniCallbacks;");
637
638    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
639
640    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
641                                                             "adapterPropertyChangedCallback",
642                                                             "([I[[B)V");
643    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
644                                                           "discoveryStateChangeCallback", "(I)V");
645
646    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
647                                                            "devicePropertyChangedCallback",
648                                                            "([B[I[[B)V");
649    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
650    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
651                                                 "([B[BIZ)V");
652    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
653                                                 "([B[BIII)V");
654
655    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
656                                                     "bondStateChangeCallback", "(I[BI)V");
657
658    method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
659                                                    "aclStateChangeCallback", "(I[BI)V");
660
661    method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
662    method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
663    method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
664    method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");
665
666    char value[PROPERTY_VALUE_MAX];
667    property_get("bluetooth.mock_stack", value, "");
668
669    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
670
671    err = hw_get_module(id, (hw_module_t const**)&module);
672
673    if (err == 0) {
674        hw_device_t* abstraction;
675        err = module->methods->open(module, id, &abstraction);
676        if (err == 0) {
677            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
678            sBluetoothInterface = btStack->get_bluetooth_interface();
679        } else {
680           ALOGE("Error while opening Bluetooth library");
681        }
682    } else {
683        ALOGE("No Bluetooth Library found");
684    }
685}
686
687static bool initNative(JNIEnv* env, jobject obj) {
688    ALOGV("%s:",__FUNCTION__);
689
690    android_bluetooth_UidTraffic.clazz = (jclass) env->NewGlobalRef(
691            env->FindClass("android/bluetooth/UidTraffic"));
692
693    sJniAdapterServiceObj = env->NewGlobalRef(obj);
694    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
695
696    if (sBluetoothInterface) {
697        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
698        if (ret != BT_STATUS_SUCCESS) {
699            ALOGE("Error while setting the callbacks: %d\n", ret);
700            sBluetoothInterface = NULL;
701            return JNI_FALSE;
702        }
703        ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);
704        if (ret != BT_STATUS_SUCCESS) {
705            ALOGE("Error while setting Bluetooth callouts: %d\n", ret);
706            sBluetoothInterface->cleanup();
707            sBluetoothInterface = NULL;
708            return JNI_FALSE;
709        }
710
711        if ( (sBluetoothSocketInterface = (btsock_interface_t *)
712                  sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
713                ALOGE("Error getting socket interface");
714        }
715
716        return JNI_TRUE;
717    }
718    return JNI_FALSE;
719}
720
721static bool cleanupNative(JNIEnv *env, jobject obj) {
722    ALOGV("%s:",__FUNCTION__);
723
724    jboolean result = JNI_FALSE;
725    if (!sBluetoothInterface) return result;
726
727    sBluetoothInterface->cleanup();
728    ALOGI("%s: return from cleanup",__FUNCTION__);
729
730    env->DeleteGlobalRef(sJniCallbacksObj);
731    env->DeleteGlobalRef(sJniAdapterServiceObj);
732    env->DeleteGlobalRef(android_bluetooth_UidTraffic.clazz);
733    android_bluetooth_UidTraffic.clazz = NULL;
734    return JNI_TRUE;
735}
736
737static jboolean enableNative(JNIEnv* env, jobject obj) {
738    ALOGV("%s:",__FUNCTION__);
739
740    jboolean result = JNI_FALSE;
741    if (!sBluetoothInterface) return result;
742
743    int ret = sBluetoothInterface->enable();
744    result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE;
745    return result;
746}
747
748static jboolean disableNative(JNIEnv* env, jobject obj) {
749    ALOGV("%s:",__FUNCTION__);
750
751    jboolean result = JNI_FALSE;
752    if (!sBluetoothInterface) return result;
753
754    int ret = sBluetoothInterface->disable();
755    /* Retrun JNI_FALSE only when BTIF explicitly reports
756       BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY
757       case which indicates that stack had not been enabled.
758    */
759    result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE;
760    return result;
761}
762
763static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
764    ALOGV("%s:",__FUNCTION__);
765
766    jboolean result = JNI_FALSE;
767    if (!sBluetoothInterface) return result;
768
769    int ret = sBluetoothInterface->start_discovery();
770    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
771    return result;
772}
773
774static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
775    ALOGV("%s:",__FUNCTION__);
776
777    jboolean result = JNI_FALSE;
778    if (!sBluetoothInterface) return result;
779
780    int ret = sBluetoothInterface->cancel_discovery();
781    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
782    return result;
783}
784
785static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
786    ALOGV("%s:",__FUNCTION__);
787
788    jbyte *addr;
789    jboolean result = JNI_FALSE;
790
791    if (!sBluetoothInterface) return result;
792
793    addr = env->GetByteArrayElements(address, NULL);
794    if (addr == NULL) {
795        jniThrowIOException(env, EINVAL);
796        return result;
797    }
798
799    int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr, transport);
800    env->ReleaseByteArrayElements(address, addr, 0);
801    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
802
803    return result;
804}
805
806static jbyteArray callByteArrayGetter(JNIEnv* env, jobject object, char* className, char* methodName) {
807    jclass myClass = env->FindClass(className);
808    jmethodID myMethod = env->GetMethodID(myClass, methodName, "()[B");
809    return (jbyteArray) env->CallObjectMethod(object, myMethod);
810}
811
812static jboolean createBondOutOfBandNative(JNIEnv* env, jobject obj, jbyteArray address,
813                jint transport, jobject oobData) {
814    jbyte *addr;
815    jboolean result = JNI_FALSE;
816    bt_out_of_band_data_t oob_data;
817
818    memset(&oob_data, 0, sizeof(oob_data));
819
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    jbyte* smTKBytes = NULL;
829    jbyteArray smTK = callByteArrayGetter(env, oobData, "android/bluetooth/OobData", "getSecurityManagerTk");
830    if (smTK != NULL) {
831        smTKBytes = env->GetByteArrayElements(smTK, NULL);
832        int len = env->GetArrayLength(smTK);
833        if (len != OOB_TK_SIZE) {
834            ALOGI("%s: wrong length of smTK, should be empty or %d bytes.", __FUNCTION__, OOB_TK_SIZE);
835            jniThrowIOException(env, EINVAL);
836            goto done;
837        }
838        memcpy(oob_data.sm_tk, smTKBytes, len);
839    }
840
841    if (sBluetoothInterface->create_bond_out_of_band((bt_bdaddr_t *)addr, transport, &oob_data)
842        == BT_STATUS_SUCCESS)
843        result = JNI_TRUE;
844
845done:
846    env->ReleaseByteArrayElements(address, addr, 0);
847
848    if (smTK != NULL)
849        env->ReleaseByteArrayElements(smTK, smTKBytes, 0);
850
851    return result;
852}
853
854static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
855    ALOGV("%s:",__FUNCTION__);
856
857    jbyte *addr;
858    jboolean result;
859    if (!sBluetoothInterface) return JNI_FALSE;
860
861    addr = env->GetByteArrayElements(address, NULL);
862    if (addr == NULL) {
863        jniThrowIOException(env, EINVAL);
864        return JNI_FALSE;
865    }
866
867    int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
868    env->ReleaseByteArrayElements(address, addr, 0);
869    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
870
871    return result;
872}
873
874static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
875    ALOGV("%s:",__FUNCTION__);
876
877    jbyte *addr;
878    jboolean result;
879    if (!sBluetoothInterface) return JNI_FALSE;
880
881    addr = env->GetByteArrayElements(address, NULL);
882    if (addr == NULL) {
883        jniThrowIOException(env, EINVAL);
884        return JNI_FALSE;
885    }
886
887    int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
888    env->ReleaseByteArrayElements(address, addr, 0);
889    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
890
891    return result;
892}
893
894static int getConnectionStateNative(JNIEnv* env, jobject obj, jbyteArray address) {
895    ALOGV("%s:",__FUNCTION__);
896    if (!sBluetoothInterface) return JNI_FALSE;
897
898    jbyte *addr = env->GetByteArrayElements(address, NULL);
899    if (addr == NULL) {
900        jniThrowIOException(env, EINVAL);
901        return JNI_FALSE;
902    }
903
904    int ret = sBluetoothInterface->get_connection_state((bt_bdaddr_t *)addr);
905    env->ReleaseByteArrayElements(address, addr, 0);
906
907    return ret;
908}
909
910static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
911                               jint len, jbyteArray pinArray) {
912    ALOGV("%s:",__FUNCTION__);
913
914    jbyte *addr, *pinPtr = NULL;
915    jboolean result = JNI_FALSE;
916    if (!sBluetoothInterface) return result;
917
918    addr = env->GetByteArrayElements(address, NULL);
919    if (addr == NULL) {
920        jniThrowIOException(env, EINVAL);
921        return result;
922    }
923
924    if (accept) {
925        pinPtr = env->GetByteArrayElements(pinArray, NULL);
926        if (pinPtr == NULL) {
927           jniThrowIOException(env, EINVAL);
928           env->ReleaseByteArrayElements(address, addr, 0);
929           return result;
930        }
931    }
932
933    int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
934                                              (bt_pin_code_t *) pinPtr);
935    env->ReleaseByteArrayElements(address, addr, 0);
936    env->ReleaseByteArrayElements(pinArray, pinPtr, 0);
937    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
938
939    return result;
940}
941
942static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
943                               jint type, jboolean accept, jint passkey) {
944    ALOGV("%s:",__FUNCTION__);
945
946    jbyte *addr;
947    jboolean result = JNI_FALSE;
948    if (!sBluetoothInterface) return result;
949
950    addr = env->GetByteArrayElements(address, NULL);
951    if (addr == NULL) {
952        jniThrowIOException(env, EINVAL);
953        return result;
954    }
955
956    int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
957         (bt_ssp_variant_t) type, accept, passkey);
958    env->ReleaseByteArrayElements(address, addr, 0);
959    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
960
961    return result;
962}
963
964static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
965    ALOGV("%s:",__FUNCTION__);
966
967    jbyte *val;
968    jboolean result = JNI_FALSE;
969    if (!sBluetoothInterface) return result;
970
971    val = env->GetByteArrayElements(value, NULL);
972    bt_property_t prop;
973    prop.type = (bt_property_type_t) type;
974    prop.len = env->GetArrayLength(value);
975    prop.val = val;
976
977    int ret = sBluetoothInterface->set_adapter_property(&prop);
978    env->ReleaseByteArrayElements(value, val, 0);
979    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
980
981    return result;
982}
983
984static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
985    ALOGV("%s:",__FUNCTION__);
986
987    jboolean result = JNI_FALSE;
988    if (!sBluetoothInterface) return result;
989
990    int ret = sBluetoothInterface->get_adapter_properties();
991    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
992
993    return result;
994}
995
996static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
997    ALOGV("%s:",__FUNCTION__);
998
999    jboolean result = JNI_FALSE;
1000    if (!sBluetoothInterface) return result;
1001
1002    int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
1003    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1004
1005    return result;
1006}
1007
1008static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
1009    ALOGV("%s:",__FUNCTION__);
1010
1011    jbyte *addr = NULL;
1012    jboolean result = JNI_FALSE;
1013    if (!sBluetoothInterface) return result;
1014
1015    addr = env->GetByteArrayElements(address, NULL);
1016    if (addr == NULL) {
1017        jniThrowIOException(env, EINVAL);
1018        return result;
1019    }
1020
1021    int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
1022                                                              (bt_property_type_t) type);
1023    env->ReleaseByteArrayElements(address, addr, 0);
1024    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1025
1026    return result;
1027}
1028
1029static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
1030                                        jint type, jbyteArray value) {
1031    ALOGV("%s:",__FUNCTION__);
1032
1033    jbyte *val, *addr;
1034    jboolean result = JNI_FALSE;
1035    if (!sBluetoothInterface) return result;
1036
1037    val = env->GetByteArrayElements(value, NULL);
1038    if (val == NULL) {
1039        jniThrowIOException(env, EINVAL);
1040        return result;
1041    }
1042
1043    addr = env->GetByteArrayElements(address, NULL);
1044    if (addr == NULL) {
1045        env->ReleaseByteArrayElements(value, val, 0);
1046        jniThrowIOException(env, EINVAL);
1047        return result;
1048    }
1049
1050
1051    bt_property_t prop;
1052    prop.type = (bt_property_type_t) type;
1053    prop.len = env->GetArrayLength(value);
1054    prop.val = val;
1055
1056    int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
1057    env->ReleaseByteArrayElements(value, val, 0);
1058    env->ReleaseByteArrayElements(address, addr, 0);
1059
1060    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1061
1062    return result;
1063}
1064
1065static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
1066    ALOGV("%s:",__FUNCTION__);
1067
1068    jbyte *addr = NULL;
1069    jboolean result = JNI_FALSE;
1070    if (!sBluetoothInterface) return result;
1071
1072    addr = env->GetByteArrayElements(address, NULL);
1073    if (addr == NULL) {
1074        jniThrowIOException(env, EINVAL);
1075        return result;
1076    }
1077
1078    int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
1079    env->ReleaseByteArrayElements(address, addr, 0);
1080    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1081    return result;
1082}
1083
1084static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
1085                                   jbyteArray uuidObj, jint channel, jint flag, jint callingUid) {
1086    jbyte *addr = NULL, *uuid = NULL;
1087    int socket_fd;
1088    bt_status_t status;
1089
1090    if (!sBluetoothSocketInterface) return -1;
1091
1092    addr = env->GetByteArrayElements(address, NULL);
1093    if (!addr) {
1094        ALOGE("failed to get Bluetooth device address");
1095        goto Fail;
1096    }
1097
1098    if(uuidObj != NULL) {
1099        uuid = env->GetByteArrayElements(uuidObj, NULL);
1100        if (!uuid) {
1101            ALOGE("failed to get uuid");
1102            goto Fail;
1103        }
1104    }
1105
1106    if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
1107                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
1108            != BT_STATUS_SUCCESS) {
1109        ALOGE("Socket connection failed: %d", status);
1110        goto Fail;
1111    }
1112
1113
1114    if (socket_fd < 0) {
1115        ALOGE("Fail to create file descriptor on socket fd");
1116        goto Fail;
1117    }
1118    env->ReleaseByteArrayElements(address, addr, 0);
1119    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1120    return socket_fd;
1121
1122Fail:
1123    if (addr) env->ReleaseByteArrayElements(address, addr, 0);
1124    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1125
1126    return -1;
1127}
1128
1129static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
1130                                     jstring name_str, jbyteArray uuidObj,
1131                                     jint channel, jint flag, jint callingUid) {
1132    const char *service_name = NULL;
1133    jbyte *uuid = NULL;
1134    int socket_fd;
1135    bt_status_t status;
1136
1137    if (!sBluetoothSocketInterface) return -1;
1138
1139    ALOGV("%s: SOCK FLAG = %x", __FUNCTION__, flag);
1140
1141    if(name_str != NULL) {
1142        service_name = env->GetStringUTFChars(name_str, NULL);
1143    }
1144
1145    if(uuidObj != NULL) {
1146        uuid = env->GetByteArrayElements(uuidObj, NULL);
1147        if (!uuid) {
1148            ALOGE("failed to get uuid");
1149            goto Fail;
1150        }
1151    }
1152    if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
1153                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
1154            != BT_STATUS_SUCCESS) {
1155        ALOGE("Socket listen failed: %d", status);
1156        goto Fail;
1157    }
1158
1159    if (socket_fd < 0) {
1160        ALOGE("Fail to creat file descriptor on socket fd");
1161        goto Fail;
1162    }
1163    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
1164    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1165    return socket_fd;
1166
1167Fail:
1168    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
1169    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1170    return -1;
1171}
1172
1173static jboolean configHciSnoopLogNative(JNIEnv* env, jobject obj, jboolean enable) {
1174    ALOGV("%s:",__FUNCTION__);
1175
1176    jboolean result = JNI_FALSE;
1177
1178    if (!sBluetoothInterface) return result;
1179
1180    int ret = sBluetoothInterface->config_hci_snoop_log(enable);
1181
1182    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1183
1184    return result;
1185}
1186
1187static int readEnergyInfo()
1188{
1189    ALOGV("%s:",__FUNCTION__);
1190    jboolean result = JNI_FALSE;
1191    if (!sBluetoothInterface) return result;
1192    int ret = sBluetoothInterface->read_energy_info();
1193    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1194    return result;
1195}
1196
1197static void dumpNative(JNIEnv *env, jobject obj, jobject fdObj,
1198                       jobjectArray argArray)
1199{
1200    ALOGV("%s()", __FUNCTION__);
1201    if (!sBluetoothInterface) return;
1202
1203    int fd = jniGetFDFromFileDescriptor(env, fdObj);
1204    if (fd < 0) return;
1205
1206    int numArgs = env->GetArrayLength(argArray);
1207
1208    jstring *argObjs = new jstring[numArgs];
1209    const char **args = nullptr;
1210    if (numArgs > 0)
1211      args = new const char*[numArgs];
1212
1213    for (int i = 0; i < numArgs; i++) {
1214      argObjs[i] = (jstring) env->GetObjectArrayElement(argArray, i);
1215      args[i] = env->GetStringUTFChars(argObjs[i], NULL);
1216    }
1217
1218    sBluetoothInterface->dump(fd, args);
1219
1220    for (int i = 0; i < numArgs; i++) {
1221      env->ReleaseStringUTFChars(argObjs[i], args[i]);
1222    }
1223
1224    delete[] args;
1225    delete[] argObjs;
1226}
1227
1228static jboolean factoryResetNative(JNIEnv *env, jobject obj) {
1229    ALOGV("%s:", __FUNCTION__);
1230    if (!sBluetoothInterface) return JNI_FALSE;
1231    int ret = sBluetoothInterface->config_clear();
1232    return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1233}
1234
1235static void interopDatabaseClearNative(JNIEnv *env, jobject obj) {
1236    ALOGV("%s()", __FUNCTION__);
1237    if (!sBluetoothInterface) return;
1238    sBluetoothInterface->interop_database_clear();
1239}
1240
1241static void interopDatabaseAddNative(JNIEnv *env, jobject obj, int feature,
1242                                      jbyteArray address, int length) {
1243    ALOGV("%s()", __FUNCTION__);
1244    if (!sBluetoothInterface) return;
1245
1246    jbyte *addr = env->GetByteArrayElements(address, NULL);
1247    if (addr == NULL) {
1248        jniThrowIOException(env, EINVAL);
1249        return;
1250    }
1251
1252    sBluetoothInterface->interop_database_add(feature, (bt_bdaddr_t *)addr, length);
1253    env->ReleaseByteArrayElements(address, addr, 0);
1254}
1255
1256static JNINativeMethod sMethods[] = {
1257    /* name, signature, funcPtr */
1258    {"classInitNative", "()V", (void *) classInitNative},
1259    {"initNative", "()Z", (void *) initNative},
1260    {"cleanupNative", "()V", (void*) cleanupNative},
1261    {"enableNative", "()Z",  (void*) enableNative},
1262    {"disableNative", "()Z",  (void*) disableNative},
1263    {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
1264    {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
1265    {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
1266    {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
1267    {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
1268    {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
1269    {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
1270    {"createBondNative", "([BI)Z", (void*) createBondNative},
1271    {"createBondOutOfBandNative", "([BILandroid/bluetooth/OobData;)Z", (void*) createBondOutOfBandNative},
1272    {"removeBondNative", "([B)Z", (void*) removeBondNative},
1273    {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
1274    {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},
1275    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
1276    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
1277    {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
1278    {"connectSocketNative", "([BI[BIII)I", (void*) connectSocketNative},
1279    {"createSocketChannelNative", "(ILjava/lang/String;[BIII)I",
1280     (void*) createSocketChannelNative},
1281    {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative},
1282    {"alarmFiredNative", "()V", (void *) alarmFiredNative},
1283    {"readEnergyInfo", "()I", (void*) readEnergyInfo},
1284    {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V", (void*) dumpNative},
1285    {"factoryResetNative", "()Z", (void*)factoryResetNative},
1286    {"interopDatabaseClearNative", "()V", (void*) interopDatabaseClearNative},
1287    {"interopDatabaseAddNative", "(I[BI)V", (void*) interopDatabaseAddNative}
1288};
1289
1290int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
1291{
1292    return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
1293                                    sMethods, NELEM(sMethods));
1294}
1295
1296} /* namespace android */
1297
1298
1299/*
1300 * JNI Initialization
1301 */
1302jint JNI_OnLoad(JavaVM *jvm, void *reserved)
1303{
1304    JNIEnv *e;
1305    int status;
1306
1307    ALOGV("Bluetooth Adapter Service : loading JNI\n");
1308
1309    // Check JNI version
1310    if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
1311        ALOGE("JNI version mismatch error");
1312        return JNI_ERR;
1313    }
1314
1315    if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
1316        ALOGE("jni adapter service registration failure, status: %d", status);
1317        return JNI_ERR;
1318    }
1319
1320    if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
1321        ALOGE("jni hfp registration failure, status: %d", status);
1322        return JNI_ERR;
1323    }
1324
1325    if ((status = android::register_com_android_bluetooth_hfpclient(e)) < 0) {
1326        ALOGE("jni hfp client registration failure, status: %d", status);
1327        return JNI_ERR;
1328    }
1329
1330    if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
1331        ALOGE("jni a2dp source registration failure: %d", status);
1332        return JNI_ERR;
1333    }
1334
1335    if ((status = android::register_com_android_bluetooth_a2dp_sink(e)) < 0) {
1336        ALOGE("jni a2dp sink registration failure: %d", status);
1337        return JNI_ERR;
1338    }
1339
1340    if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
1341        ALOGE("jni avrcp target registration failure: %d", status);
1342        return JNI_ERR;
1343    }
1344
1345    if ((status = android::register_com_android_bluetooth_avrcp_controller(e)) < 0) {
1346        ALOGE("jni avrcp controller registration failure: %d", status);
1347        return JNI_ERR;
1348    }
1349
1350    if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
1351        ALOGE("jni hid registration failure: %d", status);
1352        return JNI_ERR;
1353    }
1354
1355    if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
1356        ALOGE("jni hdp registration failure: %d", status);
1357        return JNI_ERR;
1358    }
1359
1360    if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
1361        ALOGE("jni pan registration failure: %d", status);
1362        return JNI_ERR;
1363    }
1364
1365    if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
1366        ALOGE("jni gatt registration failure: %d", status);
1367        return JNI_ERR;
1368    }
1369
1370    if ((status = android::register_com_android_bluetooth_sdp(e)) < 0) {
1371        ALOGE("jni sdp registration failure: %d", status);
1372        return JNI_ERR;
1373    }
1374
1375    return JNI_VERSION_1_6;
1376}
1377