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