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