X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fconnectivity%2Fsrc%2Fbt_le_adapter%2Fandroid%2Fcaleclient.c;h=2ac416cf08180b4d603495049e861ac9ed0cd18c;hb=c315c87e07c4080ecd0ef488e7a1047bc3c509b2;hp=3b434ea196e505042e5fe6ffe510dcdbb7dba885;hpb=e5337af1b857936fce8295ffe468e1accdfc8350;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c b/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c index 3b434ea..2ac416c 100644 --- a/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c +++ b/resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.c @@ -23,6 +23,7 @@ #include #include +#include "calestate.h" #include "caleclient.h" #include "caleserver.h" #include "caleutils.h" @@ -33,11 +34,12 @@ #include "oic_malloc.h" #include "oic_string.h" #include "cathreadpool.h" /* for thread pool */ -#include "camutex.h" +#include "octhread.h" #include "uarraylist.h" #include "org_iotivity_ca_CaLeClientInterface.h" -#define TAG PCF("OIC_CA_LE_CLIENT") +//#define TAG PCF("OIC_CA_LE_CLIENT") +#define TAG BLE_CLIENT_TAG #define MICROSECS_PER_SEC 1000000 #define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC @@ -54,6 +56,11 @@ #define GATT_REQUEST_NOT_SUPPORTED 6 #define GATT_WRITE_NOT_PERMITTED 3 +// samsung +#define BLE_SCAN_API_LEVEL (100) //(21) +#define BLE_MIN_API_LEVEL (18) +#define HIDDEN_API + static ca_thread_pool_t g_threadPoolHandle = NULL; JavaVM *g_jvm; @@ -75,39 +82,45 @@ static jbyteArray g_sendBuffer = NULL; static uint32_t g_targetCnt = 0; static uint32_t g_currentSentCnt = 0; static bool g_isFinishedSendData = false; -static ca_mutex g_SendFinishMutex = NULL; -static ca_mutex g_threadMutex = NULL; -static ca_cond g_threadCond = NULL; -static ca_cond g_deviceDescCond = NULL; - -static ca_mutex g_threadSendMutex = NULL; -static ca_mutex g_threadWriteCharacteristicMutex = NULL; -static ca_cond g_threadWriteCharacteristicCond = NULL; +static oc_mutex g_SendFinishMutex = NULL; +static oc_mutex g_threadMutex = NULL; +static oc_cond g_threadCond = NULL; +static oc_cond g_deviceDescCond = NULL; + +static oc_mutex g_threadSendMutex = NULL; +static oc_mutex g_threadWriteCharacteristicMutex = NULL; +static oc_cond g_threadWriteCharacteristicCond = NULL; static bool g_isSignalSetFlag = false; -static ca_mutex g_bleReqRespClientCbMutex = NULL; -static ca_mutex g_bleServerBDAddressMutex = NULL; +static oc_mutex g_bleReqRespClientCbMutex = NULL; +static oc_mutex g_bleServerBDAddressMutex = NULL; -static ca_mutex g_deviceListMutex = NULL; -static ca_mutex g_gattObjectMutex = NULL; -static ca_mutex g_deviceStateListMutex = NULL; +static oc_mutex g_deviceListMutex = NULL; +static oc_mutex g_gattObjectMutex = NULL; +static oc_mutex g_deviceStateListMutex = NULL; -static ca_mutex g_deviceScanRetryDelayMutex = NULL; -static ca_cond g_deviceScanRetryDelayCond = NULL; +static oc_mutex g_deviceScanRetryDelayMutex = NULL; +static oc_cond g_deviceScanRetryDelayCond = NULL; -static ca_mutex g_threadScanIntervalMutex = NULL; -static ca_cond g_threadScanIntervalCond = NULL; +static oc_mutex g_threadScanIntervalMutex = NULL; +static oc_cond g_threadScanIntervalCond = NULL; -static ca_mutex g_threadSendStateMutex = NULL; +static oc_mutex g_threadSendStateMutex = NULL; +static oc_mutex g_setValueMutex = NULL; static int32_t g_scanIntervalTime = WAIT_TIME_SCAN_INTERVAL_DEFAULT; static int32_t g_scanIntervalTimePrev = WAIT_TIME_SCAN_INTERVAL_DEFAULT; static int32_t g_intervalCount = 0; static bool g_isWorkingScanThread = false; -static CALEScanState_t g_scanningStep = BLE_SCAN_DISABLE; +static CALEScanState_t g_curScanningStep = BLE_SCAN_NONE; +static CALEScanState_t g_nextScanningStep = BLE_SCAN_ENABLE; static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL; +static int32_t g_jniIntSdk = -1; +static bool g_setHighQoS = true; +static bool g_setFullScanFlag = true; +jclass g_LEInterface = NULL; /** * check if retry logic for connection routine has to be stopped or not. * in case of error value including this method, connection routine has to be stopped. @@ -130,14 +143,33 @@ static bool CALECheckConnectionStateValue(jint state) case GATT_REQUEST_NOT_SUPPORTED: case GATT_WRITE_NOT_PERMITTED: return true; + default: + return false; } - return false; } -void CALEClientSetScanInterval(int32_t intervalTime, int32_t workingCount) +/** + * delete global reference for g_sendBuffer + * @param[in] env JNI interface pointer. + */ +static void CALEDeleteSendBuffer(JNIEnv *env) +{ + OIC_LOG(INFO, TAG, "CALEDeleteSendBuffer"); + oc_mutex_lock(g_setValueMutex); + if (g_sendBuffer) + { + OIC_LOG(INFO, TAG, "delete send buffer"); + (*env)->DeleteGlobalRef(env, g_sendBuffer); + g_sendBuffer = NULL; + } + oc_mutex_unlock(g_setValueMutex); +} + +void CALEClientSetScanInterval(int32_t intervalTime, int32_t workingCount, + CALEScanState_t nextScanningStep) { - OIC_LOG_V(DEBUG, TAG, "CALEClientSetScanInterval : %d -> %d", - g_scanIntervalTime, intervalTime); + OIC_LOG_V(DEBUG, TAG, "CALEClientSetScanInterval : %d -> %d, next scan state will be %d", + g_scanIntervalTime, intervalTime, nextScanningStep); // previous time should be stored. if (0 < workingCount) @@ -146,13 +178,24 @@ void CALEClientSetScanInterval(int32_t intervalTime, int32_t workingCount) } g_scanIntervalTime = intervalTime; g_intervalCount = workingCount; + g_nextScanningStep = nextScanningStep; } -void CALERestartScanWithInterval(int32_t intervalTime, int32_t workingCount) +void CALERestartScanWithInterval(int32_t intervalTime, int32_t workingCount, + CALEScanState_t nextScanningStep) { - // restart scan with interval - CALEClientSetScanInterval(intervalTime, workingCount); - ca_cond_signal(g_threadScanIntervalCond); + if (intervalTime == g_scanIntervalTime + && workingCount == g_intervalCount + && nextScanningStep == g_nextScanningStep) + { + OIC_LOG(DEBUG, TAG, "setting duplicate interval time"); + return; + } + + oc_mutex_lock(g_threadScanIntervalMutex); + CALEClientSetScanInterval(intervalTime, workingCount, nextScanningStep); + oc_cond_signal(g_threadScanIntervalCond); + oc_mutex_unlock(g_threadScanIntervalMutex); } static void CALEScanThread(void* object) @@ -164,7 +207,6 @@ static void CALEScanThread(void* object) jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -175,11 +217,11 @@ static void CALEScanThread(void* object) isAttached = true; } - ca_mutex_lock(g_threadScanIntervalMutex); + oc_mutex_lock(g_threadScanIntervalMutex); while(g_isWorkingScanThread) { OIC_LOG(DEBUG, TAG, "scan waiting time out"); - if (BLE_SCAN_ENABLE == g_scanningStep) + if (BLE_SCAN_ENABLE == g_curScanningStep) { //stop scan CAResult_t ret = CALEClientStopScan(); @@ -188,7 +230,7 @@ static void CALEScanThread(void* object) OIC_LOG(INFO, TAG, "CALEClientStopScan has failed"); } } - else + else if (BLE_SCAN_DISABLE == g_curScanningStep) { //start scan CAResult_t ret = CALEClientStartScan(); @@ -197,39 +239,52 @@ static void CALEScanThread(void* object) OIC_LOG(INFO, TAG, "CALEClientStartScan has failed"); } } + else + { + OIC_LOG(DEBUG, TAG, "scan thread is started"); + // standby scanning + CALEClientSetScanInterval(0, 0, BLE_SCAN_DISABLE); + } OIC_LOG_V(DEBUG, TAG, "wait for Scan Interval Time during %d sec", g_scanIntervalTime); - if (CA_WAIT_SUCCESS == ca_cond_wait_for(g_threadScanIntervalCond, + if (OC_WAIT_SUCCESS == oc_cond_wait_for(g_threadScanIntervalCond, g_threadScanIntervalMutex, g_scanIntervalTime * MICROSECS_PER_SEC)) { // called signal scan thread will be terminated OIC_LOG(DEBUG, TAG, "signal scanInterval waiting"); - g_scanningStep = BLE_SCAN_DISABLE; + if (BLE_SCAN_DISABLE == g_nextScanningStep) + { + g_curScanningStep = BLE_SCAN_ENABLE; + } + else + { + g_curScanningStep = BLE_SCAN_DISABLE; + } } else { - if (BLE_SCAN_ENABLE == g_scanningStep) + if (BLE_SCAN_ENABLE == g_curScanningStep) { if (g_intervalCount > 0) { if (g_intervalCount == 1) { OIC_LOG(DEBUG, TAG, "reset default time"); - CALEClientSetScanInterval(g_scanIntervalTimePrev, 0); + CALEClientSetScanInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE); } g_intervalCount--; OIC_LOG_V(DEBUG, TAG, "interval count : %d", g_intervalCount); } - g_scanningStep = BLE_SCAN_DISABLE; + g_curScanningStep = BLE_SCAN_DISABLE; } else { - g_scanningStep = BLE_SCAN_ENABLE; + g_curScanningStep = BLE_SCAN_ENABLE; } } } - ca_mutex_unlock(g_threadScanIntervalMutex); + oc_mutex_unlock(g_threadScanIntervalMutex); if (isAttached) { @@ -239,8 +294,6 @@ static void CALEScanThread(void* object) CAResult_t CALEClientStartScanWithInterval() { - OIC_LOG(DEBUG, TAG, "IN - CALEClientStartScanWithInterval"); - if (g_isWorkingScanThread) { OIC_LOG(DEBUG, TAG, "scan interval logic already running"); @@ -248,27 +301,26 @@ CAResult_t CALEClientStartScanWithInterval() } // initialize scan flags - g_scanningStep = BLE_SCAN_DISABLE; + g_curScanningStep = BLE_SCAN_NONE; g_isWorkingScanThread = true; g_intervalCount = 0; g_scanIntervalTime = g_scanIntervalTimePrev; + g_nextScanningStep = BLE_SCAN_ENABLE; - if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, - CALEScanThread, NULL)) + if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CALEScanThread, NULL, NULL)) { OIC_LOG(ERROR, TAG, "Failed to create read thread!"); g_isWorkingScanThread = false; return CA_STATUS_FAILED; } - OIC_LOG(DEBUG, TAG, "OUT - CALEClientStartScanWithInterval"); return CA_STATUS_OK; } void CALEClientStopScanWithInterval() { g_isWorkingScanThread = false; - ca_cond_signal(g_threadScanIntervalCond); + oc_cond_signal(g_threadScanIntervalCond); } //getting jvm @@ -305,7 +357,6 @@ CAResult_t CALECreateJniInterfaceObject() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -331,7 +382,7 @@ CAResult_t CALECreateJniInterfaceObject() if (!jApplicationContext) { OIC_LOG(ERROR, TAG, "Could not get application context"); - return CA_STATUS_FAILED; + goto error_exit; } jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface"); @@ -340,6 +391,7 @@ CAResult_t CALECreateJniInterfaceObject() OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class"); goto error_exit; } + g_LEInterface = (jclass)((*env)->NewGlobalRef(env, jni_LEInterface)); jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "", "(Landroid/content/Context;)V"); @@ -360,7 +412,7 @@ CAResult_t CALECreateJniInterfaceObject() return CA_STATUS_OK; error_exit: - + CACheckJNIException(env); if (isAttached) { (*g_jvm)->DetachCurrentThread(g_jvm); @@ -386,7 +438,6 @@ CAResult_t CALEClientInitialize() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -397,8 +448,8 @@ CAResult_t CALEClientInitialize() isAttached = true; } - CAResult_t ret = CALECheckPlatformVersion(env, 18); - if (CA_STATUS_OK != ret) + g_jniIntSdk = CALEGetBuildVersion(env); + if (g_jniIntSdk < BLE_MIN_API_LEVEL) { OIC_LOG(ERROR, TAG, "it is not supported"); @@ -406,11 +457,10 @@ CAResult_t CALEClientInitialize() { (*g_jvm)->DetachCurrentThread(g_jvm); } - - return ret; + return CA_STATUS_FAILED; } - ret = CALEClientInitGattMutexVaraibles(); + CAResult_t ret = CALEClientInitGattMutexVaraibles(); if (CA_STATUS_OK != ret) { OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!"); @@ -424,13 +474,13 @@ CAResult_t CALEClientInitialize() return ret; } - g_deviceDescCond = ca_cond_new(); + g_deviceDescCond = oc_cond_new(); // init mutex for send logic - g_threadCond = ca_cond_new(); - g_threadWriteCharacteristicCond = ca_cond_new(); - g_deviceScanRetryDelayCond = ca_cond_new(); - g_threadScanIntervalCond = ca_cond_new(); + g_threadCond = oc_cond_new(); + g_threadWriteCharacteristicCond = oc_cond_new(); + g_deviceScanRetryDelayCond = oc_cond_new(); + g_threadScanIntervalCond = oc_cond_new(); CALEClientCreateDeviceList(); CALEClientJNISetContext(); @@ -485,7 +535,6 @@ void CALEClientTerminate() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -496,6 +545,13 @@ void CALEClientTerminate() isAttached = true; } + // stop scan + CAResult_t ret = CALEClientStopScan(); + if (CA_STATUS_OK != ret) + { + OIC_LOG(INFO, TAG, "CALEClientStopScan has failed"); + } + if (g_leScanCallback) { (*env)->DeleteGlobalRef(env, g_leScanCallback); @@ -508,24 +564,32 @@ void CALEClientTerminate() g_leGattCallback = NULL; } - if (g_sendBuffer) + if (g_LEInterface) { - (*env)->DeleteGlobalRef(env, g_sendBuffer); - g_sendBuffer = NULL; + (*env)->DeleteGlobalRef(env, g_LEInterface); + g_LEInterface = NULL; } + CALEDeleteSendBuffer(env); + if (g_uuidList) { (*env)->DeleteGlobalRef(env, g_uuidList); g_uuidList = NULL; } - CAResult_t ret = CALEClientRemoveAllDeviceState(); + ret = CALERemoveAllDeviceState(g_deviceStateList, + g_deviceStateListMutex); if (CA_STATUS_OK != ret) { - OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed"); + OIC_LOG(ERROR, TAG, "CALERemoveAllDeviceState has failed"); } + oc_mutex_lock(g_deviceStateListMutex); + OICFree(g_deviceStateList); + g_deviceStateList = NULL; + oc_mutex_unlock(g_deviceStateListMutex); + ret = CALEClientRemoveAllScanDevices(env); if (CA_STATUS_OK != ret) { @@ -543,11 +607,11 @@ void CALEClientTerminate() CALEClientTerminateGattMutexVariables(); CALEClientDestroyJniInterface(); - ca_cond_free(g_deviceDescCond); - ca_cond_free(g_threadCond); - ca_cond_free(g_threadWriteCharacteristicCond); - ca_cond_free(g_deviceScanRetryDelayCond); - ca_cond_free(g_threadScanIntervalCond); + oc_cond_free(g_deviceDescCond); + oc_cond_free(g_threadCond); + oc_cond_free(g_threadWriteCharacteristicCond); + oc_cond_free(g_deviceScanRetryDelayCond); + oc_cond_free(g_threadScanIntervalCond); g_deviceDescCond = NULL; g_threadCond = NULL; @@ -566,6 +630,74 @@ void CALEClientTerminate() } } +jobject CALEClientHiddenConnectGatt(jobject btDevice, const char* address, jboolean autoconnect) +{ + OIC_LOG(INFO, TAG, "IN - CALEClientHiddenConnectGatt"); + + if (!g_jvm) + { + OIC_LOG(ERROR, TAG, "g_jvm is null"); + return NULL; + } + + bool isAttached = false; + JNIEnv* env = NULL; + jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); + if (JNI_OK != res) + { + res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); + + if (JNI_OK != res) + { + OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed"); + return NULL; + } + isAttached = true; + } + + jstring jni_address = (*env)->NewStringUTF(env, address); + jmethodID jni_connectGattHiddenMethod = (*env)->GetStaticMethodID(env, g_LEInterface, + "connectGattforHidden", + "(Landroid/bluetooth/BluetoothDevice;" + "Ljava/lang/String;Z)" + "Landroid/bluetooth/BluetoothGatt;"); + if (!jni_connectGattHiddenMethod) + { + OIC_LOG(ERROR, TAG, "Could not get jni_connectGatt Hidden Method"); + goto error_exit; + } + + jobject gatt = (*env)->CallStaticObjectMethod(env, g_LEInterface, + jni_connectGattHiddenMethod, + btDevice, jni_address, autoconnect); + + if (CACheckJNIException(env)) + { + OIC_LOG(ERROR, TAG, "connectGattforHidden has failed"); + goto detach_thread; + } + + OIC_LOG(INFO, TAG, "OUT - CALEClientHiddenConnectGatt"); + + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + + return gatt; + +error_exit: + CACheckJNIException(env); + +detach_thread: + if (isAttached) + { + (*g_jvm)->DetachCurrentThread(g_jvm); + } + + return NULL; +} + CAResult_t CALEClientDestroyJniInterface() { OIC_LOG(DEBUG, TAG, "CALEClientDestroyJniInterface"); @@ -581,7 +713,6 @@ CAResult_t CALEClientDestroyJniInterface() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -610,12 +741,10 @@ CAResult_t CALEClientDestroyJniInterface() (*env)->CallStaticVoidMethod(env, jni_LeInterface, jni_InterfaceDestroyMethod); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "destroyLeInterface has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - goto error_exit; + goto detach_thread; } OIC_LOG(DEBUG, TAG, "Destroy instance for CaLeClientInterface"); @@ -628,7 +757,9 @@ CAResult_t CALEClientDestroyJniInterface() return CA_STATUS_OK; error_exit: + CACheckJNIException(env); +detach_thread: if (isAttached) { (*g_jvm)->DetachCurrentThread(g_jvm); @@ -653,11 +784,17 @@ void CALEClientSendFinish(JNIEnv *env, jobject gatt) CALEClientUpdateSendCnt(env); } +CAResult_t CALEClientSendNegotiationMessage(const char* address) +{ + VERIFY_NON_NULL(address, TAG, "address is null"); + + return CALEClientSendUnicastMessageImpl(address, NULL, 0); +} + CAResult_t CALEClientSendUnicastMessage(const char* address, const uint8_t* data, const uint32_t dataLen) { - OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data); VERIFY_NON_NULL(address, TAG, "address is null"); VERIFY_NON_NULL(data, TAG, "data is null"); @@ -681,7 +818,6 @@ CAResult_t CALEClientSendMulticastMessage(const uint8_t* data, jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -708,6 +844,9 @@ CAResult_t CALEClientSendMulticastMessage(const uint8_t* data, CAResult_t CALEClientStartUnicastServer(const char* address) { +#ifndef TB_LOG + (void)address; +#endif OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address); return CA_NOT_SUPPORTED; @@ -746,6 +885,7 @@ CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address) if (!g_deviceList) { + OIC_LOG(ERROR, TAG, "g_deviceList is not available"); return CA_STATUS_FAILED; } @@ -761,19 +901,20 @@ CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address) 2 * MICROSECS_PER_SEC; // Microseconds // set scan interval and start scan - CALERestartScanWithInterval(WAIT_TIME_SCANNED_CHECKING, 1); + CALERestartScanWithInterval(WAIT_TIME_SCANNED_CHECKING, 1, BLE_SCAN_ENABLE); bool devicesDiscovered = false; for (size_t i = 0; i < RETRIES; ++i) { OIC_LOG(DEBUG, TAG, "waiting for target device"); - if (ca_cond_wait_for(g_deviceDescCond, + if (oc_cond_wait_for(g_deviceDescCond, g_threadSendMutex, - TIMEOUT) == CA_WAIT_SUCCESS) + TIMEOUT) == OC_WAIT_SUCCESS) { - ca_mutex_lock(g_deviceListMutex); + OIC_LOG(DEBUG, TAG, "time out"); + oc_mutex_lock(g_deviceListMutex); size_t scannedDeviceLen = u_arraylist_length(g_deviceList); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); if (0 < scannedDeviceLen) { @@ -789,16 +930,16 @@ CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address) { OIC_LOG(INFO, TAG, "waiting.."); - ca_mutex_lock(g_deviceScanRetryDelayMutex); - if (ca_cond_wait_for(g_deviceScanRetryDelayCond, + oc_mutex_lock(g_deviceScanRetryDelayMutex); + if (oc_cond_wait_for(g_deviceScanRetryDelayCond, g_deviceScanRetryDelayMutex, - MICROSECS_PER_SEC) == CA_WAIT_SUCCESS) + MICROSECS_PER_SEC) == OC_WAIT_SUCCESS) { OIC_LOG(INFO, TAG, "finish to waiting for target device"); - ca_mutex_unlock(g_deviceScanRetryDelayMutex); + oc_mutex_unlock(g_deviceScanRetryDelayMutex); break; } - ca_mutex_unlock(g_deviceScanRetryDelayMutex); + oc_mutex_unlock(g_deviceScanRetryDelayMutex); // time out // checking whether a target device is found while waiting for time-out. @@ -814,7 +955,7 @@ CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address) } // reset scan interval time after checking scanned devices - CALERestartScanWithInterval(g_scanIntervalTimePrev, 0); + CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE); // time out for scanning devices if (!devicesDiscovered) @@ -822,6 +963,10 @@ CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address) return CA_STATUS_FAILED; } } + else + { + OIC_LOG(DEBUG, TAG, "there is a target device in the scanned devices"); + } return CA_STATUS_OK; } @@ -830,10 +975,9 @@ CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address) CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data, const uint32_t dataLen) { - OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address, + OIC_LOG_V(INFO, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address, data); VERIFY_NON_NULL(address, TAG, "address is null"); - VERIFY_NON_NULL(data, TAG, "data is null"); if (!g_jvm) { @@ -846,7 +990,6 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) { @@ -856,7 +999,7 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* isAttached = true; } - ca_mutex_lock(g_threadSendMutex); + oc_mutex_lock(g_threadSendMutex); CALEClientSetSendFinishFlag(false); @@ -890,27 +1033,26 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); + CACheckJNIException(env); goto error_exit; } - OIC_LOG_V(DEBUG, TAG, "remote device address is %s", setAddress); - - if (!strcmp(setAddress, address)) + if (!strcasecmp(setAddress, address)) { (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->DeleteLocalRef(env, jni_setAddress); - // stop scan while sending - CALEClientStopScanWithInterval(); + CALEDeleteSendBuffer(env); - if (g_sendBuffer) + if (data && dataLen > 0) { - (*env)->DeleteGlobalRef(env, g_sendBuffer); - g_sendBuffer = NULL; + jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen); + CACheckJNIException(env); + (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data); + CACheckJNIException(env); + g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr); + CACheckJNIException(env); } - jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen); - (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data); - g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr); // Target device to send message is just one. g_targetCnt = 1; @@ -934,47 +1076,52 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* // wait for finish to send data through "CALeGattServicesDiscoveredCallback" // if there is no connection state. - ca_mutex_lock(g_threadMutex); + oc_mutex_lock(g_threadMutex); if (!g_isFinishedSendData) { OIC_LOG(DEBUG, TAG, "waiting send finish signal"); - ca_cond_wait(g_threadCond, g_threadMutex); - OIC_LOG(DEBUG, TAG, "the data was sent"); + oc_cond_wait(g_threadCond, g_threadMutex); + OIC_LOG(DEBUG, TAG, "connection / send is finished for unicast"); } - ca_mutex_unlock(g_threadMutex); + oc_mutex_unlock(g_threadMutex); if (isAttached) { (*g_jvm)->DetachCurrentThread(g_jvm); } - // start LE Scan again - ret = CALEClientStartScanWithInterval(); - if (CA_STATUS_OK != ret) + oc_mutex_unlock(g_threadSendMutex); + OIC_LOG(INFO, TAG, "unicast - send logic has finished"); + if (CALEIsValidState(address, CA_LE_SEND_STATE, + STATE_SEND_SUCCESS, + g_deviceStateList, + g_deviceStateListMutex)) { - OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed"); - ca_mutex_unlock(g_threadSendMutex); - return ret; + OIC_LOG(INFO, TAG, "send success"); + ret = CA_STATUS_OK; } - - ca_mutex_unlock(g_threadSendMutex); - OIC_LOG(INFO, TAG, "unicast - send logic has finished"); - if (CALEClientIsValidState(address, CA_LE_SEND_STATE, - STATE_SEND_SUCCESS)) + else if (CALEIsValidState(address, CA_LE_SEND_STATE, + STATE_SEND_MTU_NEGO_SUCCESS, + g_deviceStateList, + g_deviceStateListMutex)) { + OIC_LOG(INFO, TAG, "mtu nego success"); ret = CA_STATUS_OK; } else { + OIC_LOG(ERROR, TAG, "send failure"); ret = CA_SEND_FAILED; } // reset send state - CAResult_t resetRet = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE, - STATE_SEND_NONE); + CAResult_t resetRet = CALEUpdateDeviceState(address, CA_LE_SEND_STATE, + STATE_SEND_NONE, + g_deviceStateList, + g_deviceStateListMutex); if (CA_STATUS_OK != resetRet) { - OIC_LOG_V(ERROR, TAG, "CALEClientUpdateDeviceState has failed (%d)", resetRet); + OIC_LOG_V(ERROR, TAG, "CALEUpdateDeviceState has failed (%d)", resetRet); ret = CA_SEND_FAILED; } @@ -982,26 +1129,12 @@ CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* // error label. error_exit: - - // start LE Scan again - ret = CALEClientStartScanWithInterval(); - if (CA_STATUS_OK != ret) - { - OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed"); - ca_mutex_unlock(g_threadSendMutex); - if (isAttached) - { - (*g_jvm)->DetachCurrentThread(g_jvm); - } - return ret; - } - if (isAttached) { (*g_jvm)->DetachCurrentThread(g_jvm); } - ca_mutex_unlock(g_threadSendMutex); + oc_mutex_unlock(g_threadSendMutex); return CA_SEND_FAILED; } @@ -1018,16 +1151,12 @@ CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, return CA_STATUS_FAILED; } - ca_mutex_lock(g_threadSendMutex); + oc_mutex_lock(g_threadSendMutex); CALEClientSetSendFinishFlag(false); OIC_LOG(DEBUG, TAG, "set byteArray for data"); - if (g_sendBuffer) - { - (*env)->DeleteGlobalRef(env, g_sendBuffer); - g_sendBuffer = NULL; - } + CALEDeleteSendBuffer(env); CAResult_t res = CALEClientIsThereScannedDevices(env, NULL); if (CA_STATUS_OK != res) @@ -1036,9 +1165,6 @@ CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, goto error_exit; } - // stop scan while sending - CALEClientStopScanWithInterval(); - uint32_t length = u_arraylist_length(g_deviceList); g_targetCnt = length; @@ -1065,39 +1191,21 @@ CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast"); // wait for finish to send data through "CALeGattServicesDiscoveredCallback" - ca_mutex_lock(g_threadMutex); + oc_mutex_lock(g_threadMutex); if (!g_isFinishedSendData) { OIC_LOG(DEBUG, TAG, "waiting send finish signal"); - ca_cond_wait(g_threadCond, g_threadMutex); - OIC_LOG(DEBUG, TAG, "the data was sent"); - } - ca_mutex_unlock(g_threadMutex); - - // start LE Scan again - res = CALEClientStartScanWithInterval(); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed"); - ca_mutex_unlock(g_threadSendMutex); - return res; + oc_cond_wait(g_threadCond, g_threadMutex); + OIC_LOG(DEBUG, TAG, "connection / send is finished for multicast"); } - - ca_mutex_unlock(g_threadSendMutex); + oc_mutex_unlock(g_threadMutex); + oc_mutex_unlock(g_threadSendMutex); OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl"); return CA_STATUS_OK; error_exit: - res = CALEClientStartScanWithInterval(); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed"); - ca_mutex_unlock(g_threadSendMutex); - return res; - } - - ca_mutex_unlock(g_threadSendMutex); - OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl"); + oc_mutex_unlock(g_threadSendMutex); + OIC_LOG(ERROR, TAG, "OUT - CALEClientSendMulticastMessageImpl"); return CA_SEND_FAILED; } @@ -1118,11 +1226,28 @@ CAResult_t CALEClientSendData(JNIEnv *env, jobject device) if (!address) { OIC_LOG(ERROR, TAG, "address is not available"); + CACheckJNIException(env); return CA_STATUS_FAILED; } - ca_mutex_lock(g_deviceStateListMutex); - state = CALEClientGetStateInfo(address); - ca_mutex_unlock(g_deviceStateListMutex); + oc_mutex_lock(g_deviceStateListMutex); + state = CALEGetStateInfo(address, g_deviceStateList); + oc_mutex_unlock(g_deviceStateListMutex); + } + + // Since disconnect event can be caused from BT stack while connection step is running. + // DeviceState has to have current status for processing send failure. + OIC_LOG(INFO, TAG, "set STATE_SEND_PREPARING"); + CAResult_t res = CALEClientUpdateDeviceStateWithBtDevice(env, device, + CA_LE_SEND_STATE, + STATE_SEND_PREPARING); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceStateWithBtDevice has failed"); + if (address) + { + (*env)->ReleaseStringUTFChars(env, jni_address, address); + } + return CA_STATUS_FAILED; } if (!state) @@ -1156,8 +1281,10 @@ CAResult_t CALEClientSendData(JNIEnv *env, jobject device) } else { - if (CALEClientIsValidState(address, CA_LE_CONNECTION_STATE, - STATE_SERVICE_CONNECTED)) + if (CALEIsValidState(address, CA_LE_CONNECTION_STATE, + STATE_SERVICE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex)) { OIC_LOG(INFO, TAG, "GATT has already connected"); @@ -1178,13 +1305,17 @@ CAResult_t CALEClientSendData(JNIEnv *env, jobject device) } (*env)->ReleaseStringUTFChars(env, jni_address, address); } - else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE, - STATE_CONNECTED)) + else if(CALEIsValidState(address, CA_LE_CONNECTION_STATE, + STATE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex)) { OIC_LOG(INFO, TAG, "service connecting..."); } - else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE, - STATE_DISCONNECTED)) + else if(CALEIsValidState(address, CA_LE_CONNECTION_STATE, + STATE_DISCONNECTED, + g_deviceStateList, + g_deviceStateListMutex)) { OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE"); @@ -1206,8 +1337,10 @@ CAResult_t CALEClientSendData(JNIEnv *env, jobject device) OIC_LOG(DEBUG, TAG, "start to connect LE"); jobject gatt = CALEClientConnect(env, device, - CALEClientGetFlagFromState(env, jni_address, - CA_LE_AUTO_CONNECT_FLAG)); + CALEGetFlagFromState(env, jni_address, + CA_LE_AUTO_CONNECT_FLAG, + g_deviceStateList, + g_deviceStateListMutex)); if (NULL == gatt) { @@ -1237,6 +1370,7 @@ jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt) if (!jni_obj_device) { OIC_LOG(ERROR, TAG, "jni_obj_device is null"); + CACheckJNIException(env); return NULL; } @@ -1244,6 +1378,7 @@ jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt) if (!jni_address) { OIC_LOG(ERROR, TAG, "jni_address is null"); + CACheckJNIException(env); return NULL; } @@ -1273,11 +1408,9 @@ CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt) OIC_LOG(DEBUG, TAG, "request to close GATT"); (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "closeGATT has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } @@ -1303,8 +1436,6 @@ CAResult_t CALEClientStartScan() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); - res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) { @@ -1320,11 +1451,31 @@ CAResult_t CALEClientStartScan() // scan gatt server with UUID if (g_leScanCallback && g_uuidList) { -#ifdef UUID_SCAN - ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback); -#else - ret = CALEClientStartScanImpl(env, g_leScanCallback); -#endif + if (g_jniIntSdk >= BLE_SCAN_API_LEVEL) + { + if (!g_setFullScanFlag) + { + //new uuid scan with callback + ret = CALEClientStartScanWithUUIDImplForV21(env, g_uuidList, g_leScanCallback); + } + else + { + //new full scan with callback + ret = CALEClientStartScanImplForV21(env, g_leScanCallback); + } + } + else + { + if (!g_setFullScanFlag) + { + ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback); + } + else + { + ret = CALEClientStartScanImpl(env, g_leScanCallback); + } + } + if (CA_STATUS_OK != ret) { if (CA_ADAPTER_NOT_ENABLED == ret) @@ -1348,6 +1499,7 @@ CAResult_t CALEClientStartScan() CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback) { + OIC_LOG(DEBUG, TAG, "CALEClientStartScanImpl IN"); VERIFY_NON_NULL(callback, TAG, "callback is null"); VERIFY_NON_NULL(env, TAG, "env is null"); @@ -1362,6 +1514,7 @@ CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback) if (!jni_cid_BTAdapter) { OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -1372,6 +1525,7 @@ CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback) if (!jni_mid_getDefaultAdapter) { OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1383,6 +1537,7 @@ CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback) if (!jni_mid_startLeScan) { OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1393,6 +1548,7 @@ CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback) if (!jni_obj_BTAdapter) { OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1404,6 +1560,7 @@ CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback) if (!jni_obj_startLeScan) { OIC_LOG(INFO, TAG, "startLeScan has failed"); + CACheckJNIException(env); } else { @@ -1415,8 +1572,113 @@ CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback) return CA_STATUS_OK; } +CAResult_t CALEClientStartScanImplForV21(JNIEnv *env, jobject callback) +{ + OIC_LOG(DEBUG, TAG, "CALEClientStartScanImplForV21 IN"); + VERIFY_NON_NULL(callback, TAG, "callback is null"); + VERIFY_NON_NULL(env, TAG, "env is null"); + + if (!CALEIsEnableBTAdapter(env)) + { + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + return CA_ADAPTER_NOT_ENABLED; + } + + CAResult_t res = CA_STATUS_FAILED; + // get default bt adapter class + jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER); + if (!jni_cid_BTAdapter) + { + OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null"); + CACheckJNIException(env); + return CA_STATUS_FAILED; + } + + jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, + "getDefaultAdapter", + "()Landroid/bluetooth/" + "BluetoothAdapter;"); + if (!jni_mid_getDefaultAdapter) + { + OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + return CA_STATUS_FAILED; + } + + jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, + jni_mid_getDefaultAdapter); + if (!jni_obj_BTAdapter) + { + OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + return CA_STATUS_FAILED; + } + + // get bluetoothLeScanner class + jclass jni_cid_leScanner = (*env)->FindClass(env, CLASSPATH_LE_SCANNER); + if (!jni_cid_leScanner) + { + OIC_LOG(ERROR, TAG, "getState From leScanner: jni_cid_leScanner is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + return CA_STATUS_FAILED; + } + + // get remote bt adapter method + jmethodID jni_mid_getBluetoothLeScanner = (*env)->GetMethodID(env, jni_cid_BTAdapter, + "getBluetoothLeScanner", + "()Landroid/bluetooth/" + "le/BluetoothLeScanner;"); + if (!jni_mid_getBluetoothLeScanner) + { + OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeScanner is null"); + CACheckJNIException(env); + goto error_exit; + } + + // get startScan(ScanCallback callback) method + jmethodID jni_mid_startScan = (*env)->GetMethodID(env, jni_cid_leScanner, "startScan", + "(Landroid/bluetooth/le/ScanCallback;)V"); + if (!jni_mid_startScan) + { + OIC_LOG(ERROR, TAG, "startScan: jni_mid_startScan is null"); + CACheckJNIException(env); + goto error_exit; + } + + // gat le scanner object + jobject jni_obj_leScanner = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, + jni_mid_getBluetoothLeScanner); + if (!jni_obj_leScanner) + { + OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_leScanner is null"); + CACheckJNIException(env); + goto error_exit; + } + + // call startScan method + OIC_LOG(INFO, TAG, "CALL API - startScan(for level21)"); + (*env)->CallVoidMethod(env, jni_obj_leScanner, jni_mid_startScan, callback); + if (CACheckJNIException(env)) + { + OIC_LOG(INFO, TAG, "startScan has failed"); + (*env)->DeleteLocalRef(env, jni_obj_leScanner); + goto error_exit; + } + res = CA_STATUS_OK; + (*env)->DeleteLocalRef(env, jni_obj_leScanner); + +error_exit: + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + (*env)->DeleteLocalRef(env, jni_cid_leScanner); + return res; +} + CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback) { + OIC_LOG(DEBUG, TAG, "CALEClientStartScanWithUUIDImpl IN"); VERIFY_NON_NULL(callback, TAG, "callback is null"); VERIFY_NON_NULL(uuids, TAG, "uuids is null"); VERIFY_NON_NULL(env, TAG, "env is null"); @@ -1431,6 +1693,7 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobj if (!jni_cid_BTAdapter) { OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -1441,6 +1704,7 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobj if (!jni_mid_getDefaultAdapter) { OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1452,6 +1716,7 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobj if (!jni_mid_startLeScan) { OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1462,6 +1727,7 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobj if (!jni_obj_BTAdapter) { OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1473,6 +1739,7 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobj if (!jni_obj_startLeScan) { OIC_LOG(INFO, TAG, "startLeScan has failed"); + CACheckJNIException(env); } else { @@ -1484,38 +1751,416 @@ CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobj return CA_STATUS_OK; } -jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid) +CAResult_t CALEClientStartScanWithUUIDImplForV21(JNIEnv *env, jobjectArray uuids, jobject callback) { - VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL); - VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL); + OIC_LOG(DEBUG, TAG, "CALEClientStartScanWithUUIDImplForV21 IN"); + VERIFY_NON_NULL(callback, TAG, "callback is null"); + VERIFY_NON_NULL(uuids, TAG, "uuids is null"); + VERIFY_NON_NULL(env, TAG, "env is null"); - // setting UUID - jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID); - if (!jni_cid_uuid) + if (!CALEIsEnableBTAdapter(env)) { - OIC_LOG(ERROR, TAG, "jni_cid_uuid is null"); - return NULL; + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + return CA_ADAPTER_NOT_ENABLED; } - jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString", - "(Ljava/lang/String;)" - "Ljava/util/UUID;"); - if (!jni_mid_fromString) + // get bluetoothLeScanner class + jclass jni_cid_leScanner = (*env)->FindClass(env, CLASSPATH_LE_SCANNER); + if (!jni_cid_leScanner) { - OIC_LOG(ERROR, TAG, "jni_mid_fromString is null"); - return NULL; + OIC_LOG(ERROR, TAG, "getState From leScanner: jni_cid_leScanner is null"); + CACheckJNIException(env); + return CA_STATUS_FAILED; + } + + // get startScan(with UUID) method + jmethodID jni_mid_startScan = (*env)->GetMethodID(env, jni_cid_leScanner, + "startScan", + "(Ljava/util/List;" + "Landroid/bluetooth/le/ScanSettings;" + "Landroid/bluetooth/le/ScanCallback;" + ")V"); + if (!jni_mid_startScan) + { + OIC_LOG(ERROR, TAG, "startScan: jni_mid_startScan is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_leScanner); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_cid_leScanner); + + // get scanfilter.Builder class id + jclass jni_cid_scanfilterBuilder = (*env)->FindClass(env, + "android/bluetooth/le/" + "ScanFilter$Builder"); + if (!jni_cid_scanfilterBuilder) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_cid_scanfilterBuilder is null"); + CACheckJNIException(env); + return CA_STATUS_FAILED; + } + + // get scanfilter.Builder(ctor) method id + jmethodID jni_mid_scanfilterBuilderCtor = (*env)->GetMethodID(env, jni_cid_scanfilterBuilder, + "", "()V"); + if (!jni_mid_scanfilterBuilderCtor) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_cid_scanfilterBuilderCtor is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder); + return CA_STATUS_FAILED; + } + + // call scanfilter.Builder() + jobject jni_obj_scanfilterBuilder = (*env)->NewObject(env, jni_cid_scanfilterBuilder, + jni_mid_scanfilterBuilderCtor); + if (!jni_obj_scanfilterBuilder) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanfilterBuilder is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder); + return CA_STATUS_FAILED; + } + + // get scanfilter.Builder.setServiceUuid method id + jmethodID jni_mid_setServiceUuid = (*env)->GetMethodID(env, jni_cid_scanfilterBuilder, + "setServiceUuid", + "(Landroid/os/ParcelUuid;)Landroid/" + "bluetooth/le/ScanFilter$Builder;"); + if (!jni_mid_setServiceUuid) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_mid_setServiceUuid is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder); + (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder); + return CA_STATUS_FAILED; + } + + // get scanfilter.Builder.build method id + jmethodID jni_mid_build_scanfilterBuilder = (*env)->GetMethodID(env, + jni_cid_scanfilterBuilder, + "build", + "()Landroid/bluetooth/le/" + "ScanFilter;"); + if (!jni_mid_build_scanfilterBuilder) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_mid_build_scanfilterBuilder is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder); + (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_cid_scanfilterBuilder); + + // call ParcelUuid.fromSting(uuid) + jobject jni_obj_parcelUuid = CALEGetParcelUuidFromString(env, OIC_GATT_SERVICE_UUID); + if (!jni_obj_parcelUuid) + { + OIC_LOG(ERROR, TAG, "scanSettings: jni_obj_parcelUuid is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder); + return CA_STATUS_FAILED; + } + + // call setServiceUuid(uuid) + jobject jni_obj_setServiceUuid = (*env)->CallObjectMethod(env, + jni_obj_scanfilterBuilder, + jni_mid_setServiceUuid, + jni_obj_parcelUuid); + if (!jni_obj_setServiceUuid) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_setServiceUuid is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder); + (*env)->DeleteLocalRef(env, jni_obj_parcelUuid); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_obj_parcelUuid); + (*env)->DeleteLocalRef(env, jni_obj_setServiceUuid); + + // call build() + jobject jni_obj_scanfilter = (*env)->CallObjectMethod(env, + jni_obj_scanfilterBuilder, + jni_mid_build_scanfilterBuilder); + if (!jni_obj_scanfilter) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanfilter is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_obj_scanfilterBuilder); + + // get scanSettings.Builder class id + jclass jni_cid_scanSettingsBuilder = (*env)->FindClass(env, + "android/bluetooth/le/" + "ScanSettings$Builder"); + if (!jni_cid_scanSettingsBuilder) + { + OIC_LOG(ERROR, TAG, "scanSettings: jni_cid_scanSettingsBuilder is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + return CA_STATUS_FAILED; + } + + // get scanSettings.Builder(ctor) method id + jmethodID jni_mid_scanSettingsBuilderCtor = (*env)->GetMethodID(env, jni_cid_scanSettingsBuilder, + "", "()V"); + if (!jni_mid_scanSettingsBuilderCtor) + { + OIC_LOG(ERROR, TAG, "scanSettings: jni_mid_scanSettingsBuilderCtor is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder); + return CA_STATUS_FAILED; + } + + // get scanSettings.Builder.setScanMode method id + jmethodID jni_mid_setScanMode = (*env)->GetMethodID(env, jni_cid_scanSettingsBuilder, + "setScanMode", + "(I)Landroid/" + "bluetooth/le/ScanSettings$Builder;"); + if (!jni_mid_setScanMode) + { + OIC_LOG(ERROR, TAG, "scanSettings: jni_mid_setScanMode is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder); + return CA_STATUS_FAILED; + } + + // get scanSettings.Builder.build method id + jmethodID jni_mid_build_scanSettings = (*env)->GetMethodID(env, + jni_cid_scanSettingsBuilder, + "build", + "()Landroid/bluetooth/le/" + "ScanSettings;"); + if (!jni_mid_build_scanSettings) + { + OIC_LOG(ERROR, TAG, "scanSettings: jni_mid_build_scanSettings is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder); + return CA_STATUS_FAILED; + } + + // call scanSettings.Builder() + jobject jni_obj_scanSettingBuilder = (*env)->NewObject(env, jni_cid_scanSettingsBuilder, + jni_mid_scanSettingsBuilderCtor); + if (!jni_obj_scanSettingBuilder) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanSettingBuilder is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_cid_scanSettingsBuilder); + + jclass jni_cid_arrayList = (*env)->FindClass(env, "java/util/ArrayList"); + if (!jni_cid_arrayList) + { + OIC_LOG(ERROR, TAG, "ArrayList: jni_cid_arrayList is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + return CA_STATUS_FAILED; + } + + jmethodID jni_mid_arrayListCtor = (*env)->GetMethodID(env, jni_cid_arrayList, "", "()V"); + if (!jni_mid_arrayListCtor) + { + OIC_LOG(ERROR, TAG, "ArrayList: jni_mid_arrayListCtor is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_cid_arrayList); + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + return CA_STATUS_FAILED; + } + + jmethodID jni_mid_arrayListAdd = (*env)->GetMethodID(env, jni_cid_arrayList, + "add", "(Ljava/lang/Object;)Z"); + if (!jni_mid_arrayListAdd) + { + OIC_LOG(ERROR, TAG, "ArrayList: jni_mid_arrayListAdd is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_cid_arrayList); + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + return CA_STATUS_FAILED; + } + + jobject jni_obj_filterList = (*env)->NewObject(env, jni_cid_arrayList, jni_mid_arrayListCtor); + if (!jni_obj_filterList) + { + OIC_LOG(ERROR, TAG, "ArrayList: jni_obj_filterList is null"); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_cid_arrayList); + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_cid_arrayList); + + jboolean jni_bool_arrayListIsAdded = (*env)->CallBooleanMethod(env, jni_obj_filterList, + jni_mid_arrayListAdd, + jni_obj_scanfilter); + if (!jni_bool_arrayListIsAdded) + { + OIC_LOG(ERROR, TAG, "ArrayList: jni_bool_arrayListIsAdded is null"); + (*env)->DeleteLocalRef(env, jni_obj_filterList); + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_obj_scanfilter); + + // get ScanSettings.SCAN_MODE_BALANCED jint value + jint jni_int_scanBalancedMode = CALEGetConstantsValue(env, CLASSPATH_LE_SCANSETTINGS, + "SCAN_MODE_BALANCED"); + CACheckJNIException(env); + + // call setScanMode(SCAN_MODE_BALANCED) + jobject jni_obj_setScanMode = (*env)->CallObjectMethod(env, jni_obj_scanSettingBuilder, + jni_mid_setScanMode, + jni_int_scanBalancedMode); + if (!jni_obj_setScanMode) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_setScanMode is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + (*env)->DeleteLocalRef(env, jni_obj_filterList); + return CA_STATUS_FAILED; + } + + // call build + jobject jni_obj_scanSettings = (*env)->CallObjectMethod(env, jni_obj_scanSettingBuilder, + jni_mid_build_scanSettings); + if (!jni_obj_scanSettings) + { + OIC_LOG(ERROR, TAG, "scanfilter: jni_obj_scanSettings is null"); + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + (*env)->DeleteLocalRef(env, jni_obj_filterList); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_obj_scanSettingBuilder); + + CAResult_t res = CA_STATUS_FAILED; + // get default bt adapter class + jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER); + if (!jni_cid_BTAdapter) + { + OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null"); + CACheckJNIException(env); + goto error_exit; + } + + jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, + "getDefaultAdapter", + "()Landroid/bluetooth/" + "BluetoothAdapter;"); + if (!jni_mid_getDefaultAdapter) + { + OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + goto error_exit; + } + + jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, + jni_mid_getDefaultAdapter); + if (!jni_obj_BTAdapter) + { + OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + goto error_exit; + } + + // get remote bt adapter method + jmethodID jni_mid_getBluetoothLeScanner = (*env)->GetMethodID(env, jni_cid_BTAdapter, + "getBluetoothLeScanner", + "()Landroid/bluetooth/" + "le/BluetoothLeScanner;"); + if (!jni_mid_getBluetoothLeScanner) + { + OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeScanner is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + goto error_exit; + } + + // get le scanner object + jobject jni_obj_leScanner = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, + jni_mid_getBluetoothLeScanner); + if (!jni_obj_leScanner) + { + OIC_LOG(ERROR, TAG, "jni_obj_leScanner is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + goto error_exit; + } + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + + // call startScan method + OIC_LOG(INFO, TAG, "CALL API - startScanWithUUID(for level 21)"); + (*env)->CallVoidMethod(env, jni_obj_leScanner, jni_mid_startScan, jni_obj_filterList, + jni_obj_scanSettings, callback); + if (CACheckJNIException(env)) + { + OIC_LOG(INFO, TAG, "startScan has failed"); + } + else + { + res = CA_STATUS_OK; + } + (*env)->DeleteLocalRef(env, jni_obj_leScanner); + +error_exit: + (*env)->DeleteLocalRef(env, jni_obj_scanSettings); + (*env)->DeleteLocalRef(env, jni_obj_filterList); + return res; +} + +jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid) +{ + VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL); + VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL); + + // setting UUID + jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID); + if (!jni_cid_uuid) + { + OIC_LOG(ERROR, TAG, "jni_cid_uuid is null"); + goto error_exit; + } + + jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString", + "(Ljava/lang/String;)" + "Ljava/util/UUID;"); + if (!jni_mid_fromString) + { + OIC_LOG(ERROR, TAG, "jni_mid_fromString is null"); + goto error_exit; } jstring jni_uuid = (*env)->NewStringUTF(env, uuid); + CACheckJNIException(env); jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString, jni_uuid); if (!jni_obj_uuid) { OIC_LOG(ERROR, TAG, "jni_obj_uuid is null"); - return NULL; + goto error_exit; } return jni_obj_uuid; + +error_exit: + CACheckJNIException(env); + return NULL; } CAResult_t CALEClientStopScan() @@ -1531,7 +2176,6 @@ CAResult_t CALEClientStopScan() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) { @@ -1541,7 +2185,17 @@ CAResult_t CALEClientStopScan() isAttached = true; } - CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback); + CAResult_t ret = CA_STATUS_FAILED; + + if (g_jniIntSdk >= BLE_SCAN_API_LEVEL) + { + ret = CALEClientStopScanImplForV21(env, g_leScanCallback); + } + else + { + ret = CALEClientStopScanImpl(env, g_leScanCallback); + } + if (CA_STATUS_OK != ret) { if (CA_ADAPTER_NOT_ENABLED == ret) @@ -1564,7 +2218,7 @@ CAResult_t CALEClientStopScan() CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback) { - OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl"); + OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl IN"); VERIFY_NON_NULL(callback, TAG, "callback is null"); VERIFY_NON_NULL(env, TAG, "env is null"); @@ -1579,6 +2233,7 @@ CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback) if (!jni_cid_BTAdapter) { OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -1589,6 +2244,7 @@ CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback) if (!jni_mid_getDefaultAdapter) { OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1600,16 +2256,18 @@ CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback) if (!jni_mid_stopLeScan) { OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } - // gat bt adapter object + // get bt adapter object jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, jni_mid_getDefaultAdapter); if (!jni_obj_BTAdapter) { OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); return CA_STATUS_FAILED; } @@ -1617,13 +2275,11 @@ CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback) OIC_LOG(INFO, TAG, "CALL API - stopLeScan"); // call start le scan method (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "stopLeScan has failed"); (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } @@ -1632,94 +2288,111 @@ CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback) return CA_STATUS_OK; } -CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, jint state_idx, jboolean flag) +CAResult_t CALEClientStopScanImplForV21(JNIEnv *env, jobject callback) { - OIC_LOG(DEBUG, TAG, "IN - CALEClientSetFlagToState"); - VERIFY_NON_NULL(env, TAG, "env"); - VERIFY_NON_NULL(jni_address, TAG, "jni_address"); + OIC_LOG(DEBUG, TAG, "CALEClientStopScanImplForV21 IN"); + VERIFY_NON_NULL(callback, TAG, "callback is null"); + VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_deviceStateListMutex); + if (!CALEIsEnableBTAdapter(env)) + { + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + return CA_ADAPTER_NOT_ENABLED; + } - char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL); - if (!address) + // get default bt adapter class + jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER); + if (!jni_cid_BTAdapter) { - OIC_LOG(ERROR, TAG, "address is not available"); + OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null"); + CACheckJNIException(env); return CA_STATUS_FAILED; } - if (CALEClientIsDeviceInList(address)) + jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter, + "getDefaultAdapter", + "()Landroid/bluetooth/" + "BluetoothAdapter;"); + if (!jni_mid_getDefaultAdapter) { - CALEState_t* curState = CALEClientGetStateInfo(address); - if(!curState) - { - OIC_LOG(ERROR, TAG, "curState is null"); - (*env)->ReleaseStringUTFChars(env, jni_address, address); - ca_mutex_unlock(g_deviceStateListMutex); - return CA_STATUS_FAILED; - } - OIC_LOG_V(INFO, TAG, "%d flag is set : %d", state_idx, flag); - - switch(state_idx) - { - case CA_LE_AUTO_CONNECT_FLAG: - curState->autoConnectFlag = flag; - break; - case CA_LE_DESCRIPTOR_FOUND: - curState->isDescriptorFound = flag; - break; - default: - break; - } + OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + return CA_STATUS_FAILED; } - (*env)->ReleaseStringUTFChars(env, jni_address, address); - ca_mutex_unlock(g_deviceStateListMutex); - OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetFlagToState"); - return CA_STATUS_OK; -} + jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter, + jni_mid_getDefaultAdapter); + if (!jni_obj_BTAdapter) + { + OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + return CA_STATUS_FAILED; + } -jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx) -{ - OIC_LOG(DEBUG, TAG, "IN - CALEClientGetFlagFromState"); - VERIFY_NON_NULL_RET(env, TAG, "env", false); - VERIFY_NON_NULL_RET(jni_address, TAG, "jni_address", false); + // get bluetoothLeScanner class + jclass jni_cid_leScanner = (*env)->FindClass(env, CLASSPATH_LE_SCANNER); + if (!jni_cid_leScanner) + { + OIC_LOG(ERROR, TAG, "getState From leScanner: jni_cid_leScanner is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + return CA_STATUS_FAILED; + } - ca_mutex_lock(g_deviceStateListMutex); + // get remote bt adapter method + jmethodID jni_mid_getBluetoothLeScanner = (*env)->GetMethodID(env, jni_cid_BTAdapter, + "getBluetoothLeScanner", + "()Landroid/bluetooth/" + "le/BluetoothLeScanner;"); + if (!jni_mid_getBluetoothLeScanner) + { + OIC_LOG(ERROR, TAG, "jni_mid_getBluetoothLeScanner is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + (*env)->DeleteLocalRef(env, jni_cid_leScanner); + return CA_STATUS_FAILED; + } + (*env)->DeleteLocalRef(env, jni_cid_BTAdapter); - char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL); - if (!address) + // get stopScan(ScanCallback callback) method + jmethodID jni_mid_stopScan = (*env)->GetMethodID(env, jni_cid_leScanner, "stopScan", + "(Landroid/bluetooth/le/ScanCallback;)V"); + if (!jni_mid_stopScan) { - OIC_LOG(ERROR, TAG, "address is not available"); - ca_mutex_unlock(g_deviceStateListMutex); - return JNI_FALSE; + OIC_LOG(ERROR, TAG, "stopScan: jni_mid_stopScan is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_obj_BTAdapter); + (*env)->DeleteLocalRef(env, jni_cid_leScanner); + return CA_STATUS_FAILED; } + (*env)->DeleteLocalRef(env, jni_cid_leScanner); - CALEState_t* curState = CALEClientGetStateInfo(address); - (*env)->ReleaseStringUTFChars(env, jni_address, address); - if(!curState) + // gat le scanner object + jobject jni_obj_leScanner = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, + jni_mid_getBluetoothLeScanner); + if (!jni_obj_leScanner) { - OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false"); - ca_mutex_unlock(g_deviceStateListMutex); - return JNI_FALSE; + OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_leScanner is null"); + CACheckJNIException(env); + return CA_STATUS_FAILED; } - jboolean ret = JNI_FALSE; - switch(state_idx) + // call stopScan method + OIC_LOG(INFO, TAG, "CALL API - stopScan for level 21"); + (*env)->CallVoidMethod(env, jni_obj_leScanner, jni_mid_stopScan, callback); + if (CACheckJNIException(env)) { - case CA_LE_AUTO_CONNECT_FLAG: - ret = curState->autoConnectFlag; - break; - case CA_LE_DESCRIPTOR_FOUND: - ret = curState->isDescriptorFound; - break; - default: - break; + OIC_LOG(INFO, TAG, "stopScan for level 21 has failed"); + (*env)->DeleteLocalRef(env, jni_obj_leScanner); + return CA_STATUS_FAILED; } - ca_mutex_unlock(g_deviceStateListMutex); - OIC_LOG_V(INFO, TAG, "%d flag is %d", state_idx, ret); - OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetFlagFromState"); - return ret; + (*env)->DeleteLocalRef(env, jni_obj_leScanner); + return CA_STATUS_OK; } CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect) @@ -1728,13 +2401,13 @@ CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolea VERIFY_NON_NULL(env, TAG, "env is null"); VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null"); - ca_mutex_lock(g_threadSendMutex); + oc_mutex_lock(g_threadSendMutex); jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice); if (!jni_address) { OIC_LOG(ERROR, TAG, "jni_address is not available"); - ca_mutex_unlock(g_threadSendMutex); + oc_mutex_unlock(g_threadSendMutex); return CA_STATUS_FAILED; } @@ -1742,13 +2415,16 @@ CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolea if (!address) { OIC_LOG(ERROR, TAG, "address is not available"); - ca_mutex_unlock(g_threadSendMutex); + CACheckJNIException(env); + oc_mutex_unlock(g_threadSendMutex); return CA_STATUS_FAILED; } CAResult_t res = CA_STATUS_OK; - if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE, - STATE_DISCONNECTED)) + if(CALEIsValidState(address, CA_LE_CONNECTION_STATE, + STATE_DISCONNECTED, + g_deviceStateList, + g_deviceStateListMutex)) { jobject newGatt = CALEClientConnect(env, bluetoothDevice, autoconnect); if (NULL == newGatt) @@ -1757,7 +2433,7 @@ CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolea res = CA_STATUS_FAILED; } } - ca_mutex_unlock(g_threadSendMutex); + oc_mutex_unlock(g_threadSendMutex); return res; } @@ -1768,6 +2444,14 @@ jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autocon VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL); VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL); + // reset scan interval time after checking scanned devices + CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE); + + // since there is no callback related stop success + // and scanning should be stopped before connectGatt is called. + // it should wait a few micro seconds. + usleep(100000); + // get gatt object from Bluetooth Device object for closeProfileProxy(..) jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice); if (jni_address) @@ -1846,38 +2530,104 @@ jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean aut return NULL; } - // get BluetoothDevice method - OIC_LOG(DEBUG, TAG, "get BluetoothDevice method"); - jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice", - "connectGatt", - "(Landroid/content/Context;ZLandroid/" - "bluetooth/BluetoothGattCallback;)" - "Landroid/bluetooth/BluetoothGatt;"); - if (!jni_mid_connectGatt) + jobject jni_obj_connectGatt = NULL; + jint jni_int_sdk = CALEGetBuildVersion(env); + OIC_LOG_V(INFO, TAG, "API level is %d", jni_int_sdk); + if (jni_int_sdk >= 23) // upper than API level 23 { - OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null"); - return NULL; - } + jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice", + "connectGatt", + "(Landroid/content/Context;ZLandroid/" + "bluetooth/BluetoothGattCallback;I)" + "Landroid/bluetooth/BluetoothGatt;"); + if (!jni_mid_connectGatt) + { + OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null"); + return NULL; + } - OIC_LOG(INFO, TAG, "CALL API - connectGatt"); - jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice, - jni_mid_connectGatt, - NULL, - autoconnect, g_leGattCallback); - if (!jni_obj_connectGatt) - { - OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed"); - CALEClientRemoveDeviceInScanDeviceList(env, jni_address); - CALEClientUpdateSendCnt(env); - return NULL; + jint jni_transport_le = CALEGetConstantsValue(env, CLASSPATH_BT_DEVICE, "TRANSPORT_LE"); + OIC_LOG_V(INFO, TAG, "CALL API - connectGatt with transport LE(%d)", jni_transport_le); + jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice, + jni_mid_connectGatt, NULL, + autoconnect, g_leGattCallback, + jni_transport_le); + if (!jni_obj_connectGatt) + { + OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed"); + CACheckJNIException(env); + CALEClientRemoveDeviceInScanDeviceList(env, jni_address); + CALEClientUpdateSendCnt(env); + return NULL; + } + else + { + OIC_LOG(DEBUG, TAG, "le connecting..please wait.."); + } } - else + else // lower than API level 23 { - OIC_LOG(DEBUG, TAG, "le connecting..please wait.."); +#ifdef HIDDEN_API + const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); + if (!address) + { + OIC_LOG(ERROR, TAG, "GetStringUTFChars has failed"); + return NULL; + } + OIC_LOG(INFO, TAG, "CALL API - connectGatt for hidden"); + jni_obj_connectGatt = CALEClientHiddenConnectGatt(bluetoothDevice, address, autoconnect); + +#else + + jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice", + "connectGatt", + "(Landroid/content/Context;ZLandroid/" + "bluetooth/BluetoothGattCallback;)" + "Landroid/bluetooth/BluetoothGatt;"); + if (!jni_mid_connectGatt) + { + OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null"); + return NULL; + } + + OIC_LOG(INFO, TAG, "CALL API - connectGatt"); + jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice, + jni_mid_connectGatt, + NULL, + autoconnect, g_leGattCallback); +#endif + if (!jni_obj_connectGatt) + { + OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed"); + CACheckJNIException(env); + CALEClientRemoveDeviceInScanDeviceList(env, jni_address); + CALEClientUpdateSendCnt(env); + return NULL; + } + else + { + OIC_LOG(DEBUG, TAG, "le connecting..please wait.."); + } + } + return jni_obj_connectGatt; } +bool CALEClientIsConnected(const char* address) +{ + if (CALEIsValidState(address, CA_LE_CONNECTION_STATE, + STATE_SERVICE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex)) + { + OIC_LOG(DEBUG, TAG, "current state is connected"); + return true; + } + OIC_LOG(DEBUG, TAG, "current state is not connected"); + return false; +} + CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt) { OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy"); @@ -1889,7 +2639,7 @@ CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt) if (!jni_cid_BTAdapter) { OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null"); - return CA_STATUS_FAILED; + goto error_exit; } // get remote bt adapter method @@ -1899,7 +2649,7 @@ CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt) if (!jni_mid_getDefaultAdapter) { OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null"); - return CA_STATUS_FAILED; + goto error_exit; } // gat bt adapter object @@ -1908,7 +2658,7 @@ CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt) if (!jni_obj_BTAdapter) { OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null"); - return CA_STATUS_FAILED; + goto error_exit; } // get closeProfileProxy method @@ -1919,14 +2669,14 @@ CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt) if (!jni_mid_closeProfileProxy) { OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null"); - return CA_STATUS_FAILED; + goto error_exit; } jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE); if (!jni_cid_BTProfile) { OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null"); - return CA_STATUS_FAILED; + goto error_exit; } // GATT - Constant value : 7 (0x00000007) @@ -1935,23 +2685,26 @@ CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt) if (!id_gatt) { OIC_LOG(ERROR, TAG, "id_gatt is null"); - return CA_STATUS_FAILED; + goto error_exit; } jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt); + CACheckJNIException(env); OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service"); (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "closeProfileProxy has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy"); return CA_STATUS_OK; + +error_exit: + CACheckJNIException(env); + return CA_STATUS_FAILED; } @@ -1974,11 +2727,9 @@ CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt) // call disconnect gatt method OIC_LOG(INFO, TAG, "CALL API - disconnect"); (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt); - if ((*env)->ExceptionCheck(env)) + if (CACheckJNIException(env)) { OIC_LOG(ERROR, TAG, "disconnect has failed"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); return CA_STATUS_FAILED; } @@ -2035,6 +2786,7 @@ CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address) if (!address) { OIC_LOG(ERROR, TAG, "address is null"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -2060,12 +2812,13 @@ CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address) if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); + CACheckJNIException(env); (*env)->ReleaseStringUTFChars(env, remote_address, address); return CA_STATUS_FAILED; } OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress); - if (!strcmp(address, setAddress)) + if (!strcasecmp(address, setAddress)) { CAResult_t res = CALEClientDisconnect(env, jarrayObj); if (CA_STATUS_OK != res) @@ -2087,6 +2840,40 @@ CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address) return CA_STATUS_OK; } +CAResult_t CALEClientRequestMTU(JNIEnv *env, jobject bluetoothGatt, jint size) +{ + VERIFY_NON_NULL(env, TAG, "env is null"); + VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null"); + + if (!CALEIsEnableBTAdapter(env)) + { + OIC_LOG(INFO, TAG, "BT adapter is not enabled"); + return CA_ADAPTER_NOT_ENABLED; + } + + // get BluetoothGatt.requestMtu method + OIC_LOG(DEBUG, TAG, "get BluetoothGatt.requestMtu method"); + jmethodID jni_mid_requestMtu = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, + "requestMtu", "(I)Z"); + if (!jni_mid_requestMtu) + { + OIC_LOG(ERROR, TAG, "jni_mid_requestMtu is null"); + return CA_STATUS_FAILED; + } + + // call requestMtu + OIC_LOG(INFO, TAG, "CALL API - requestMtu"); + jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_requestMtu, size); + if (!ret) + { + OIC_LOG(ERROR, TAG, "requestMtu has failed"); + CACheckJNIException(env); + return CA_STATUS_FAILED; + } + + return CA_STATUS_OK; +} + CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt) { VERIFY_NON_NULL(env, TAG, "env is null"); @@ -2114,6 +2901,7 @@ CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt) if (!ret) { OIC_LOG(ERROR, TAG, "discoverServices has not been started"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -2129,7 +2917,6 @@ static void CALEWriteCharacteristicThread(void* object) jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -2170,42 +2957,71 @@ CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt) const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); if (!address) { + CACheckJNIException(env); CALEClientSendFinish(env, gatt); return CA_STATUS_FAILED; } - ca_mutex_lock(g_threadSendStateMutex); + oc_mutex_lock(g_threadSendStateMutex); - if (CALEClientIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING)) + if (CALEIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING, + g_deviceStateList, + g_deviceStateListMutex)) { OIC_LOG(INFO, TAG, "current state is SENDING"); (*env)->ReleaseStringUTFChars(env, jni_address, address); - ca_mutex_unlock(g_threadSendStateMutex); + oc_mutex_unlock(g_threadSendStateMutex); return CA_STATUS_OK; } - if (CA_STATUS_OK != CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE, - STATE_SENDING)) + if (CA_STATUS_OK != CALEUpdateDeviceState(address, CA_LE_SEND_STATE, + STATE_SENDING, + g_deviceStateList, + g_deviceStateListMutex)) { - OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed"); + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); (*env)->ReleaseStringUTFChars(env, jni_address, address); CALEClientSendFinish(env, gatt); - ca_mutex_unlock(g_threadSendStateMutex); + oc_mutex_unlock(g_threadSendStateMutex); return CA_STATUS_FAILED; } (*env)->ReleaseStringUTFChars(env, jni_address, address); - ca_mutex_unlock(g_threadSendStateMutex); + oc_mutex_unlock(g_threadSendStateMutex); + + jbyteArray sendData = NULL; + oc_mutex_lock(g_setValueMutex); + if (g_sendBuffer) + { + OIC_LOG(INFO, TAG, "alloc local reference for data"); + sendData = (jbyteArray)(*env)->NewLocalRef(env, g_sendBuffer); + } + else + { + OIC_LOG(ERROR, TAG, "send Buffer is empty"); + oc_mutex_unlock(g_setValueMutex); + return CA_STATUS_FAILED; + } + oc_mutex_unlock(g_setValueMutex); // send data - jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer); + jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, sendData); if (!jni_obj_character) { + if (sendData) + { + (*env)->DeleteLocalRef(env, sendData); + } CALEClientSendFinish(env, gatt); return CA_STATUS_FAILED; } + if (sendData) + { + (*env)->DeleteLocalRef(env, sendData); + } + CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character); if (CA_STATUS_OK != ret) { @@ -2215,23 +3031,25 @@ CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt) // wait for callback for write Characteristic with success to sent data OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag); - ca_mutex_lock(g_threadWriteCharacteristicMutex); + oc_mutex_lock(g_threadWriteCharacteristicMutex); if (!g_isSignalSetFlag) { OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success"); - if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond, + if (OC_WAIT_SUCCESS != oc_cond_wait_for(g_threadWriteCharacteristicCond, g_threadWriteCharacteristicMutex, WAIT_TIME_WRITE_CHARACTERISTIC)) { OIC_LOG(ERROR, TAG, "there is no response. write has failed"); g_isSignalSetFlag = false; - ca_mutex_unlock(g_threadWriteCharacteristicMutex); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); return CA_STATUS_FAILED; } } // reset flag set by writeCharacteristic Callback g_isSignalSetFlag = false; - ca_mutex_unlock(g_threadWriteCharacteristicMutex); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); + + CALEClientUpdateSendCnt(env); OIC_LOG(INFO, TAG, "writeCharacteristic success!!"); return CA_STATUS_OK; @@ -2244,8 +3062,9 @@ CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt) VERIFY_NON_NULL(gatt, TAG, "gatt is null"); jobject gattParam = (*env)->NewGlobalRef(env, gatt); - if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, - CALEWriteCharacteristicThread, (void*)gattParam)) + CACheckJNIException(env); + if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CALEWriteCharacteristicThread, + (void*)gattParam, NULL)) { OIC_LOG(ERROR, TAG, "Failed to create read thread!"); return CA_STATUS_FAILED; @@ -2292,6 +3111,7 @@ CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt, } else { + CACheckJNIException(env); OIC_LOG(ERROR, TAG, "writeCharacteristic has failed"); return CA_STATUS_FAILED; } @@ -2314,6 +3134,7 @@ CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt) if (!jni_uuid) { OIC_LOG(ERROR, TAG, "jni_uuid is null"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -2346,6 +3167,7 @@ CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt) else { OIC_LOG(ERROR, TAG, "readCharacteristic has failed"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -2387,6 +3209,7 @@ CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoot else { OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed"); + CACheckJNIException(env); return CA_STATUS_FAILED; } @@ -2431,6 +3254,7 @@ jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring cha if (!jni_obj_gattService) { OIC_LOG(ERROR, TAG, "jni_obj_gattService is null"); + CACheckJNIException(env); return NULL; } @@ -2451,6 +3275,7 @@ jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring cha if (!uuid) { OIC_LOG(ERROR, TAG, "uuid is null"); + CACheckJNIException(env); return NULL; } @@ -2462,10 +3287,16 @@ jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring cha return NULL; } - OIC_LOG(DEBUG, TAG, "request to get Characteristic"); + OIC_LOG(DEBUG, TAG, "CALL API getCharacteristic"); jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService, jni_mid_getCharacteristic, jni_obj_tx_uuid); + if (!jni_obj_GattCharacteristic) + { + OIC_LOG(ERROR, TAG, "getCharacteristic has failed"); + CACheckJNIException(env); + return NULL; + } (*env)->ReleaseStringUTFChars(env, characterUUID, uuid); return jni_obj_GattCharacteristic; @@ -2488,7 +3319,7 @@ jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, j if (!jni_uuid) { OIC_LOG(ERROR, TAG, "jni_uuid is null"); - return NULL; + goto error_exit; } jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid); @@ -2503,7 +3334,7 @@ jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, j if (!jni_cid_BTGattCharacteristic) { OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null"); - return NULL; + goto error_exit; } OIC_LOG(DEBUG, TAG, "set value in Characteristic"); @@ -2512,9 +3343,10 @@ jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, j if (!jni_mid_setValue) { OIC_LOG(ERROR, TAG, "jni_mid_setValue is null"); - return NULL; + goto error_exit; } + OIC_LOG(DEBUG, TAG, "CALL API - setValue"); jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue, data); if (JNI_TRUE == ret) @@ -2524,32 +3356,49 @@ jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, j else { OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set"); - return NULL; + goto error_exit; } - // set Write Type - jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, - "setWriteType", "(I)V"); - if (!jni_mid_setWriteType) + if (!g_setHighQoS) { - OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null"); - return NULL; - } + OIC_LOG(DEBUG, TAG, "setWriteType with WRITE_TYPE_NO_RESPONSE"); + // set Write Type + jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, + "setWriteType", "(I)V"); + if (!jni_mid_setWriteType) + { + OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null"); + goto error_exit; + } - jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic, - "WRITE_TYPE_NO_RESPONSE", "I"); - if (!jni_fid_no_response) - { - OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available"); - return NULL; - } + jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic, + "WRITE_TYPE_NO_RESPONSE", "I"); + if (!jni_fid_no_response) + { + OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available"); + goto error_exit; + } - jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic, - jni_fid_no_response); + jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic, + jni_fid_no_response); + CACheckJNIException(env); - (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val); + (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val); + if (CACheckJNIException(env)) + { + OIC_LOG(ERROR, TAG, "setWriteType has failed"); + } + } + else + { + OIC_LOG(DEBUG, TAG, "It will run with response property"); + } return jni_obj_GattCharacteristic; + +error_exit: + CACheckJNIException(env); + return NULL; } jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic) @@ -2574,6 +3423,7 @@ jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteris jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic, jni_mid_getValue); + CACheckJNIException(env); return jni_obj_data_array; } @@ -2590,7 +3440,6 @@ CAResult_t CALEClientCreateUUIDList() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -2606,6 +3455,7 @@ CAResult_t CALEClientCreateUUIDList() if (!jni_cid_uuid_list) { OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null"); + CACheckJNIException(env); goto error_exit; } @@ -2614,6 +3464,7 @@ CAResult_t CALEClientCreateUUIDList() if (!jni_obj_uuid_list) { OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null"); + CACheckJNIException(env); goto error_exit; } @@ -2627,6 +3478,7 @@ CAResult_t CALEClientCreateUUIDList() (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid); g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list); + CACheckJNIException(env); if (isAttached) { @@ -2674,7 +3526,6 @@ CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt, if (!jni_obj_cc_uuid) { OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null"); - return CA_STATUS_FAILED; } OIC_LOG(DEBUG, TAG, "request to get descriptor"); @@ -2683,7 +3534,7 @@ CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt, if (!jni_obj_descriptor) { OIC_LOG(INFO, TAG, "jni_obj_descriptor is null"); - return CA_NOT_SUPPORTED; + goto error_exit; } OIC_LOG(DEBUG, TAG, "set value in descriptor"); @@ -2692,25 +3543,39 @@ CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt, if (!jni_cid_descriptor) { OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z"); if (!jni_mid_setValue) { OIC_LOG(ERROR, TAG, "jni_mid_setValue is null"); - return CA_STATUS_FAILED; + goto error_exit; } - jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor, - "ENABLE_NOTIFICATION_VALUE", "[B"); - if (!jni_fid_NotiValue) + jfieldID jni_fid_NotiValue = NULL; + if (g_setHighQoS) { - OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null"); - return CA_STATUS_FAILED; + OIC_LOG(DEBUG, TAG, "get ENABLE_INDICATION_VALUE"); + jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor, + "ENABLE_INDICATION_VALUE", "[B"); + if (!jni_fid_NotiValue) + { + OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null"); + goto error_exit; + } + } + else + { + OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE"); + jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor, + "ENABLE_NOTIFICATION_VALUE", "[B"); + if (!jni_fid_NotiValue) + { + OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null"); + goto error_exit; + } } - - OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE"); jboolean jni_setvalue = (*env)->CallBooleanMethod( env, jni_obj_descriptor, jni_mid_setValue, @@ -2722,7 +3587,7 @@ CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt, else { OIC_LOG(ERROR, TAG, "setValue has failed"); - return CA_STATUS_FAILED; + goto error_exit; } jmethodID jni_mid_writeDescriptor = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt", @@ -2745,10 +3610,14 @@ CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt, else { OIC_LOG(ERROR, TAG, "writeDescriptor has failed"); - return CA_STATUS_FAILED; + goto error_exit; } return CA_STATUS_OK; + +error_exit: + CACheckJNIException(env); + return CA_STATUS_FAILED; } void CALEClientCreateScanDeviceList(JNIEnv *env) @@ -2756,7 +3625,7 @@ void CALEClientCreateScanDeviceList(JNIEnv *env) OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList"); VERIFY_NON_NULL_VOID(env, TAG, "env is null"); - ca_mutex_lock(g_deviceListMutex); + oc_mutex_lock(g_deviceListMutex); // create new object array if (g_deviceList == NULL) { @@ -2764,7 +3633,7 @@ void CALEClientCreateScanDeviceList(JNIEnv *env) g_deviceList = u_arraylist_create(); } - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); } CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device) @@ -2772,14 +3641,12 @@ CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device) VERIFY_NON_NULL(device, TAG, "device is null"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_deviceListMutex); + oc_mutex_lock(g_deviceListMutex); if (!g_deviceList) { OIC_LOG(ERROR, TAG, "gdevice_list is null"); - CALEClientStopScanWithInterval(); - - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } @@ -2787,7 +3654,7 @@ CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device) if (!jni_remoteAddress) { OIC_LOG(ERROR, TAG, "jni_remoteAddress is null"); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } @@ -2795,22 +3662,24 @@ CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device) if (!remoteAddress) { OIC_LOG(ERROR, TAG, "remoteAddress is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_remoteAddress); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress)) { jobject gdevice = (*env)->NewGlobalRef(env, device); + CACheckJNIException(env); u_arraylist_add(g_deviceList, gdevice); - ca_cond_signal(g_deviceDescCond); + oc_cond_signal(g_deviceDescCond); OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress); } (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); (*env)->DeleteLocalRef(env, jni_remoteAddress); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_OK; } @@ -2847,11 +3716,12 @@ bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress) if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); + CACheckJNIException(env); (*env)->DeleteLocalRef(env, jni_setAddress); return true; } - if (!strcmp(remoteAddress, setAddress)) + if (!strcasecmp(remoteAddress, setAddress)) { (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->DeleteLocalRef(env, jni_setAddress); @@ -2860,10 +3730,7 @@ bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress) (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->DeleteLocalRef(env, jni_setAddress); - } - - OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress); - + } return false; } @@ -2872,12 +3739,12 @@ CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env) OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_deviceListMutex); + oc_mutex_lock(g_deviceListMutex); if (!g_deviceList) { OIC_LOG(ERROR, TAG, "g_deviceList is null"); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } @@ -2897,7 +3764,7 @@ CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env) OICFree(g_deviceList); g_deviceList = NULL; - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_OK; } @@ -2907,12 +3774,12 @@ CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address) VERIFY_NON_NULL(address, TAG, "address is null"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_deviceListMutex); + oc_mutex_lock(g_deviceListMutex); if (!g_deviceList) { OIC_LOG(ERROR, TAG, "g_deviceList is null"); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } @@ -2923,7 +3790,7 @@ CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address) if (!jarrayObj) { OIC_LOG(ERROR, TAG, "jarrayObj is null"); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } @@ -2931,7 +3798,7 @@ CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address) if (!jni_setAddress) { OIC_LOG(ERROR, TAG, "jni_setAddress is null"); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } @@ -2939,7 +3806,8 @@ CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address) if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); - ca_mutex_unlock(g_deviceListMutex); + CACheckJNIException(env); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } @@ -2947,12 +3815,13 @@ CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address) if (!remoteAddress) { OIC_LOG(ERROR, TAG, "remoteAddress is null"); + CACheckJNIException(env); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } - if (!strcmp(setAddress, remoteAddress)) + if (!strcasecmp(setAddress, remoteAddress)) { OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress); (*env)->DeleteGlobalRef(env, jarrayObj); @@ -2963,17 +3832,17 @@ CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address) if (NULL == u_arraylist_remove(g_deviceList, index)) { OIC_LOG(ERROR, TAG, "List removal failed."); - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_FAILED; } - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); return CA_STATUS_OK; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, address, remoteAddress); } - ca_mutex_unlock(g_deviceListMutex); + oc_mutex_unlock(g_deviceListMutex); OIC_LOG(DEBUG, TAG, "There are no object in the device list"); return CA_STATUS_OK; @@ -2989,12 +3858,12 @@ CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt) VERIFY_NON_NULL(env, TAG, "env is null"); VERIFY_NON_NULL(gatt, TAG, "gatt is null"); - ca_mutex_lock(g_gattObjectMutex); + oc_mutex_lock(g_gattObjectMutex); if (!g_gattObjectList) { OIC_LOG(ERROR, TAG, "g_gattObjectList is not available"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3002,7 +3871,7 @@ CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt) if (!jni_remoteAddress) { OIC_LOG(ERROR, TAG, "jni_remoteAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3010,7 +3879,9 @@ CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt) if (!remoteAddress) { OIC_LOG(ERROR, TAG, "remoteAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_remoteAddress); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3023,20 +3894,19 @@ CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt) } (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); - ca_mutex_unlock(g_gattObjectMutex); + (*env)->DeleteLocalRef(env, jni_remoteAddress); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_OK; } bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress) { - OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList"); VERIFY_NON_NULL(env, TAG, "env is null"); VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true); uint32_t length = u_arraylist_length(g_gattObjectList); for (uint32_t index = 0; index < length; index++) { - jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index); if (!jarrayObj) { @@ -3055,20 +3925,20 @@ bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress) if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_setAddress); return true; } - if (!strcmp(remoteAddress, setAddress)) + if (!strcasecmp(remoteAddress, setAddress)) { OIC_LOG(DEBUG, TAG, "the device is already set"); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); + (*env)->DeleteLocalRef(env, jni_setAddress); return true; } - else - { - (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - continue; - } + (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); + (*env)->DeleteLocalRef(env, jni_setAddress); } OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added"); @@ -3081,7 +3951,7 @@ jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress) VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL); VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL); - ca_mutex_lock(g_gattObjectMutex); + oc_mutex_lock(g_gattObjectMutex); uint32_t length = u_arraylist_length(g_gattObjectList); for (uint32_t index = 0; index < length; index++) { @@ -3089,7 +3959,7 @@ jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress) if (!jarrayObj) { OIC_LOG(ERROR, TAG, "jarrayObj is null"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return NULL; } @@ -3097,7 +3967,7 @@ jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress) if (!jni_setAddress) { OIC_LOG(ERROR, TAG, "jni_setAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return NULL; } @@ -3105,21 +3975,24 @@ jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress) if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_setAddress); + oc_mutex_unlock(g_gattObjectMutex); return NULL; } - if (!strcmp(remoteAddress, setAddress)) + if (!strcasecmp(remoteAddress, setAddress)) { OIC_LOG(DEBUG, TAG, "the device is already set"); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return jarrayObj; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); + (*env)->DeleteLocalRef(env, jni_setAddress); } - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); OIC_LOG(DEBUG, TAG, "There are no the gatt object in list"); return NULL; } @@ -3129,11 +4002,11 @@ CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env) OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_gattObjectMutex); + oc_mutex_lock(g_gattObjectMutex); if (!g_gattObjectList) { OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_OK; } @@ -3153,7 +4026,7 @@ CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env) OICFree(g_gattObjectList); g_gattObjectList = NULL; OIC_LOG(INFO, TAG, "g_gattObjectList is removed"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_OK; } @@ -3163,11 +4036,11 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) VERIFY_NON_NULL(gatt, TAG, "gatt is null"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_gattObjectMutex); + oc_mutex_lock(g_gattObjectMutex); if (!g_gattObjectList) { OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_OK; } @@ -3178,7 +4051,7 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) if (!jarrayObj) { OIC_LOG(ERROR, TAG, "jarrayObj is null"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3186,7 +4059,7 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) if (!jni_setAddress) { OIC_LOG(ERROR, TAG, "jni_setAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3194,7 +4067,8 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + CACheckJNIException(env); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3203,7 +4077,7 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) { OIC_LOG(ERROR, TAG, "jni_remoteAddress is null"); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3211,12 +4085,13 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) if (!remoteAddress) { OIC_LOG(ERROR, TAG, "remoteAddress is null"); + CACheckJNIException(env); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } - if (!strcmp(setAddress, remoteAddress)) + if (!strcasecmp(setAddress, remoteAddress)) { OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress); (*env)->DeleteGlobalRef(env, jarrayObj); @@ -3227,17 +4102,17 @@ CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt) if (NULL == u_arraylist_remove(g_gattObjectList, index)) { OIC_LOG(ERROR, TAG, "List removal failed."); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_OK; } (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress); } - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); OIC_LOG(DEBUG, TAG, "there are no target object"); return CA_STATUS_OK; } @@ -3248,11 +4123,11 @@ CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr) VERIFY_NON_NULL(addr, TAG, "addr is null"); VERIFY_NON_NULL(env, TAG, "env is null"); - ca_mutex_lock(g_gattObjectMutex); + oc_mutex_lock(g_gattObjectMutex); if (!g_gattObjectList) { OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_OK; } @@ -3263,7 +4138,7 @@ CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr) if (!jarrayObj) { OIC_LOG(ERROR, TAG, "jarrayObj is null"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3271,7 +4146,7 @@ CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr) if (!jni_setAddress) { OIC_LOG(ERROR, TAG, "jni_setAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3279,7 +4154,8 @@ CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr) if (!setAddress) { OIC_LOG(ERROR, TAG, "setAddress is null"); - ca_mutex_unlock(g_gattObjectMutex); + CACheckJNIException(env); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } @@ -3288,451 +4164,209 @@ CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr) { OIC_LOG(ERROR, TAG, "remoteAddress is null"); (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - ca_mutex_unlock(g_gattObjectMutex); - return CA_STATUS_FAILED; - } - - if (!strcmp(setAddress, remoteAddress)) - { - OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress); - (*env)->DeleteGlobalRef(env, jarrayObj); - jarrayObj = NULL; - (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - (*env)->ReleaseStringUTFChars(env, addr, remoteAddress); - if (NULL == u_arraylist_remove(g_gattObjectList, index)) - { - OIC_LOG(ERROR, TAG, "List removal failed."); - ca_mutex_unlock(g_gattObjectMutex); - return CA_STATUS_FAILED; - } - ca_mutex_unlock(g_gattObjectMutex); - return CA_STATUS_OK; - } - (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); - (*env)->ReleaseStringUTFChars(env, addr, remoteAddress); - } - - ca_mutex_unlock(g_gattObjectMutex); - OIC_LOG(DEBUG, TAG, "there are no target object"); - return CA_STATUS_FAILED; -} - -jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice) -{ - OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice"); - - VERIFY_NON_NULL_RET(env, TAG, "env", NULL); - VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL); - - // get Bluetooth Address - jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice); - if (!jni_btTargetAddress) - { - OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed"); - return NULL; - } - - const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL); - if (!targetAddress) - { - OIC_LOG(ERROR, TAG, "targetAddress is not available"); - return NULL; - } - - // get method ID of getDevice() - jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, - "getDevice", METHODID_BT_DEVICE); - if (!jni_mid_getDevice) - { - OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null"); - (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); - return NULL; - } - - ca_mutex_lock(g_gattObjectMutex); - - size_t length = u_arraylist_length(g_gattObjectList); - OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length); - OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress); - - for (size_t index = 0; index < length; index++) - { - jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index); - if (!jarrayObj) - { - ca_mutex_unlock(g_gattObjectMutex); - OIC_LOG(ERROR, TAG, "jarrayObj is null"); - (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); - return NULL; - } - - jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice); - if (!jni_obj_device) - { - ca_mutex_unlock(g_gattObjectMutex); - OIC_LOG(ERROR, TAG, "jni_obj_device is null"); - (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); - return NULL; - } - - jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device); - if (!jni_btAddress) - { - ca_mutex_unlock(g_gattObjectMutex); - OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed"); - (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); - return NULL; - } - - const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL); - if (!btAddress) - { - ca_mutex_unlock(g_gattObjectMutex); - OIC_LOG(ERROR, TAG, "btAddress is not available"); - (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); - return NULL; - } - - OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index); - if (!strcmp(targetAddress, btAddress)) - { - OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device"); - - // get LE address - jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj); - if (!jni_LEAddress) - { - OIC_LOG(ERROR, TAG, "jni_LEAddress is null"); - } - ca_mutex_unlock(g_gattObjectMutex); - (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); - (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress); - (*env)->DeleteLocalRef(env, jni_btAddress); - (*env)->DeleteLocalRef(env, jni_obj_device); - return jni_LEAddress; - } - (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress); - (*env)->DeleteLocalRef(env, jni_btAddress); - (*env)->DeleteLocalRef(env, jni_obj_device); - } - ca_mutex_unlock(g_gattObjectMutex); - - (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); - OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress); - return NULL; -} - -/** - * BT State List - */ - -CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type, - uint16_t target_state) -{ - VERIFY_NON_NULL(address, TAG, "address is null"); - VERIFY_NON_NULL(address, TAG, "state_type is null"); - VERIFY_NON_NULL(address, TAG, "target_state is null"); - - if (!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "gdevice_list is null"); - return CA_STATUS_FAILED; - } - - ca_mutex_lock(g_deviceStateListMutex); - - if (CALEClientIsDeviceInList(address)) - { - CALEState_t* curState = CALEClientGetStateInfo(address); - if(!curState) - { - OIC_LOG(ERROR, TAG, "curState is null"); - ca_mutex_unlock(g_deviceStateListMutex); - return CA_STATUS_FAILED; - } - - switch(state_type) - { - case CA_LE_CONNECTION_STATE: - curState->connectedState = target_state; - break; - case CA_LE_SEND_STATE: - curState->sendState = target_state; - break; - default: - break; - } - OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d", - curState->address, curState->connectedState, curState->sendState, - curState->autoConnectFlag); - } - else /** state is added newly **/ - { - if (strlen(address) > CA_MACADDR_SIZE) - { - OIC_LOG(ERROR, TAG, "address is not proper"); - ca_mutex_unlock(g_deviceStateListMutex); - return CA_STATUS_INVALID_PARAM; - } - - CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate)); - if (!newstate) - { - OIC_LOG(ERROR, TAG, "out of memory"); - ca_mutex_unlock(g_deviceStateListMutex); - return CA_MEMORY_ALLOC_FAILED; - } - - OICStrcpy(newstate->address, sizeof(newstate->address), address); - - switch(state_type) - { - case CA_LE_CONNECTION_STATE: - newstate->connectedState = target_state; - newstate->sendState = STATE_SEND_NONE; - break; - case CA_LE_SEND_STATE: - newstate->connectedState = STATE_DISCONNECTED; - newstate->sendState = target_state; - break; - default: - break; - } - OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, " - "conn : %d, send : %d, ACFlag : %d", - newstate->address, newstate->connectedState, newstate->sendState, - newstate->autoConnectFlag); - u_arraylist_add(g_deviceStateList, newstate); // update new state - } - ca_mutex_unlock(g_deviceStateListMutex); - - return CA_STATUS_OK; -} - -bool CALEClientIsDeviceInList(const char* remoteAddress) -{ - VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false); - - if (!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "g_deviceStateList is null"); - return false; - } - - uint32_t length = u_arraylist_length(g_deviceStateList); - for (uint32_t index = 0; index < length; index++) - { - CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index); - if (!state) - { - OIC_LOG(ERROR, TAG, "CALEState_t object is null"); - return false; - } - - if (!strcmp(remoteAddress, state->address)) - { - OIC_LOG(DEBUG, TAG, "the device is already set"); - return true; - } - else - { - continue; - } - } - - OIC_LOG(DEBUG, TAG, "there are no the device in list."); - return false; -} - -CAResult_t CALEClientRemoveAllDeviceState() -{ - OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState"); - - ca_mutex_lock(g_deviceStateListMutex); - if (!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "g_deviceStateList is null"); - ca_mutex_unlock(g_deviceStateListMutex); - return CA_STATUS_FAILED; - } - - uint32_t length = u_arraylist_length(g_deviceStateList); - for (uint32_t index = 0; index < length; index++) - { - CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index); - if (!state) - { - OIC_LOG(ERROR, TAG, "jarrayObj is null"); - continue; - } - OICFree(state); - } - - OICFree(g_deviceStateList); - g_deviceStateList = NULL; - ca_mutex_unlock(g_deviceStateListMutex); - - return CA_STATUS_OK; -} - -CAResult_t CALEClientResetDeviceStateForAll() -{ - OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll"); - - ca_mutex_lock(g_deviceStateListMutex); - if (!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "g_deviceStateList is null"); - ca_mutex_unlock(g_deviceStateListMutex); - return CA_STATUS_FAILED; - } - - size_t length = u_arraylist_length(g_deviceStateList); - for (size_t index = 0; index < length; index++) - { - CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index); - if (!state) - { - OIC_LOG(ERROR, TAG, "jarrayObj is null"); - continue; - } - - // autoConnectFlag value will be not changed, - // since it has reset only termination case. - state->connectedState = STATE_DISCONNECTED; - state->sendState = STATE_SEND_NONE; - } - ca_mutex_unlock(g_deviceStateListMutex); - - return CA_STATUS_OK; -} - -CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress) -{ - OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState"); - VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null"); - - if (!g_deviceStateList) - { - OIC_LOG(ERROR, TAG, "g_deviceStateList is null"); - return CA_STATUS_FAILED; - } - - uint32_t length = u_arraylist_length(g_deviceStateList); - for (uint32_t index = 0; index < length; index++) - { - CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index); - if (!state) - { - OIC_LOG(ERROR, TAG, "CALEState_t object is null"); - continue; + oc_mutex_unlock(g_gattObjectMutex); + return CA_STATUS_FAILED; } - if (!strcmp(state->address, remoteAddress)) + if (!strcasecmp(setAddress, remoteAddress)) { - OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address); - - CALEState_t* targetState = (CALEState_t*)u_arraylist_remove(g_deviceStateList, - index); - if (NULL == targetState) + OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress); + (*env)->DeleteGlobalRef(env, jarrayObj); + jarrayObj = NULL; + (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); + (*env)->ReleaseStringUTFChars(env, addr, remoteAddress); + if (NULL == u_arraylist_remove(g_gattObjectList, index)) { OIC_LOG(ERROR, TAG, "List removal failed."); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_FAILED; } - - OICFree(targetState); + oc_mutex_unlock(g_gattObjectMutex); return CA_STATUS_OK; } + (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress); + (*env)->ReleaseStringUTFChars(env, addr, remoteAddress); } - return CA_STATUS_OK; + oc_mutex_unlock(g_gattObjectMutex); + OIC_LOG(DEBUG, TAG, "there are no target object"); + return CA_STATUS_FAILED; } -CALEState_t* CALEClientGetStateInfo(const char* remoteAddress) +jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice) { - VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL); + VERIFY_NON_NULL_RET(env, TAG, "env", NULL); + VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL); - if (!g_deviceStateList) + // get Bluetooth Address + jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice); + if (!jni_btTargetAddress) { - OIC_LOG(ERROR, TAG, "g_deviceStateList is null"); + OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed"); return NULL; } - uint32_t length = u_arraylist_length(g_deviceStateList); - OIC_LOG_V(DEBUG, TAG, "length of deviceStateList : %d", length); - OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress); + const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL); + if (!targetAddress) + { + OIC_LOG(ERROR, TAG, "targetAddress is not available"); + CACheckJNIException(env); + return NULL; + } - for (uint32_t index = 0; index < length; index++) + // get method ID of getDevice() + jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, + "getDevice", METHODID_BT_DEVICE); + if (!jni_mid_getDevice) + { + OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null"); + (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); + return NULL; + } + + oc_mutex_lock(g_gattObjectMutex); + + size_t length = u_arraylist_length(g_gattObjectList); + OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length); + OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress); + + for (size_t index = 0; index < length; index++) { - CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index); - if (!state) + jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index); + if (!jarrayObj) { - OIC_LOG(ERROR, TAG, "CALEState_t object is null"); - continue; + oc_mutex_unlock(g_gattObjectMutex); + OIC_LOG(ERROR, TAG, "jarrayObj is null"); + (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); + return NULL; + } + + jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice); + if (!jni_obj_device) + { + CACheckJNIException(env); + oc_mutex_unlock(g_gattObjectMutex); + OIC_LOG(ERROR, TAG, "jni_obj_device is null"); + (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); + return NULL; + } + + jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device); + if (!jni_btAddress) + { + oc_mutex_unlock(g_gattObjectMutex); + OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed"); + (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); + (*env)->DeleteLocalRef(env, jni_obj_device); + return NULL; } - OIC_LOG_V(DEBUG, TAG, "state address : %s (idx: %d)", state->address, index); + const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL); + if (!btAddress) + { + CACheckJNIException(env); + oc_mutex_unlock(g_gattObjectMutex); + OIC_LOG(ERROR, TAG, "btAddress is not available"); + (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); + (*env)->DeleteLocalRef(env, jni_btAddress); + (*env)->DeleteLocalRef(env, jni_obj_device); + return NULL; + } - if (!strcmp(state->address, remoteAddress)) + OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index); + if (!strcasecmp(targetAddress, btAddress)) { - OIC_LOG(DEBUG, TAG, "found state"); - return state; + OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device"); + + // get LE address + jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj); + if (!jni_LEAddress) + { + OIC_LOG(ERROR, TAG, "jni_LEAddress is null"); + } + oc_mutex_unlock(g_gattObjectMutex); + (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); + (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress); + (*env)->DeleteLocalRef(env, jni_btAddress); + (*env)->DeleteLocalRef(env, jni_obj_device); + return jni_LEAddress; } + (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress); + (*env)->DeleteLocalRef(env, jni_btAddress); + (*env)->DeleteLocalRef(env, jni_obj_device); } + oc_mutex_unlock(g_gattObjectMutex); - OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in deviceStateList", remoteAddress); + (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress); + OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress); return NULL; } -bool CALEClientIsValidState(const char* remoteAddress, uint16_t state_type, - uint16_t target_state) +/** + * BT State List + */ +CAResult_t CALEClientUpdateDeviceStateWithBtDevice(JNIEnv *env, + jobject device, + uint16_t state_type, + uint16_t target_state) { - OIC_LOG_V(DEBUG, TAG, "CALEClientIsValidState : type[%d], target state[%d]", - state_type, target_state); - VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false); + VERIFY_NON_NULL(device, TAG, "device is null"); - ca_mutex_lock(g_deviceStateListMutex); - if (!g_deviceStateList) + // get Bluetooth Address + jstring jni_Address = CALEGetAddressFromBTDevice(env, device); + if (!jni_Address) { - OIC_LOG(ERROR, TAG, "g_deviceStateList is null"); - ca_mutex_unlock(g_deviceStateListMutex); - return false; + OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed"); + return CA_STATUS_FAILED; } - CALEState_t* state = CALEClientGetStateInfo(remoteAddress); - if (NULL == state) + const char* address = (*env)->GetStringUTFChars(env, jni_Address, NULL); + if (!address) { - OIC_LOG(ERROR, TAG, "state is null"); - ca_mutex_unlock(g_deviceStateListMutex); - return false; + OIC_LOG(ERROR, TAG, "targetAddress is not available"); + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_Address); + return CA_STATUS_FAILED; } - uint16_t curValue = 0; - switch(state_type) + if (CALEIsValidState(address, state_type, target_state, + g_deviceStateList, + g_deviceStateListMutex)) { - case CA_LE_CONNECTION_STATE: - curValue = state->connectedState; - break; - case CA_LE_SEND_STATE: - curValue = state->sendState; - break; - default: - break; + (*env)->DeleteLocalRef(env, jni_Address); + return CA_STATUS_OK; } - if (target_state == curValue) - { - ca_mutex_unlock(g_deviceStateListMutex); - return true; - } - else + CAResult_t res = CALEUpdateDeviceState(address, state_type, + target_state, + g_deviceStateList, + g_deviceStateListMutex); + if (CA_STATUS_OK != res) { - ca_mutex_unlock(g_deviceStateListMutex); - return false; + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); } + (*env)->ReleaseStringUTFChars(env, jni_Address, address); + (*env)->DeleteLocalRef(env, jni_Address); - ca_mutex_unlock(g_deviceStateListMutex); - return false; + return res; +} + +CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, + jint state_idx, jboolean flag) +{ + return CALESetFlagToState(env, jni_address, state_idx, flag, + g_deviceStateList, g_deviceStateListMutex); +} + +jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx) +{ + return CALEGetFlagFromState(env, jni_address, state_idx, g_deviceStateList, + g_deviceStateListMutex); +} + +uint16_t CALEClientGetMtuSize(const char* address) +{ + return CALEGetMtuSize(address, g_deviceStateList, g_deviceStateListMutex); } void CALEClientCreateDeviceList() @@ -3762,6 +4396,11 @@ void CALEClientCreateDeviceList() } } +CAResult_t CALEClientResetDeviceStateForAll() +{ + return CALEResetDeviceStateForAll(g_deviceStateList, g_deviceStateListMutex); +} + /** * Check Sent Count for remove g_sendBuffer */ @@ -3771,7 +4410,7 @@ void CALEClientUpdateSendCnt(JNIEnv *env) VERIFY_NON_NULL_VOID(env, TAG, "env is null"); // mutex lock - ca_mutex_lock(g_threadMutex); + oc_mutex_lock(g_threadMutex); g_currentSentCnt++; @@ -3780,139 +4419,153 @@ void CALEClientUpdateSendCnt(JNIEnv *env) g_targetCnt = 0; g_currentSentCnt = 0; - if (g_sendBuffer) - { - (*env)->DeleteGlobalRef(env, g_sendBuffer); - g_sendBuffer = NULL; - } + CALEDeleteSendBuffer(env); + // notity the thread - ca_cond_signal(g_threadCond); + oc_cond_signal(g_threadCond); + oc_cond_signal(g_threadWriteCharacteristicCond); CALEClientSetSendFinishFlag(true); OIC_LOG(DEBUG, TAG, "set signal for send data"); } + +#ifdef SCAN_INTERVAL + // reset interval scan logic + CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE); +#endif + // mutex unlock - ca_mutex_unlock(g_threadMutex); + oc_mutex_unlock(g_threadMutex); } CAResult_t CALEClientInitGattMutexVaraibles() { if (NULL == g_bleReqRespClientCbMutex) { - g_bleReqRespClientCbMutex = ca_mutex_new(); + g_bleReqRespClientCbMutex = oc_mutex_new(); if (NULL == g_bleReqRespClientCbMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_bleServerBDAddressMutex) { - g_bleServerBDAddressMutex = ca_mutex_new(); + g_bleServerBDAddressMutex = oc_mutex_new(); if (NULL == g_bleServerBDAddressMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_threadMutex) { - g_threadMutex = ca_mutex_new(); + g_threadMutex = oc_mutex_new(); if (NULL == g_threadMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_threadSendMutex) { - g_threadSendMutex = ca_mutex_new(); + g_threadSendMutex = oc_mutex_new(); if (NULL == g_threadSendMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_deviceListMutex) { - g_deviceListMutex = ca_mutex_new(); + g_deviceListMutex = oc_mutex_new(); if (NULL == g_deviceListMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_gattObjectMutex) { - g_gattObjectMutex = ca_mutex_new(); + g_gattObjectMutex = oc_mutex_new(); if (NULL == g_gattObjectMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_deviceStateListMutex) { - g_deviceStateListMutex = ca_mutex_new(); + g_deviceStateListMutex = oc_mutex_new(); if (NULL == g_deviceStateListMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_SendFinishMutex) { - g_SendFinishMutex = ca_mutex_new(); + g_SendFinishMutex = oc_mutex_new(); if (NULL == g_SendFinishMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_threadWriteCharacteristicMutex) { - g_threadWriteCharacteristicMutex = ca_mutex_new(); + g_threadWriteCharacteristicMutex = oc_mutex_new(); if (NULL == g_threadWriteCharacteristicMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_deviceScanRetryDelayMutex) { - g_deviceScanRetryDelayMutex = ca_mutex_new(); + g_deviceScanRetryDelayMutex = oc_mutex_new(); if (NULL == g_deviceScanRetryDelayMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_threadSendStateMutex) { - g_threadSendStateMutex = ca_mutex_new(); + g_threadSendStateMutex = oc_mutex_new(); if (NULL == g_threadSendStateMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } if (NULL == g_threadScanIntervalMutex) { - g_threadScanIntervalMutex = ca_mutex_new(); + g_threadScanIntervalMutex = oc_mutex_new(); if (NULL == g_threadScanIntervalMutex) { - OIC_LOG(ERROR, TAG, "ca_mutex_new has failed"); + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); + return CA_STATUS_FAILED; + } + } + + if (NULL == g_setValueMutex) + { + g_setValueMutex = oc_mutex_new(); + if (NULL == g_setValueMutex) + { + OIC_LOG(ERROR, TAG, "oc_mutex_new has failed"); return CA_STATUS_FAILED; } } @@ -3922,44 +4575,53 @@ CAResult_t CALEClientInitGattMutexVaraibles() void CALEClientTerminateGattMutexVariables() { - ca_mutex_free(g_bleReqRespClientCbMutex); + oc_mutex_free(g_bleReqRespClientCbMutex); g_bleReqRespClientCbMutex = NULL; - ca_mutex_free(g_bleServerBDAddressMutex); + oc_mutex_free(g_bleServerBDAddressMutex); g_bleServerBDAddressMutex = NULL; - ca_mutex_free(g_threadMutex); + oc_mutex_free(g_threadMutex); g_threadMutex = NULL; - ca_mutex_free(g_threadSendMutex); + oc_mutex_free(g_threadSendMutex); g_threadSendMutex = NULL; - ca_mutex_free(g_deviceListMutex); + oc_mutex_free(g_deviceListMutex); g_deviceListMutex = NULL; - ca_mutex_free(g_SendFinishMutex); + oc_mutex_free(g_SendFinishMutex); g_SendFinishMutex = NULL; - ca_mutex_free(g_threadWriteCharacteristicMutex); + oc_mutex_free(g_threadWriteCharacteristicMutex); g_threadWriteCharacteristicMutex = NULL; - ca_mutex_free(g_deviceScanRetryDelayMutex); + oc_mutex_free(g_deviceScanRetryDelayMutex); g_deviceScanRetryDelayMutex = NULL; - ca_mutex_free(g_threadSendStateMutex); + oc_mutex_free(g_threadSendStateMutex); g_threadSendStateMutex = NULL; - ca_mutex_free(g_threadScanIntervalMutex); + oc_mutex_free(g_threadScanIntervalMutex); g_threadScanIntervalMutex = NULL; + + oc_mutex_free(g_gattObjectMutex); + g_gattObjectMutex = NULL; + + oc_mutex_free(g_deviceStateListMutex); + g_deviceStateListMutex = NULL; + + oc_mutex_free(g_setValueMutex); + g_setValueMutex = NULL; } void CALEClientSetSendFinishFlag(bool flag) { OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag); - ca_mutex_lock(g_SendFinishMutex); + oc_mutex_lock(g_SendFinishMutex); g_isFinishedSendData = flag; - ca_mutex_unlock(g_SendFinishMutex); + oc_mutex_unlock(g_SendFinishMutex); } /** @@ -3971,22 +4633,22 @@ CAResult_t CAStartLEGattClient() // init mutex for send logic if (!g_deviceDescCond) { - g_deviceDescCond = ca_cond_new(); + g_deviceDescCond = oc_cond_new(); } if (!g_threadCond) { - g_threadCond = ca_cond_new(); + g_threadCond = oc_cond_new(); } if (!g_threadWriteCharacteristicCond) { - g_threadWriteCharacteristicCond = ca_cond_new(); + g_threadWriteCharacteristicCond = oc_cond_new(); } if (!g_threadScanIntervalCond) { - g_threadScanIntervalCond = ca_cond_new(); + g_threadScanIntervalCond = oc_cond_new(); } CAResult_t ret = CALEClientStartScanWithInterval(); @@ -4015,7 +4677,6 @@ void CAStopLEGattClient() jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6); if (JNI_OK != res) { - OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer"); res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL); if (JNI_OK != res) @@ -4034,32 +4695,37 @@ void CAStopLEGattClient() CALEClientStopScanWithInterval(); - ca_mutex_lock(g_threadMutex); - OIC_LOG(DEBUG, TAG, "signal - connection cond"); - ca_cond_signal(g_threadCond); - CALEClientSetSendFinishFlag(true); - ca_mutex_unlock(g_threadMutex); - - ca_mutex_lock(g_threadWriteCharacteristicMutex); + oc_mutex_lock(g_threadWriteCharacteristicMutex); OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond"); - ca_cond_signal(g_threadWriteCharacteristicCond); - ca_mutex_unlock(g_threadWriteCharacteristicMutex); + oc_cond_signal(g_threadWriteCharacteristicCond); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); - ca_mutex_lock(g_deviceScanRetryDelayMutex); + CALEClientSetSendFinishFlag(true); + oc_mutex_lock(g_threadMutex); + OIC_LOG(DEBUG, TAG, "signal - g_threadCond cond"); + oc_cond_signal(g_threadCond); + oc_mutex_unlock(g_threadMutex); + + oc_mutex_lock(g_deviceScanRetryDelayMutex); OIC_LOG(DEBUG, TAG, "signal - delay cond"); - ca_cond_signal(g_deviceScanRetryDelayCond); - ca_mutex_unlock(g_deviceScanRetryDelayMutex); + oc_cond_signal(g_deviceScanRetryDelayCond); + oc_mutex_unlock(g_deviceScanRetryDelayMutex); - ca_mutex_lock(g_threadScanIntervalMutex); + oc_mutex_lock(g_threadScanIntervalMutex); OIC_LOG(DEBUG, TAG, "signal - delay cond"); - ca_cond_signal(g_threadScanIntervalCond); - ca_mutex_unlock(g_threadScanIntervalMutex); + oc_cond_signal(g_threadScanIntervalCond); + oc_mutex_unlock(g_threadScanIntervalMutex); - ca_cond_free(g_deviceDescCond); - ca_cond_free(g_threadCond); - ca_cond_free(g_threadWriteCharacteristicCond); - ca_cond_free(g_deviceScanRetryDelayCond); - ca_cond_free(g_threadScanIntervalCond); + oc_mutex_lock(g_threadSendMutex); + OIC_LOG(DEBUG, TAG, "signal - g_deviceDesc cond"); + oc_cond_signal(g_deviceDescCond); + oc_mutex_unlock(g_threadSendMutex); + + oc_cond_free(g_deviceDescCond); + oc_cond_free(g_threadCond); + oc_cond_free(g_threadWriteCharacteristicCond); + oc_cond_free(g_deviceScanRetryDelayCond); + oc_cond_free(g_threadScanIntervalCond); g_deviceDescCond = NULL; g_threadCond = NULL; @@ -4083,17 +4749,17 @@ CAResult_t CAInitializeLEGattClient() void CATerminateLEGattClient() { - OIC_LOG(DEBUG, TAG, "Terminate GATT Client"); + OIC_LOG(INFO, TAG, "IN - Terminate GATT Client"); CAStopLEGattClient(); CALEClientTerminate(); + OIC_LOG(INFO, TAG, "OUT - Terminate GATT Client"); } CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t *data, uint32_t dataLen, CALETransferType_t type, int32_t position) { - OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage"); - VERIFY_NON_NULL(data, TAG, "data is null"); + OIC_LOG(INFO, TAG, "call CALEClientSendUnicastMessage"); VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null"); if (LE_UNICAST != type || position < 0) @@ -4115,9 +4781,9 @@ CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback) { - ca_mutex_lock(g_bleReqRespClientCbMutex); + oc_mutex_lock(g_bleReqRespClientCbMutex); g_CABLEClientDataReceivedCallback = callback; - ca_mutex_unlock(g_bleReqRespClientCbMutex); + oc_mutex_unlock(g_bleReqRespClientCbMutex); } void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle) @@ -4128,7 +4794,6 @@ void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle) CAResult_t CAGetLEAddress(char **local_address) { VERIFY_NON_NULL(local_address, TAG, "local_address"); - OIC_LOG(INFO, TAG, "CAGetLEAddress is not support"); return CA_NOT_SUPPORTED; } @@ -4142,6 +4807,21 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, VERIFY_NON_NULL_VOID(callback, TAG, "callback is null"); g_leScanCallback = (*env)->NewGlobalRef(env, callback); + CACheckJNIException(env); +} + +JNIEXPORT void JNICALL +Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallbackForV21(JNIEnv *env, + jobject obj, + jobject callback) +{ + OIC_LOG(DEBUG, TAG, "caLeRegisterLeScanCallbackForV21"); + VERIFY_NON_NULL_VOID(env, TAG, "env is null"); + VERIFY_NON_NULL_VOID(obj, TAG, "obj is null"); + VERIFY_NON_NULL_VOID(callback, TAG, "callback is null"); + + g_leScanCallback = (*env)->NewGlobalRef(env, callback); + CACheckJNIException(env); } JNIEXPORT void JNICALL @@ -4154,6 +4834,7 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, j VERIFY_NON_NULL_VOID(callback, TAG, "callback is null"); g_leGattCallback = (*env)->NewGlobalRef(env, callback); + CACheckJNIException(env); } JNIEXPORT void JNICALL @@ -4171,6 +4852,38 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject o } } +JNIEXPORT void JNICALL +Java_org_iotivity_ca_CaLeClientInterface_caLeScanFailedCallback(JNIEnv *env, jobject obj, + jint errorCode) +{ + VERIFY_NON_NULL_VOID(env, TAG, "env is null"); + VERIFY_NON_NULL_VOID(obj, TAG, "obj is null"); + + switch (errorCode) + { + case 1: + OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_ALREADY_STARTED"); + break; + + case 2: + OIC_LOG(ERROR, TAG, + "BLE scan has failed, error is SCAN_FAILED_APPLICATION_REGISTRATION_FAILED"); + break; + + case 3: + OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_INTERNAL_ERROR"); + break; + + case 4: + OIC_LOG(ERROR, TAG, "BLE scan has failed, error is SCAN_FAILED_FEATURE_UNSUPPORTED"); + break; + + default: + OIC_LOG(ERROR, TAG, "BLE scan has failed with unknown error"); + break; + } +} + /* * Class: org_iotivity_ca_jar_caleinterface * Method: CALeGattConnectionStateChangeCallback @@ -4202,22 +4915,25 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(J if (!address) { OIC_LOG(ERROR, TAG, "address is null"); + CACheckJNIException(env); goto error_exit; } - OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address); + OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address); if (state_connected == newstate) { OIC_LOG(DEBUG, TAG, "LE is connected"); if (GATT_SUCCESS == status) { - CAResult_t res = CALEClientUpdateDeviceState(address, - CA_LE_CONNECTION_STATE, - STATE_CONNECTED); + CAResult_t res = CALEUpdateDeviceState(address, + CA_LE_CONNECTION_STATE, + STATE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex); (*env)->ReleaseStringUTFChars(env, jni_address, address); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed"); + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); goto error_exit; } @@ -4245,15 +4961,30 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(J { OIC_LOG(DEBUG, TAG, "LE is disconnected"); - CAResult_t res = CALEClientUpdateDeviceState(address, - CA_LE_CONNECTION_STATE, - STATE_DISCONNECTED); - (*env)->ReleaseStringUTFChars(env, jni_address, address); + if (CALEIsValidState(address, CA_LE_SEND_STATE, STATE_SEND_PREPARING, + g_deviceStateList, g_deviceStateListMutex)) + { + OIC_LOG(INFO, TAG, "current state is STATE_SEND_PREPARING"); + CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE, + STATE_SEND_FAIL, + g_deviceStateList, + g_deviceStateListMutex); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); + } + } + + CAResult_t res = CALEUpdateDeviceState(address, + CA_LE_CONNECTION_STATE, + STATE_DISCONNECTED, + g_deviceStateList, + g_deviceStateListMutex); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed"); - goto error_exit; + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); } + (*env)->ReleaseStringUTFChars(env, jni_address, address); res = CALEClientGattClose(env, gatt); if (CA_STATUS_OK != res) @@ -4266,22 +4997,14 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(J // this state is unexpected reason to disconnect // if the reason is suitable, connection logic of the device will be destroyed. OIC_LOG(INFO, TAG, "connection logic destroy"); - goto error_exit; } else { // other reason except for gatt_success is expected to running // background connection in BT platform. OIC_LOG(INFO, TAG, "unknown status or manual disconnected state"); - CALEClientUpdateSendCnt(env); - return; - } - - if (g_sendBuffer) - { - (*env)->DeleteGlobalRef(env, g_sendBuffer); - g_sendBuffer = NULL; } + CALEClientUpdateSendCnt(env); } return; @@ -4323,6 +5046,7 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIE const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); if (!address) { + CACheckJNIException(env); CALEClientSendFinish(env, gatt); return; } @@ -4354,41 +5078,47 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIE { OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res); - res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE); + res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE, + g_deviceStateList, g_deviceStateListMutex); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed"); + OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed"); goto error_exit; } - res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, - STATE_SERVICE_CONNECTED); + res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE, + STATE_SERVICE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed"); + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); goto error_exit; } - if (g_sendBuffer) + res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE); + if (CA_STATUS_OK != res) { - CAResult_t res = CALEClientWriteCharacteristic(env, gatt); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed"); - goto error_exit; - } + OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed"); + goto error_exit; } } else { - res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE); + res = CALESetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE, + g_deviceStateList, g_deviceStateListMutex); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed"); + OIC_LOG(ERROR, TAG, "CALESetFlagToState has failed"); goto error_exit; } } +#ifdef SCAN_INTERVAL + // reset interval scan logic + CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE); +#endif + OIC_LOG(INFO, TAG, "ServicesDiscovery is successful"); (*env)->ReleaseStringUTFChars(env, jni_address, address); return; @@ -4425,6 +5155,7 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback( const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); if (!address) { + CACheckJNIException(env); goto error_exit; } @@ -4437,22 +5168,27 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback( if (CA_STATUS_OK != res) { OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed"); - ca_mutex_lock(g_threadWriteCharacteristicMutex); + oc_mutex_lock(g_threadWriteCharacteristicMutex); g_isSignalSetFlag = true; - ca_cond_signal(g_threadWriteCharacteristicCond); - ca_mutex_unlock(g_threadWriteCharacteristicMutex); + oc_cond_signal(g_threadWriteCharacteristicCond); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); - CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE, - STATE_SEND_FAIL); + CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE, + STATE_SEND_FAIL, + g_deviceStateList, + g_deviceStateListMutex); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed"); + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); } if (g_clientErrorCallback) { jint length = (*env)->GetArrayLength(env, data); + CACheckJNIException(env); g_clientErrorCallback(address, data, length, CA_SEND_FAILED); + CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, length, + false, "writeChar failure"); } (*env)->ReleaseStringUTFChars(env, jni_address, address); @@ -4462,20 +5198,24 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback( else { OIC_LOG(DEBUG, TAG, "send success"); - CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE, - STATE_SEND_SUCCESS); + CAResult_t res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE, + STATE_SEND_SUCCESS, + g_deviceStateList, + g_deviceStateListMutex); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed"); + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); } - ca_mutex_lock(g_threadWriteCharacteristicMutex); + oc_mutex_lock(g_threadWriteCharacteristicMutex); OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal"); g_isSignalSetFlag = true; - ca_cond_signal(g_threadWriteCharacteristicCond); - ca_mutex_unlock(g_threadWriteCharacteristicMutex); + oc_cond_signal(g_threadWriteCharacteristicCond); + oc_mutex_unlock(g_threadWriteCharacteristicMutex); - CALEClientUpdateSendCnt(env); + CALogSendStateInfo(CA_ADAPTER_GATT_BTLE, address, 0, + (*env)->GetArrayLength(env, data), + true, "writeChar success"); } (*env)->ReleaseStringUTFChars(env, jni_address, address); @@ -4497,7 +5237,7 @@ JNIEXPORT void JNICALL Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback( JNIEnv *env, jobject obj, jobject gatt, jbyteArray data) { - OIC_LOG(INFO, TAG, "CALeGattCharacteristicChangedCallback"); + OIC_LOG(DEBUG, TAG, "CALeGattCharacteristicChangedCallback"); VERIFY_NON_NULL_VOID(env, TAG, "env is null"); VERIFY_NON_NULL_VOID(obj, TAG, "obj is null"); VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null"); @@ -4508,9 +5248,7 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback( jboolean isCopy; jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy); - - OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p", - jni_byte_responseData); + CACheckJNIException(env); uint8_t* receivedData = OICMalloc(length); if (!receivedData) @@ -4534,6 +5272,7 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback( if (!address) { OIC_LOG(ERROR, TAG, "address is null"); + CACheckJNIException(env); OICFree(receivedData); return; } @@ -4542,9 +5281,9 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback( receivedData, length); uint32_t sentLength = 0; - ca_mutex_lock(g_bleServerBDAddressMutex); + oc_mutex_lock(g_bleServerBDAddressMutex); g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength); - ca_mutex_unlock(g_bleServerBDAddressMutex); + oc_mutex_unlock(g_bleServerBDAddressMutex); (*env)->ReleaseStringUTFChars(env, jni_address, address); } @@ -4578,26 +5317,26 @@ Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); if (!address) { + CACheckJNIException(env); goto error_exit; } - CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, - STATE_SERVICE_CONNECTED); + CAResult_t res = CALEUpdateDeviceState(address, CA_LE_CONNECTION_STATE, + STATE_SERVICE_CONNECTED, + g_deviceStateList, + g_deviceStateListMutex); (*env)->ReleaseStringUTFChars(env, jni_address, address); if (CA_STATUS_OK != res) { - OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed"); + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); goto error_exit; } - if (g_sendBuffer) + res = CALEClientRequestMTU(env, gatt, CA_SUPPORTED_BLE_MTU_SIZE); + if (CA_STATUS_OK != res) { - CAResult_t res = CALEClientWriteCharacteristic(env, gatt); - if (CA_STATUS_OK != res) - { - OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed"); - goto error_exit; - } + OIC_LOG(ERROR, TAG, "CALEClientRequestMTU has failed"); + goto error_exit; } return; @@ -4607,3 +5346,67 @@ error_exit: CALEClientSendFinish(env, gatt); return; } + +JNIEXPORT void JNICALL +Java_org_iotivity_ca_CaLeClientInterface_caLeGattMtuChangedCallback(JNIEnv *env, + jobject obj, + jobject gatt, + jint mtu, + jint status) +{ + OIC_LOG_V(INFO, TAG, "caLeGattMtuChangedCallback - status %d, " + "mtu[%d-including Header size 3 byte]", status, mtu); + + (void)obj; + + if (0 == status || 133 == status) + { + if (g_sendBuffer) + { + CAResult_t res = CALEClientWriteCharacteristic(env, gatt); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed"); + } + } + else + { + OIC_LOG(INFO, TAG, "mtu nego is done"); + jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt); + if (!jni_address) + { + CALEClientSendFinish(env, gatt); + return; + } + + const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL); + if (!address) + { + CACheckJNIException(env); + (*env)->DeleteLocalRef(env, jni_address); + CALEClientSendFinish(env, gatt); + return; + } + + // update mtu size + CAResult_t res = CALESetMtuSize(address, mtu - CA_BLE_MTU_HEADER_SIZE, + g_deviceStateList, g_deviceStateListMutex); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALESetMtuSize has failed"); + } + + res = CALEUpdateDeviceState(address, CA_LE_SEND_STATE, + STATE_SEND_MTU_NEGO_SUCCESS, + g_deviceStateList, + g_deviceStateListMutex); + if (CA_STATUS_OK != res) + { + OIC_LOG(ERROR, TAG, "CALEUpdateDeviceState has failed"); + } + CALEClientUpdateSendCnt(env); + (*env)->ReleaseStringUTFChars(env, jni_address, address); + (*env)->DeleteLocalRef(env, jni_address); + } + } +}