com_android_bluetooth_btservice_AdapterService.cpp revision e1ad2a10ea9d1fbf41441a535192ff7a7379bda2
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    int i;
298    if (!checkCallbackThread()) {
299       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
300       return;
301    }
302    if (!bd_addr) {
303        ALOGE("Address is null in %s", __FUNCTION__);
304        return;
305    }
306    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
307    if (addr == NULL) {
308       ALOGE("Address allocation failed in %s", __FUNCTION__);
309       return;
310    }
311    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
312
313    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
314                                addr, (jint)state);
315    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
316    callbackEnv->DeleteLocalRef(addr);
317}
318
319static void acl_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
320                                       bt_acl_state_t state)
321{
322    jbyteArray addr;
323    int i;
324    if (!checkCallbackThread()) {
325       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
326       return;
327    }
328    if (!bd_addr) {
329        ALOGE("Address is null in %s", __FUNCTION__);
330        return;
331    }
332    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
333    if (addr == NULL) {
334       ALOGE("Address allocation failed in %s", __FUNCTION__);
335       return;
336    }
337    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
338
339    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_aclStateChangeCallback, (jint) status,
340                                addr, (jint)state);
341    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
342    callbackEnv->DeleteLocalRef(addr);
343}
344
345static void discovery_state_changed_callback(bt_discovery_state_t state) {
346    jbyteArray addr;
347    if (!checkCallbackThread()) {
348       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
349       return;
350    }
351
352    ALOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
353
354    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
355                                (jint)state);
356
357    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
358}
359
360static void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
361        bool min_16_digits) {
362    jbyteArray addr, devname;
363    if (!checkCallbackThread()) {
364       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
365       return;
366    }
367    if (!bd_addr) {
368        ALOGE("Address is null in %s", __FUNCTION__);
369        return;
370    }
371
372    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
373    if (addr == NULL) goto Fail;
374    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
375
376    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
377    if (devname == NULL) goto Fail;
378
379    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
380
381    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod,
382            min_16_digits);
383
384    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
385    callbackEnv->DeleteLocalRef(addr);
386    callbackEnv->DeleteLocalRef(devname);
387    return;
388
389Fail:
390    if (addr) callbackEnv->DeleteLocalRef(addr);
391    if (devname) callbackEnv->DeleteLocalRef(devname);
392    ALOGE("Error while allocating in: %s", __FUNCTION__);
393}
394
395static void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
396                                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
397    jbyteArray addr, devname;
398    if (!checkCallbackThread()) {
399       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
400       return;
401    }
402    if (!bd_addr) {
403        ALOGE("Address is null in %s", __FUNCTION__);
404        return;
405    }
406
407    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
408    if (addr == NULL) goto Fail;
409    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
410
411    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
412    if (devname == NULL) goto Fail;
413    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
414
415    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
416                                (jint) pairing_variant, pass_key);
417
418    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
419    callbackEnv->DeleteLocalRef(addr);
420    callbackEnv->DeleteLocalRef(devname);
421    return;
422
423Fail:
424    if (addr) callbackEnv->DeleteLocalRef(addr);
425    if (devname) callbackEnv->DeleteLocalRef(devname);
426
427    ALOGE("Error while allocating in: %s", __FUNCTION__);
428}
429
430static void callback_thread_event(bt_cb_thread_evt event) {
431    JavaVM* vm = AndroidRuntime::getJavaVM();
432    if (event  == ASSOCIATE_JVM) {
433        JavaVMAttachArgs args;
434        char name[] = "BT Service Callback Thread";
435        args.version = JNI_VERSION_1_6;
436        args.name = name;
437        args.group = NULL;
438        vm->AttachCurrentThread(&callbackEnv, &args);
439        ALOGV("Callback thread attached: %p", callbackEnv);
440    } else if (event == DISASSOCIATE_JVM) {
441        if (!checkCallbackThread()) {
442            ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
443            return;
444        }
445        vm->DetachCurrentThread();
446    }
447}
448
449static void dut_mode_recv_callback (uint16_t opcode, uint8_t *buf, uint8_t len) {
450
451}
452static void le_test_mode_recv_callback (bt_status_t status, uint16_t packet_count) {
453
454    ALOGV("%s: status:%d packet_count:%d ", __FUNCTION__, status, packet_count);
455}
456
457static void energy_info_recv_callback(bt_activity_energy_info *p_energy_info,
458                                      bt_uid_traffic_t* uid_data)
459{
460    if (!checkCallbackThread()) {
461       ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
462       return;
463    }
464
465    jsize len = 0;
466    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
467        len++;
468    }
469
470    jobjectArray array = callbackEnv->NewObjectArray(len, android_bluetooth_UidTraffic.clazz, NULL);
471    jsize i = 0;
472    for (bt_uid_traffic_t* data = uid_data; data->app_uid != -1; data++) {
473        jobject uidObj = callbackEnv->NewObject(android_bluetooth_UidTraffic.clazz,
474                                                android_bluetooth_UidTraffic.constructor,
475                                                (jint) data->app_uid, (jlong) data->rx_bytes,
476                                                (jlong) data->tx_bytes);
477        callbackEnv->SetObjectArrayElement(array, i++, uidObj);
478        callbackEnv->DeleteLocalRef(uidObj);
479    }
480
481    callbackEnv->CallVoidMethod(sJniAdapterServiceObj, method_energyInfo, p_energy_info->status,
482        p_energy_info->ctrl_state, p_energy_info->tx_time, p_energy_info->rx_time,
483        p_energy_info->idle_time, p_energy_info->energy_used, array);
484
485    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
486    callbackEnv->DeleteLocalRef(array);
487}
488
489static bt_callbacks_t sBluetoothCallbacks = {
490    sizeof(sBluetoothCallbacks),
491    adapter_state_change_callback,
492    adapter_properties_callback,
493    remote_device_properties_callback,
494    device_found_callback,
495    discovery_state_changed_callback,
496    pin_request_callback,
497    ssp_request_callback,
498    bond_state_changed_callback,
499    acl_state_changed_callback,
500    callback_thread_event,
501    dut_mode_recv_callback,
502    le_test_mode_recv_callback,
503    energy_info_recv_callback
504};
505
506// The callback to call when the wake alarm fires.
507static alarm_cb sAlarmCallback;
508
509// The data to pass to the wake alarm callback.
510static void *sAlarmCallbackData;
511
512static JavaVMAttachArgs sAttachArgs = {
513  .version = JNI_VERSION_1_6,
514  .name = "bluedroid wake/alarm thread",
515  .group = NULL
516};
517
518static bool set_wake_alarm_callout(uint64_t delay_millis, bool should_wake,
519        alarm_cb cb, void *data) {
520    JNIEnv *env;
521    JavaVM *vm = AndroidRuntime::getJavaVM();
522    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
523
524    if (status != JNI_OK && status != JNI_EDETACHED) {
525        ALOGE("%s unable to get environment for JNI call", __func__);
526        return false;
527    }
528
529    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
530        ALOGE("%s unable to attach thread to VM", __func__);
531        return false;
532    }
533
534    sAlarmCallback = cb;
535    sAlarmCallbackData = data;
536
537    jboolean jshould_wake = should_wake ? JNI_TRUE : JNI_FALSE;
538    jboolean ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_setWakeAlarm,
539            (jlong)delay_millis, jshould_wake);
540    if (!ret) {
541        sAlarmCallback = NULL;
542        sAlarmCallbackData = NULL;
543    }
544
545    if (status == JNI_EDETACHED) {
546        vm->DetachCurrentThread();
547    }
548
549    return !!ret;
550}
551
552static int acquire_wake_lock_callout(const char *lock_name) {
553    JNIEnv *env;
554    JavaVM *vm = AndroidRuntime::getJavaVM();
555    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
556    if (status != JNI_OK && status != JNI_EDETACHED) {
557        ALOGE("%s unable to get environment for JNI call", __func__);
558        return BT_STATUS_FAIL;
559    }
560    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
561        ALOGE("%s unable to attach thread to VM", __func__);
562        return BT_STATUS_FAIL;
563    }
564
565    jboolean ret = JNI_FALSE;
566    jstring lock_name_jni = env->NewStringUTF(lock_name);
567    if (lock_name_jni) {
568        ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_acquireWakeLock, lock_name_jni);
569        env->DeleteLocalRef(lock_name_jni);
570    } else {
571        ALOGE("%s unable to allocate string: %s", __func__, lock_name);
572    }
573
574    if (status == JNI_EDETACHED) {
575        vm->DetachCurrentThread();
576    }
577
578    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
579}
580
581static int release_wake_lock_callout(const char *lock_name) {
582    JNIEnv *env;
583    JavaVM *vm = AndroidRuntime::getJavaVM();
584    jint status = vm->GetEnv((void **)&env, JNI_VERSION_1_6);
585
586    if (status != JNI_OK && status != JNI_EDETACHED) {
587        ALOGE("%s unable to get environment for JNI call", __func__);
588        return BT_STATUS_FAIL;
589    }
590    if (status == JNI_EDETACHED && vm->AttachCurrentThread(&env, &sAttachArgs) != 0) {
591        ALOGE("%s unable to attach thread to VM", __func__);
592        return BT_STATUS_FAIL;
593    }
594    jboolean ret = JNI_FALSE;
595    jstring lock_name_jni = env->NewStringUTF(lock_name);
596    if (lock_name_jni) {
597        ret = env->CallBooleanMethod(sJniAdapterServiceObj, method_releaseWakeLock, lock_name_jni);
598        env->DeleteLocalRef(lock_name_jni);
599    } else {
600        ALOGE("%s unable to allocate string: %s", __func__, lock_name);
601    }
602    if (status == JNI_EDETACHED) {
603        vm->DetachCurrentThread();
604    }
605    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
606}
607
608// Called by Java code when alarm is fired. A wake lock is held by the caller
609// over the duration of this callback.
610static void alarmFiredNative(JNIEnv *env, jobject obj) {
611    if (sAlarmCallback) {
612        sAlarmCallback(sAlarmCallbackData);
613    } else {
614        ALOGE("%s() - Alarm fired with callback not set!", __FUNCTION__);
615    }
616}
617
618static bt_os_callouts_t sBluetoothOsCallouts = {
619    sizeof(sBluetoothOsCallouts),
620    set_wake_alarm_callout,
621    acquire_wake_lock_callout,
622    release_wake_lock_callout,
623};
624
625
626
627static void classInitNative(JNIEnv* env, jclass clazz) {
628    int err;
629    hw_module_t* module;
630
631
632    jclass jniUidTrafficClass = env->FindClass("android/bluetooth/UidTraffic");
633    android_bluetooth_UidTraffic.constructor = env->GetMethodID(jniUidTrafficClass,
634                                                                "<init>", "(IJJ)V");
635
636    jclass jniCallbackClass =
637        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
638    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
639        "Lcom/android/bluetooth/btservice/JniCallbacks;");
640
641    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
642
643    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
644                                                             "adapterPropertyChangedCallback",
645                                                             "([I[[B)V");
646    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
647                                                           "discoveryStateChangeCallback", "(I)V");
648
649    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
650                                                            "devicePropertyChangedCallback",
651                                                            "([B[I[[B)V");
652    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
653    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
654                                                 "([B[BIZ)V");
655    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
656                                                 "([B[BIII)V");
657
658    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
659                                                     "bondStateChangeCallback", "(I[BI)V");
660
661    method_aclStateChangeCallback = env->GetMethodID(jniCallbackClass,
662                                                    "aclStateChangeCallback", "(I[BI)V");
663
664    method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
665    method_acquireWakeLock = env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
666    method_releaseWakeLock = env->GetMethodID(clazz, "releaseWakeLock", "(Ljava/lang/String;)Z");
667    method_energyInfo = env->GetMethodID(clazz, "energyInfoCallback", "(IIJJJJ[Landroid/bluetooth/UidTraffic;)V");
668
669    char value[PROPERTY_VALUE_MAX];
670    property_get("bluetooth.mock_stack", value, "");
671
672    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
673
674    err = hw_get_module(id, (hw_module_t const**)&module);
675
676    if (err == 0) {
677        hw_device_t* abstraction;
678        err = module->methods->open(module, id, &abstraction);
679        if (err == 0) {
680            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
681            sBluetoothInterface = btStack->get_bluetooth_interface();
682        } else {
683           ALOGE("Error while opening Bluetooth library");
684        }
685    } else {
686        ALOGE("No Bluetooth Library found");
687    }
688}
689
690static bool initNative(JNIEnv* env, jobject obj) {
691    ALOGV("%s:",__FUNCTION__);
692
693    android_bluetooth_UidTraffic.clazz = (jclass) env->NewGlobalRef(
694            env->FindClass("android/bluetooth/UidTraffic"));
695
696    sJniAdapterServiceObj = env->NewGlobalRef(obj);
697    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
698
699    if (sBluetoothInterface) {
700        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
701        if (ret != BT_STATUS_SUCCESS) {
702            ALOGE("Error while setting the callbacks: %d\n", ret);
703            sBluetoothInterface = NULL;
704            return JNI_FALSE;
705        }
706        ret = sBluetoothInterface->set_os_callouts(&sBluetoothOsCallouts);
707        if (ret != BT_STATUS_SUCCESS) {
708            ALOGE("Error while setting Bluetooth callouts: %d\n", ret);
709            sBluetoothInterface->cleanup();
710            sBluetoothInterface = NULL;
711            return JNI_FALSE;
712        }
713
714        if ( (sBluetoothSocketInterface = (btsock_interface_t *)
715                  sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
716                ALOGE("Error getting socket interface");
717        }
718
719        return JNI_TRUE;
720    }
721    return JNI_FALSE;
722}
723
724static bool cleanupNative(JNIEnv *env, jobject obj) {
725    ALOGV("%s:",__FUNCTION__);
726
727    jboolean result = JNI_FALSE;
728    if (!sBluetoothInterface) return result;
729
730    sBluetoothInterface->cleanup();
731    ALOGI("%s: return from cleanup",__FUNCTION__);
732
733    env->DeleteGlobalRef(sJniCallbacksObj);
734    env->DeleteGlobalRef(sJniAdapterServiceObj);
735    env->DeleteGlobalRef(android_bluetooth_UidTraffic.clazz);
736    android_bluetooth_UidTraffic.clazz = NULL;
737    return JNI_TRUE;
738}
739
740static jboolean enableNative(JNIEnv* env, jobject obj) {
741    ALOGV("%s:",__FUNCTION__);
742
743    jboolean result = JNI_FALSE;
744    if (!sBluetoothInterface) return result;
745
746    int ret = sBluetoothInterface->enable();
747    result = (ret == BT_STATUS_SUCCESS || ret == BT_STATUS_DONE) ? JNI_TRUE : JNI_FALSE;
748    return result;
749}
750
751static jboolean disableNative(JNIEnv* env, jobject obj) {
752    ALOGV("%s:",__FUNCTION__);
753
754    jboolean result = JNI_FALSE;
755    if (!sBluetoothInterface) return result;
756
757    int ret = sBluetoothInterface->disable();
758    /* Retrun JNI_FALSE only when BTIF explicitly reports
759       BT_STATUS_FAIL. It is fine for the BT_STATUS_NOT_READY
760       case which indicates that stack had not been enabled.
761    */
762    result = (ret == BT_STATUS_FAIL) ? JNI_FALSE : JNI_TRUE;
763    return result;
764}
765
766static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
767    ALOGV("%s:",__FUNCTION__);
768
769    jboolean result = JNI_FALSE;
770    if (!sBluetoothInterface) return result;
771
772    int ret = sBluetoothInterface->start_discovery();
773    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
774    return result;
775}
776
777static jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
778    ALOGV("%s:",__FUNCTION__);
779
780    jboolean result = JNI_FALSE;
781    if (!sBluetoothInterface) return result;
782
783    int ret = sBluetoothInterface->cancel_discovery();
784    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
785    return result;
786}
787
788static jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address, jint transport) {
789    ALOGV("%s:",__FUNCTION__);
790
791    jbyte *addr;
792    jboolean result = JNI_FALSE;
793
794    if (!sBluetoothInterface) return result;
795
796    addr = env->GetByteArrayElements(address, NULL);
797    if (addr == NULL) {
798        jniThrowIOException(env, EINVAL);
799        return result;
800    }
801
802    int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr, transport);
803    env->ReleaseByteArrayElements(address, addr, 0);
804    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
805
806    return result;
807}
808
809static jbyteArray callByteArrayGetter(JNIEnv* env, jobject object, char* className, char* methodName) {
810    jclass myClass = env->FindClass(className);
811    jmethodID myMethod = env->GetMethodID(myClass, methodName, "()[B");
812    return (jbyteArray) env->CallObjectMethod(object, myMethod);
813}
814
815static jboolean createBondOutOfBandNative(JNIEnv* env, jobject obj, jbyteArray address,
816                jint transport, jobject oobData) {
817    jbyte *addr;
818    jboolean result = JNI_FALSE;
819    bt_out_of_band_data_t oob_data;
820
821    memset(&oob_data, 0, sizeof(oob_data));
822
823    if (!sBluetoothInterface) return result;
824
825    addr = env->GetByteArrayElements(address, NULL);
826    if (addr == NULL) {
827        jniThrowIOException(env, EINVAL);
828        return result;
829    }
830
831    jbyte* smTKBytes = NULL;
832    jbyteArray smTK = callByteArrayGetter(env, oobData, "android/bluetooth/OobData", "getSecurityManagerTk");
833    if (smTK != NULL) {
834        smTKBytes = env->GetByteArrayElements(smTK, NULL);
835        int len = env->GetArrayLength(smTK);
836        if (len != OOB_TK_SIZE) {
837            ALOGI("%s: wrong length of smTK, should be empty or %d bytes.", __FUNCTION__, OOB_TK_SIZE);
838            jniThrowIOException(env, EINVAL);
839            goto done;
840        }
841        memcpy(oob_data.sm_tk, smTKBytes, len);
842    }
843
844    if (sBluetoothInterface->create_bond_out_of_band((bt_bdaddr_t *)addr, transport, &oob_data)
845        == BT_STATUS_SUCCESS)
846        result = JNI_TRUE;
847
848done:
849    env->ReleaseByteArrayElements(address, addr, 0);
850
851    if (smTK != NULL)
852        env->ReleaseByteArrayElements(smTK, smTKBytes, 0);
853
854    return result;
855}
856
857static jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
858    ALOGV("%s:",__FUNCTION__);
859
860    jbyte *addr;
861    jboolean result;
862    if (!sBluetoothInterface) return JNI_FALSE;
863
864    addr = env->GetByteArrayElements(address, NULL);
865    if (addr == NULL) {
866        jniThrowIOException(env, EINVAL);
867        return JNI_FALSE;
868    }
869
870    int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
871    env->ReleaseByteArrayElements(address, addr, 0);
872    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
873
874    return result;
875}
876
877static jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
878    ALOGV("%s:",__FUNCTION__);
879
880    jbyte *addr;
881    jboolean result;
882    if (!sBluetoothInterface) return JNI_FALSE;
883
884    addr = env->GetByteArrayElements(address, NULL);
885    if (addr == NULL) {
886        jniThrowIOException(env, EINVAL);
887        return JNI_FALSE;
888    }
889
890    int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
891    env->ReleaseByteArrayElements(address, addr, 0);
892    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
893
894    return result;
895}
896
897static int getConnectionStateNative(JNIEnv* env, jobject obj, jbyteArray address) {
898    ALOGV("%s:",__FUNCTION__);
899    if (!sBluetoothInterface) return JNI_FALSE;
900
901    jbyte *addr = env->GetByteArrayElements(address, NULL);
902    if (addr == NULL) {
903        jniThrowIOException(env, EINVAL);
904        return JNI_FALSE;
905    }
906
907    int ret = sBluetoothInterface->get_connection_state((bt_bdaddr_t *)addr);
908    env->ReleaseByteArrayElements(address, addr, 0);
909
910    return ret;
911}
912
913static jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
914                               jint len, jbyteArray pinArray) {
915    ALOGV("%s:",__FUNCTION__);
916
917    jbyte *addr, *pinPtr = NULL;
918    jboolean result = JNI_FALSE;
919    if (!sBluetoothInterface) return result;
920
921    addr = env->GetByteArrayElements(address, NULL);
922    if (addr == NULL) {
923        jniThrowIOException(env, EINVAL);
924        return result;
925    }
926
927    if (accept) {
928        pinPtr = env->GetByteArrayElements(pinArray, NULL);
929        if (pinPtr == NULL) {
930           jniThrowIOException(env, EINVAL);
931           env->ReleaseByteArrayElements(address, addr, 0);
932           return result;
933        }
934    }
935
936    int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
937                                              (bt_pin_code_t *) pinPtr);
938    env->ReleaseByteArrayElements(address, addr, 0);
939    env->ReleaseByteArrayElements(pinArray, pinPtr, 0);
940    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
941
942    return result;
943}
944
945static jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
946                               jint type, jboolean accept, jint passkey) {
947    ALOGV("%s:",__FUNCTION__);
948
949    jbyte *addr;
950    jboolean result = JNI_FALSE;
951    if (!sBluetoothInterface) return result;
952
953    addr = env->GetByteArrayElements(address, NULL);
954    if (addr == NULL) {
955        jniThrowIOException(env, EINVAL);
956        return result;
957    }
958
959    int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
960         (bt_ssp_variant_t) type, accept, passkey);
961    env->ReleaseByteArrayElements(address, addr, 0);
962    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
963
964    return result;
965}
966
967static jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
968    ALOGV("%s:",__FUNCTION__);
969
970    jbyte *val;
971    jboolean result = JNI_FALSE;
972    if (!sBluetoothInterface) return result;
973
974    val = env->GetByteArrayElements(value, NULL);
975    bt_property_t prop;
976    prop.type = (bt_property_type_t) type;
977    prop.len = env->GetArrayLength(value);
978    prop.val = val;
979
980    int ret = sBluetoothInterface->set_adapter_property(&prop);
981    env->ReleaseByteArrayElements(value, val, 0);
982    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
983
984    return result;
985}
986
987static jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
988    ALOGV("%s:",__FUNCTION__);
989
990    jboolean result = JNI_FALSE;
991    if (!sBluetoothInterface) return result;
992
993    int ret = sBluetoothInterface->get_adapter_properties();
994    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
995
996    return result;
997}
998
999static jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
1000    ALOGV("%s:",__FUNCTION__);
1001
1002    jboolean result = JNI_FALSE;
1003    if (!sBluetoothInterface) return result;
1004
1005    int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
1006    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1007
1008    return result;
1009}
1010
1011static jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
1012    ALOGV("%s:",__FUNCTION__);
1013
1014    jbyte *addr = NULL;
1015    jboolean result = JNI_FALSE;
1016    if (!sBluetoothInterface) return result;
1017
1018    addr = env->GetByteArrayElements(address, NULL);
1019    if (addr == NULL) {
1020        jniThrowIOException(env, EINVAL);
1021        return result;
1022    }
1023
1024    int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
1025                                                              (bt_property_type_t) type);
1026    env->ReleaseByteArrayElements(address, addr, 0);
1027    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1028
1029    return result;
1030}
1031
1032static jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
1033                                        jint type, jbyteArray value) {
1034    ALOGV("%s:",__FUNCTION__);
1035
1036    jbyte *val, *addr;
1037    jboolean result = JNI_FALSE;
1038    if (!sBluetoothInterface) return result;
1039
1040    val = env->GetByteArrayElements(value, NULL);
1041    if (val == NULL) {
1042        jniThrowIOException(env, EINVAL);
1043        return result;
1044    }
1045
1046    addr = env->GetByteArrayElements(address, NULL);
1047    if (addr == NULL) {
1048        env->ReleaseByteArrayElements(value, val, 0);
1049        jniThrowIOException(env, EINVAL);
1050        return result;
1051    }
1052
1053
1054    bt_property_t prop;
1055    prop.type = (bt_property_type_t) type;
1056    prop.len = env->GetArrayLength(value);
1057    prop.val = val;
1058
1059    int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
1060    env->ReleaseByteArrayElements(value, val, 0);
1061    env->ReleaseByteArrayElements(address, addr, 0);
1062
1063    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1064
1065    return result;
1066}
1067
1068static jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
1069    ALOGV("%s:",__FUNCTION__);
1070
1071    jbyte *addr = NULL;
1072    jboolean result = JNI_FALSE;
1073    if (!sBluetoothInterface) return result;
1074
1075    addr = env->GetByteArrayElements(address, NULL);
1076    if (addr == NULL) {
1077        jniThrowIOException(env, EINVAL);
1078        return result;
1079    }
1080
1081    int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
1082    env->ReleaseByteArrayElements(address, addr, 0);
1083    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1084    return result;
1085}
1086
1087static int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
1088                                   jbyteArray uuidObj, jint channel, jint flag, jint callingUid) {
1089    jbyte *addr = NULL, *uuid = NULL;
1090    int socket_fd;
1091    bt_status_t status;
1092
1093    if (!sBluetoothSocketInterface) return -1;
1094
1095    addr = env->GetByteArrayElements(address, NULL);
1096    if (!addr) {
1097        ALOGE("failed to get Bluetooth device address");
1098        goto Fail;
1099    }
1100
1101    if(uuidObj != NULL) {
1102        uuid = env->GetByteArrayElements(uuidObj, NULL);
1103        if (!uuid) {
1104            ALOGE("failed to get uuid");
1105            goto Fail;
1106        }
1107    }
1108
1109    if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
1110                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
1111            != BT_STATUS_SUCCESS) {
1112        ALOGE("Socket connection failed: %d", status);
1113        goto Fail;
1114    }
1115
1116
1117    if (socket_fd < 0) {
1118        ALOGE("Fail to create file descriptor on socket fd");
1119        goto Fail;
1120    }
1121    env->ReleaseByteArrayElements(address, addr, 0);
1122    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1123    return socket_fd;
1124
1125Fail:
1126    if (addr) env->ReleaseByteArrayElements(address, addr, 0);
1127    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1128
1129    return -1;
1130}
1131
1132static int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
1133                                     jstring name_str, jbyteArray uuidObj,
1134                                     jint channel, jint flag, jint callingUid) {
1135    const char *service_name = NULL;
1136    jbyte *uuid = NULL;
1137    int socket_fd;
1138    bt_status_t status;
1139
1140    if (!sBluetoothSocketInterface) return -1;
1141
1142    ALOGV("%s: SOCK FLAG = %x", __FUNCTION__, flag);
1143
1144    if(name_str != NULL) {
1145        service_name = env->GetStringUTFChars(name_str, NULL);
1146    }
1147
1148    if(uuidObj != NULL) {
1149        uuid = env->GetByteArrayElements(uuidObj, NULL);
1150        if (!uuid) {
1151            ALOGE("failed to get uuid");
1152            goto Fail;
1153        }
1154    }
1155    if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
1156                       (const uint8_t*) uuid, channel, &socket_fd, flag, callingUid))
1157            != BT_STATUS_SUCCESS) {
1158        ALOGE("Socket listen failed: %d", status);
1159        goto Fail;
1160    }
1161
1162    if (socket_fd < 0) {
1163        ALOGE("Fail to creat file descriptor on socket fd");
1164        goto Fail;
1165    }
1166    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
1167    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1168    return socket_fd;
1169
1170Fail:
1171    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
1172    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
1173    return -1;
1174}
1175
1176static jboolean configHciSnoopLogNative(JNIEnv* env, jobject obj, jboolean enable) {
1177    ALOGV("%s:",__FUNCTION__);
1178
1179    jboolean result = JNI_FALSE;
1180
1181    if (!sBluetoothInterface) return result;
1182
1183    int ret = sBluetoothInterface->config_hci_snoop_log(enable);
1184
1185    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1186
1187    return result;
1188}
1189
1190static int readEnergyInfo()
1191{
1192    ALOGV("%s:",__FUNCTION__);
1193    jboolean result = JNI_FALSE;
1194    if (!sBluetoothInterface) return result;
1195    int ret = sBluetoothInterface->read_energy_info();
1196    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1197    return result;
1198}
1199
1200static void dumpNative(JNIEnv *env, jobject obj, jobject fdObj,
1201                       jobjectArray argArray)
1202{
1203    ALOGV("%s()", __FUNCTION__);
1204    if (!sBluetoothInterface) return;
1205
1206    int fd = jniGetFDFromFileDescriptor(env, fdObj);
1207    if (fd < 0) return;
1208
1209    int numArgs = env->GetArrayLength(argArray);
1210
1211    jstring *argObjs = new jstring[numArgs];
1212    const char **args = nullptr;
1213    if (numArgs > 0)
1214      args = new const char*[numArgs];
1215
1216    for (int i = 0; i < numArgs; i++) {
1217      argObjs[i] = (jstring) env->GetObjectArrayElement(argArray, i);
1218      args[i] = env->GetStringUTFChars(argObjs[i], NULL);
1219    }
1220
1221    sBluetoothInterface->dump(fd, args);
1222
1223    for (int i = 0; i < numArgs; i++) {
1224      env->ReleaseStringUTFChars(argObjs[i], args[i]);
1225    }
1226
1227    delete[] args;
1228    delete[] argObjs;
1229}
1230
1231static jboolean factoryResetNative(JNIEnv *env, jobject obj) {
1232    ALOGV("%s:", __FUNCTION__);
1233    if (!sBluetoothInterface) return JNI_FALSE;
1234    int ret = sBluetoothInterface->config_clear();
1235    return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
1236}
1237
1238static JNINativeMethod sMethods[] = {
1239    /* name, signature, funcPtr */
1240    {"classInitNative", "()V", (void *) classInitNative},
1241    {"initNative", "()Z", (void *) initNative},
1242    {"cleanupNative", "()V", (void*) cleanupNative},
1243    {"enableNative", "()Z",  (void*) enableNative},
1244    {"disableNative", "()Z",  (void*) disableNative},
1245    {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
1246    {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
1247    {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
1248    {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
1249    {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
1250    {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
1251    {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
1252    {"createBondNative", "([BI)Z", (void*) createBondNative},
1253    {"createBondOutOfBandNative", "([BILandroid/bluetooth/OobData;)Z", (void*) createBondOutOfBandNative},
1254    {"removeBondNative", "([B)Z", (void*) removeBondNative},
1255    {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
1256    {"getConnectionStateNative", "([B)I", (void*) getConnectionStateNative},
1257    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
1258    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
1259    {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
1260    {"connectSocketNative", "([BI[BIII)I", (void*) connectSocketNative},
1261    {"createSocketChannelNative", "(ILjava/lang/String;[BIII)I",
1262     (void*) createSocketChannelNative},
1263    {"configHciSnoopLogNative", "(Z)Z", (void*) configHciSnoopLogNative},
1264    {"alarmFiredNative", "()V", (void *) alarmFiredNative},
1265    {"readEnergyInfo", "()I", (void*) readEnergyInfo},
1266    {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V", (void*) dumpNative},
1267    {"factoryResetNative", "()Z", (void*)factoryResetNative}
1268};
1269
1270int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
1271{
1272    return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
1273                                    sMethods, NELEM(sMethods));
1274}
1275
1276} /* namespace android */
1277
1278
1279/*
1280 * JNI Initialization
1281 */
1282jint JNI_OnLoad(JavaVM *jvm, void *reserved)
1283{
1284    JNIEnv *e;
1285    int status;
1286
1287    ALOGV("Bluetooth Adapter Service : loading JNI\n");
1288
1289    // Check JNI version
1290    if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
1291        ALOGE("JNI version mismatch error");
1292        return JNI_ERR;
1293    }
1294
1295    if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
1296        ALOGE("jni adapter service registration failure, status: %d", status);
1297        return JNI_ERR;
1298    }
1299
1300    if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
1301        ALOGE("jni hfp registration failure, status: %d", status);
1302        return JNI_ERR;
1303    }
1304
1305    if ((status = android::register_com_android_bluetooth_hfpclient(e)) < 0) {
1306        ALOGE("jni hfp client registration failure, status: %d", status);
1307        return JNI_ERR;
1308    }
1309
1310    if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
1311        ALOGE("jni a2dp source registration failure: %d", status);
1312        return JNI_ERR;
1313    }
1314
1315    if ((status = android::register_com_android_bluetooth_a2dp_sink(e)) < 0) {
1316        ALOGE("jni a2dp sink registration failure: %d", status);
1317        return JNI_ERR;
1318    }
1319
1320    if ((status = android::register_com_android_bluetooth_avrcp(e)) < 0) {
1321        ALOGE("jni avrcp target registration failure: %d", status);
1322        return JNI_ERR;
1323    }
1324
1325    if ((status = android::register_com_android_bluetooth_avrcp_controller(e)) < 0) {
1326        ALOGE("jni avrcp controller registration failure: %d", status);
1327        return JNI_ERR;
1328    }
1329
1330    if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
1331        ALOGE("jni hid registration failure: %d", status);
1332        return JNI_ERR;
1333    }
1334
1335    if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
1336        ALOGE("jni hdp registration failure: %d", status);
1337        return JNI_ERR;
1338    }
1339
1340    if ((status = android::register_com_android_bluetooth_pan(e)) < 0) {
1341        ALOGE("jni pan registration failure: %d", status);
1342        return JNI_ERR;
1343    }
1344
1345    if ((status = android::register_com_android_bluetooth_gatt(e)) < 0) {
1346        ALOGE("jni gatt registration failure: %d", status);
1347        return JNI_ERR;
1348    }
1349
1350    if ((status = android::register_com_android_bluetooth_sdp(e)) < 0) {
1351        ALOGE("jni sdp registration failure: %d", status);
1352        return JNI_ERR;
1353    }
1354
1355    return JNI_VERSION_1_6;
1356}
1357