1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
26 #include "caleclient.h"
27 #include "caleserver.h"
28 #include "caleutils.h"
29 #include "caleinterface.h"
30 #include "caadapterutils.h"
33 #include "oic_malloc.h"
34 #include "oic_string.h"
35 #include "cathreadpool.h" /* for thread pool */
37 #include "uarraylist.h"
38 #include "org_iotivity_ca_CaLeClientInterface.h"
40 #define TAG PCF("OIC_CA_LE_CLIENT")
42 #define MICROSECS_PER_SEC 1000000
43 #define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC
44 #define WAIT_TIME_SCAN_INTERVAL_DEFAULT 10
45 #define WAIT_TIME_SCANNED_CHECKING 30
47 #define GATT_CONNECTION_PRIORITY_BALANCED 0
48 #define GATT_FAILURE 257
49 #define GATT_INSUFFICIENT_AUTHENTICATION 5
50 #define GATT_INSUFFICIENT_ENCRYPTION 15
51 #define GATT_INVALID_ATTRIBUTE_LENGTH 13
52 #define GATT_INVALID_OFFSET 7
53 #define GATT_READ_NOT_PERMITTED 2
54 #define GATT_REQUEST_NOT_SUPPORTED 6
55 #define GATT_WRITE_NOT_PERMITTED 3
57 static ca_thread_pool_t g_threadPoolHandle = NULL;
60 static u_arraylist_t *g_deviceList = NULL; // device list to have same UUID
61 static u_arraylist_t *g_gattObjectList = NULL;
62 static u_arraylist_t *g_deviceStateList = NULL;
64 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
65 static CABLEErrorHandleCallback g_clientErrorCallback;
66 static jobject g_leScanCallback = NULL;
67 static jobject g_leGattCallback = NULL;
68 static jobject g_context = NULL;
69 static jobjectArray g_uuidList = NULL;
71 // it will be prevent to start send logic when adapter has stopped.
72 static bool g_isStartedLEClient = false;
74 static jbyteArray g_sendBuffer = NULL;
75 static uint32_t g_targetCnt = 0;
76 static uint32_t g_currentSentCnt = 0;
77 static bool g_isFinishedSendData = false;
78 static ca_mutex g_SendFinishMutex = NULL;
79 static ca_mutex g_threadMutex = NULL;
80 static ca_cond g_threadCond = NULL;
81 static ca_cond g_deviceDescCond = NULL;
83 static ca_mutex g_threadSendMutex = NULL;
84 static ca_mutex g_threadWriteCharacteristicMutex = NULL;
85 static ca_cond g_threadWriteCharacteristicCond = NULL;
86 static bool g_isSignalSetFlag = false;
88 static ca_mutex g_bleReqRespClientCbMutex = NULL;
89 static ca_mutex g_bleServerBDAddressMutex = NULL;
91 static ca_mutex g_deviceListMutex = NULL;
92 static ca_mutex g_gattObjectMutex = NULL;
93 static ca_mutex g_deviceStateListMutex = NULL;
95 static ca_mutex g_deviceScanRetryDelayMutex = NULL;
96 static ca_cond g_deviceScanRetryDelayCond = NULL;
98 static ca_mutex g_threadScanIntervalMutex = NULL;
99 static ca_cond g_threadScanIntervalCond = NULL;
101 static ca_mutex g_threadSendStateMutex = NULL;
103 static int32_t g_scanIntervalTime = WAIT_TIME_SCAN_INTERVAL_DEFAULT;
104 static int32_t g_scanIntervalTimePrev = WAIT_TIME_SCAN_INTERVAL_DEFAULT;
105 static int32_t g_intervalCount = 0;
106 static bool g_isWorkingScanThread = false;
107 static CALEScanState_t g_curScanningStep = BLE_SCAN_DISABLE;
108 static CALEScanState_t g_nextScanningStep = BLE_SCAN_ENABLE;
110 static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
113 * check if retry logic for connection routine has to be stopped or not.
114 * in case of error value including this method, connection routine has to be stopped.
115 * since there is no retry logic for this error reason in this client.
116 * @param state constant value of bluetoothgatt.
117 * @return true - waiting for background connection in BT platform.
118 * false - connection routine has to be stopped.
120 static bool CALECheckConnectionStateValue(jint state)
124 case GATT_CONNECTION_PRIORITY_BALANCED:
126 case GATT_INSUFFICIENT_AUTHENTICATION:
127 case GATT_INSUFFICIENT_ENCRYPTION:
128 case GATT_INVALID_ATTRIBUTE_LENGTH:
129 case GATT_INVALID_OFFSET:
130 case GATT_READ_NOT_PERMITTED:
131 case GATT_REQUEST_NOT_SUPPORTED:
132 case GATT_WRITE_NOT_PERMITTED:
139 void CALEClientSetScanInterval(int32_t intervalTime, int32_t workingCount,
140 CALEScanState_t nextScanningStep)
142 OIC_LOG_V(DEBUG, TAG, "CALEClientSetScanInterval : %d -> %d, next scan state will be %d",
143 g_scanIntervalTime, intervalTime, nextScanningStep);
145 // previous time should be stored.
146 if (0 < workingCount)
148 g_scanIntervalTimePrev = g_scanIntervalTime;
150 g_scanIntervalTime = intervalTime;
151 g_intervalCount = workingCount;
152 g_nextScanningStep = nextScanningStep;
155 void CALERestartScanWithInterval(int32_t intervalTime, int32_t workingCount,
156 CALEScanState_t nextScanningStep)
158 if (intervalTime == g_scanIntervalTime
159 && workingCount == g_intervalCount
160 && nextScanningStep == g_nextScanningStep)
162 OIC_LOG(DEBUG, TAG, "setting duplicate interval time");
166 CALEClientSetScanInterval(intervalTime, workingCount, nextScanningStep);
167 ca_cond_signal(g_threadScanIntervalCond);
170 static void CALEScanThread(void* object)
174 bool isAttached = false;
176 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
179 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
180 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
184 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
190 ca_mutex_lock(g_threadScanIntervalMutex);
191 while(g_isWorkingScanThread)
193 OIC_LOG(DEBUG, TAG, "scan waiting time out");
194 if (BLE_SCAN_ENABLE == g_curScanningStep)
197 CAResult_t ret = CALEClientStopScan();
198 if (CA_STATUS_OK != ret)
200 OIC_LOG(INFO, TAG, "CALEClientStopScan has failed");
206 CAResult_t ret = CALEClientStartScan();
207 if (CA_STATUS_OK != ret)
209 OIC_LOG(INFO, TAG, "CALEClientStartScan has failed");
213 OIC_LOG_V(DEBUG, TAG, "wait for Scan Interval Time during %d sec", g_scanIntervalTime);
214 if (CA_WAIT_SUCCESS == ca_cond_wait_for(g_threadScanIntervalCond,
215 g_threadScanIntervalMutex,
216 g_scanIntervalTime * MICROSECS_PER_SEC))
218 // called signal scan thread will be terminated
219 OIC_LOG(DEBUG, TAG, "signal scanInterval waiting");
220 if (BLE_SCAN_DISABLE == g_nextScanningStep)
222 g_curScanningStep = BLE_SCAN_ENABLE;
226 g_curScanningStep = BLE_SCAN_DISABLE;
231 if (BLE_SCAN_ENABLE == g_curScanningStep)
233 if (g_intervalCount > 0)
235 if (g_intervalCount == 1)
237 OIC_LOG(DEBUG, TAG, "reset default time");
238 CALEClientSetScanInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
241 OIC_LOG_V(DEBUG, TAG, "interval count : %d", g_intervalCount);
243 g_curScanningStep = BLE_SCAN_DISABLE;
247 g_curScanningStep = BLE_SCAN_ENABLE;
251 ca_mutex_unlock(g_threadScanIntervalMutex);
255 (*g_jvm)->DetachCurrentThread(g_jvm);
259 CAResult_t CALEClientStartScanWithInterval()
261 OIC_LOG(DEBUG, TAG, "IN - CALEClientStartScanWithInterval");
263 if (g_isWorkingScanThread)
265 OIC_LOG(DEBUG, TAG, "scan interval logic already running");
269 // initialize scan flags
270 g_curScanningStep = BLE_SCAN_DISABLE;
271 g_isWorkingScanThread = true;
273 g_scanIntervalTime = g_scanIntervalTimePrev;
274 g_nextScanningStep = BLE_SCAN_ENABLE;
276 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
277 CALEScanThread, NULL))
279 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
280 g_isWorkingScanThread = false;
281 return CA_STATUS_FAILED;
284 OIC_LOG(DEBUG, TAG, "OUT - CALEClientStartScanWithInterval");
288 void CALEClientStopScanWithInterval()
290 g_isWorkingScanThread = false;
291 ca_cond_signal(g_threadScanIntervalCond);
295 void CALEClientJniInit()
297 OIC_LOG(DEBUG, TAG, "CALEClientJniInit");
298 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
301 void CALEClientJNISetContext()
303 OIC_LOG(DEBUG, TAG, "CALEClientJNISetContext");
304 g_context = (jobject) CANativeJNIGetContext();
307 CAResult_t CALECreateJniInterfaceObject()
309 OIC_LOG(DEBUG, TAG, "CALECreateJniInterfaceObject");
313 OIC_LOG(ERROR, TAG, "g_context is null");
314 return CA_STATUS_FAILED;
319 OIC_LOG(ERROR, TAG, "g_jvm is null");
320 return CA_STATUS_FAILED;
323 bool isAttached = false;
325 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
328 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
329 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
333 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
334 return CA_STATUS_FAILED;
339 jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, "android/content/Context",
340 "getApplicationContext",
341 "()Landroid/content/Context;");
343 if (!mid_getApplicationContext)
345 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
346 return CA_STATUS_FAILED;
349 jobject jApplicationContext = (*env)->CallObjectMethod(env, g_context,
350 mid_getApplicationContext);
351 if (!jApplicationContext)
353 OIC_LOG(ERROR, TAG, "Could not get application context");
354 return CA_STATUS_FAILED;
357 jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
358 if (!jni_LEInterface)
360 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
364 jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
365 "(Landroid/content/Context;)V");
366 if (!LeInterfaceConstructorMethod)
368 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface constructor method");
372 (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, jApplicationContext);
373 OIC_LOG(DEBUG, TAG, "Create instance for CaLeClientInterface");
377 (*g_jvm)->DetachCurrentThread(g_jvm);
386 (*g_jvm)->DetachCurrentThread(g_jvm);
389 return CA_STATUS_FAILED;
392 CAResult_t CALEClientInitialize()
394 OIC_LOG(DEBUG, TAG, "CALEClientInitialize");
400 OIC_LOG(ERROR, TAG, "g_jvm is null");
401 return CA_STATUS_FAILED;
404 bool isAttached = false;
406 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
409 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
410 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
414 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
415 return CA_STATUS_FAILED;
420 CAResult_t ret = CALECheckPlatformVersion(env, 18);
421 if (CA_STATUS_OK != ret)
423 OIC_LOG(ERROR, TAG, "it is not supported");
427 (*g_jvm)->DetachCurrentThread(g_jvm);
433 ret = CALEClientInitGattMutexVaraibles();
434 if (CA_STATUS_OK != ret)
436 OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
437 CALEClientTerminateGattMutexVariables();
441 (*g_jvm)->DetachCurrentThread(g_jvm);
447 g_deviceDescCond = ca_cond_new();
449 // init mutex for send logic
450 g_threadCond = ca_cond_new();
451 g_threadWriteCharacteristicCond = ca_cond_new();
452 g_deviceScanRetryDelayCond = ca_cond_new();
453 g_threadScanIntervalCond = ca_cond_new();
455 CALEClientCreateDeviceList();
456 CALEClientJNISetContext();
458 ret = CALEClientCreateUUIDList();
459 if (CA_STATUS_OK != ret)
461 OIC_LOG(ERROR, TAG, "CALEClientCreateUUIDList has failed");
465 (*g_jvm)->DetachCurrentThread(g_jvm);
471 ret = CALECreateJniInterfaceObject(); /* create java caleinterface instance*/
472 if (CA_STATUS_OK != ret)
474 OIC_LOG(ERROR, TAG, "CALECreateJniInterfaceObject has failed");
478 (*g_jvm)->DetachCurrentThread(g_jvm);
483 g_isStartedLEClient = true;
487 (*g_jvm)->DetachCurrentThread(g_jvm);
493 void CALEClientTerminate()
495 OIC_LOG(DEBUG, TAG, "CALEClientTerminate");
499 OIC_LOG(ERROR, TAG, "g_jvm is null");
503 bool isAttached = false;
505 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
508 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
509 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
513 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
519 if (g_leScanCallback)
521 (*env)->DeleteGlobalRef(env, g_leScanCallback);
522 g_leScanCallback = NULL;
525 if (g_leGattCallback)
527 (*env)->DeleteGlobalRef(env, g_leGattCallback);
528 g_leGattCallback = NULL;
533 (*env)->DeleteGlobalRef(env, g_sendBuffer);
539 (*env)->DeleteGlobalRef(env, g_uuidList);
543 CAResult_t ret = CALEClientRemoveAllDeviceState();
544 if (CA_STATUS_OK != ret)
546 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed");
549 ret = CALEClientRemoveAllScanDevices(env);
550 if (CA_STATUS_OK != ret)
552 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
555 ret = CALEClientRemoveAllGattObjs(env);
556 if (CA_STATUS_OK != ret)
558 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllGattObjs has failed");
561 CALEClientSetSendFinishFlag(true);
563 CALEClientTerminateGattMutexVariables();
564 CALEClientDestroyJniInterface();
566 ca_cond_free(g_deviceDescCond);
567 ca_cond_free(g_threadCond);
568 ca_cond_free(g_threadWriteCharacteristicCond);
569 ca_cond_free(g_deviceScanRetryDelayCond);
570 ca_cond_free(g_threadScanIntervalCond);
572 g_deviceDescCond = NULL;
574 g_threadWriteCharacteristicCond = NULL;
575 g_deviceScanRetryDelayCond = NULL;
576 g_threadScanIntervalCond = NULL;
578 g_isSignalSetFlag = false;
581 CALEClientStopScanWithInterval();
585 (*g_jvm)->DetachCurrentThread(g_jvm);
589 CAResult_t CALEClientDestroyJniInterface()
591 OIC_LOG(DEBUG, TAG, "CALEClientDestroyJniInterface");
595 OIC_LOG(ERROR, TAG, "g_jvm is null");
596 return CA_STATUS_FAILED;
599 bool isAttached = false;
601 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
604 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
605 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
609 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
610 return CA_STATUS_FAILED;
615 jclass jni_LeInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
616 if (!jni_LeInterface)
618 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
622 jmethodID jni_InterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_LeInterface,
623 "destroyLeInterface",
625 if (!jni_InterfaceDestroyMethod)
627 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface destroy method");
631 (*env)->CallStaticVoidMethod(env, jni_LeInterface, jni_InterfaceDestroyMethod);
633 if ((*env)->ExceptionCheck(env))
635 OIC_LOG(ERROR, TAG, "destroyLeInterface has failed");
636 (*env)->ExceptionDescribe(env);
637 (*env)->ExceptionClear(env);
641 OIC_LOG(DEBUG, TAG, "Destroy instance for CaLeClientInterface");
645 (*g_jvm)->DetachCurrentThread(g_jvm);
654 (*g_jvm)->DetachCurrentThread(g_jvm);
657 return CA_STATUS_FAILED;
660 void CALEClientSendFinish(JNIEnv *env, jobject gatt)
662 OIC_LOG(DEBUG, TAG, "CALEClientSendFinish");
663 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
667 CAResult_t res = CALEClientDisconnect(env, gatt);
668 if (CA_STATUS_OK != res)
670 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
673 CALEClientUpdateSendCnt(env);
676 CAResult_t CALEClientSendUnicastMessage(const char* address,
678 const uint32_t dataLen)
680 OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data);
681 VERIFY_NON_NULL(address, TAG, "address is null");
682 VERIFY_NON_NULL(data, TAG, "data is null");
684 return CALEClientSendUnicastMessageImpl(address, data, dataLen);
687 CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
688 const uint32_t dataLen)
690 OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
691 VERIFY_NON_NULL(data, TAG, "data is null");
695 OIC_LOG(ERROR, TAG, "g_jvm is null");
696 return CA_STATUS_FAILED;
699 bool isAttached = false;
701 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
704 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
705 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
709 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
710 return CA_STATUS_FAILED;
715 CAResult_t ret = CALEClientSendMulticastMessageImpl(env, data, dataLen);
716 if (CA_STATUS_OK != ret)
718 OIC_LOG(ERROR, TAG, "CALEClientSendMulticastMessageImpl has failed");
723 (*g_jvm)->DetachCurrentThread(g_jvm);
729 CAResult_t CALEClientStartUnicastServer(const char* address)
734 OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address);
736 return CA_NOT_SUPPORTED;
739 CAResult_t CALEClientStartMulticastServer()
741 OIC_LOG(DEBUG, TAG, "it is not needed in this platform");
743 return CA_NOT_SUPPORTED;
746 void CALEClientStopUnicastServer()
748 OIC_LOG(DEBUG, TAG, "CALEClientStopUnicastServer");
751 void CALEClientStopMulticastServer()
753 OIC_LOG(DEBUG, TAG, "CALEClientStopMulticastServer");
756 void CALEClientSetCallback(CAPacketReceiveCallback callback)
758 g_packetReceiveCallback = callback;
761 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
763 g_clientErrorCallback = callback;
766 CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address)
768 VERIFY_NON_NULL(env, TAG, "env");
772 OIC_LOG(ERROR, TAG, "g_deviceList is not available");
773 return CA_STATUS_FAILED;
776 if (0 == u_arraylist_length(g_deviceList) // multicast
777 || (address && !CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
779 // Wait for LE peripherals to be discovered.
781 // Number of times to wait for discovery to complete.
782 static size_t const RETRIES = 5;
784 static uint64_t const TIMEOUT =
785 2 * MICROSECS_PER_SEC; // Microseconds
787 // set scan interval and start scan
788 CALERestartScanWithInterval(WAIT_TIME_SCANNED_CHECKING, 1, BLE_SCAN_ENABLE);
790 bool devicesDiscovered = false;
791 for (size_t i = 0; i < RETRIES; ++i)
793 OIC_LOG(DEBUG, TAG, "waiting for target device");
794 if (ca_cond_wait_for(g_deviceDescCond,
796 TIMEOUT) == CA_WAIT_SUCCESS)
798 ca_mutex_lock(g_deviceListMutex);
799 size_t scannedDeviceLen = u_arraylist_length(g_deviceList);
800 ca_mutex_unlock(g_deviceListMutex);
802 if (0 < scannedDeviceLen)
804 if (!address // multicast
805 || (address && CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
807 devicesDiscovered = true;
814 OIC_LOG(INFO, TAG, "waiting..");
816 ca_mutex_lock(g_deviceScanRetryDelayMutex);
817 if (ca_cond_wait_for(g_deviceScanRetryDelayCond,
818 g_deviceScanRetryDelayMutex,
819 MICROSECS_PER_SEC) == CA_WAIT_SUCCESS)
821 OIC_LOG(INFO, TAG, "finish to waiting for target device");
822 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
825 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
828 // checking whether a target device is found while waiting for time-out.
829 if (CALEClientIsDeviceInScanDeviceList(env, address))
831 devicesDiscovered = true;
840 // reset scan interval time after checking scanned devices
841 CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE);
843 // time out for scanning devices
844 if (!devicesDiscovered)
846 return CA_STATUS_FAILED;
851 OIC_LOG(DEBUG, TAG, "there is a target device in the scanned devices");
858 CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data,
859 const uint32_t dataLen)
861 OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address,
863 VERIFY_NON_NULL(address, TAG, "address is null");
864 VERIFY_NON_NULL(data, TAG, "data is null");
868 OIC_LOG(ERROR, TAG, "g_jvm is null");
869 return CA_STATUS_FAILED;
872 bool isAttached = false;
874 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
877 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
878 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
881 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
882 return CA_STATUS_FAILED;
887 ca_mutex_lock(g_threadSendMutex);
889 CALEClientSetSendFinishFlag(false);
891 CAResult_t ret = CALEClientIsThereScannedDevices(env, address);
892 if (CA_STATUS_OK != ret)
894 OIC_LOG(INFO, TAG, "there is no scanned device");
898 if (g_context && g_deviceList)
900 uint32_t length = u_arraylist_length(g_deviceList);
901 for (uint32_t index = 0; index < length; index++)
903 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
906 OIC_LOG(ERROR, TAG, "jarrayObj is null");
910 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
913 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
917 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
920 OIC_LOG(ERROR, TAG, "setAddress is null");
924 OIC_LOG_V(DEBUG, TAG, "remote device address is %s", setAddress);
926 if (!strcmp(setAddress, address))
928 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
929 (*env)->DeleteLocalRef(env, jni_setAddress);
933 (*env)->DeleteGlobalRef(env, g_sendBuffer);
936 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
937 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
938 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
940 // Target device to send message is just one.
943 ret = CALEClientSendData(env, jarrayObj);
944 if (CA_STATUS_OK != ret)
946 OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
950 OIC_LOG(INFO, TAG, "wake up");
953 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
954 (*env)->DeleteLocalRef(env, jni_setAddress);
958 OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
960 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
961 // if there is no connection state.
962 ca_mutex_lock(g_threadMutex);
963 if (!g_isFinishedSendData)
965 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
966 ca_cond_wait(g_threadCond, g_threadMutex);
967 OIC_LOG(DEBUG, TAG, "the data was sent");
969 ca_mutex_unlock(g_threadMutex);
973 (*g_jvm)->DetachCurrentThread(g_jvm);
976 ca_mutex_unlock(g_threadSendMutex);
977 OIC_LOG(INFO, TAG, "unicast - send logic has finished");
978 if (CALEClientIsValidState(address, CA_LE_SEND_STATE,
985 ret = CA_SEND_FAILED;
989 CAResult_t resetRet = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
991 if (CA_STATUS_OK != resetRet)
993 OIC_LOG_V(ERROR, TAG, "CALEClientUpdateDeviceState has failed (%d)", resetRet);
994 ret = CA_SEND_FAILED;
1003 (*g_jvm)->DetachCurrentThread(g_jvm);
1006 ca_mutex_unlock(g_threadSendMutex);
1007 return CA_SEND_FAILED;
1010 CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
1011 const uint32_t dataLen)
1013 OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
1014 VERIFY_NON_NULL(data, TAG, "data is null");
1015 VERIFY_NON_NULL(env, TAG, "env is null");
1019 OIC_LOG(ERROR, TAG, "g_deviceList is null");
1020 return CA_STATUS_FAILED;
1023 ca_mutex_lock(g_threadSendMutex);
1025 CALEClientSetSendFinishFlag(false);
1027 OIC_LOG(DEBUG, TAG, "set byteArray for data");
1030 (*env)->DeleteGlobalRef(env, g_sendBuffer);
1031 g_sendBuffer = NULL;
1034 CAResult_t res = CALEClientIsThereScannedDevices(env, NULL);
1035 if (CA_STATUS_OK != res)
1037 OIC_LOG(INFO, TAG, "there is no scanned device");
1041 uint32_t length = u_arraylist_length(g_deviceList);
1042 g_targetCnt = length;
1044 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
1045 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
1046 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
1048 for (uint32_t index = 0; index < length; index++)
1050 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
1053 OIC_LOG(ERROR, TAG, "jarrayObj is not available");
1057 res = CALEClientSendData(env, jarrayObj);
1058 if (res != CA_STATUS_OK)
1060 OIC_LOG(ERROR, TAG, "BT device - send has failed");
1064 OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
1066 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
1067 ca_mutex_lock(g_threadMutex);
1068 if (!g_isFinishedSendData)
1070 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
1071 ca_cond_wait(g_threadCond, g_threadMutex);
1072 OIC_LOG(DEBUG, TAG, "the data was sent");
1074 ca_mutex_unlock(g_threadMutex);
1075 ca_mutex_unlock(g_threadSendMutex);
1076 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
1077 return CA_STATUS_OK;
1080 ca_mutex_unlock(g_threadSendMutex);
1081 OIC_LOG(ERROR, TAG, "OUT - CALEClientSendMulticastMessageImpl");
1082 return CA_SEND_FAILED;
1085 CAResult_t CALEClientSendData(JNIEnv *env, jobject device)
1087 OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
1088 VERIFY_NON_NULL(device, TAG, "device is null");
1089 VERIFY_NON_NULL(env, TAG, "env is null");
1091 // get BLE address from bluetooth device object.
1092 char* address = NULL;
1093 CALEState_t* state = NULL;
1094 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, device);
1097 OIC_LOG(INFO, TAG, "there is gatt object..it's not first connection");
1098 address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1101 OIC_LOG(ERROR, TAG, "address is not available");
1102 return CA_STATUS_FAILED;
1104 ca_mutex_lock(g_deviceStateListMutex);
1105 state = CALEClientGetStateInfo(address);
1106 ca_mutex_unlock(g_deviceStateListMutex);
1111 OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
1113 // cancel previous connection request before connection
1114 // if there is gatt object in g_gattObjectList.
1117 jobject gatt = CALEClientGetGattObjInList(env, address);
1120 CAResult_t res = CALEClientDisconnect(env, gatt);
1121 if (CA_STATUS_OK != res)
1123 OIC_LOG(INFO, TAG, "there is no gatt object");
1126 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1129 // connection request
1130 jobject newGatt = CALEClientConnect(env, device,
1132 if (NULL == newGatt)
1134 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1135 return CA_STATUS_FAILED;
1140 if (CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1141 STATE_SERVICE_CONNECTED))
1143 OIC_LOG(INFO, TAG, "GATT has already connected");
1145 jobject gatt = CALEClientGetGattObjInList(env, address);
1148 OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
1149 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1150 return CA_STATUS_FAILED;
1153 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1154 if (CA_STATUS_OK != ret)
1156 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1157 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1160 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1162 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1165 OIC_LOG(INFO, TAG, "service connecting...");
1167 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1168 STATE_DISCONNECTED))
1170 OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
1172 // cancel previous connection request before connection
1173 // if there is gatt object in g_gattObjectList.
1176 jobject gatt = CALEClientGetGattObjInList(env, address);
1179 CAResult_t res = CALEClientDisconnect(env, gatt);
1180 if (CA_STATUS_OK != res)
1182 OIC_LOG(INFO, TAG, "there is no gatt object");
1185 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1188 OIC_LOG(DEBUG, TAG, "start to connect LE");
1189 jobject gatt = CALEClientConnect(env, device,
1190 CALEClientGetFlagFromState(env, jni_address,
1191 CA_LE_AUTO_CONNECT_FLAG));
1195 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1196 return CA_STATUS_FAILED;
1201 return CA_STATUS_OK;
1204 jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
1206 VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
1207 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1209 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
1210 "()Landroid/bluetooth/BluetoothDevice;");
1211 if (!jni_mid_getDevice)
1213 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
1217 jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
1218 if (!jni_obj_device)
1220 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
1224 jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
1227 OIC_LOG(ERROR, TAG, "jni_address is null");
1237 CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
1240 OIC_LOG(DEBUG, TAG, "Gatt Close");
1241 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1242 VERIFY_NON_NULL(env, TAG, "env is null");
1244 // get BluetoothGatt method
1245 OIC_LOG(DEBUG, TAG, "get BluetoothGatt method");
1246 jmethodID jni_mid_closeGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "close", "()V");
1247 if (!jni_mid_closeGatt)
1249 OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1250 return CA_STATUS_OK;
1253 // call disconnect gatt method
1254 OIC_LOG(DEBUG, TAG, "request to close GATT");
1255 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
1257 if ((*env)->ExceptionCheck(env))
1259 OIC_LOG(ERROR, TAG, "closeGATT has failed");
1260 (*env)->ExceptionDescribe(env);
1261 (*env)->ExceptionClear(env);
1262 return CA_STATUS_FAILED;
1265 return CA_STATUS_OK;
1268 CAResult_t CALEClientStartScan()
1270 if (!g_isStartedLEClient)
1272 OIC_LOG(ERROR, TAG, "LE client is not started");
1273 return CA_STATUS_FAILED;
1278 OIC_LOG(ERROR, TAG, "g_jvm is null");
1279 return CA_STATUS_FAILED;
1282 bool isAttached = false;
1284 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1287 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1289 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1292 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1293 return CA_STATUS_FAILED;
1298 OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1300 CAResult_t ret = CA_STATUS_OK;
1301 // scan gatt server with UUID
1302 if (g_leScanCallback && g_uuidList)
1305 ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
1307 ret = CALEClientStartScanImpl(env, g_leScanCallback);
1309 if (CA_STATUS_OK != ret)
1311 if (CA_ADAPTER_NOT_ENABLED == ret)
1313 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1317 OIC_LOG(ERROR, TAG, "start scan has failed");
1324 (*g_jvm)->DetachCurrentThread(g_jvm);
1330 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
1332 VERIFY_NON_NULL(callback, TAG, "callback is null");
1333 VERIFY_NON_NULL(env, TAG, "env is null");
1335 if (!CALEIsEnableBTAdapter(env))
1337 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1338 return CA_ADAPTER_NOT_ENABLED;
1341 // get default bt adapter class
1342 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1343 if (!jni_cid_BTAdapter)
1345 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1346 return CA_STATUS_FAILED;
1349 // get remote bt adapter method
1350 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1351 "getDefaultAdapter",
1352 METHODID_OBJECTNONPARAM);
1353 if (!jni_mid_getDefaultAdapter)
1355 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1356 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1357 return CA_STATUS_FAILED;
1360 // get start le scan method
1361 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1362 "(Landroid/bluetooth/BluetoothAdapter$"
1363 "LeScanCallback;)Z");
1364 if (!jni_mid_startLeScan)
1366 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1367 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1368 return CA_STATUS_FAILED;
1371 // gat bt adapter object
1372 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1373 jni_mid_getDefaultAdapter);
1374 if (!jni_obj_BTAdapter)
1376 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1377 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1378 return CA_STATUS_FAILED;
1381 // call start le scan method
1382 OIC_LOG(INFO, TAG, "CALL API - startLeScan");
1383 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1384 jni_mid_startLeScan, callback);
1385 if (!jni_obj_startLeScan)
1387 OIC_LOG(INFO, TAG, "startLeScan has failed");
1391 OIC_LOG(DEBUG, TAG, "LeScan has started");
1394 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1395 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1396 return CA_STATUS_OK;
1399 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
1401 VERIFY_NON_NULL(callback, TAG, "callback is null");
1402 VERIFY_NON_NULL(uuids, TAG, "uuids is null");
1403 VERIFY_NON_NULL(env, TAG, "env is null");
1405 if (!CALEIsEnableBTAdapter(env))
1407 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1408 return CA_ADAPTER_NOT_ENABLED;
1411 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1412 if (!jni_cid_BTAdapter)
1414 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1415 return CA_STATUS_FAILED;
1418 // get remote bt adapter method
1419 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1420 "getDefaultAdapter",
1421 METHODID_OBJECTNONPARAM);
1422 if (!jni_mid_getDefaultAdapter)
1424 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1425 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1426 return CA_STATUS_FAILED;
1429 // get start le scan method
1430 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1431 "([Ljava/util/UUID;Landroid/bluetooth/"
1432 "BluetoothAdapter$LeScanCallback;)Z");
1433 if (!jni_mid_startLeScan)
1435 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1436 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1437 return CA_STATUS_FAILED;
1440 // get bt adapter object
1441 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1442 jni_mid_getDefaultAdapter);
1443 if (!jni_obj_BTAdapter)
1445 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1446 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1447 return CA_STATUS_FAILED;
1450 // call start le scan method
1451 OIC_LOG(INFO, TAG, "CALL API - startLeScan (with UUID)");
1452 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1453 jni_mid_startLeScan, uuids, callback);
1454 if (!jni_obj_startLeScan)
1456 OIC_LOG(INFO, TAG, "startLeScan has failed");
1460 OIC_LOG(DEBUG, TAG, "LeScan has started");
1463 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1464 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1465 return CA_STATUS_OK;
1468 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
1470 VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
1471 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1474 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1477 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1481 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString",
1482 "(Ljava/lang/String;)"
1483 "Ljava/util/UUID;");
1484 if (!jni_mid_fromString)
1486 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1490 jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1491 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1495 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1499 return jni_obj_uuid;
1502 CAResult_t CALEClientStopScan()
1506 OIC_LOG(ERROR, TAG, "g_jvm is null");
1507 return CA_STATUS_FAILED;
1510 bool isAttached = false;
1512 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1515 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1516 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1519 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1520 return CA_STATUS_FAILED;
1525 CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
1526 if (CA_STATUS_OK != ret)
1528 if (CA_ADAPTER_NOT_ENABLED == ret)
1530 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1534 OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1540 (*g_jvm)->DetachCurrentThread(g_jvm);
1546 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
1548 OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
1549 VERIFY_NON_NULL(callback, TAG, "callback is null");
1550 VERIFY_NON_NULL(env, TAG, "env is null");
1552 if (!CALEIsEnableBTAdapter(env))
1554 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1555 return CA_ADAPTER_NOT_ENABLED;
1558 // get default bt adapter class
1559 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1560 if (!jni_cid_BTAdapter)
1562 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1563 return CA_STATUS_FAILED;
1566 // get remote bt adapter method
1567 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1568 "getDefaultAdapter",
1569 METHODID_OBJECTNONPARAM);
1570 if (!jni_mid_getDefaultAdapter)
1572 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1573 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1574 return CA_STATUS_FAILED;
1577 // get start le scan method
1578 jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
1579 "(Landroid/bluetooth/"
1580 "BluetoothAdapter$LeScanCallback;)V");
1581 if (!jni_mid_stopLeScan)
1583 OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
1584 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1585 return CA_STATUS_FAILED;
1588 // gat bt adapter object
1589 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1590 jni_mid_getDefaultAdapter);
1591 if (!jni_obj_BTAdapter)
1593 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1594 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1595 return CA_STATUS_FAILED;
1598 OIC_LOG(INFO, TAG, "CALL API - stopLeScan");
1599 // call start le scan method
1600 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
1601 if ((*env)->ExceptionCheck(env))
1603 OIC_LOG(ERROR, TAG, "stopLeScan has failed");
1604 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1605 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1606 (*env)->ExceptionDescribe(env);
1607 (*env)->ExceptionClear(env);
1608 return CA_STATUS_FAILED;
1611 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1612 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1613 return CA_STATUS_OK;
1616 CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, jint state_idx, jboolean flag)
1618 OIC_LOG(DEBUG, TAG, "IN - CALEClientSetFlagToState");
1619 VERIFY_NON_NULL(env, TAG, "env");
1620 VERIFY_NON_NULL(jni_address, TAG, "jni_address");
1622 ca_mutex_lock(g_deviceStateListMutex);
1624 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1627 OIC_LOG(ERROR, TAG, "address is not available");
1628 return CA_STATUS_FAILED;
1631 if (CALEClientIsDeviceInList(address))
1633 CALEState_t* curState = CALEClientGetStateInfo(address);
1636 OIC_LOG(ERROR, TAG, "curState is null");
1637 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1638 ca_mutex_unlock(g_deviceStateListMutex);
1639 return CA_STATUS_FAILED;
1641 OIC_LOG_V(INFO, TAG, "%d flag is set : %d", state_idx, flag);
1645 case CA_LE_AUTO_CONNECT_FLAG:
1646 curState->autoConnectFlag = flag;
1648 case CA_LE_DESCRIPTOR_FOUND:
1649 curState->isDescriptorFound = flag;
1656 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1657 ca_mutex_unlock(g_deviceStateListMutex);
1658 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetFlagToState");
1659 return CA_STATUS_OK;
1662 jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx)
1664 OIC_LOG(DEBUG, TAG, "IN - CALEClientGetFlagFromState");
1665 VERIFY_NON_NULL_RET(env, TAG, "env", false);
1666 VERIFY_NON_NULL_RET(jni_address, TAG, "jni_address", false);
1668 ca_mutex_lock(g_deviceStateListMutex);
1670 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1673 OIC_LOG(ERROR, TAG, "address is not available");
1674 ca_mutex_unlock(g_deviceStateListMutex);
1678 CALEState_t* curState = CALEClientGetStateInfo(address);
1679 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1682 OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false");
1683 ca_mutex_unlock(g_deviceStateListMutex);
1687 jboolean ret = JNI_FALSE;
1690 case CA_LE_AUTO_CONNECT_FLAG:
1691 ret = curState->autoConnectFlag;
1693 case CA_LE_DESCRIPTOR_FOUND:
1694 ret = curState->isDescriptorFound;
1699 ca_mutex_unlock(g_deviceStateListMutex);
1701 OIC_LOG_V(INFO, TAG, "%d flag is %d", state_idx, ret);
1702 OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetFlagFromState");
1706 CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1708 OIC_LOG(DEBUG, TAG, "CALEClientDirectConnect");
1709 VERIFY_NON_NULL(env, TAG, "env is null");
1710 VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1712 ca_mutex_lock(g_threadSendMutex);
1714 jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1717 OIC_LOG(ERROR, TAG, "jni_address is not available");
1718 ca_mutex_unlock(g_threadSendMutex);
1719 return CA_STATUS_FAILED;
1722 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1725 OIC_LOG(ERROR, TAG, "address is not available");
1726 ca_mutex_unlock(g_threadSendMutex);
1727 return CA_STATUS_FAILED;
1730 CAResult_t res = CA_STATUS_OK;
1731 if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1732 STATE_DISCONNECTED))
1734 jobject newGatt = CALEClientConnect(env, bluetoothDevice, autoconnect);
1735 if (NULL == newGatt)
1737 OIC_LOG(INFO, TAG, "newGatt is not available");
1738 res = CA_STATUS_FAILED;
1741 ca_mutex_unlock(g_threadSendMutex);
1746 jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1748 OIC_LOG(DEBUG, TAG, "CALEClientConnect");
1749 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1750 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1752 // reset scan interval time after checking scanned devices
1753 CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE);
1755 // get gatt object from Bluetooth Device object for closeProfileProxy(..)
1756 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
1759 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1762 OIC_LOG(ERROR, TAG, "address is not available");
1766 // close the gatt service
1767 jobject gatt = CALEClientGetGattObjInList(env, address);
1770 CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
1771 if (CA_STATUS_OK != res)
1773 OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
1774 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1778 // clean previous gatt object after close profile service
1779 res = CALEClientRemoveGattObjForAddr(env, jni_address);
1780 if (CA_STATUS_OK != res)
1782 OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
1783 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1787 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1790 jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
1793 OIC_LOG(DEBUG, TAG, "re-connection will be started");
1797 // add new gatt object into g_gattObjectList
1798 CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
1799 if (CA_STATUS_OK != res)
1801 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
1808 jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1810 OIC_LOG(DEBUG, TAG, "GATT CONNECT");
1811 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1812 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1814 if (!g_leGattCallback)
1816 OIC_LOG(INFO, TAG, "g_leGattCallback is null");
1820 if (!CALEIsEnableBTAdapter(env))
1822 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1826 jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1829 OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
1833 // get BluetoothDevice method
1834 OIC_LOG(DEBUG, TAG, "get BluetoothDevice method");
1835 jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
1837 "(Landroid/content/Context;ZLandroid/"
1838 "bluetooth/BluetoothGattCallback;)"
1839 "Landroid/bluetooth/BluetoothGatt;");
1840 if (!jni_mid_connectGatt)
1842 OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
1846 OIC_LOG(INFO, TAG, "CALL API - connectGatt");
1847 jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
1848 jni_mid_connectGatt,
1850 autoconnect, g_leGattCallback);
1851 if (!jni_obj_connectGatt)
1853 OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
1854 CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
1855 CALEClientUpdateSendCnt(env);
1860 OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
1862 return jni_obj_connectGatt;
1865 CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
1867 OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
1869 VERIFY_NON_NULL(env, TAG, "env is null");
1870 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1872 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1873 if (!jni_cid_BTAdapter)
1875 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
1876 return CA_STATUS_FAILED;
1879 // get remote bt adapter method
1880 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1881 "getDefaultAdapter",
1882 METHODID_OBJECTNONPARAM);
1883 if (!jni_mid_getDefaultAdapter)
1885 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1886 return CA_STATUS_FAILED;
1889 // gat bt adapter object
1890 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1891 jni_mid_getDefaultAdapter);
1892 if (!jni_obj_BTAdapter)
1894 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1895 return CA_STATUS_FAILED;
1898 // get closeProfileProxy method
1899 jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1900 "closeProfileProxy",
1901 "(ILandroid/bluetooth/"
1902 "BluetoothProfile;)V");
1903 if (!jni_mid_closeProfileProxy)
1905 OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
1906 return CA_STATUS_FAILED;
1909 jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
1910 if (!jni_cid_BTProfile)
1912 OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
1913 return CA_STATUS_FAILED;
1916 // GATT - Constant value : 7 (0x00000007)
1917 jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
1921 OIC_LOG(ERROR, TAG, "id_gatt is null");
1922 return CA_STATUS_FAILED;
1925 jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
1927 OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
1928 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
1929 if ((*env)->ExceptionCheck(env))
1931 OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
1932 (*env)->ExceptionDescribe(env);
1933 (*env)->ExceptionClear(env);
1934 return CA_STATUS_FAILED;
1937 OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
1938 return CA_STATUS_OK;
1942 CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
1944 OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1945 VERIFY_NON_NULL(env, TAG, "env is null");
1946 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1948 // get BluetoothGatt method
1949 OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
1950 jmethodID jni_mid_disconnectGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1951 "disconnect", "()V");
1952 if (!jni_mid_disconnectGatt)
1954 OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
1955 return CA_STATUS_FAILED;
1958 // call disconnect gatt method
1959 OIC_LOG(INFO, TAG, "CALL API - disconnect");
1960 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
1961 if ((*env)->ExceptionCheck(env))
1963 OIC_LOG(ERROR, TAG, "disconnect has failed");
1964 (*env)->ExceptionDescribe(env);
1965 (*env)->ExceptionClear(env);
1966 return CA_STATUS_FAILED;
1969 OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
1971 return CA_STATUS_OK;
1974 CAResult_t CALEClientDisconnectAll(JNIEnv *env)
1976 OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1977 VERIFY_NON_NULL(env, TAG, "env is null");
1979 if (!g_gattObjectList)
1981 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1982 return CA_STATUS_OK;
1985 uint32_t length = u_arraylist_length(g_gattObjectList);
1986 OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
1987 for (uint32_t index = 0; index < length; index++)
1989 OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
1990 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1993 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1996 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1997 if (CA_STATUS_OK != res)
1999 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
2004 return CA_STATUS_OK;
2007 CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
2009 OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
2010 VERIFY_NON_NULL(env, TAG, "env is null");
2012 if (!g_gattObjectList)
2014 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2015 return CA_STATUS_OK;
2018 char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
2021 OIC_LOG(ERROR, TAG, "address is null");
2022 return CA_STATUS_FAILED;
2025 uint32_t length = u_arraylist_length(g_gattObjectList);
2026 for (uint32_t index = 0; index < length; index++)
2028 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2031 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2035 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2036 if (!jni_setAddress)
2038 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2039 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2040 return CA_STATUS_FAILED;
2043 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2046 OIC_LOG(ERROR, TAG, "setAddress is null");
2047 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2048 return CA_STATUS_FAILED;
2051 OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
2052 if (!strcmp(address, setAddress))
2054 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
2055 if (CA_STATUS_OK != res)
2057 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
2058 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2059 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2060 return CA_STATUS_FAILED;
2062 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2063 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2064 return CA_STATUS_OK;
2066 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2068 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2070 OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
2071 return CA_STATUS_OK;
2074 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
2076 VERIFY_NON_NULL(env, TAG, "env is null");
2077 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2079 if (!CALEIsEnableBTAdapter(env))
2081 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2082 return CA_ADAPTER_NOT_ENABLED;
2085 // get BluetoothGatt.discoverServices method
2086 OIC_LOG(DEBUG, TAG, "get BluetoothGatt.discoverServices method");
2087 jmethodID jni_mid_discoverServices = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2088 "discoverServices", "()Z");
2089 if (!jni_mid_discoverServices)
2091 OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
2092 return CA_STATUS_FAILED;
2095 // call disconnect gatt method
2096 OIC_LOG(INFO, TAG, "CALL API - discoverServices");
2097 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
2100 OIC_LOG(ERROR, TAG, "discoverServices has not been started");
2101 return CA_STATUS_FAILED;
2104 return CA_STATUS_OK;
2107 static void CALEWriteCharacteristicThread(void* object)
2109 VERIFY_NON_NULL_VOID(object, TAG, "object is null");
2111 bool isAttached = false;
2113 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2116 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2117 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2121 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2127 jobject gatt = (jobject)object;
2128 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
2129 if (CA_STATUS_OK != ret)
2131 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
2136 (*g_jvm)->DetachCurrentThread(g_jvm);
2140 CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
2142 OIC_LOG(DEBUG, TAG, "CALESetValueAndWriteCharacteristic");
2144 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2145 VERIFY_NON_NULL(env, TAG, "env is null");
2147 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
2150 CALEClientSendFinish(env, gatt);
2151 return CA_STATUS_FAILED;
2154 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
2157 CALEClientSendFinish(env, gatt);
2158 return CA_STATUS_FAILED;
2161 ca_mutex_lock(g_threadSendStateMutex);
2163 if (CALEClientIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING))
2165 OIC_LOG(INFO, TAG, "current state is SENDING");
2166 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2167 ca_mutex_unlock(g_threadSendStateMutex);
2168 return CA_STATUS_OK;
2171 if (CA_STATUS_OK != CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
2174 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
2175 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2176 CALEClientSendFinish(env, gatt);
2177 ca_mutex_unlock(g_threadSendStateMutex);
2178 return CA_STATUS_FAILED;
2181 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2183 ca_mutex_unlock(g_threadSendStateMutex);
2186 jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
2187 if (!jni_obj_character)
2189 CALEClientSendFinish(env, gatt);
2190 return CA_STATUS_FAILED;
2193 CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
2194 if (CA_STATUS_OK != ret)
2196 CALEClientSendFinish(env, gatt);
2197 return CA_STATUS_FAILED;
2200 // wait for callback for write Characteristic with success to sent data
2201 OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
2202 ca_mutex_lock(g_threadWriteCharacteristicMutex);
2203 if (!g_isSignalSetFlag)
2205 OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
2206 if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
2207 g_threadWriteCharacteristicMutex,
2208 WAIT_TIME_WRITE_CHARACTERISTIC))
2210 OIC_LOG(ERROR, TAG, "there is no response. write has failed");
2211 g_isSignalSetFlag = false;
2212 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2213 return CA_STATUS_FAILED;
2216 // reset flag set by writeCharacteristic Callback
2217 g_isSignalSetFlag = false;
2218 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2220 CALEClientUpdateSendCnt(env);
2222 OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
2223 return CA_STATUS_OK;
2226 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
2228 OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
2229 VERIFY_NON_NULL(env, TAG, "env is null");
2230 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2232 jobject gattParam = (*env)->NewGlobalRef(env, gatt);
2233 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
2234 CALEWriteCharacteristicThread, (void*)gattParam))
2236 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
2237 return CA_STATUS_FAILED;
2240 OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
2241 return CA_STATUS_OK;
2244 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
2245 jobject gattCharacteristic)
2247 OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
2248 VERIFY_NON_NULL(env, TAG, "env is null");
2249 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2250 VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
2252 if (!CALEIsEnableBTAdapter(env))
2254 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2255 return CA_STATUS_FAILED;
2258 // get BluetoothGatt.write characteristic method
2259 OIC_LOG(DEBUG, TAG, "write characteristic method");
2260 jmethodID jni_mid_writeCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2261 "writeCharacteristic",
2262 "(Landroid/bluetooth/"
2263 "BluetoothGattCharacteristic;)Z");
2264 if (!jni_mid_writeCharacteristic)
2266 OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
2267 return CA_STATUS_FAILED;
2270 // call disconnect gatt method
2271 OIC_LOG(INFO, TAG, "CALL API - writeCharacteristic");
2272 jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
2273 jni_mid_writeCharacteristic,
2274 gattCharacteristic);
2277 OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
2281 OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
2282 return CA_STATUS_FAILED;
2285 return CA_STATUS_OK;
2288 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
2290 VERIFY_NON_NULL(env, TAG, "env is null");
2291 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2293 if (!CALEIsEnableBTAdapter(env))
2295 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2296 return CA_STATUS_FAILED;
2299 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
2302 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2303 return CA_STATUS_FAILED;
2306 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2307 if (!jni_obj_GattCharacteristic)
2309 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2310 return CA_STATUS_FAILED;
2313 OIC_LOG(DEBUG, TAG, "read characteristic method");
2314 jmethodID jni_mid_readCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2315 "readCharacteristic",
2316 "(Landroid/bluetooth/"
2317 "BluetoothGattCharacteristic;)Z");
2318 if (!jni_mid_readCharacteristic)
2320 OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
2321 return CA_STATUS_FAILED;
2324 // call disconnect gatt method
2325 OIC_LOG(INFO, TAG, "CALL API - readCharacteristic");
2326 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
2327 jni_obj_GattCharacteristic);
2330 OIC_LOG(DEBUG, TAG, "readCharacteristic success");
2334 OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
2335 return CA_STATUS_FAILED;
2338 return CA_STATUS_OK;
2341 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
2342 jobject characteristic)
2344 VERIFY_NON_NULL(env, TAG, "env is null");
2345 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2346 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2348 if (!CALEIsEnableBTAdapter(env))
2350 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2351 return CA_ADAPTER_NOT_ENABLED;
2354 // get BluetoothGatt.setCharacteristicNotification method
2355 OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
2356 jmethodID jni_mid_setNotification = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2357 "setCharacteristicNotification",
2358 "(Landroid/bluetooth/"
2359 "BluetoothGattCharacteristic;Z)Z");
2360 if (!jni_mid_setNotification)
2362 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2363 return CA_STATUS_FAILED;
2366 OIC_LOG(INFO, TAG, "CALL API - setCharacteristicNotification");
2367 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
2368 characteristic, JNI_TRUE);
2369 if (JNI_TRUE == ret)
2371 OIC_LOG(DEBUG, TAG, "setCharacteristicNotification success");
2375 OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed");
2376 return CA_STATUS_FAILED;
2379 return CA_STATUS_OK;
2382 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
2384 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2385 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2386 VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
2388 if (!CALEIsEnableBTAdapter(env))
2390 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2394 // get BluetoothGatt.getService method
2395 OIC_LOG(DEBUG, TAG, "BluetoothGatt.getService");
2396 jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2398 "(Ljava/util/UUID;)Landroid/bluetooth/"
2399 "BluetoothGattService;");
2400 if (!jni_mid_getService)
2402 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2406 jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2407 if (!jni_obj_service_uuid)
2409 OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
2413 // get bluetooth gatt service
2414 OIC_LOG(DEBUG, TAG, "request to get service");
2415 jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
2416 jni_obj_service_uuid);
2417 if (!jni_obj_gattService)
2419 OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
2423 // get bluetooth gatt service method
2424 jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/"
2425 "BluetoothGattService",
2426 "getCharacteristic",
2427 "(Ljava/util/UUID;)"
2428 "Landroid/bluetooth/"
2429 "BluetoothGattCharacteristic;");
2430 if (!jni_mid_getCharacteristic)
2432 OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
2436 const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
2439 OIC_LOG(ERROR, TAG, "uuid is null");
2443 jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
2444 if (!jni_obj_tx_uuid)
2446 OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
2447 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2451 OIC_LOG(DEBUG, TAG, "request to get Characteristic");
2452 jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
2453 jni_mid_getCharacteristic,
2456 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2457 return jni_obj_GattCharacteristic;
2460 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
2462 OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
2463 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2464 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2465 VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
2467 if (!CALEIsEnableBTAdapter(env))
2469 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2473 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
2476 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2480 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2481 if (!jni_obj_GattCharacteristic)
2483 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2487 jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
2488 "/BluetoothGattCharacteristic");
2489 if (!jni_cid_BTGattCharacteristic)
2491 OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
2495 OIC_LOG(DEBUG, TAG, "set value in Characteristic");
2496 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
2498 if (!jni_mid_setValue)
2500 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2504 jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
2506 if (JNI_TRUE == ret)
2508 OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
2512 OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
2517 jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
2518 "setWriteType", "(I)V");
2519 if (!jni_mid_setWriteType)
2521 OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
2525 jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
2526 "WRITE_TYPE_NO_RESPONSE", "I");
2527 if (!jni_fid_no_response)
2529 OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
2533 jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
2534 jni_fid_no_response);
2536 (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
2538 return jni_obj_GattCharacteristic;
2541 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
2543 VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
2544 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2546 if (!CALEIsEnableBTAdapter(env))
2548 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2552 jmethodID jni_mid_getValue = CAGetJNIMethodID(env, "android/bluetooth/"
2553 "BluetoothGattCharacteristic",
2554 "getValue", "()[B");
2555 if (!jni_mid_getValue)
2557 OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
2561 jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
2563 return jni_obj_data_array;
2566 CAResult_t CALEClientCreateUUIDList()
2570 OIC_LOG(ERROR, TAG, "g_jvm is null");
2571 return CA_STATUS_FAILED;
2574 bool isAttached = false;
2576 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2579 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2580 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2584 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2585 return CA_STATUS_FAILED;
2590 // create new object array
2591 jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
2592 if (!jni_cid_uuid_list)
2594 OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
2598 jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
2599 jni_cid_uuid_list, NULL);
2600 if (!jni_obj_uuid_list)
2602 OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
2607 jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2610 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
2613 (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
2615 g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
2619 (*g_jvm)->DetachCurrentThread(g_jvm);
2622 return CA_STATUS_OK;
2629 (*g_jvm)->DetachCurrentThread(g_jvm);
2631 return CA_STATUS_FAILED;
2634 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
2635 jobject characteristic)
2637 VERIFY_NON_NULL(env, TAG, "env is null");
2638 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2639 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2641 if (!CALEIsEnableBTAdapter(env))
2643 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2644 return CA_ADAPTER_NOT_ENABLED;
2647 OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
2648 jmethodID jni_mid_getDescriptor = CAGetJNIMethodID(env, "android/bluetooth/"
2649 "BluetoothGattCharacteristic",
2651 "(Ljava/util/UUID;)Landroid/bluetooth/"
2652 "BluetoothGattDescriptor;");
2653 if (!jni_mid_getDescriptor)
2655 OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
2656 return CA_STATUS_FAILED;
2659 jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
2660 if (!jni_obj_cc_uuid)
2662 OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
2663 return CA_STATUS_FAILED;
2666 OIC_LOG(DEBUG, TAG, "request to get descriptor");
2667 jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
2668 jni_mid_getDescriptor, jni_obj_cc_uuid);
2669 if (!jni_obj_descriptor)
2671 OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
2672 return CA_NOT_SUPPORTED;
2675 OIC_LOG(DEBUG, TAG, "set value in descriptor");
2676 jclass jni_cid_descriptor = (*env)->FindClass(env,
2677 "android/bluetooth/BluetoothGattDescriptor");
2678 if (!jni_cid_descriptor)
2680 OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2681 return CA_STATUS_FAILED;
2684 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2685 if (!jni_mid_setValue)
2687 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2688 return CA_STATUS_FAILED;
2691 jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2692 "ENABLE_NOTIFICATION_VALUE", "[B");
2693 if (!jni_fid_NotiValue)
2695 OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2696 return CA_STATUS_FAILED;
2699 OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2701 jboolean jni_setvalue = (*env)->CallBooleanMethod(
2702 env, jni_obj_descriptor, jni_mid_setValue,
2703 (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2706 OIC_LOG(DEBUG, TAG, "setValue success");
2710 OIC_LOG(ERROR, TAG, "setValue has failed");
2711 return CA_STATUS_FAILED;
2714 jmethodID jni_mid_writeDescriptor = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt",
2716 "(Landroid/bluetooth/"
2717 "BluetoothGattDescriptor;)Z");
2718 if (!jni_mid_writeDescriptor)
2720 OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2721 return CA_STATUS_FAILED;
2724 OIC_LOG(INFO, TAG, "CALL API - writeDescriptor");
2725 jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2726 jni_obj_descriptor);
2729 OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2733 OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2734 return CA_STATUS_FAILED;
2737 return CA_STATUS_OK;
2740 void CALEClientCreateScanDeviceList(JNIEnv *env)
2742 OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2743 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2745 ca_mutex_lock(g_deviceListMutex);
2746 // create new object array
2747 if (g_deviceList == NULL)
2749 OIC_LOG(DEBUG, TAG, "Create device list");
2751 g_deviceList = u_arraylist_create();
2753 ca_mutex_unlock(g_deviceListMutex);
2756 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2758 VERIFY_NON_NULL(device, TAG, "device is null");
2759 VERIFY_NON_NULL(env, TAG, "env is null");
2761 ca_mutex_lock(g_deviceListMutex);
2765 OIC_LOG(ERROR, TAG, "gdevice_list is null");
2766 ca_mutex_unlock(g_deviceListMutex);
2767 return CA_STATUS_FAILED;
2770 jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2771 if (!jni_remoteAddress)
2773 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2774 ca_mutex_unlock(g_deviceListMutex);
2775 return CA_STATUS_FAILED;
2778 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2781 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2782 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2783 ca_mutex_unlock(g_deviceListMutex);
2784 return CA_STATUS_FAILED;
2787 if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2789 jobject gdevice = (*env)->NewGlobalRef(env, device);
2790 u_arraylist_add(g_deviceList, gdevice);
2791 ca_cond_signal(g_deviceDescCond);
2792 OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress);
2794 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2795 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2797 ca_mutex_unlock(g_deviceListMutex);
2799 return CA_STATUS_OK;
2802 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2804 VERIFY_NON_NULL_RET(env, TAG, "env is null", true);
2805 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2809 OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2813 uint32_t length = u_arraylist_length(g_deviceList);
2814 for (uint32_t index = 0; index < length; index++)
2816 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2819 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2823 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2824 if (!jni_setAddress)
2826 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2830 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2833 OIC_LOG(ERROR, TAG, "setAddress is null");
2834 (*env)->DeleteLocalRef(env, jni_setAddress);
2838 if (!strcmp(remoteAddress, setAddress))
2840 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2841 (*env)->DeleteLocalRef(env, jni_setAddress);
2845 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2846 (*env)->DeleteLocalRef(env, jni_setAddress);
2849 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress);
2854 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2856 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2857 VERIFY_NON_NULL(env, TAG, "env is null");
2859 ca_mutex_lock(g_deviceListMutex);
2863 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2864 ca_mutex_unlock(g_deviceListMutex);
2865 return CA_STATUS_FAILED;
2868 uint32_t length = u_arraylist_length(g_deviceList);
2869 for (uint32_t index = 0; index < length; index++)
2871 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2874 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2877 (*env)->DeleteGlobalRef(env, jarrayObj);
2881 OICFree(g_deviceList);
2882 g_deviceList = NULL;
2884 ca_mutex_unlock(g_deviceListMutex);
2885 return CA_STATUS_OK;
2888 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2890 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2891 VERIFY_NON_NULL(address, TAG, "address is null");
2892 VERIFY_NON_NULL(env, TAG, "env is null");
2894 ca_mutex_lock(g_deviceListMutex);
2898 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2899 ca_mutex_unlock(g_deviceListMutex);
2900 return CA_STATUS_FAILED;
2903 uint32_t length = u_arraylist_length(g_deviceList);
2904 for (uint32_t index = 0; index < length; index++)
2906 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2909 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2910 ca_mutex_unlock(g_deviceListMutex);
2911 return CA_STATUS_FAILED;
2914 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2915 if (!jni_setAddress)
2917 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2918 ca_mutex_unlock(g_deviceListMutex);
2919 return CA_STATUS_FAILED;
2922 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2925 OIC_LOG(ERROR, TAG, "setAddress is null");
2926 ca_mutex_unlock(g_deviceListMutex);
2927 return CA_STATUS_FAILED;
2930 const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2933 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2934 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2935 ca_mutex_unlock(g_deviceListMutex);
2936 return CA_STATUS_FAILED;
2939 if (!strcmp(setAddress, remoteAddress))
2941 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2942 (*env)->DeleteGlobalRef(env, jarrayObj);
2944 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2945 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2947 if (NULL == u_arraylist_remove(g_deviceList, index))
2949 OIC_LOG(ERROR, TAG, "List removal failed.");
2950 ca_mutex_unlock(g_deviceListMutex);
2951 return CA_STATUS_FAILED;
2953 ca_mutex_unlock(g_deviceListMutex);
2954 return CA_STATUS_OK;
2956 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2957 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2960 ca_mutex_unlock(g_deviceListMutex);
2961 OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2963 return CA_STATUS_OK;
2970 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2972 OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2973 VERIFY_NON_NULL(env, TAG, "env is null");
2974 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2976 ca_mutex_lock(g_gattObjectMutex);
2978 if (!g_gattObjectList)
2980 OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
2981 ca_mutex_unlock(g_gattObjectMutex);
2982 return CA_STATUS_FAILED;
2985 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2986 if (!jni_remoteAddress)
2988 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2989 ca_mutex_unlock(g_gattObjectMutex);
2990 return CA_STATUS_FAILED;
2993 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2996 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2997 ca_mutex_unlock(g_gattObjectMutex);
2998 return CA_STATUS_FAILED;
3001 OIC_LOG_V(DEBUG, TAG, "remote address : %s", remoteAddress);
3002 if (!CALEClientIsGattObjInList(env, remoteAddress))
3004 jobject newGatt = (*env)->NewGlobalRef(env, gatt);
3005 u_arraylist_add(g_gattObjectList, newGatt);
3006 OIC_LOG(INFO, TAG, "added a newGatt object to gattObjectList");
3009 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3010 ca_mutex_unlock(g_gattObjectMutex);
3011 return CA_STATUS_OK;
3014 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
3016 OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
3017 VERIFY_NON_NULL(env, TAG, "env is null");
3018 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
3020 uint32_t length = u_arraylist_length(g_gattObjectList);
3021 for (uint32_t index = 0; index < length; index++)
3024 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3027 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3031 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3032 if (!jni_setAddress)
3034 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3038 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3041 OIC_LOG(ERROR, TAG, "setAddress is null");
3045 if (!strcmp(remoteAddress, setAddress))
3047 OIC_LOG(DEBUG, TAG, "the device is already set");
3048 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3053 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3058 OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
3062 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
3064 OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
3065 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
3066 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3068 ca_mutex_lock(g_gattObjectMutex);
3069 uint32_t length = u_arraylist_length(g_gattObjectList);
3070 for (uint32_t index = 0; index < length; index++)
3072 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3075 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3076 ca_mutex_unlock(g_gattObjectMutex);
3080 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3081 if (!jni_setAddress)
3083 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3084 ca_mutex_unlock(g_gattObjectMutex);
3088 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3091 OIC_LOG(ERROR, TAG, "setAddress is null");
3092 ca_mutex_unlock(g_gattObjectMutex);
3096 if (!strcmp(remoteAddress, setAddress))
3098 OIC_LOG(DEBUG, TAG, "the device is already set");
3099 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3100 ca_mutex_unlock(g_gattObjectMutex);
3103 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3106 ca_mutex_unlock(g_gattObjectMutex);
3107 OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
3111 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
3113 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
3114 VERIFY_NON_NULL(env, TAG, "env is null");
3116 ca_mutex_lock(g_gattObjectMutex);
3117 if (!g_gattObjectList)
3119 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3120 ca_mutex_unlock(g_gattObjectMutex);
3121 return CA_STATUS_OK;
3124 uint32_t length = u_arraylist_length(g_gattObjectList);
3125 for (uint32_t index = 0; index < length; index++)
3127 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3130 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3133 (*env)->DeleteGlobalRef(env, jarrayObj);
3137 OICFree(g_gattObjectList);
3138 g_gattObjectList = NULL;
3139 OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
3140 ca_mutex_unlock(g_gattObjectMutex);
3141 return CA_STATUS_OK;
3144 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
3146 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
3147 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
3148 VERIFY_NON_NULL(env, TAG, "env is null");
3150 ca_mutex_lock(g_gattObjectMutex);
3151 if (!g_gattObjectList)
3153 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3154 ca_mutex_unlock(g_gattObjectMutex);
3155 return CA_STATUS_OK;
3158 uint32_t length = u_arraylist_length(g_gattObjectList);
3159 for (uint32_t index = 0; index < length; index++)
3161 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3164 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3165 ca_mutex_unlock(g_gattObjectMutex);
3166 return CA_STATUS_FAILED;
3169 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3170 if (!jni_setAddress)
3172 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3173 ca_mutex_unlock(g_gattObjectMutex);
3174 return CA_STATUS_FAILED;
3177 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3180 OIC_LOG(ERROR, TAG, "setAddress is null");
3181 ca_mutex_unlock(g_gattObjectMutex);
3182 return CA_STATUS_FAILED;
3185 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3186 if (!jni_remoteAddress)
3188 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3189 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3190 ca_mutex_unlock(g_gattObjectMutex);
3191 return CA_STATUS_FAILED;
3194 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3197 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3198 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3199 ca_mutex_unlock(g_gattObjectMutex);
3200 return CA_STATUS_FAILED;
3203 if (!strcmp(setAddress, remoteAddress))
3205 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3206 (*env)->DeleteGlobalRef(env, jarrayObj);
3208 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3209 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3211 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3213 OIC_LOG(ERROR, TAG, "List removal failed.");
3214 ca_mutex_unlock(g_gattObjectMutex);
3215 return CA_STATUS_FAILED;
3217 ca_mutex_unlock(g_gattObjectMutex);
3218 return CA_STATUS_OK;
3220 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3221 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3224 ca_mutex_unlock(g_gattObjectMutex);
3225 OIC_LOG(DEBUG, TAG, "there are no target object");
3226 return CA_STATUS_OK;
3229 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
3231 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
3232 VERIFY_NON_NULL(addr, TAG, "addr is null");
3233 VERIFY_NON_NULL(env, TAG, "env is null");
3235 ca_mutex_lock(g_gattObjectMutex);
3236 if (!g_gattObjectList)
3238 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3239 ca_mutex_unlock(g_gattObjectMutex);
3240 return CA_STATUS_OK;
3243 uint32_t length = u_arraylist_length(g_gattObjectList);
3244 for (uint32_t index = 0; index < length; index++)
3246 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3249 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3250 ca_mutex_unlock(g_gattObjectMutex);
3251 return CA_STATUS_FAILED;
3254 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3255 if (!jni_setAddress)
3257 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3258 ca_mutex_unlock(g_gattObjectMutex);
3259 return CA_STATUS_FAILED;
3262 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3265 OIC_LOG(ERROR, TAG, "setAddress is null");
3266 ca_mutex_unlock(g_gattObjectMutex);
3267 return CA_STATUS_FAILED;
3270 const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
3273 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3274 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3275 ca_mutex_unlock(g_gattObjectMutex);
3276 return CA_STATUS_FAILED;
3279 if (!strcmp(setAddress, remoteAddress))
3281 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3282 (*env)->DeleteGlobalRef(env, jarrayObj);
3284 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3285 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3286 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3288 OIC_LOG(ERROR, TAG, "List removal failed.");
3289 ca_mutex_unlock(g_gattObjectMutex);
3290 return CA_STATUS_FAILED;
3292 ca_mutex_unlock(g_gattObjectMutex);
3293 return CA_STATUS_OK;
3295 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3296 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3299 ca_mutex_unlock(g_gattObjectMutex);
3300 OIC_LOG(DEBUG, TAG, "there are no target object");
3301 return CA_STATUS_FAILED;
3304 jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
3306 OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice");
3308 VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
3309 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
3311 // get Bluetooth Address
3312 jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
3313 if (!jni_btTargetAddress)
3315 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3319 const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
3322 OIC_LOG(ERROR, TAG, "targetAddress is not available");
3326 // get method ID of getDevice()
3327 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3328 "getDevice", METHODID_BT_DEVICE);
3329 if (!jni_mid_getDevice)
3331 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
3332 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3336 ca_mutex_lock(g_gattObjectMutex);
3338 size_t length = u_arraylist_length(g_gattObjectList);
3339 OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length);
3340 OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
3342 for (size_t index = 0; index < length; index++)
3344 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3347 ca_mutex_unlock(g_gattObjectMutex);
3348 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3349 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3353 jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
3354 if (!jni_obj_device)
3356 ca_mutex_unlock(g_gattObjectMutex);
3357 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
3358 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3362 jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
3365 ca_mutex_unlock(g_gattObjectMutex);
3366 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3367 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3371 const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
3374 ca_mutex_unlock(g_gattObjectMutex);
3375 OIC_LOG(ERROR, TAG, "btAddress is not available");
3376 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3380 OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index);
3381 if (!strcmp(targetAddress, btAddress))
3383 OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
3386 jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3389 OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
3391 ca_mutex_unlock(g_gattObjectMutex);
3392 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3393 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3394 (*env)->DeleteLocalRef(env, jni_btAddress);
3395 (*env)->DeleteLocalRef(env, jni_obj_device);
3396 return jni_LEAddress;
3398 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3399 (*env)->DeleteLocalRef(env, jni_btAddress);
3400 (*env)->DeleteLocalRef(env, jni_obj_device);
3402 ca_mutex_unlock(g_gattObjectMutex);
3404 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3405 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress);
3413 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
3414 uint16_t target_state)
3416 VERIFY_NON_NULL(address, TAG, "address is null");
3417 VERIFY_NON_NULL(address, TAG, "state_type is null");
3418 VERIFY_NON_NULL(address, TAG, "target_state is null");
3420 if (!g_deviceStateList)
3422 OIC_LOG(ERROR, TAG, "gdevice_list is null");
3423 return CA_STATUS_FAILED;
3426 ca_mutex_lock(g_deviceStateListMutex);
3428 if (CALEClientIsDeviceInList(address))
3430 CALEState_t* curState = CALEClientGetStateInfo(address);
3433 OIC_LOG(ERROR, TAG, "curState is null");
3434 ca_mutex_unlock(g_deviceStateListMutex);
3435 return CA_STATUS_FAILED;
3440 case CA_LE_CONNECTION_STATE:
3441 curState->connectedState = target_state;
3443 case CA_LE_SEND_STATE:
3444 curState->sendState = target_state;
3449 OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
3450 curState->address, curState->connectedState, curState->sendState,
3451 curState->autoConnectFlag);
3453 else /** state is added newly **/
3455 if (strlen(address) > CA_MACADDR_SIZE)
3457 OIC_LOG(ERROR, TAG, "address is not proper");
3458 ca_mutex_unlock(g_deviceStateListMutex);
3459 return CA_STATUS_INVALID_PARAM;
3462 CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
3465 OIC_LOG(ERROR, TAG, "out of memory");
3466 ca_mutex_unlock(g_deviceStateListMutex);
3467 return CA_MEMORY_ALLOC_FAILED;
3470 OICStrcpy(newstate->address, sizeof(newstate->address), address);
3474 case CA_LE_CONNECTION_STATE:
3475 newstate->connectedState = target_state;
3476 newstate->sendState = STATE_SEND_NONE;
3478 case CA_LE_SEND_STATE:
3479 newstate->connectedState = STATE_DISCONNECTED;
3480 newstate->sendState = target_state;
3485 OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, "
3486 "conn : %d, send : %d, ACFlag : %d",
3487 newstate->address, newstate->connectedState, newstate->sendState,
3488 newstate->autoConnectFlag);
3489 u_arraylist_add(g_deviceStateList, newstate); // update new state
3491 ca_mutex_unlock(g_deviceStateListMutex);
3493 return CA_STATUS_OK;
3496 bool CALEClientIsDeviceInList(const char* remoteAddress)
3498 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3500 if (!g_deviceStateList)
3502 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3506 uint32_t length = u_arraylist_length(g_deviceStateList);
3507 for (uint32_t index = 0; index < length; index++)
3509 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3512 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3516 if (!strcmp(remoteAddress, state->address))
3518 OIC_LOG(DEBUG, TAG, "the device is already set");
3527 OIC_LOG(DEBUG, TAG, "there are no the device in list.");
3531 CAResult_t CALEClientRemoveAllDeviceState()
3533 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
3535 ca_mutex_lock(g_deviceStateListMutex);
3536 if (!g_deviceStateList)
3538 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3539 ca_mutex_unlock(g_deviceStateListMutex);
3540 return CA_STATUS_FAILED;
3543 uint32_t length = u_arraylist_length(g_deviceStateList);
3544 for (uint32_t index = 0; index < length; index++)
3546 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3549 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3555 OICFree(g_deviceStateList);
3556 g_deviceStateList = NULL;
3557 ca_mutex_unlock(g_deviceStateListMutex);
3559 return CA_STATUS_OK;
3562 CAResult_t CALEClientResetDeviceStateForAll()
3564 OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll");
3566 ca_mutex_lock(g_deviceStateListMutex);
3567 if (!g_deviceStateList)
3569 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3570 ca_mutex_unlock(g_deviceStateListMutex);
3571 return CA_STATUS_FAILED;
3574 size_t length = u_arraylist_length(g_deviceStateList);
3575 for (size_t index = 0; index < length; index++)
3577 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3580 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3584 // autoConnectFlag value will be not changed,
3585 // since it has reset only termination case.
3586 state->connectedState = STATE_DISCONNECTED;
3587 state->sendState = STATE_SEND_NONE;
3589 ca_mutex_unlock(g_deviceStateListMutex);
3591 return CA_STATUS_OK;
3594 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
3596 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
3597 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3599 if (!g_deviceStateList)
3601 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3602 return CA_STATUS_FAILED;
3605 uint32_t length = u_arraylist_length(g_deviceStateList);
3606 for (uint32_t index = 0; index < length; index++)
3608 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3611 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3615 if (!strcmp(state->address, remoteAddress))
3617 OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
3619 CALEState_t* targetState = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
3621 if (NULL == targetState)
3623 OIC_LOG(ERROR, TAG, "List removal failed.");
3624 return CA_STATUS_FAILED;
3627 OICFree(targetState);
3628 return CA_STATUS_OK;
3632 return CA_STATUS_OK;
3635 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
3637 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3639 if (!g_deviceStateList)
3641 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3645 uint32_t length = u_arraylist_length(g_deviceStateList);
3646 OIC_LOG_V(DEBUG, TAG, "length of deviceStateList : %d", length);
3647 OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
3649 for (uint32_t index = 0; index < length; index++)
3651 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3654 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3658 OIC_LOG_V(DEBUG, TAG, "state address : %s (idx: %d)", state->address, index);
3660 if (!strcmp(state->address, remoteAddress))
3662 OIC_LOG(DEBUG, TAG, "found state");
3667 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in deviceStateList", remoteAddress);
3671 bool CALEClientIsValidState(const char* remoteAddress, uint16_t state_type,
3672 uint16_t target_state)
3674 OIC_LOG_V(DEBUG, TAG, "CALEClientIsValidState : type[%d], target state[%d]",
3675 state_type, target_state);
3676 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3678 ca_mutex_lock(g_deviceStateListMutex);
3679 if (!g_deviceStateList)
3681 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3682 ca_mutex_unlock(g_deviceStateListMutex);
3686 CALEState_t* state = CALEClientGetStateInfo(remoteAddress);
3689 OIC_LOG(ERROR, TAG, "state is null");
3690 ca_mutex_unlock(g_deviceStateListMutex);
3694 uint16_t curValue = 0;
3697 case CA_LE_CONNECTION_STATE:
3698 curValue = state->connectedState;
3700 case CA_LE_SEND_STATE:
3701 curValue = state->sendState;
3707 if (target_state == curValue)
3709 ca_mutex_unlock(g_deviceStateListMutex);
3714 ca_mutex_unlock(g_deviceStateListMutex);
3718 ca_mutex_unlock(g_deviceStateListMutex);
3722 void CALEClientCreateDeviceList()
3724 OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
3726 // create new object array
3727 if (!g_gattObjectList)
3729 OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
3731 g_gattObjectList = u_arraylist_create();
3734 if (!g_deviceStateList)
3736 OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
3738 g_deviceStateList = u_arraylist_create();
3743 OIC_LOG(DEBUG, TAG, "Create g_deviceList");
3745 g_deviceList = u_arraylist_create();
3750 * Check Sent Count for remove g_sendBuffer
3752 void CALEClientUpdateSendCnt(JNIEnv *env)
3754 OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
3756 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3758 ca_mutex_lock(g_threadMutex);
3762 if (g_targetCnt <= g_currentSentCnt)
3765 g_currentSentCnt = 0;
3769 (*env)->DeleteGlobalRef(env, g_sendBuffer);
3770 g_sendBuffer = NULL;
3772 // notity the thread
3773 ca_cond_signal(g_threadCond);
3775 CALEClientSetSendFinishFlag(true);
3776 OIC_LOG(DEBUG, TAG, "set signal for send data");
3779 // reset interval scan logic
3780 CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
3783 ca_mutex_unlock(g_threadMutex);
3786 CAResult_t CALEClientInitGattMutexVaraibles()
3788 if (NULL == g_bleReqRespClientCbMutex)
3790 g_bleReqRespClientCbMutex = ca_mutex_new();
3791 if (NULL == g_bleReqRespClientCbMutex)
3793 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3794 return CA_STATUS_FAILED;
3798 if (NULL == g_bleServerBDAddressMutex)
3800 g_bleServerBDAddressMutex = ca_mutex_new();
3801 if (NULL == g_bleServerBDAddressMutex)
3803 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3804 return CA_STATUS_FAILED;
3808 if (NULL == g_threadMutex)
3810 g_threadMutex = ca_mutex_new();
3811 if (NULL == g_threadMutex)
3813 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3814 return CA_STATUS_FAILED;
3818 if (NULL == g_threadSendMutex)
3820 g_threadSendMutex = ca_mutex_new();
3821 if (NULL == g_threadSendMutex)
3823 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3824 return CA_STATUS_FAILED;
3828 if (NULL == g_deviceListMutex)
3830 g_deviceListMutex = ca_mutex_new();
3831 if (NULL == g_deviceListMutex)
3833 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3834 return CA_STATUS_FAILED;
3838 if (NULL == g_gattObjectMutex)
3840 g_gattObjectMutex = ca_mutex_new();
3841 if (NULL == g_gattObjectMutex)
3843 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3844 return CA_STATUS_FAILED;
3848 if (NULL == g_deviceStateListMutex)
3850 g_deviceStateListMutex = ca_mutex_new();
3851 if (NULL == g_deviceStateListMutex)
3853 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3854 return CA_STATUS_FAILED;
3858 if (NULL == g_SendFinishMutex)
3860 g_SendFinishMutex = ca_mutex_new();
3861 if (NULL == g_SendFinishMutex)
3863 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3864 return CA_STATUS_FAILED;
3868 if (NULL == g_threadWriteCharacteristicMutex)
3870 g_threadWriteCharacteristicMutex = ca_mutex_new();
3871 if (NULL == g_threadWriteCharacteristicMutex)
3873 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3874 return CA_STATUS_FAILED;
3878 if (NULL == g_deviceScanRetryDelayMutex)
3880 g_deviceScanRetryDelayMutex = ca_mutex_new();
3881 if (NULL == g_deviceScanRetryDelayMutex)
3883 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3884 return CA_STATUS_FAILED;
3888 if (NULL == g_threadSendStateMutex)
3890 g_threadSendStateMutex = ca_mutex_new();
3891 if (NULL == g_threadSendStateMutex)
3893 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3894 return CA_STATUS_FAILED;
3898 if (NULL == g_threadScanIntervalMutex)
3900 g_threadScanIntervalMutex = ca_mutex_new();
3901 if (NULL == g_threadScanIntervalMutex)
3903 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3904 return CA_STATUS_FAILED;
3908 return CA_STATUS_OK;
3911 void CALEClientTerminateGattMutexVariables()
3913 ca_mutex_free(g_bleReqRespClientCbMutex);
3914 g_bleReqRespClientCbMutex = NULL;
3916 ca_mutex_free(g_bleServerBDAddressMutex);
3917 g_bleServerBDAddressMutex = NULL;
3919 ca_mutex_free(g_threadMutex);
3920 g_threadMutex = NULL;
3922 ca_mutex_free(g_threadSendMutex);
3923 g_threadSendMutex = NULL;
3925 ca_mutex_free(g_deviceListMutex);
3926 g_deviceListMutex = NULL;
3928 ca_mutex_free(g_SendFinishMutex);
3929 g_SendFinishMutex = NULL;
3931 ca_mutex_free(g_threadWriteCharacteristicMutex);
3932 g_threadWriteCharacteristicMutex = NULL;
3934 ca_mutex_free(g_deviceScanRetryDelayMutex);
3935 g_deviceScanRetryDelayMutex = NULL;
3937 ca_mutex_free(g_threadSendStateMutex);
3938 g_threadSendStateMutex = NULL;
3940 ca_mutex_free(g_threadScanIntervalMutex);
3941 g_threadScanIntervalMutex = NULL;
3944 void CALEClientSetSendFinishFlag(bool flag)
3946 OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3948 ca_mutex_lock(g_SendFinishMutex);
3949 g_isFinishedSendData = flag;
3950 ca_mutex_unlock(g_SendFinishMutex);
3957 CAResult_t CAStartLEGattClient()
3959 // init mutex for send logic
3960 if (!g_deviceDescCond)
3962 g_deviceDescCond = ca_cond_new();
3967 g_threadCond = ca_cond_new();
3970 if (!g_threadWriteCharacteristicCond)
3972 g_threadWriteCharacteristicCond = ca_cond_new();
3975 if (!g_threadScanIntervalCond)
3977 g_threadScanIntervalCond = ca_cond_new();
3980 CAResult_t ret = CALEClientStartScanWithInterval();
3981 if (CA_STATUS_OK != ret)
3983 OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
3987 g_isStartedLEClient = true;
3988 return CA_STATUS_OK;
3991 void CAStopLEGattClient()
3993 OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
3997 OIC_LOG(ERROR, TAG, "g_jvm is null");
4001 bool isAttached = false;
4003 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
4006 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
4007 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
4011 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
4017 CAResult_t ret = CALEClientDisconnectAll(env);
4018 if (CA_STATUS_OK != ret)
4020 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
4023 CALEClientStopScanWithInterval();
4025 ca_mutex_lock(g_threadMutex);
4026 OIC_LOG(DEBUG, TAG, "signal - connection cond");
4027 ca_cond_signal(g_threadCond);
4028 CALEClientSetSendFinishFlag(true);
4029 ca_mutex_unlock(g_threadMutex);
4031 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4032 OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
4033 ca_cond_signal(g_threadWriteCharacteristicCond);
4034 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4036 ca_mutex_lock(g_deviceScanRetryDelayMutex);
4037 OIC_LOG(DEBUG, TAG, "signal - delay cond");
4038 ca_cond_signal(g_deviceScanRetryDelayCond);
4039 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
4041 ca_mutex_lock(g_threadScanIntervalMutex);
4042 OIC_LOG(DEBUG, TAG, "signal - delay cond");
4043 ca_cond_signal(g_threadScanIntervalCond);
4044 ca_mutex_unlock(g_threadScanIntervalMutex);
4046 ca_cond_free(g_deviceDescCond);
4047 ca_cond_free(g_threadCond);
4048 ca_cond_free(g_threadWriteCharacteristicCond);
4049 ca_cond_free(g_deviceScanRetryDelayCond);
4050 ca_cond_free(g_threadScanIntervalCond);
4052 g_deviceDescCond = NULL;
4053 g_threadCond = NULL;
4054 g_threadWriteCharacteristicCond = NULL;
4055 g_deviceScanRetryDelayCond = NULL;
4056 g_threadScanIntervalCond = NULL;
4060 (*g_jvm)->DetachCurrentThread(g_jvm);
4065 CAResult_t CAInitializeLEGattClient()
4067 OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
4068 CALEClientInitialize();
4069 return CA_STATUS_OK;
4072 void CATerminateLEGattClient()
4074 OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
4075 CAStopLEGattClient();
4076 CALEClientTerminate();
4079 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t *data,
4080 uint32_t dataLen, CALETransferType_t type,
4083 OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
4084 VERIFY_NON_NULL(data, TAG, "data is null");
4085 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
4087 if (LE_UNICAST != type || position < 0)
4089 OIC_LOG(ERROR, TAG, "this request is not unicast");
4090 return CA_STATUS_INVALID_PARAM;
4093 return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
4096 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
4098 OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
4099 VERIFY_NON_NULL(data, TAG, "data is null");
4101 return CALEClientSendMulticastMessage(data, dataLen);
4104 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
4106 ca_mutex_lock(g_bleReqRespClientCbMutex);
4107 g_CABLEClientDataReceivedCallback = callback;
4108 ca_mutex_unlock(g_bleReqRespClientCbMutex);
4111 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
4113 g_threadPoolHandle = handle;
4116 CAResult_t CAGetLEAddress(char **local_address)
4118 VERIFY_NON_NULL(local_address, TAG, "local_address");
4119 OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
4120 return CA_NOT_SUPPORTED;
4123 JNIEXPORT void JNICALL
4124 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
4127 OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
4128 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4129 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4130 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4132 g_leScanCallback = (*env)->NewGlobalRef(env, callback);
4135 JNIEXPORT void JNICALL
4136 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
4139 OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
4140 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4141 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4142 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4144 g_leGattCallback = (*env)->NewGlobalRef(env, callback);
4147 JNIEXPORT void JNICALL
4148 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
4151 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4152 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4153 VERIFY_NON_NULL_VOID(device, TAG, "device is null");
4155 CAResult_t res = CALEClientAddScanDeviceToList(env, device);
4156 if (CA_STATUS_OK != res)
4158 OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
4163 * Class: org_iotivity_ca_jar_caleinterface
4164 * Method: CALeGattConnectionStateChangeCallback
4165 * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
4167 JNIEXPORT void JNICALL
4168 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
4174 OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
4176 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4177 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4178 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4180 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
4182 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4185 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
4189 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4192 OIC_LOG(ERROR, TAG, "address is null");
4195 OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
4197 if (state_connected == newstate)
4199 OIC_LOG(DEBUG, TAG, "LE is connected");
4200 if (GATT_SUCCESS == status)
4202 CAResult_t res = CALEClientUpdateDeviceState(address,
4203 CA_LE_CONNECTION_STATE,
4205 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4206 if (CA_STATUS_OK != res)
4208 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4212 res = CALEClientAddGattobjToList(env, gatt);
4213 if (CA_STATUS_OK != res)
4215 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
4219 res = CALEClientDiscoverServices(env, gatt);
4220 if (CA_STATUS_OK != res)
4222 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
4228 OIC_LOG(INFO, TAG, "unknown status");
4229 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4232 else // STATE_DISCONNECTED == newstate
4234 OIC_LOG(DEBUG, TAG, "LE is disconnected");
4236 CAResult_t res = CALEClientUpdateDeviceState(address,
4237 CA_LE_CONNECTION_STATE,
4238 STATE_DISCONNECTED);
4239 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4240 if (CA_STATUS_OK != res)
4242 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4246 res = CALEClientGattClose(env, gatt);
4247 if (CA_STATUS_OK != res)
4249 OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
4252 if (CALECheckConnectionStateValue(status))
4254 // this state is unexpected reason to disconnect
4255 // if the reason is suitable, connection logic of the device will be destroyed.
4256 OIC_LOG(INFO, TAG, "connection logic destroy");
4261 // other reason except for gatt_success is expected to running
4262 // background connection in BT platform.
4263 OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
4264 CALEClientUpdateSendCnt(env);
4270 (*env)->DeleteGlobalRef(env, g_sendBuffer);
4271 g_sendBuffer = NULL;
4278 CALEClientSendFinish(env, gatt);
4283 * Class: org_iotivity_ca_jar_caleinterface
4284 * Method: CALeGattServicesDiscoveredCallback
4285 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
4287 JNIEXPORT void JNICALL
4288 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
4293 OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d", status);
4294 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4295 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4296 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4298 if (GATT_SUCCESS != status) // discovery error
4300 CALEClientSendFinish(env, gatt);
4304 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4307 CALEClientSendFinish(env, gatt);
4311 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4314 CALEClientSendFinish(env, gatt);
4318 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
4321 OIC_LOG(ERROR, TAG, "jni_uuid is null");
4325 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
4326 if (!jni_obj_GattCharacteristic)
4328 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
4332 CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
4333 jni_obj_GattCharacteristic);
4334 if (CA_STATUS_OK != res)
4336 OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
4340 res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
4341 if (CA_STATUS_OK != res)
4343 OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
4345 res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE);
4346 if (CA_STATUS_OK != res)
4348 OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4352 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4353 STATE_SERVICE_CONNECTED);
4354 if (CA_STATUS_OK != res)
4356 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4362 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4363 if (CA_STATUS_OK != res)
4365 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4372 res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE);
4373 if (CA_STATUS_OK != res)
4375 OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4380 // reset interval scan logic
4381 CALERestartScanWithInterval(g_scanIntervalTimePrev, 0, BLE_SCAN_ENABLE);
4383 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
4384 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4389 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
4390 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4391 CALEClientSendFinish(env, gatt);
4396 * Class: org_iotivity_ca_jar_caleinterface
4397 * Method: CALeGattCharacteristicWritjclasseCallback
4398 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
4400 JNIEXPORT void JNICALL
4401 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
4402 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
4404 OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
4405 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4406 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4407 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4409 // send success & signal
4410 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4416 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4422 if (GATT_SUCCESS != status) // error case
4424 OIC_LOG(ERROR, TAG, "send failure");
4427 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4428 if (CA_STATUS_OK != res)
4430 OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
4431 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4432 g_isSignalSetFlag = true;
4433 ca_cond_signal(g_threadWriteCharacteristicCond);
4434 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4436 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4438 if (CA_STATUS_OK != res)
4440 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4443 if (g_clientErrorCallback)
4445 jint length = (*env)->GetArrayLength(env, data);
4446 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
4449 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4455 OIC_LOG(DEBUG, TAG, "send success");
4456 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4457 STATE_SEND_SUCCESS);
4458 if (CA_STATUS_OK != res)
4460 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4463 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4464 OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
4465 g_isSignalSetFlag = true;
4466 ca_cond_signal(g_threadWriteCharacteristicCond);
4467 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4470 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4476 CALEClientSendFinish(env, gatt);
4481 * Class: org_iotivity_ca_jar_caleinterface
4482 * Method: CALeGattCharacteristicChangedCallback
4483 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
4485 JNIEXPORT void JNICALL
4486 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
4487 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
4489 OIC_LOG(INFO, TAG, "CALeGattCharacteristicChangedCallback");
4490 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4491 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4492 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4493 VERIFY_NON_NULL_VOID(data, TAG, "data is null");
4495 // get Byte Array and convert to uint8_t*
4496 jint length = (*env)->GetArrayLength(env, data);
4499 jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
4501 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
4502 jni_byte_responseData);
4504 uint8_t* receivedData = OICMalloc(length);
4507 OIC_LOG(ERROR, TAG, "receivedData is null");
4511 memcpy(receivedData, jni_byte_responseData, length);
4512 (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
4514 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4517 OIC_LOG(ERROR, TAG, "jni_address is null");
4518 OICFree(receivedData);
4522 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4525 OIC_LOG(ERROR, TAG, "address is null");
4526 OICFree(receivedData);
4530 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
4531 receivedData, length);
4533 uint32_t sentLength = 0;
4534 ca_mutex_lock(g_bleServerBDAddressMutex);
4535 g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
4536 ca_mutex_unlock(g_bleServerBDAddressMutex);
4538 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4542 * Class: org_iotivity_ca_jar_caleinterface
4543 * Method: CALeGattDescriptorWriteCallback
4544 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
4546 JNIEXPORT void JNICALL
4547 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
4551 OIC_LOG_V(INFO, TAG, "CALeGattDescriptorWriteCallback - status %d", status);
4552 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4553 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4554 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4556 if (GATT_SUCCESS != status) // error
4561 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4567 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4573 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4574 STATE_SERVICE_CONNECTED);
4575 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4576 if (CA_STATUS_OK != res)
4578 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4584 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4585 if (CA_STATUS_OK != res)
4587 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4596 CALEClientSendFinish(env, gatt);