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