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