com_android_bluetooth_hid.cpp revision 89d2a16ff98d1b6254139e1589404161d5c419c7
135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie/* 235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie * Copyright (C) 2012 Google Inc. 335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie */ 435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#define LOG_TAG "BluetoothHidServiceJni" 635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#define LOG_NDEBUG 0 835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#define CHECK_CALLBACK_ENV \ 1035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (!checkCallbackThread()) { \ 1135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\ 1235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return; \ 1335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 1435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 1535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#include "com_android_bluetooth.h" 1635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#include "hardware/bt_hh.h" 1735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#include "utils/Log.h" 1835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#include "android_runtime/AndroidRuntime.h" 1935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 2035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie#include <string.h> 2135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 2235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xienamespace android { 2335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 2435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic jmethodID method_onConnectStateChanged; 2535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 2635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic const bthh_interface_t *sBluetoothHidInterface = NULL; 2735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic jobject mCallbacksObj = NULL; 2835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic JNIEnv *sCallbackEnv = NULL; 2935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 3035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic bool checkCallbackThread() { 3189d2a16ff98d1b6254139e1589404161d5c419c7Priti Aghera 3289d2a16ff98d1b6254139e1589404161d5c419c7Priti Aghera // Always fetch the latest callbackEnv from AdapterService. 3389d2a16ff98d1b6254139e1589404161d5c419c7Priti Aghera // Caching this could cause this sCallbackEnv to go out-of-sync 3489d2a16ff98d1b6254139e1589404161d5c419c7Priti Aghera // with the AdapterService's ENV if an ASSOCIATE/DISASSOCIATE event 3589d2a16ff98d1b6254139e1589404161d5c419c7Priti Aghera // is received 3689d2a16ff98d1b6254139e1589404161d5c419c7Priti Aghera 3789d2a16ff98d1b6254139e1589404161d5c419c7Priti Aghera sCallbackEnv = getCallbackEnv(); 3835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 3935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie JNIEnv* env = AndroidRuntime::getJNIEnv(); 4035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (sCallbackEnv != env || sCallbackEnv == NULL) return false; 4135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return true; 4235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 4335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 4435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic void connection_state_callback(bt_bdaddr_t *bd_addr, bthh_connection_state_t state) { 4535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie jbyteArray addr; 4635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 4735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie CHECK_CALLBACK_ENV 4835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie addr = sCallbackEnv->NewByteArray(sizeof(bt_bdaddr_t)); 4935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (!addr) { 5035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Fail to new jbyteArray bd addr for HID channel state"); 5135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 5235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return; 5335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 5435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie sCallbackEnv->SetByteArrayRegion(addr, 0, sizeof(bt_bdaddr_t), (jbyte *) bd_addr); 5535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 5635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectStateChanged, addr, (jint) state); 5735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__); 5835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie sCallbackEnv->DeleteLocalRef(addr); 5935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 6035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 6135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic bthh_callbacks_t sBluetoothHidCallbacks = { 6235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie sizeof(sBluetoothHidCallbacks), 6335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie connection_state_callback, 6435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie NULL, 6535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie NULL, 6635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie NULL, 6735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie NULL, 6835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie NULL 6935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie}; 7035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 7135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie// Define native functions 7235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 7335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic void classInitNative(JNIEnv* env, jclass clazz) { 7435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie int err; 7535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie const bt_interface_t* btInf; 7635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie bt_status_t status; 7735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 7835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie method_onConnectStateChanged = env->GetMethodID(clazz, "onConnectStateChanged", 7935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie "([BI)V"); 8035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 8135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if ( (btInf = getBluetoothInterface()) == NULL) { 8235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Bluetooth module is not loaded"); 8335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return; 8435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 8535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 8635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if ( (sBluetoothHidInterface = (bthh_interface_t *) 8735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie btInf->get_profile_interface(BT_PROFILE_HIDHOST_ID)) == NULL) { 8835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Failed to get Bluetooth Handsfree Interface"); 8935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return; 9035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 9135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 9235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie // TODO(BT) do this only once or 9335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie // Do we need to do this every time the BT reenables? 9435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if ( (status = sBluetoothHidInterface->init(&sBluetoothHidCallbacks)) != BT_STATUS_SUCCESS) { 9535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Failed to initialize Bluetooth HID, status: %d", status); 9635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie sBluetoothHidInterface = NULL; 9735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return; 9835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 9935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 10035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGI("%s: succeeds", __FUNCTION__); 10135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 10235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 10335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic void initializeNativeDataNative(JNIEnv *env, jobject object) { 10435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie // TODO(BT) clean it up when hid service is stopped 10535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie mCallbacksObj = env->NewGlobalRef(object); 10635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 10735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 10835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic jboolean connectHidNative(JNIEnv *env, jobject object, jbyteArray address) { 10935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie bt_status_t status; 11035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie jbyte *addr; 11135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie jboolean ret = JNI_TRUE; 11235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (!sBluetoothHidInterface) return JNI_FALSE; 11335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 11435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie addr = env->GetByteArrayElements(address, NULL); 11535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (!addr) { 11635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Bluetooth device address null"); 11735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return JNI_FALSE; 11835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 11935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 12035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if ((status = sBluetoothHidInterface->connect((bt_bdaddr_t *) addr)) != 12135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie BT_STATUS_SUCCESS) { 12235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Failed HID channel connection, status: %d", status); 12335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie ret = JNI_FALSE; 12435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 12535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie env->ReleaseByteArrayElements(address, addr, 0); 12635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 12735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return ret; 12835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 12935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 13035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic jboolean disconnectHidNative(JNIEnv *env, jobject object, jbyteArray address) { 13135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie bt_status_t status; 13235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie jbyte *addr; 13335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie jboolean ret = JNI_TRUE; 13435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (!sBluetoothHidInterface) return JNI_FALSE; 13535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 13635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie addr = env->GetByteArrayElements(address, NULL); 13735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if (!addr) { 13835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Bluetooth device address null"); 13935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return JNI_FALSE; 14035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 14135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 14235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie if ( (status = sBluetoothHidInterface->disconnect((bt_bdaddr_t *) addr)) != 14335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie BT_STATUS_SUCCESS) { 14435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie LOGE("Failed disconnect hid channel, status: %d", status); 14535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie ret = JNI_FALSE; 14635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie } 14735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie env->ReleaseByteArrayElements(address, addr, 0); 14835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 14935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return ret; 15035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 15135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 15235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xiestatic JNINativeMethod sMethods[] = { 15335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie {"classInitNative", "()V", (void *) classInitNative}, 15435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie {"initializeNativeDataNative", "()V", (void *) initializeNativeDataNative}, 15535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie {"connectHidNative", "([B)Z", (void *) connectHidNative}, 15635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie {"disconnectHidNative", "([B)Z", (void *) disconnectHidNative}, 15735207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie // TBD 15835207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie}; 15935207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 16035207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xieint register_com_android_bluetooth_hid(JNIEnv* env) 16135207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie{ 16235207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie return jniRegisterNativeMethods(env, "com/android/bluetooth/hid/HidService", 16335207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie sMethods, NELEM(sMethods)); 16435207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 16535207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie 16635207a5638f61caca5b9abb31e5c6850a9478a52Matthew Xie} 167