com_android_bluetooth_pan.cpp revision e469f16e5a7d99471d7db1b216d422e8d12cc4cf
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} 55 56static void connection_state_callback(btpan_connection_state_t state, bt_status_t error, const bt_bdaddr_t *bd_addr, 57 int local_role, int remote_role) { 58 jbyteArray addr; 59 debug("state:%d, local_role:%d, remote_role:%d", state, local_role, remote_role); 60 CHECK_CALLBACK_ENV 61 addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 62 if (!addr) { 63 error("Fail to new jbyteArray bd addr for PAN channel state"); 64 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 65 return; 66 } 67 sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 68 69 sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged, addr, (jint) state, 70 (jint)error, (jint)local_role, (jint)remote_role); 71 checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 72 sCallbackEnv->DeleteLocalRef(addr); 73} 74 75static btpan_callbacks_t sBluetoothPanCallbacks = { 76 sizeof(sBluetoothPanCallbacks), 77 control_state_callback, 78 connection_state_callback 79}; 80 81// Define native functions 82 83static void classInitNative(JNIEnv* env, jclass clazz) { 84 int err; 85 bt_status_t status; 86 87 method_onConnectStateChanged = env->GetMethodID(clazz, "onConnectStateChanged", 88 "([BIIII)V"); 89 method_onControlStateChanged = env->GetMethodID(clazz, "onControlStateChanged", 90 "(IIILjava/lang/String;)V"); 91 92 info("succeeds"); 93} 94static const bt_interface_t* btIf; 95 96static void initializeNative(JNIEnv *env, jobject object) { 97 debug("pan"); 98 if(btIf) 99 return; 100 101 if ( (btIf = getBluetoothInterface()) == NULL) { 102 error("Bluetooth module is not loaded"); 103 return; 104 } 105 106 if (sPanIf !=NULL) { 107 ALOGW("Cleaning up Bluetooth PAN Interface before initializing..."); 108 sPanIf->cleanup(); 109 sPanIf = NULL; 110 } 111 112 if (mCallbacksObj != NULL) { 113 ALOGW("Cleaning up Bluetooth PAN callback object"); 114 env->DeleteGlobalRef(mCallbacksObj); 115 mCallbacksObj = NULL; 116 } 117 118 if ( (sPanIf = (btpan_interface_t *) 119 btIf->get_profile_interface(BT_PROFILE_PAN_ID)) == NULL) { 120 error("Failed to get Bluetooth PAN Interface"); 121 return; 122 } 123 124 bt_status_t status; 125 if ( (status = sPanIf->init(&sBluetoothPanCallbacks)) != BT_STATUS_SUCCESS) { 126 error("Failed to initialize Bluetooth PAN, status: %d", status); 127 sPanIf = NULL; 128 return; 129 } 130 131 mCallbacksObj = env->NewGlobalRef(object); 132} 133 134static void cleanupNative(JNIEnv *env, jobject object) { 135 bt_status_t status; 136 if (!btIf) return; 137 138 if (sPanIf !=NULL) { 139 ALOGW("Cleaning up Bluetooth PAN Interface..."); 140 sPanIf->cleanup(); 141 sPanIf = NULL; 142 } 143 144 if (mCallbacksObj != NULL) { 145 ALOGW("Cleaning up Bluetooth PAN callback object"); 146 env->DeleteGlobalRef(mCallbacksObj); 147 mCallbacksObj = NULL; 148 } 149 btIf = NULL; 150} 151 152static jboolean enablePanNative(JNIEnv *env, jobject object, jint local_role) { 153 bt_status_t status = BT_STATUS_FAIL; 154 debug("in"); 155 jbyte *addr; 156 if (sPanIf) 157 status = sPanIf->enable(local_role); 158 debug("out"); 159 return status == BT_STATUS_SUCCESS ? JNI_TRUE : JNI_FALSE; 160} 161static jint getPanLocalRoleNative(JNIEnv *env, jobject object) { 162 debug("in"); 163 int local_role = 0; 164 jbyte *addr; 165 if (sPanIf) 166 local_role = sPanIf->get_local_role(); 167 debug("out"); 168 return (jint)local_role; 169} 170 171 172 173static jboolean connectPanNative(JNIEnv *env, jobject object, jbyteArray address, 174 jint src_role, jint dest_role) { 175 debug("in"); 176 bt_status_t status; 177 jbyte *addr; 178 jboolean ret = JNI_TRUE; 179 if (!sPanIf) return JNI_FALSE; 180 181 addr = env->GetByteArrayElements(address, NULL); 182 if (!addr) { 183 error("Bluetooth device address null"); 184 return JNI_FALSE; 185 } 186 187 if ((status = sPanIf->connect((bt_bdaddr_t *) addr, src_role, dest_role)) != 188 BT_STATUS_SUCCESS) { 189 error("Failed PAN channel connection, status: %d", status); 190 ret = JNI_FALSE; 191 } 192 env->ReleaseByteArrayElements(address, addr, 0); 193 194 return ret; 195} 196 197static jboolean disconnectPanNative(JNIEnv *env, jobject object, jbyteArray address) { 198 bt_status_t status; 199 jbyte *addr; 200 jboolean ret = JNI_TRUE; 201 if (!sPanIf) return JNI_FALSE; 202 203 addr = env->GetByteArrayElements(address, NULL); 204 if (!addr) { 205 error("Bluetooth device address null"); 206 return JNI_FALSE; 207 } 208 209 if ( (status = sPanIf->disconnect((bt_bdaddr_t *) addr)) != 210 BT_STATUS_SUCCESS) { 211 error("Failed disconnect pan channel, status: %d", status); 212 ret = JNI_FALSE; 213 } 214 env->ReleaseByteArrayElements(address, addr, 0); 215 216 return ret; 217} 218 219static JNINativeMethod sMethods[] = { 220 {"classInitNative", "()V", (void *) classInitNative}, 221 {"initializeNative", "()V", (void *) initializeNative}, 222 {"cleanupNative", "()V", (void *) cleanupNative}, 223 {"connectPanNative", "([BII)Z", (void *) connectPanNative}, 224 {"enablePanNative", "(I)Z", (void *) enablePanNative}, 225 {"getPanLocalRoleNative", "()I", (void *) getPanLocalRoleNative}, 226 {"disconnectPanNative", "([B)Z", (void *) disconnectPanNative}, 227 // TBD cleanup 228}; 229 230int register_com_android_bluetooth_pan(JNIEnv* env) 231{ 232 return jniRegisterNativeMethods(env, "com/android/bluetooth/pan/PanService", 233 sMethods, NELEM(sMethods)); 234} 235 236} 237