com_android_bluetooth_btservice_AdapterService.cpp revision c55ac7d42cf2d78c7edc67abf6c66813245b2c93
1ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/*
2ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * Copyright (C) 2012 Google Inc.
3ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
4ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
5ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#define LOG_TAG "BluetoothServiceJni"
6ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
76c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#include "com_android_bluetooth.h"
8cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie#include "hardware/bt_sock.h"
9ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include "utils/Log.h"
10ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include "utils/misc.h"
11ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include "cutils/properties.h"
12ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include "android_runtime/AndroidRuntime.h"
13ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
14ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include <string.h>
15ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include <pthread.h>
16ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
17ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include <sys/stat.h>
18ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh#include <fcntl.h>
19ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
20ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshnamespace android {
21ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
226c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie#define ADDITIONAL_NREFS 50
236c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
24ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_stateChangeCallback;
25ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_adapterPropertyChangedCallback;
26ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_devicePropertyChangedCallback;
27ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_deviceFoundCallback;
28ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_pinRequestCallback;
29ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_sspRequestCallback;
30ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_bondStateChangeCallback;
31ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jmethodID method_discoveryStateChangeCallback;
32ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
33ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic const bt_interface_t *sBluetoothInterface = NULL;
34cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xiestatic const btsock_interface_t *sBluetoothSocketInterface = NULL;
35ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic JNIEnv *callbackEnv = NULL;
36ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
37ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jobject sJniCallbacksObj;
38ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jfieldID sJniCallbacksField;
39ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
40cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
416c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xieconst bt_interface_t* getBluetoothInterface() {
426c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    return sBluetoothInterface;
436c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
446c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
456c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew XieJNIEnv* getCallbackEnv() {
466c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   return callbackEnv;
476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie}
486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
496c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xievoid checkAndClearExceptionFromCallback(JNIEnv* env,
50ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                               const char* methodName) {
51ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (env->ExceptionCheck()) {
52ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("An exception was thrown by callback '%s'.", methodName);
53ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE_EX(env);
54ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        env->ExceptionClear();
55ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
56ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
57ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
58ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic bool checkCallbackThread() {
59ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    JNIEnv* env = AndroidRuntime::getJNIEnv();
60676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie    if (callbackEnv != env || callbackEnv == NULL) {
61676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie        LOGE("Callback env check fail: env: %p, callback: %p", env, callbackEnv);
62676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie        return false;
63676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie    }
64ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return true;
65ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
66ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
67ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void adapter_state_change_callback(bt_state_t status) {
68ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!checkCallbackThread()) {
69ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
70ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
71ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
72ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s: Status is: %d", __FUNCTION__, status);
73ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
74ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_stateChangeCallback, (jint)status);
75ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
76ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
77ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
78ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
79ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
80ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                        jobjectArray *props) {
81ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyteArray propVal, val;
82ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
83ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (val == NULL) goto Fail;
84ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
85ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    //TODO(BT) Is this the best way to do it ?
86ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    *props = callbackEnv->NewObjectArray(num_properties, callbackEnv->GetObjectClass(val),
87ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                             NULL);
88ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (*props == NULL) goto Fail;
89ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
90ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    *types = callbackEnv->NewIntArray(num_properties);
91ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (*types == NULL) goto Fail;
92ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
93ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    for (int i = 0; i < num_properties; i++) {
94f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy
95f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy       /* The higher layers expect rssi as a short int value, while the value is sent as a byte
96f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy        * to jni. Converting rssi value to the expected format.*/
97f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy       if (properties[i].type == BT_PROPERTY_REMOTE_RSSI)
98f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy       {
99f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy           jbyte rssi = *((jbyte *) properties[i].val);
100f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy           short rssiValue = rssi;
101f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy           properties[i].len = sizeof(rssiValue);
102f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy           properties[i].val = &rssiValue;
103f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy       }
104f8d98da947bbb9e2380a60df89acbcbd4ca680afKausik Sinnaswamy
105ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       propVal = callbackEnv->NewByteArray(properties[i].len);
106ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       if (propVal == NULL) goto Fail;
107ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
108ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       callbackEnv->SetByteArrayRegion(propVal, 0, properties[i].len,
109ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                            (jbyte*)properties[i].val);
110ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       callbackEnv->SetObjectArrayElement(*props, i, propVal);
111ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
112ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       callbackEnv->SetIntArrayRegion(*types, i, 1, (jint *)&properties[i].type);
113ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
114ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return 0;
115ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar GaneshFail:
116ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (val) callbackEnv->DeleteLocalRef(val);
117ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (propVal) callbackEnv->DeleteLocalRef(propVal);
118ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGE("Error while allocation of array in %s", __FUNCTION__);
119ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return -1;
120ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
121ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
122ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void adapter_properties_callback(bt_status_t status, int num_properties,
123ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                        bt_property_t *properties) {
124ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jobjectArray props;
125ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jintArray types;
126ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!checkCallbackThread()) {
127ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
128ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
129ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
130ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
131ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
132ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
133ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (status != BT_STATUS_SUCCESS) {
134ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("%s: Status %d is incorrect", __FUNCTION__, status);
135ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
136ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
137ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
138ff68148a7fb74947ea5e7a337161108363cbe9f5Jaikumar Ganesh    if (get_properties(num_properties, properties, &types, &props) < 0) {
139ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (props) callbackEnv->DeleteLocalRef(props);
140ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (types) callbackEnv->DeleteLocalRef(types);
141ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
142ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
143ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
144ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_adapterPropertyChangedCallback, types,
145ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                props);
146ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
1476c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(props);
1486c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(types);
149ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return;
150ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
151ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
152ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
153ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void remote_device_properties_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
154ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                              int num_properties, bt_property_t *properties) {
155ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!checkCallbackThread()) {
156ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
157ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
158ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
159ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
160ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s: Status is: %d, Properties: %d", __FUNCTION__, status, num_properties);
161ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
162ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (status != BT_STATUS_SUCCESS) {
163ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("%s: Status %d is incorrect", __FUNCTION__, status);
164ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
165ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
166ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
1676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->PushLocalFrame(ADDITIONAL_NREFS);
1686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
1696c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    jobjectArray props;
1706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    jbyteArray addr;
1716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    jintArray types;
1726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
173ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
174ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) goto Fail;
175ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr) callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
176ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
177ff68148a7fb74947ea5e7a337161108363cbe9f5Jaikumar Ganesh    if (get_properties(num_properties, properties, &types, &props) < 0) {
178ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (props) callbackEnv->DeleteLocalRef(props);
179ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (types) callbackEnv->DeleteLocalRef(types);
1806c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie        callbackEnv->PopLocalFrame(NULL);
181ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
182ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
183ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
184ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_devicePropertyChangedCallback, addr,
185ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                types, props);
186ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
1876c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(props);
1886c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(types);
1896c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->PopLocalFrame(NULL);
190ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return;
191ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
192ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar GaneshFail:
193ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGE("Error while allocation byte array in %s", __FUNCTION__);
194ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
195ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
196ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
197ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void device_found_callback(int num_properties, bt_property_t *properties) {
198ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyteArray addr = NULL;
199ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int addr_index;
200ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
201ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    for (int i = 0; i < num_properties; i++) {
202ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (properties[i].type == BT_PROPERTY_BDADDR) {
203ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            addr = callbackEnv->NewByteArray(properties[i].len);
204ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            if (addr) {
205ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                callbackEnv->SetByteArrayRegion(addr, 0, properties[i].len,
206ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                (jbyte*)properties[i].val);
207ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                addr_index = i;
208ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            } else {
209ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                LOGE("Address is NULL (unable to allocate) in %s", __FUNCTION__);
210ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                return;
211ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            }
212ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
213ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
214ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
215ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("Address is NULL in %s", __FUNCTION__);
216ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
217ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
218ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
219ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s: Properties: %d, Address: %s", __FUNCTION__, num_properties,
220ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        (const char *)properties[addr_index].val);
221ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
222ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    remote_device_properties_callback(BT_STATUS_SUCCESS, (bt_bdaddr_t *)properties[addr_index].val,
223ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                      num_properties, properties);
224ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
225ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
226ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
2276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(addr);
228ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
229ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
230ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void bond_state_changed_callback(bt_status_t status, bt_bdaddr_t *bd_addr,
231ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                        bt_bond_state_t state) {
232ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyteArray addr;
233ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int i;
234ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!checkCallbackThread()) {
235ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
236ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
237ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
238ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!bd_addr) {
239ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("Address is null in %s", __FUNCTION__);
240ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
241ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
242ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
243ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
244ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Address allocation failed in %s", __FUNCTION__);
245ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
246ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
247ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
248ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
249ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_bondStateChangeCallback, (jint) status,
250ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                addr, (jint)state);
251ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
2526c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(addr);
253ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
254ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
255ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void discovery_state_changed_callback(bt_discovery_state_t state) {
256ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyteArray addr;
257ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!checkCallbackThread()) {
258ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
259ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
260ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
261ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
262ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s: DiscoveryState:%d ", __FUNCTION__, state);
263ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
264ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_discoveryStateChangeCallback,
265ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                (jint)state);
266ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
267ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
268ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
269ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
270ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void pin_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod) {
271ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyteArray addr, devname;
272ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!checkCallbackThread()) {
273ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
274ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
275ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
276ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!bd_addr) {
277ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("Address is null in %s", __FUNCTION__);
278ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
279ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
280ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
281ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
282ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) goto Fail;
28361c4100eb0606f8ba630f5c45d07a88d612fbc85Matthew Xie    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte*)bd_addr);
284ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
285ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
286ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (devname == NULL) goto Fail;
287ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
288ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
289ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
290ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_pinRequestCallback, addr, devname, cod);
291ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
292ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
2936c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(addr);
2946c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(devname);
295ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return;
296ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
297ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar GaneshFail:
298ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr) callbackEnv->DeleteLocalRef(addr);
299ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (devname) callbackEnv->DeleteLocalRef(devname);
300ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGE("Error while allocating in: %s", __FUNCTION__);
301ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
302ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
303ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void ssp_request_callback(bt_bdaddr_t *bd_addr, bt_bdname_t *bdname, uint32_t cod,
304ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
305ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyteArray addr, devname;
306ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!checkCallbackThread()) {
307ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
308ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh       return;
309ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
310ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!bd_addr) {
311ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("Address is null in %s", __FUNCTION__);
312ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return;
313ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
314ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
315ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
316ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) goto Fail;
317ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *)bd_addr);
318ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
319ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    devname = callbackEnv->NewByteArray(sizeof(bt_bdname_t));
320ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (devname == NULL) goto Fail;
321ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->SetByteArrayRegion(devname, 0, sizeof(bt_bdname_t), (jbyte*)bdname);
322ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
323ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callbackEnv->CallVoidMethod(sJniCallbacksObj, method_sspRequestCallback, addr, devname, cod,
324ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                (jint) pairing_variant, pass_key);
325ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
326ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
3276c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(addr);
3286c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie    callbackEnv->DeleteLocalRef(devname);
329ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return;
330ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
331ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar GaneshFail:
332ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr) callbackEnv->DeleteLocalRef(addr);
333ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (devname) callbackEnv->DeleteLocalRef(devname);
334ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
335ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGE("Error while allocating in: %s", __FUNCTION__);
336ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
337ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
338ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void callback_thread_event(bt_cb_thread_evt event) {
339ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    JavaVM* vm = AndroidRuntime::getJavaVM();
340ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (event  == ASSOCIATE_JVM) {
341ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        JavaVMAttachArgs args;
342ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        char name[] = "BT Service Callback Thread";
343ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        //TODO(BT)
344ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        //args.version = nat->envVer;
345ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        args.name = name;
346ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        args.group = NULL;
347ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        vm->AttachCurrentThread(&callbackEnv, &args);
348ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGV("Callback thread attached: %p", callbackEnv);
349ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    } else if (event == DISASSOCIATE_JVM) {
350ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (!checkCallbackThread()) {
351ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
352ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return;
353ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
354ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        vm->DetachCurrentThread();
355ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
356ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
357ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
358ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshbt_callbacks_t sBluetoothCallbacks = {
359ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    sizeof(sBluetoothCallbacks),
360ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    adapter_state_change_callback,
361ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    adapter_properties_callback,
362ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    remote_device_properties_callback,
363ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    device_found_callback,
364ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    discovery_state_changed_callback,
365ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    pin_request_callback,
366ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    ssp_request_callback,
367ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    bond_state_changed_callback,
368ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    callback_thread_event,
369ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh};
370ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
371ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic void classInitNative(JNIEnv* env, jclass clazz) {
372ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int err;
373ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    hw_module_t* module;
374ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
375ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jclass jniCallbackClass =
376ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        env->FindClass("com/android/bluetooth/btservice/JniCallbacks");
377ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    sJniCallbacksField = env->GetFieldID(clazz, "mJniCallbacks",
378ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        "Lcom/android/bluetooth/btservice/JniCallbacks;");
379ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
380ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_stateChangeCallback = env->GetMethodID(jniCallbackClass, "stateChangeCallback", "(I)V");
381ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
382ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_adapterPropertyChangedCallback = env->GetMethodID(jniCallbackClass,
383ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                             "adapterPropertyChangedCallback",
384ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                             "([I[[B)V");
385ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_discoveryStateChangeCallback = env->GetMethodID(jniCallbackClass,
386ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                           "discoveryStateChangeCallback", "(I)V");
387ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
388ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_devicePropertyChangedCallback = env->GetMethodID(jniCallbackClass,
389ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                            "devicePropertyChangedCallback",
390ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                            "([B[I[[B)V");
391ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_deviceFoundCallback = env->GetMethodID(jniCallbackClass, "deviceFoundCallback", "([B)V");
392ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_pinRequestCallback = env->GetMethodID(jniCallbackClass, "pinRequestCallback",
393ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                 "([B[BI)V");
394ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_sspRequestCallback = env->GetMethodID(jniCallbackClass, "sspRequestCallback",
395ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                 "([B[BIII)V");
396ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
397ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    method_bondStateChangeCallback = env->GetMethodID(jniCallbackClass,
398ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                     "bondStateChangeCallback", "(I[BI)V");
399ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
400ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    char value[PROPERTY_VALUE_MAX];
401ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    property_get("bluetooth.mock_stack", value, "");
402ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
403ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
404ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
405ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    err = hw_get_module(id, (hw_module_t const**)&module);
406ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
407ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (err == 0) {
408ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        hw_device_t* abstraction;
409ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        err = module->methods->open(module, id, &abstraction);
410ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (err == 0) {
411ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
412ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            sBluetoothInterface = btStack->get_bluetooth_interface();
413ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        } else {
414ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh           LOGE("Error while opening Bluetooth library");
415ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
416ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    } else {
417ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        LOGE("No Bluetooth Library found");
418ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
419ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
420ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
421ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic bool initNative(JNIEnv* env, jobject obj) {
422ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
423ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
424ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    sJniCallbacksObj = env->NewGlobalRef(env->GetObjectField(obj, sJniCallbacksField));
425ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
426ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (sBluetoothInterface) {
427ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        int ret = sBluetoothInterface->init(&sBluetoothCallbacks);
428ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (ret != BT_STATUS_SUCCESS) {
429ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            LOGE("Error while setting the callbacks \n");
430ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            sBluetoothInterface = NULL;
431ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh            return JNI_FALSE;
432ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
433cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        if ( (sBluetoothSocketInterface = (btsock_interface_t *)
434cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie                  sBluetoothInterface->get_profile_interface(BT_PROFILE_SOCKETS_ID)) == NULL) {
435cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie                LOGE("Error getting socket interface");
436cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        }
437ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return JNI_TRUE;
438ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
439ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return JNI_FALSE;
440ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
441ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
442ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic bool cleanupNative(JNIEnv *env, jobject obj) {
443ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
444ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
445ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
446ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
447ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
448ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    sBluetoothInterface->cleanup();
449ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->DeleteGlobalRef(sJniCallbacksObj);
450ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return JNI_TRUE;
451ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
452ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
453ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean enableNative(JNIEnv* env, jobject obj) {
454ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
455ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
456ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
457ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
458ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
459ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->enable();
460ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
461ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
462ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
463ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
464ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean disableNative(JNIEnv* env, jobject obj) {
465ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
466ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
467ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
468ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
469ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
470ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->disable();
471ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
472ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
473ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
474ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
475ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
476ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
477ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
478ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
479ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
480ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
481ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->start_discovery();
482ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
483ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
484ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
485ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
486ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean cancelDiscoveryNative(JNIEnv* env, jobject obj) {
487ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
488ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
489ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
490ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
491ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
492ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->cancel_discovery();
493ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
494ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
495ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
496ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
497ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean createBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
498ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
499ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
500ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *addr;
501ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
502ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
503ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
504ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
505ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = env->GetByteArrayElements(address, NULL);
506ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
507ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
508ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return result;
509ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
510ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
511ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->create_bond((bt_bdaddr_t *)addr);
512ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(address, addr, NULL);
513ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
514ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
515ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
516ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
517ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
518ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean removeBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
519ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
520ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
521ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *addr;
522ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result;
523ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return JNI_FALSE;
524ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
525ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = env->GetByteArrayElements(address, NULL);
526ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
527ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
528ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return JNI_FALSE;
529ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
530ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
531ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->remove_bond((bt_bdaddr_t *)addr);
532ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(address, addr, NULL);
533ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
534ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
535ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
536ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
537ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
538ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean cancelBondNative(JNIEnv* env, jobject obj, jbyteArray address) {
539ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
540ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
541ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *addr;
542ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result;
543ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return JNI_FALSE;
544ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
545ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = env->GetByteArrayElements(address, NULL);
546ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
547ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
548ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return JNI_FALSE;
549ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
550ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
551ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->cancel_bond((bt_bdaddr_t *)addr);
552ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(address, addr, NULL);
553ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
554ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
555ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
556ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
557ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
558ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean pinReplyNative(JNIEnv *env, jobject obj, jbyteArray address, jboolean accept,
559ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                               jint len, jbyteArray pinArray) {
560ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
561ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
562ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *addr, *pinPtr = NULL;
563ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
564ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
565ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
566ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = env->GetByteArrayElements(address, NULL);
567ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
568ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
569ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return result;
570ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
571ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
572ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (accept) {
573ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        pinPtr = env->GetByteArrayElements(pinArray, NULL);
574ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        if (pinPtr == NULL) {
575ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh           jniThrowIOException(env, EINVAL);
576ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh           env->ReleaseByteArrayElements(address, addr, NULL);
577ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh           return result;
578ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        }
579ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
580ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
581ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->pin_reply((bt_bdaddr_t*)addr, accept, len,
582ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                              (bt_pin_code_t *) pinPtr);
583ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(address, addr, NULL);
584ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(pinArray, pinPtr, NULL);
585ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
586ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
587ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
588ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
589ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
590ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean sspReplyNative(JNIEnv *env, jobject obj, jbyteArray address,
591581bb31a8165ff0f9c7d638cfe4a81aaaafa2dedJaikumar Ganesh                               jint type, jboolean accept, jint passkey) {
592ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
593ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
594ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *addr;
595ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
596ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
597ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
598ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = env->GetByteArrayElements(address, NULL);
599ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
600ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
601ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return result;
602ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
603ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
604581bb31a8165ff0f9c7d638cfe4a81aaaafa2dedJaikumar Ganesh    int ret = sBluetoothInterface->ssp_reply((bt_bdaddr_t *)addr,
605581bb31a8165ff0f9c7d638cfe4a81aaaafa2dedJaikumar Ganesh         (bt_ssp_variant_t) type, accept, passkey);
606ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(address, addr, NULL);
607ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
608ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
609ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
610ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
611ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
612ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean setAdapterPropertyNative(JNIEnv *env, jobject obj, jint type, jbyteArray value) {
613ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
614ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
615ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *val;
616ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
617ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
618ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
619ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    val = env->GetByteArrayElements(value, NULL);
620ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    bt_property_t prop;
621ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    prop.type = (bt_property_type_t) type;
622ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    prop.len = env->GetArrayLength(value);
623ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    prop.val = val;
624ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
625ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->set_adapter_property(&prop);
626ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(value, val, NULL);
627ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
628ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
629ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
630ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
631ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
632ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean getAdapterPropertiesNative(JNIEnv *env, jobject obj) {
633ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
634ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
635ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
636ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
637ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
638ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->get_adapter_properties();
639ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
640ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
641ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
642ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
643ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
644ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean getAdapterPropertyNative(JNIEnv *env, jobject obj, jint type) {
645ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
646ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
647ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
648ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
649ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
650ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->get_adapter_property((bt_property_type_t) type);
651ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
652ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
653ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
654ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
655ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
656ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean getDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address, jint type) {
657ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
658ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
659ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *addr = NULL;
660ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
661ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
662ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
663ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = env->GetByteArrayElements(address, NULL);
664ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
665ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
666ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return result;
667ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
668ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
669ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->get_remote_device_property((bt_bdaddr_t *)addr,
670ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                                              (bt_property_type_t) type);
671ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(address, addr, NULL);
672ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
673ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
674ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
675ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
676ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
677ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic jboolean setDevicePropertyNative(JNIEnv *env, jobject obj, jbyteArray address,
678ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                        jint type, jbyteArray value) {
679ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    LOGV("%s:",__FUNCTION__);
680ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
681ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jbyte *val, *addr;
682ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    jboolean result = JNI_FALSE;
683ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (!sBluetoothInterface) return result;
684ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
685ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    val = env->GetByteArrayElements(value, NULL);
686ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (val == NULL) {
687ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
688ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return result;
689ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
690ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
691ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    addr = env->GetByteArrayElements(address, NULL);
692ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    if (addr == NULL) {
693ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        env->ReleaseByteArrayElements(value, val, NULL);
694ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        jniThrowIOException(env, EINVAL);
695ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh        return result;
696ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    }
697ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
698ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
699ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    bt_property_t prop;
700ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    prop.type = (bt_property_type_t) type;
701ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    prop.len = env->GetArrayLength(value);
702ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    prop.val = val;
703ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
704ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    int ret = sBluetoothInterface->set_remote_device_property((bt_bdaddr_t *)addr, &prop);
705ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(value, val, NULL);
706ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    env->ReleaseByteArrayElements(address, addr, NULL);
707ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
708ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
709ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
710ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return result;
711ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
712ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
713c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredcstatic jboolean getRemoteServicesNative(JNIEnv *env, jobject obj, jbyteArray address) {
714c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    LOGV("%s:",__FUNCTION__);
715c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc
716c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    jbyte *addr = NULL;
717c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    jboolean result = JNI_FALSE;
718c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    if (!sBluetoothInterface) return result;
719c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc
720c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    addr = env->GetByteArrayElements(address, NULL);
721c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    if (addr == NULL) {
722c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc        jniThrowIOException(env, EINVAL);
723c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc        return result;
724c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    }
725c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc
726c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    int ret = sBluetoothInterface->get_remote_services((bt_bdaddr_t *)addr);
727c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    env->ReleaseByteArrayElements(address, addr, NULL);
728c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    result = (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
729c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    return result;
730c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc}
731c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc
732cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xiestatic int connectSocketNative(JNIEnv *env, jobject object, jbyteArray address, jint type,
733cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie                                   jbyteArray uuidObj, jint channel, jint flag) {
734cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    jbyte *addr = NULL, *uuid = NULL;
735cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    int socket_fd;
736cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    bt_status_t status;
737cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
738cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (!sBluetoothSocketInterface) return NULL;
739cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
740cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    addr = env->GetByteArrayElements(address, NULL);
741cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (!addr) {
742cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        LOGE("failed to get Bluetooth device address");
743cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        goto Fail;
744cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
745cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
746cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    uuid = env->GetByteArrayElements(uuidObj, NULL);
747cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (!uuid) {
748cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        LOGE("failed to get uuid");
749cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        goto Fail;
750cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
751cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
752cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if ( (status = sBluetoothSocketInterface->connect((bt_bdaddr_t *) addr, (btsock_type_t) type,
753cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
754cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        LOGE("Socket connection failed: %d", status);
755cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        goto Fail;
756cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
757cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
758cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
759cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (socket_fd < 0) {
760cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        LOGE("Fail to creat file descriptor on socket fd");
761cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        goto Fail;
762cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
763cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    env->ReleaseByteArrayElements(address, addr, 0);
764cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
765cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    return socket_fd;
766cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
767cc80b2261351dc74ad1bed237b0423c12d340514Matthew XieFail:
768cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (addr) env->ReleaseByteArrayElements(address, addr, 0);
769cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
770cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
771cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    return -1;
772cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie}
773cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
774cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xiestatic int createSocketChannelNative(JNIEnv *env, jobject object, jint type,
775cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie                                         jstring name_str, jbyteArray uuidObj, jint channel, jint flag) {
776cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    const char *service_name;
777cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    jbyte *uuid = NULL;
778cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    int socket_fd;
779cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    bt_status_t status;
780cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
781cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (!sBluetoothSocketInterface) return NULL;
782cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
783cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    service_name = env->GetStringUTFChars(name_str, NULL);
784cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
785cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    uuid = env->GetByteArrayElements(uuidObj, NULL);
786cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (!uuid) {
787cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        LOGE("failed to get uuid");
788cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        goto Fail;
789cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
790cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
791cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if ( (status = sBluetoothSocketInterface->listen((btsock_type_t) type, service_name,
792cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie                       (const uint8_t*) uuid, channel, &socket_fd, flag)) != BT_STATUS_SUCCESS) {
793cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        LOGE("Socket listen failed: %d", status);
794cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        goto Fail;
795cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
796cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
797cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (socket_fd < 0) {
798cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        LOGE("Fail to creat file descriptor on socket fd");
799cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie        goto Fail;
800cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    }
801cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
802cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
803cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    return socket_fd;
804cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
805cc80b2261351dc74ad1bed237b0423c12d340514Matthew XieFail:
806cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (service_name) env->ReleaseStringUTFChars(name_str, service_name);
807cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    if (uuid) env->ReleaseByteArrayElements(uuidObj, uuid, 0);
808cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
809cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    return -1;
810cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie}
811cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie
812ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshstatic JNINativeMethod sMethods[] = {
813ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh     /* name, signature, funcPtr */
814ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"classInitNative", "()V", (void *) classInitNative},
815ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"initNative", "()Z", (void *) initNative},
816ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"cleanupNative", "()V", (void*) cleanupNative},
817ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"enableNative", "()Z",  (void*) enableNative},
818ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"disableNative", "()Z",  (void*) disableNative},
819ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"setAdapterPropertyNative", "(I[B)Z", (void*) setAdapterPropertyNative},
820ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"getAdapterPropertiesNative", "()Z", (void*) getAdapterPropertiesNative},
821ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"getAdapterPropertyNative", "(I)Z", (void*) getAdapterPropertyNative},
822ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"getDevicePropertyNative", "([BI)Z", (void*) getDevicePropertyNative},
823ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"setDevicePropertyNative", "([BI[B)Z", (void*) setDevicePropertyNative},
824ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"startDiscoveryNative", "()Z", (void*) startDiscoveryNative},
825ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"cancelDiscoveryNative", "()Z", (void*) cancelDiscoveryNative},
826ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"createBondNative", "([B)Z", (void*) createBondNative},
827ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"removeBondNative", "([B)Z", (void*) removeBondNative},
828ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"cancelBondNative", "([B)Z", (void*) cancelBondNative},
829ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    {"pinReplyNative", "([BZI[B)Z", (void*) pinReplyNative},
830581bb31a8165ff0f9c7d638cfe4a81aaaafa2dedJaikumar Ganesh    {"sspReplyNative", "([BIZI)Z", (void*) sspReplyNative},
831c55ac7d42cf2d78c7edc67abf6c66813245b2c93fredc    {"getRemoteServicesNative", "([B)Z", (void*) getRemoteServicesNative},
832cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    {"connectSocketNative", "([BI[BII)I", (void*) connectSocketNative},
833cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie    {"createSocketChannelNative", "(ILjava/lang/String;[BII)I",
834cc80b2261351dc74ad1bed237b0423c12d340514Matthew Xie     (void*) createSocketChannelNative},
835ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh};
836ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
837ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshint register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env)
838ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh{
839ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh    return jniRegisterNativeMethods(env, "com/android/bluetooth/btservice/AdapterService",
840ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh                                    sMethods, NELEM(sMethods));
841ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
842ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
843ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh} /* namespace android */
844ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
845ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
846ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh/*
847ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh * JNI Initialization
848ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh */
849ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganeshjint JNI_OnLoad(JavaVM *jvm, void *reserved)
850ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh{
851ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh   JNIEnv *e;
8526c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   int status;
853ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
854ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh   LOGV("Bluetooth Adapter Service : loading JNI\n");
855ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
856ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh   // Check JNI version
8576c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
8586c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie       LOGE("JNI version mismatch error");
859ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh      return JNI_ERR;
8606c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   }
861ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh
8626c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   if ((status = android::register_com_android_bluetooth_btservice_AdapterService(e)) < 0) {
8636c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie       LOGE("jni adapter service registration failure, status: %d", status);
864ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh      return JNI_ERR;
8656c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   }
8666c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
8676c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   if ((status = android::register_com_android_bluetooth_hfp(e)) < 0) {
8686c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie       LOGE("jni hfp registration failure, status: %d", status);
8696c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie      return JNI_ERR;
8706c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   }
8716c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
8726c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   if ((status = android::register_com_android_bluetooth_a2dp(e)) < 0) {
8736c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie       LOGE("jni a2dp registration failure: %d", status);
8746c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie      return JNI_ERR;
8756c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie   }
8766c91bc0a163cc7600c40d7fb979777fd911d1ef1Matthew Xie
87735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie   if ((status = android::register_com_android_bluetooth_hid(e)) < 0) {
87835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie       LOGE("jni hid registration failure: %d", status);
879676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie       return JNI_ERR;
880676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie   }
881676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie
882676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie   if ((status = android::register_com_android_bluetooth_hdp(e)) < 0) {
883676cb1bdd1c14c7af56562bab51f168e7f8f6d62Matthew Xie       LOGE("jni hdp registration failure: %d", status);
88435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie      return JNI_ERR;
88535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie   }
88635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie
887ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh   return JNI_VERSION_1_6;
888ff4f17bf64978d0738c66e1b6dd70be8664efc24Jaikumar Ganesh}
889