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