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