com_android_bluetooth_pan.cpp revision 3237754f492015699fc91508d76c2e123d6f3c42
1/* 2 * Copyright (C) 2012 Google Inc. 3 */ 4 5#define LOG_TAG "BluetoothPanServiceJni" 6 7#define LOG_NDEBUG 0 8 9#define CHECK_CALLBACK_ENV \ 10 if (!checkCallbackThread()) { \ 11 error("Callback: '%s' is not called on the correct thread", __FUNCTION__);\ 12 return; \ 13 } 14 15#include "com_android_bluetooth.h" 16#include "hardware/bt_pan.h" 17#include "utils/Log.h" 18#include "android_runtime/AndroidRuntime.h" 19 20#include <string.h> 21 22#include <cutils/log.h> 23#define info(fmt, ...) ALOGI ("%s(L%d): " fmt,__FUNCTION__, __LINE__, ## __VA_ARGS__) 24#define debug(fmt, ...) ALOGD ("%s(L%d): " fmt,__FUNCTION__, __LINE__, ## __VA_ARGS__) 25#define warn(fmt, ...) ALOGW ("## WARNING : %s(L%d): " fmt "##",__FUNCTION__, __LINE__, ## __VA_ARGS__) 26#define error(fmt, ...) ALOGE ("## ERROR : %s(L%d): " fmt "##",__FUNCTION__, __LINE__, ## __VA_ARGS__) 27#define asrt(s) if(!(s)) ALOGE ("## %s(L%d): ASSERT %s failed! ##",__FUNCTION__, __LINE__, #s) 28 29 30namespace android { 31 32static jmethodID method_onConnectStateChanged; 33static jmethodID method_onControlStateChanged; 34 35static const btpan_interface_t *sPanIf = NULL; 36static jobject mCallbacksObj = NULL; 37static JNIEnv *sCallbackEnv = NULL; 38 39static bool checkCallbackThread() { 40 sCallbackEnv = getCallbackEnv(); 41 42 JNIEnv* env = AndroidRuntime::getJNIEnv(); 43 if (sCallbackEnv != env || sCallbackEnv == NULL) return false; 44 return true; 45} 46 47static void control_state_callback(btpan_control_state_t state, bt_status_t error, int local_role, 48 const char* ifname) { 49 debug("state:%d, local_role:%d, ifname:%s", state, local_role, ifname); 50 CHECK_CALLBACK_ENV 51 jstring js_ifname = sCallbackEnv->NewStringUTF(ifname); 52 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onControlStateChanged, (jint)state, (jint)error, 53 (jint)local_role, js_ifname); 54 sCallbackEnv->DeleteLocalRef(js_ifname); 55} 56 57static void connection_state_callback(btpan_connection_state_t state, bt_status_t error, const bt_bdaddr_t *bd_addr, 58 int local_role, int remote_role) { 59 jbyteArray addr; 60 debug("state:%d, local_role:%d, remote_role:%d", state, local_role, remote_role); 61 CHECK_CALLBACK_ENV 62 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 63 if (!addr) { 64 error("Fail to new jbyteArray bd addr for PAN channel state"); 65 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 66 return; 67 } 68 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 69 70 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged, addr, (jint) state, 71 (jint)error, (jint)local_role, (jint)remote_role); 72 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 73 sCallbackEnv->DeleteLocalRef(addr); 74} 75 76static btpan_callbacks_t sBluetoothPanCallbacks = { 77 sizeof(sBluetoothPanCallbacks), 78 control_state_callback, 79 connection_state_callback 80}; 81 82// Define native functions 83 84static void classInitNative(JNIEnv* env, jclass clazz) { 85 int err; 86 bt_status_t status; 87 88 method_onConnectStateChanged = env->GetMethodID(clazz, "onConnectStateChanged", 89 "([BIIII)V"); 90 method_onControlStateChanged = env->GetMethodID(clazz, "onControlStateChanged", 91 "(IIILjava/lang/String;)V"); 92 93 info("succeeds"); 94} 95static const bt_interface_t* btIf; 96 97static void initializeNative(JNIEnv *env, jobject object) { 98 debug("pan"); 99 if(btIf) 100 return; 101 102 if ( (btIf = getBluetoothInterface()) == NULL) { 103 error("Bluetooth module is not loaded"); 104 return; 105 } 106 107 if (sPanIf !=NULL) { 108 ALOGW("Cleaning up Bluetooth PAN Interface before initializing..."); 109 sPanIf->cleanup(); 110 sPanIf = NULL; 111 } 112 113 if (mCallbacksObj != NULL) { 114 ALOGW("Cleaning up Bluetooth PAN callback object"); 115 env->DeleteGlobalRef(mCallbacksObj); 116 mCallbacksObj = NULL; 117 } 118 119 if ( (sPanIf = (btpan_interface_t *) 120 btIf->get_profile_interface(BT_PROFILE_PAN_ID)) == NULL) { 121 error("Failed to get Bluetooth PAN Interface"); 122 return; 123 } 124 125 bt_status_t status; 126 if ( (status = sPanIf->init(&sBluetoothPanCallbacks)) != BT_STATUS_SUCCESS) { 127 error("Failed to initialize Bluetooth PAN, status: %d", status); 128 sPanIf = NULL; 129 return; 130 } 131 132 mCallbacksObj = env->NewGlobalRef(object); 133} 134 135static void cleanupNative(JNIEnv *env, jobject object) { 136 bt_status_t status; 137 if (!btIf) return; 138 139 if (sPanIf !=NULL) { 140 ALOGW("Cleaning up Bluetooth PAN Interface..."); 141 sPanIf->cleanup(); 142 sPanIf = NULL; 143 } 144 145 if (mCallbacksObj != NULL) { 146 ALOGW("Cleaning up Bluetooth PAN callback object"); 147 env->DeleteGlobalRef(mCallbacksObj); 148 mCallbacksObj = NULL; 149 } 150 btIf = NULL; 151} 152 153static jboolean enablePanNative(JNIEnv *env, jobject object, jint local_role) { 154 bt_status_t status = BT_STATUS_FAIL; 155 debug("in"); 156 jbyte *addr; 157 if (sPanIf) 158 status = sPanIf->enable(local_role); 159 debug("out"); 160 return status == BT_STATUS_SUCCESS ? JNI_TRUE : JNI_FALSE; 161} 162static jint getPanLocalRoleNative(JNIEnv *env, jobject object) { 163 debug("in"); 164 int local_role = 0; 165 jbyte *addr; 166 if (sPanIf) 167 local_role = sPanIf->get_local_role(); 168 debug("out"); 169 return (jint)local_role; 170} 171 172 173 174static jboolean connectPanNative(JNIEnv *env, jobject object, jbyteArray address, 175 jint src_role, jint dest_role) { 176 debug("in"); 177 bt_status_t status; 178 jbyte *addr; 179 jboolean ret = JNI_TRUE; 180 if (!sPanIf) return JNI_FALSE; 181 182 addr = env->GetByteArrayElements(address, NULL); 183 if (!addr) { 184 error("Bluetooth device address null"); 185 return JNI_FALSE; 186 } 187 188 if ((status = sPanIf->connect((bt_bdaddr_t *) addr, src_role, dest_role)) != 189 BT_STATUS_SUCCESS) { 190 error("Failed PAN channel connection, status: %d", status); 191 ret = JNI_FALSE; 192 } 193 env->ReleaseByteArrayElements(address, addr, 0); 194 195 return ret; 196} 197 198static jboolean disconnectPanNative(JNIEnv *env, jobject object, jbyteArray address) { 199 bt_status_t status; 200 jbyte *addr; 201 jboolean ret = JNI_TRUE; 202 if (!sPanIf) return JNI_FALSE; 203 204 addr = env->GetByteArrayElements(address, NULL); 205 if (!addr) { 206 error("Bluetooth device address null"); 207 return JNI_FALSE; 208 } 209 210 if ( (status = sPanIf->disconnect((bt_bdaddr_t *) addr)) != 211 BT_STATUS_SUCCESS) { 212 error("Failed disconnect pan channel, status: %d", status); 213 ret = JNI_FALSE; 214 } 215 env->ReleaseByteArrayElements(address, addr, 0); 216 217 return ret; 218} 219 220static JNINativeMethod sMethods[] = { 221 {"classInitNative", "()V", (void *) classInitNative}, 222 {"initializeNative", "()V", (void *) initializeNative}, 223 {"cleanupNative", "()V", (void *) cleanupNative}, 224 {"connectPanNative", "([BII)Z", (void *) connectPanNative}, 225 {"enablePanNative", "(I)Z", (void *) enablePanNative}, 226 {"getPanLocalRoleNative", "()I", (void *) getPanLocalRoleNative}, 227 {"disconnectPanNative", "([B)Z", (void *) disconnectPanNative}, 228 // TBD cleanup 229}; 230 231int register_com_android_bluetooth_pan(JNIEnv* env) 232{ 233 return jniRegisterNativeMethods(env, "com/android/bluetooth/pan/PanService", 234 sMethods, NELEM(sMethods)); 235} 236 237} 238