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_scanningStep = BLE_SCAN_DISABLE;
109 static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
112 * check if retry logic for connection routine has to be stopped or not.
113 * in case of error value including this method, connection routine has to be stopped.
114 * since there is no retry logic for this error reason in this client.
115 * @param state constant value of bluetoothgatt.
116 * @return true - waiting for background connection in BT platform.
117 * false - connection routine has to be stopped.
119 static bool CALECheckConnectionStateValue(jint state)
123 case GATT_CONNECTION_PRIORITY_BALANCED:
125 case GATT_INSUFFICIENT_AUTHENTICATION:
126 case GATT_INSUFFICIENT_ENCRYPTION:
127 case GATT_INVALID_ATTRIBUTE_LENGTH:
128 case GATT_INVALID_OFFSET:
129 case GATT_READ_NOT_PERMITTED:
130 case GATT_REQUEST_NOT_SUPPORTED:
131 case GATT_WRITE_NOT_PERMITTED:
137 void CALEClientSetScanInterval(int32_t intervalTime, int32_t workingCount)
139 OIC_LOG_V(DEBUG, TAG, "CALEClientSetScanInterval : %d -> %d",
140 g_scanIntervalTime, intervalTime);
142 // previous time should be stored.
143 if (0 < workingCount)
145 g_scanIntervalTimePrev = g_scanIntervalTime;
147 g_scanIntervalTime = intervalTime;
148 g_intervalCount = workingCount;
151 void CALERestartScanWithInterval(int32_t intervalTime, int32_t workingCount)
153 // restart scan with interval
154 CALEClientSetScanInterval(intervalTime, workingCount);
155 ca_cond_signal(g_threadScanIntervalCond);
158 static void CALEScanThread(void* object)
162 bool isAttached = false;
164 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
167 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
168 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
172 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
178 ca_mutex_lock(g_threadScanIntervalMutex);
179 while(g_isWorkingScanThread)
181 OIC_LOG(DEBUG, TAG, "scan waiting time out");
182 if (BLE_SCAN_ENABLE == g_scanningStep)
185 CAResult_t ret = CALEClientStopScan();
186 if (CA_STATUS_OK != ret)
188 OIC_LOG(INFO, TAG, "CALEClientStopScan has failed");
194 CAResult_t ret = CALEClientStartScan();
195 if (CA_STATUS_OK != ret)
197 OIC_LOG(INFO, TAG, "CALEClientStartScan has failed");
201 OIC_LOG_V(DEBUG, TAG, "wait for Scan Interval Time during %d sec", g_scanIntervalTime);
202 if (CA_WAIT_SUCCESS == ca_cond_wait_for(g_threadScanIntervalCond,
203 g_threadScanIntervalMutex,
204 g_scanIntervalTime * MICROSECS_PER_SEC))
206 // called signal scan thread will be terminated
207 OIC_LOG(DEBUG, TAG, "signal scanInterval waiting");
208 g_scanningStep = BLE_SCAN_DISABLE;
212 if (BLE_SCAN_ENABLE == g_scanningStep)
214 if (g_intervalCount > 0)
216 if (g_intervalCount == 1)
218 OIC_LOG(DEBUG, TAG, "reset default time");
219 CALEClientSetScanInterval(g_scanIntervalTimePrev, 0);
222 OIC_LOG_V(DEBUG, TAG, "interval count : %d", g_intervalCount);
224 g_scanningStep = BLE_SCAN_DISABLE;
228 g_scanningStep = BLE_SCAN_ENABLE;
232 ca_mutex_unlock(g_threadScanIntervalMutex);
236 (*g_jvm)->DetachCurrentThread(g_jvm);
240 CAResult_t CALEClientStartScanWithInterval()
242 OIC_LOG(DEBUG, TAG, "IN - CALEClientStartScanWithInterval");
244 if (g_isWorkingScanThread)
246 OIC_LOG(DEBUG, TAG, "scan interval logic already running");
250 // initialize scan flags
251 g_scanningStep = BLE_SCAN_DISABLE;
252 g_isWorkingScanThread = true;
254 g_scanIntervalTime = g_scanIntervalTimePrev;
256 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
257 CALEScanThread, NULL))
259 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
260 g_isWorkingScanThread = false;
261 return CA_STATUS_FAILED;
264 OIC_LOG(DEBUG, TAG, "OUT - CALEClientStartScanWithInterval");
268 void CALEClientStopScanWithInterval()
270 g_isWorkingScanThread = false;
271 ca_cond_signal(g_threadScanIntervalCond);
275 void CALEClientJniInit()
277 OIC_LOG(DEBUG, TAG, "CALEClientJniInit");
278 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
281 void CALEClientJNISetContext()
283 OIC_LOG(DEBUG, TAG, "CALEClientJNISetContext");
284 g_context = (jobject) CANativeJNIGetContext();
287 CAResult_t CALECreateJniInterfaceObject()
289 OIC_LOG(DEBUG, TAG, "CALECreateJniInterfaceObject");
293 OIC_LOG(ERROR, TAG, "g_context is null");
294 return CA_STATUS_FAILED;
299 OIC_LOG(ERROR, TAG, "g_jvm is null");
300 return CA_STATUS_FAILED;
303 bool isAttached = false;
305 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
308 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
309 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
313 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
314 return CA_STATUS_FAILED;
319 jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, "android/content/Context",
320 "getApplicationContext",
321 "()Landroid/content/Context;");
323 if (!mid_getApplicationContext)
325 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
326 return CA_STATUS_FAILED;
329 jobject jApplicationContext = (*env)->CallObjectMethod(env, g_context,
330 mid_getApplicationContext);
331 if (!jApplicationContext)
333 OIC_LOG(ERROR, TAG, "Could not get application context");
334 return CA_STATUS_FAILED;
337 jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
338 if (!jni_LEInterface)
340 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
344 jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
345 "(Landroid/content/Context;)V");
346 if (!LeInterfaceConstructorMethod)
348 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface constructor method");
352 (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, jApplicationContext);
353 OIC_LOG(DEBUG, TAG, "Create instance for CaLeClientInterface");
357 (*g_jvm)->DetachCurrentThread(g_jvm);
366 (*g_jvm)->DetachCurrentThread(g_jvm);
369 return CA_STATUS_FAILED;
372 CAResult_t CALEClientInitialize()
374 OIC_LOG(DEBUG, TAG, "CALEClientInitialize");
380 OIC_LOG(ERROR, TAG, "g_jvm is null");
381 return CA_STATUS_FAILED;
384 bool isAttached = false;
386 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
389 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
390 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
394 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
395 return CA_STATUS_FAILED;
400 CAResult_t ret = CALECheckPlatformVersion(env, 18);
401 if (CA_STATUS_OK != ret)
403 OIC_LOG(ERROR, TAG, "it is not supported");
407 (*g_jvm)->DetachCurrentThread(g_jvm);
413 ret = CALEClientInitGattMutexVaraibles();
414 if (CA_STATUS_OK != ret)
416 OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
417 CALEClientTerminateGattMutexVariables();
421 (*g_jvm)->DetachCurrentThread(g_jvm);
427 g_deviceDescCond = ca_cond_new();
429 // init mutex for send logic
430 g_threadCond = ca_cond_new();
431 g_threadWriteCharacteristicCond = ca_cond_new();
432 g_deviceScanRetryDelayCond = ca_cond_new();
433 g_threadScanIntervalCond = ca_cond_new();
435 CALEClientCreateDeviceList();
436 CALEClientJNISetContext();
438 ret = CALEClientCreateUUIDList();
439 if (CA_STATUS_OK != ret)
441 OIC_LOG(ERROR, TAG, "CALEClientCreateUUIDList has failed");
445 (*g_jvm)->DetachCurrentThread(g_jvm);
451 ret = CALECreateJniInterfaceObject(); /* create java caleinterface instance*/
452 if (CA_STATUS_OK != ret)
454 OIC_LOG(ERROR, TAG, "CALECreateJniInterfaceObject has failed");
458 (*g_jvm)->DetachCurrentThread(g_jvm);
463 g_isStartedLEClient = true;
467 (*g_jvm)->DetachCurrentThread(g_jvm);
473 void CALEClientTerminate()
475 OIC_LOG(DEBUG, TAG, "CALEClientTerminate");
479 OIC_LOG(ERROR, TAG, "g_jvm is null");
483 bool isAttached = false;
485 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
488 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
489 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
493 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
499 if (g_leScanCallback)
501 (*env)->DeleteGlobalRef(env, g_leScanCallback);
502 g_leScanCallback = NULL;
505 if (g_leGattCallback)
507 (*env)->DeleteGlobalRef(env, g_leGattCallback);
508 g_leGattCallback = NULL;
513 (*env)->DeleteGlobalRef(env, g_sendBuffer);
519 (*env)->DeleteGlobalRef(env, g_uuidList);
523 CAResult_t ret = CALEClientRemoveAllDeviceState();
524 if (CA_STATUS_OK != ret)
526 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed");
529 ret = CALEClientRemoveAllScanDevices(env);
530 if (CA_STATUS_OK != ret)
532 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
535 ret = CALEClientRemoveAllGattObjs(env);
536 if (CA_STATUS_OK != ret)
538 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllGattObjs has failed");
541 CALEClientSetSendFinishFlag(true);
543 CALEClientTerminateGattMutexVariables();
544 CALEClientDestroyJniInterface();
546 ca_cond_free(g_deviceDescCond);
547 ca_cond_free(g_threadCond);
548 ca_cond_free(g_threadWriteCharacteristicCond);
549 ca_cond_free(g_deviceScanRetryDelayCond);
550 ca_cond_free(g_threadScanIntervalCond);
552 g_deviceDescCond = NULL;
554 g_threadWriteCharacteristicCond = NULL;
555 g_deviceScanRetryDelayCond = NULL;
556 g_threadScanIntervalCond = NULL;
558 g_isSignalSetFlag = false;
561 CALEClientStopScanWithInterval();
565 (*g_jvm)->DetachCurrentThread(g_jvm);
569 CAResult_t CALEClientDestroyJniInterface()
571 OIC_LOG(DEBUG, TAG, "CALEClientDestroyJniInterface");
575 OIC_LOG(ERROR, TAG, "g_jvm is null");
576 return CA_STATUS_FAILED;
579 bool isAttached = false;
581 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
584 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
585 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
589 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
590 return CA_STATUS_FAILED;
595 jclass jni_LeInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
596 if (!jni_LeInterface)
598 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
602 jmethodID jni_InterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_LeInterface,
603 "destroyLeInterface",
605 if (!jni_InterfaceDestroyMethod)
607 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface destroy method");
611 (*env)->CallStaticVoidMethod(env, jni_LeInterface, jni_InterfaceDestroyMethod);
613 if ((*env)->ExceptionCheck(env))
615 OIC_LOG(ERROR, TAG, "destroyLeInterface has failed");
616 (*env)->ExceptionDescribe(env);
617 (*env)->ExceptionClear(env);
621 OIC_LOG(DEBUG, TAG, "Destroy instance for CaLeClientInterface");
625 (*g_jvm)->DetachCurrentThread(g_jvm);
634 (*g_jvm)->DetachCurrentThread(g_jvm);
637 return CA_STATUS_FAILED;
640 void CALEClientSendFinish(JNIEnv *env, jobject gatt)
642 OIC_LOG(DEBUG, TAG, "CALEClientSendFinish");
643 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
647 CAResult_t res = CALEClientDisconnect(env, gatt);
648 if (CA_STATUS_OK != res)
650 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
653 CALEClientUpdateSendCnt(env);
656 CAResult_t CALEClientSendUnicastMessage(const char* address,
658 const uint32_t dataLen)
660 OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data);
661 VERIFY_NON_NULL(address, TAG, "address is null");
662 VERIFY_NON_NULL(data, TAG, "data is null");
664 return CALEClientSendUnicastMessageImpl(address, data, dataLen);
667 CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
668 const uint32_t dataLen)
670 OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
671 VERIFY_NON_NULL(data, TAG, "data is null");
675 OIC_LOG(ERROR, TAG, "g_jvm is null");
676 return CA_STATUS_FAILED;
679 bool isAttached = false;
681 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
684 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
685 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
689 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
690 return CA_STATUS_FAILED;
695 CAResult_t ret = CALEClientSendMulticastMessageImpl(env, data, dataLen);
696 if (CA_STATUS_OK != ret)
698 OIC_LOG(ERROR, TAG, "CALEClientSendMulticastMessageImpl has failed");
703 (*g_jvm)->DetachCurrentThread(g_jvm);
709 CAResult_t CALEClientStartUnicastServer(const char* address)
714 OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address);
716 return CA_NOT_SUPPORTED;
719 CAResult_t CALEClientStartMulticastServer()
721 OIC_LOG(DEBUG, TAG, "it is not needed in this platform");
723 return CA_NOT_SUPPORTED;
726 void CALEClientStopUnicastServer()
728 OIC_LOG(DEBUG, TAG, "CALEClientStopUnicastServer");
731 void CALEClientStopMulticastServer()
733 OIC_LOG(DEBUG, TAG, "CALEClientStopMulticastServer");
736 void CALEClientSetCallback(CAPacketReceiveCallback callback)
738 g_packetReceiveCallback = callback;
741 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
743 g_clientErrorCallback = callback;
746 CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address)
748 VERIFY_NON_NULL(env, TAG, "env");
752 return CA_STATUS_FAILED;
755 if (0 == u_arraylist_length(g_deviceList) // multicast
756 || (address && !CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
758 // Wait for LE peripherals to be discovered.
760 // Number of times to wait for discovery to complete.
761 static size_t const RETRIES = 5;
763 static uint64_t const TIMEOUT =
764 2 * MICROSECS_PER_SEC; // Microseconds
766 // set scan interval and start scan
767 CALERestartScanWithInterval(WAIT_TIME_SCANNED_CHECKING, 1);
769 bool devicesDiscovered = false;
770 for (size_t i = 0; i < RETRIES; ++i)
772 OIC_LOG(DEBUG, TAG, "waiting for target device");
773 if (ca_cond_wait_for(g_deviceDescCond,
775 TIMEOUT) == CA_WAIT_SUCCESS)
777 ca_mutex_lock(g_deviceListMutex);
778 size_t scannedDeviceLen = u_arraylist_length(g_deviceList);
779 ca_mutex_unlock(g_deviceListMutex);
781 if (0 < scannedDeviceLen)
783 if (!address // multicast
784 || (address && CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
786 devicesDiscovered = true;
793 OIC_LOG(INFO, TAG, "waiting..");
795 ca_mutex_lock(g_deviceScanRetryDelayMutex);
796 if (ca_cond_wait_for(g_deviceScanRetryDelayCond,
797 g_deviceScanRetryDelayMutex,
798 MICROSECS_PER_SEC) == CA_WAIT_SUCCESS)
800 OIC_LOG(INFO, TAG, "finish to waiting for target device");
801 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
804 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
807 // checking whether a target device is found while waiting for time-out.
808 if (CALEClientIsDeviceInScanDeviceList(env, address))
810 devicesDiscovered = true;
819 // reset scan interval time after checking scanned devices
820 CALERestartScanWithInterval(g_scanIntervalTimePrev, 0);
822 // time out for scanning devices
823 if (!devicesDiscovered)
825 return CA_STATUS_FAILED;
833 CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data,
834 const uint32_t dataLen)
836 OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address,
838 VERIFY_NON_NULL(address, TAG, "address is null");
839 VERIFY_NON_NULL(data, TAG, "data is null");
843 OIC_LOG(ERROR, TAG, "g_jvm is null");
844 return CA_STATUS_FAILED;
847 bool isAttached = false;
849 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
852 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
853 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
856 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
857 return CA_STATUS_FAILED;
862 ca_mutex_lock(g_threadSendMutex);
864 CALEClientSetSendFinishFlag(false);
866 CAResult_t ret = CALEClientIsThereScannedDevices(env, address);
867 if (CA_STATUS_OK != ret)
869 OIC_LOG(INFO, TAG, "there is no scanned device");
873 if (g_context && g_deviceList)
875 uint32_t length = u_arraylist_length(g_deviceList);
876 for (uint32_t index = 0; index < length; index++)
878 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
881 OIC_LOG(ERROR, TAG, "jarrayObj is null");
885 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
888 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
892 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
895 OIC_LOG(ERROR, TAG, "setAddress is null");
899 OIC_LOG_V(DEBUG, TAG, "remote device address is %s", setAddress);
901 if (!strcmp(setAddress, address))
903 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
904 (*env)->DeleteLocalRef(env, jni_setAddress);
906 // stop scan while sending
907 CALEClientStopScanWithInterval();
911 (*env)->DeleteGlobalRef(env, g_sendBuffer);
914 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
915 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
916 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
918 // Target device to send message is just one.
921 ret = CALEClientSendData(env, jarrayObj);
922 if (CA_STATUS_OK != ret)
924 OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
928 OIC_LOG(INFO, TAG, "wake up");
931 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
932 (*env)->DeleteLocalRef(env, jni_setAddress);
936 OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
938 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
939 // if there is no connection state.
940 ca_mutex_lock(g_threadMutex);
941 if (!g_isFinishedSendData)
943 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
944 ca_cond_wait(g_threadCond, g_threadMutex);
945 OIC_LOG(DEBUG, TAG, "the data was sent");
947 ca_mutex_unlock(g_threadMutex);
951 (*g_jvm)->DetachCurrentThread(g_jvm);
954 // start LE Scan again
955 ret = CALEClientStartScanWithInterval();
956 if (CA_STATUS_OK != ret)
958 OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
959 ca_mutex_unlock(g_threadSendMutex);
963 ca_mutex_unlock(g_threadSendMutex);
964 OIC_LOG(INFO, TAG, "unicast - send logic has finished");
965 if (CALEClientIsValidState(address, CA_LE_SEND_STATE,
972 ret = CA_SEND_FAILED;
976 CAResult_t resetRet = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
978 if (CA_STATUS_OK != resetRet)
980 OIC_LOG_V(ERROR, TAG, "CALEClientUpdateDeviceState has failed (%d)", resetRet);
981 ret = CA_SEND_FAILED;
989 // start LE Scan again
990 ret = CALEClientStartScanWithInterval();
991 if (CA_STATUS_OK != ret)
993 OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
994 ca_mutex_unlock(g_threadSendMutex);
997 (*g_jvm)->DetachCurrentThread(g_jvm);
1004 (*g_jvm)->DetachCurrentThread(g_jvm);
1007 ca_mutex_unlock(g_threadSendMutex);
1008 return CA_SEND_FAILED;
1011 CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
1012 const uint32_t dataLen)
1014 OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
1015 VERIFY_NON_NULL(data, TAG, "data is null");
1016 VERIFY_NON_NULL(env, TAG, "env is null");
1020 OIC_LOG(ERROR, TAG, "g_deviceList is null");
1021 return CA_STATUS_FAILED;
1024 ca_mutex_lock(g_threadSendMutex);
1026 CALEClientSetSendFinishFlag(false);
1028 OIC_LOG(DEBUG, TAG, "set byteArray for data");
1031 (*env)->DeleteGlobalRef(env, g_sendBuffer);
1032 g_sendBuffer = NULL;
1035 CAResult_t res = CALEClientIsThereScannedDevices(env, NULL);
1036 if (CA_STATUS_OK != res)
1038 OIC_LOG(INFO, TAG, "there is no scanned device");
1042 // stop scan while sending
1043 CALEClientStopScanWithInterval();
1045 uint32_t length = u_arraylist_length(g_deviceList);
1046 g_targetCnt = length;
1048 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
1049 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
1050 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
1052 for (uint32_t index = 0; index < length; index++)
1054 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
1057 OIC_LOG(ERROR, TAG, "jarrayObj is not available");
1061 res = CALEClientSendData(env, jarrayObj);
1062 if (res != CA_STATUS_OK)
1064 OIC_LOG(ERROR, TAG, "BT device - send has failed");
1068 OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
1070 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
1071 ca_mutex_lock(g_threadMutex);
1072 if (!g_isFinishedSendData)
1074 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
1075 ca_cond_wait(g_threadCond, g_threadMutex);
1076 OIC_LOG(DEBUG, TAG, "the data was sent");
1078 ca_mutex_unlock(g_threadMutex);
1080 // start LE Scan again
1081 res = CALEClientStartScanWithInterval();
1082 if (CA_STATUS_OK != res)
1084 OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
1085 ca_mutex_unlock(g_threadSendMutex);
1089 ca_mutex_unlock(g_threadSendMutex);
1090 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
1091 return CA_STATUS_OK;
1094 res = CALEClientStartScanWithInterval();
1095 if (CA_STATUS_OK != res)
1097 OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
1098 ca_mutex_unlock(g_threadSendMutex);
1102 ca_mutex_unlock(g_threadSendMutex);
1103 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
1104 return CA_SEND_FAILED;
1107 CAResult_t CALEClientSendData(JNIEnv *env, jobject device)
1109 OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
1110 VERIFY_NON_NULL(device, TAG, "device is null");
1111 VERIFY_NON_NULL(env, TAG, "env is null");
1113 // get BLE address from bluetooth device object.
1114 char* address = NULL;
1115 CALEState_t* state = NULL;
1116 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, device);
1119 OIC_LOG(INFO, TAG, "there is gatt object..it's not first connection");
1120 address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1123 OIC_LOG(ERROR, TAG, "address is not available");
1124 return CA_STATUS_FAILED;
1126 ca_mutex_lock(g_deviceStateListMutex);
1127 state = CALEClientGetStateInfo(address);
1128 ca_mutex_unlock(g_deviceStateListMutex);
1133 OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
1135 // cancel previous connection request before connection
1136 // if there is gatt object in g_gattObjectList.
1139 jobject gatt = CALEClientGetGattObjInList(env, address);
1142 CAResult_t res = CALEClientDisconnect(env, gatt);
1143 if (CA_STATUS_OK != res)
1145 OIC_LOG(INFO, TAG, "there is no gatt object");
1148 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1151 // connection request
1152 jobject newGatt = CALEClientConnect(env, device,
1154 if (NULL == newGatt)
1156 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1157 return CA_STATUS_FAILED;
1162 if (CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1163 STATE_SERVICE_CONNECTED))
1165 OIC_LOG(INFO, TAG, "GATT has already connected");
1167 jobject gatt = CALEClientGetGattObjInList(env, address);
1170 OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
1171 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1172 return CA_STATUS_FAILED;
1175 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1176 if (CA_STATUS_OK != ret)
1178 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1179 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1182 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1184 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1187 OIC_LOG(INFO, TAG, "service connecting...");
1189 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1190 STATE_DISCONNECTED))
1192 OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
1194 // cancel previous connection request before connection
1195 // if there is gatt object in g_gattObjectList.
1198 jobject gatt = CALEClientGetGattObjInList(env, address);
1201 CAResult_t res = CALEClientDisconnect(env, gatt);
1202 if (CA_STATUS_OK != res)
1204 OIC_LOG(INFO, TAG, "there is no gatt object");
1207 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1210 OIC_LOG(DEBUG, TAG, "start to connect LE");
1211 jobject gatt = CALEClientConnect(env, device,
1212 CALEClientGetFlagFromState(env, jni_address,
1213 CA_LE_AUTO_CONNECT_FLAG));
1217 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1218 return CA_STATUS_FAILED;
1223 return CA_STATUS_OK;
1226 jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
1228 VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
1229 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1231 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
1232 "()Landroid/bluetooth/BluetoothDevice;");
1233 if (!jni_mid_getDevice)
1235 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
1239 jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
1240 if (!jni_obj_device)
1242 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
1246 jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
1249 OIC_LOG(ERROR, TAG, "jni_address is null");
1259 CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
1262 OIC_LOG(DEBUG, TAG, "Gatt Close");
1263 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1264 VERIFY_NON_NULL(env, TAG, "env is null");
1266 // get BluetoothGatt method
1267 OIC_LOG(DEBUG, TAG, "get BluetoothGatt method");
1268 jmethodID jni_mid_closeGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "close", "()V");
1269 if (!jni_mid_closeGatt)
1271 OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1272 return CA_STATUS_OK;
1275 // call disconnect gatt method
1276 OIC_LOG(DEBUG, TAG, "request to close GATT");
1277 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
1279 if ((*env)->ExceptionCheck(env))
1281 OIC_LOG(ERROR, TAG, "closeGATT has failed");
1282 (*env)->ExceptionDescribe(env);
1283 (*env)->ExceptionClear(env);
1284 return CA_STATUS_FAILED;
1287 return CA_STATUS_OK;
1290 CAResult_t CALEClientStartScan()
1292 if (!g_isStartedLEClient)
1294 OIC_LOG(ERROR, TAG, "LE client is not started");
1295 return CA_STATUS_FAILED;
1300 OIC_LOG(ERROR, TAG, "g_jvm is null");
1301 return CA_STATUS_FAILED;
1304 bool isAttached = false;
1306 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1309 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1311 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1314 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1315 return CA_STATUS_FAILED;
1320 OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1322 CAResult_t ret = CA_STATUS_OK;
1323 // scan gatt server with UUID
1324 if (g_leScanCallback && g_uuidList)
1327 ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
1329 ret = CALEClientStartScanImpl(env, g_leScanCallback);
1331 if (CA_STATUS_OK != ret)
1333 if (CA_ADAPTER_NOT_ENABLED == ret)
1335 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1339 OIC_LOG(ERROR, TAG, "start scan has failed");
1346 (*g_jvm)->DetachCurrentThread(g_jvm);
1352 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
1354 VERIFY_NON_NULL(callback, TAG, "callback is null");
1355 VERIFY_NON_NULL(env, TAG, "env is null");
1357 if (!CALEIsEnableBTAdapter(env))
1359 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1360 return CA_ADAPTER_NOT_ENABLED;
1363 // get default bt adapter class
1364 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1365 if (!jni_cid_BTAdapter)
1367 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1368 return CA_STATUS_FAILED;
1371 // get remote bt adapter method
1372 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1373 "getDefaultAdapter",
1374 METHODID_OBJECTNONPARAM);
1375 if (!jni_mid_getDefaultAdapter)
1377 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1378 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1379 return CA_STATUS_FAILED;
1382 // get start le scan method
1383 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1384 "(Landroid/bluetooth/BluetoothAdapter$"
1385 "LeScanCallback;)Z");
1386 if (!jni_mid_startLeScan)
1388 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1389 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1390 return CA_STATUS_FAILED;
1393 // gat bt adapter object
1394 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1395 jni_mid_getDefaultAdapter);
1396 if (!jni_obj_BTAdapter)
1398 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1399 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1400 return CA_STATUS_FAILED;
1403 // call start le scan method
1404 OIC_LOG(INFO, TAG, "CALL API - startLeScan");
1405 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1406 jni_mid_startLeScan, callback);
1407 if (!jni_obj_startLeScan)
1409 OIC_LOG(INFO, TAG, "startLeScan has failed");
1413 OIC_LOG(DEBUG, TAG, "LeScan has started");
1416 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1417 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1418 return CA_STATUS_OK;
1421 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
1423 VERIFY_NON_NULL(callback, TAG, "callback is null");
1424 VERIFY_NON_NULL(uuids, TAG, "uuids is null");
1425 VERIFY_NON_NULL(env, TAG, "env is null");
1427 if (!CALEIsEnableBTAdapter(env))
1429 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1430 return CA_ADAPTER_NOT_ENABLED;
1433 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1434 if (!jni_cid_BTAdapter)
1436 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1437 return CA_STATUS_FAILED;
1440 // get remote bt adapter method
1441 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1442 "getDefaultAdapter",
1443 METHODID_OBJECTNONPARAM);
1444 if (!jni_mid_getDefaultAdapter)
1446 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1447 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1448 return CA_STATUS_FAILED;
1451 // get start le scan method
1452 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1453 "([Ljava/util/UUID;Landroid/bluetooth/"
1454 "BluetoothAdapter$LeScanCallback;)Z");
1455 if (!jni_mid_startLeScan)
1457 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1458 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1459 return CA_STATUS_FAILED;
1462 // get bt adapter object
1463 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1464 jni_mid_getDefaultAdapter);
1465 if (!jni_obj_BTAdapter)
1467 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1468 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1469 return CA_STATUS_FAILED;
1472 // call start le scan method
1473 OIC_LOG(INFO, TAG, "CALL API - startLeScan (with UUID)");
1474 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1475 jni_mid_startLeScan, uuids, callback);
1476 if (!jni_obj_startLeScan)
1478 OIC_LOG(INFO, TAG, "startLeScan has failed");
1482 OIC_LOG(DEBUG, TAG, "LeScan has started");
1485 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1486 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1487 return CA_STATUS_OK;
1490 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
1492 VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
1493 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1496 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1499 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1503 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString",
1504 "(Ljava/lang/String;)"
1505 "Ljava/util/UUID;");
1506 if (!jni_mid_fromString)
1508 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1512 jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1513 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1517 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1521 return jni_obj_uuid;
1524 CAResult_t CALEClientStopScan()
1528 OIC_LOG(ERROR, TAG, "g_jvm is null");
1529 return CA_STATUS_FAILED;
1532 bool isAttached = false;
1534 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1537 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1538 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1541 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1542 return CA_STATUS_FAILED;
1547 CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
1548 if (CA_STATUS_OK != ret)
1550 if (CA_ADAPTER_NOT_ENABLED == ret)
1552 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1556 OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1562 (*g_jvm)->DetachCurrentThread(g_jvm);
1568 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
1570 OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
1571 VERIFY_NON_NULL(callback, TAG, "callback is null");
1572 VERIFY_NON_NULL(env, TAG, "env is null");
1574 if (!CALEIsEnableBTAdapter(env))
1576 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1577 return CA_ADAPTER_NOT_ENABLED;
1580 // get default bt adapter class
1581 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1582 if (!jni_cid_BTAdapter)
1584 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1585 return CA_STATUS_FAILED;
1588 // get remote bt adapter method
1589 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1590 "getDefaultAdapter",
1591 METHODID_OBJECTNONPARAM);
1592 if (!jni_mid_getDefaultAdapter)
1594 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1595 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1596 return CA_STATUS_FAILED;
1599 // get start le scan method
1600 jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
1601 "(Landroid/bluetooth/"
1602 "BluetoothAdapter$LeScanCallback;)V");
1603 if (!jni_mid_stopLeScan)
1605 OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
1606 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1607 return CA_STATUS_FAILED;
1610 // gat bt adapter object
1611 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1612 jni_mid_getDefaultAdapter);
1613 if (!jni_obj_BTAdapter)
1615 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1616 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1617 return CA_STATUS_FAILED;
1620 OIC_LOG(INFO, TAG, "CALL API - stopLeScan");
1621 // call start le scan method
1622 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
1623 if ((*env)->ExceptionCheck(env))
1625 OIC_LOG(ERROR, TAG, "stopLeScan has failed");
1626 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1627 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1628 (*env)->ExceptionDescribe(env);
1629 (*env)->ExceptionClear(env);
1630 return CA_STATUS_FAILED;
1633 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1634 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1635 return CA_STATUS_OK;
1638 CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, jint state_idx, jboolean flag)
1640 OIC_LOG(DEBUG, TAG, "IN - CALEClientSetFlagToState");
1641 VERIFY_NON_NULL(env, TAG, "env");
1642 VERIFY_NON_NULL(jni_address, TAG, "jni_address");
1644 ca_mutex_lock(g_deviceStateListMutex);
1646 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1649 OIC_LOG(ERROR, TAG, "address is not available");
1650 return CA_STATUS_FAILED;
1653 if (CALEClientIsDeviceInList(address))
1655 CALEState_t* curState = CALEClientGetStateInfo(address);
1658 OIC_LOG(ERROR, TAG, "curState is null");
1659 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1660 ca_mutex_unlock(g_deviceStateListMutex);
1661 return CA_STATUS_FAILED;
1663 OIC_LOG_V(INFO, TAG, "%d flag is set : %d", state_idx, flag);
1667 case CA_LE_AUTO_CONNECT_FLAG:
1668 curState->autoConnectFlag = flag;
1670 case CA_LE_DESCRIPTOR_FOUND:
1671 curState->isDescriptorFound = flag;
1678 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1679 ca_mutex_unlock(g_deviceStateListMutex);
1680 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetFlagToState");
1681 return CA_STATUS_OK;
1684 jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx)
1686 OIC_LOG(DEBUG, TAG, "IN - CALEClientGetFlagFromState");
1687 VERIFY_NON_NULL_RET(env, TAG, "env", false);
1688 VERIFY_NON_NULL_RET(jni_address, TAG, "jni_address", false);
1690 ca_mutex_lock(g_deviceStateListMutex);
1692 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1695 OIC_LOG(ERROR, TAG, "address is not available");
1696 ca_mutex_unlock(g_deviceStateListMutex);
1700 CALEState_t* curState = CALEClientGetStateInfo(address);
1701 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1704 OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false");
1705 ca_mutex_unlock(g_deviceStateListMutex);
1709 jboolean ret = JNI_FALSE;
1712 case CA_LE_AUTO_CONNECT_FLAG:
1713 ret = curState->autoConnectFlag;
1715 case CA_LE_DESCRIPTOR_FOUND:
1716 ret = curState->isDescriptorFound;
1721 ca_mutex_unlock(g_deviceStateListMutex);
1723 OIC_LOG_V(INFO, TAG, "%d flag is %d", state_idx, ret);
1724 OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetFlagFromState");
1728 CAResult_t CALEClientDirectConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1730 OIC_LOG(DEBUG, TAG, "CALEClientDirectConnect");
1731 VERIFY_NON_NULL(env, TAG, "env is null");
1732 VERIFY_NON_NULL(bluetoothDevice, TAG, "bluetoothDevice is null");
1734 ca_mutex_lock(g_threadSendMutex);
1736 jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1739 OIC_LOG(ERROR, TAG, "jni_address is not available");
1740 ca_mutex_unlock(g_threadSendMutex);
1741 return CA_STATUS_FAILED;
1744 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1747 OIC_LOG(ERROR, TAG, "address is not available");
1748 ca_mutex_unlock(g_threadSendMutex);
1749 return CA_STATUS_FAILED;
1752 CAResult_t res = CA_STATUS_OK;
1753 if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1754 STATE_DISCONNECTED))
1756 jobject newGatt = CALEClientConnect(env, bluetoothDevice, autoconnect);
1757 if (NULL == newGatt)
1759 OIC_LOG(INFO, TAG, "newGatt is not available");
1760 res = CA_STATUS_FAILED;
1763 ca_mutex_unlock(g_threadSendMutex);
1768 jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1770 OIC_LOG(DEBUG, TAG, "CALEClientConnect");
1771 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1772 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1774 // get gatt object from Bluetooth Device object for closeProfileProxy(..)
1775 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
1778 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1781 OIC_LOG(ERROR, TAG, "address is not available");
1785 // close the gatt service
1786 jobject gatt = CALEClientGetGattObjInList(env, address);
1789 CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
1790 if (CA_STATUS_OK != res)
1792 OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
1793 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1797 // clean previous gatt object after close profile service
1798 res = CALEClientRemoveGattObjForAddr(env, jni_address);
1799 if (CA_STATUS_OK != res)
1801 OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
1802 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1806 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1809 jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
1812 OIC_LOG(DEBUG, TAG, "re-connection will be started");
1816 // add new gatt object into g_gattObjectList
1817 CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
1818 if (CA_STATUS_OK != res)
1820 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
1827 jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1829 OIC_LOG(DEBUG, TAG, "GATT CONNECT");
1830 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1831 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1833 if (!g_leGattCallback)
1835 OIC_LOG(INFO, TAG, "g_leGattCallback is null");
1839 if (!CALEIsEnableBTAdapter(env))
1841 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1845 jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1848 OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
1852 // get BluetoothDevice method
1853 OIC_LOG(DEBUG, TAG, "get BluetoothDevice method");
1854 jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
1856 "(Landroid/content/Context;ZLandroid/"
1857 "bluetooth/BluetoothGattCallback;)"
1858 "Landroid/bluetooth/BluetoothGatt;");
1859 if (!jni_mid_connectGatt)
1861 OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
1865 OIC_LOG(INFO, TAG, "CALL API - connectGatt");
1866 jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
1867 jni_mid_connectGatt,
1869 autoconnect, g_leGattCallback);
1870 if (!jni_obj_connectGatt)
1872 OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
1873 CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
1874 CALEClientUpdateSendCnt(env);
1879 OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
1881 return jni_obj_connectGatt;
1884 CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
1886 OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
1888 VERIFY_NON_NULL(env, TAG, "env is null");
1889 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1891 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1892 if (!jni_cid_BTAdapter)
1894 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
1895 return CA_STATUS_FAILED;
1898 // get remote bt adapter method
1899 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1900 "getDefaultAdapter",
1901 METHODID_OBJECTNONPARAM);
1902 if (!jni_mid_getDefaultAdapter)
1904 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1905 return CA_STATUS_FAILED;
1908 // gat bt adapter object
1909 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1910 jni_mid_getDefaultAdapter);
1911 if (!jni_obj_BTAdapter)
1913 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1914 return CA_STATUS_FAILED;
1917 // get closeProfileProxy method
1918 jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1919 "closeProfileProxy",
1920 "(ILandroid/bluetooth/"
1921 "BluetoothProfile;)V");
1922 if (!jni_mid_closeProfileProxy)
1924 OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
1925 return CA_STATUS_FAILED;
1928 jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
1929 if (!jni_cid_BTProfile)
1931 OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
1932 return CA_STATUS_FAILED;
1935 // GATT - Constant value : 7 (0x00000007)
1936 jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
1940 OIC_LOG(ERROR, TAG, "id_gatt is null");
1941 return CA_STATUS_FAILED;
1944 jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
1946 OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
1947 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
1948 if ((*env)->ExceptionCheck(env))
1950 OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
1951 (*env)->ExceptionDescribe(env);
1952 (*env)->ExceptionClear(env);
1953 return CA_STATUS_FAILED;
1956 OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
1957 return CA_STATUS_OK;
1961 CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
1963 OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1964 VERIFY_NON_NULL(env, TAG, "env is null");
1965 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1967 // get BluetoothGatt method
1968 OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
1969 jmethodID jni_mid_disconnectGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1970 "disconnect", "()V");
1971 if (!jni_mid_disconnectGatt)
1973 OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
1974 return CA_STATUS_FAILED;
1977 // call disconnect gatt method
1978 OIC_LOG(INFO, TAG, "CALL API - disconnect");
1979 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
1980 if ((*env)->ExceptionCheck(env))
1982 OIC_LOG(ERROR, TAG, "disconnect has failed");
1983 (*env)->ExceptionDescribe(env);
1984 (*env)->ExceptionClear(env);
1985 return CA_STATUS_FAILED;
1988 OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
1990 return CA_STATUS_OK;
1993 CAResult_t CALEClientDisconnectAll(JNIEnv *env)
1995 OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1996 VERIFY_NON_NULL(env, TAG, "env is null");
1998 if (!g_gattObjectList)
2000 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2001 return CA_STATUS_OK;
2004 uint32_t length = u_arraylist_length(g_gattObjectList);
2005 OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
2006 for (uint32_t index = 0; index < length; index++)
2008 OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
2009 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2012 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2015 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
2016 if (CA_STATUS_OK != res)
2018 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
2023 return CA_STATUS_OK;
2026 CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
2028 OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
2029 VERIFY_NON_NULL(env, TAG, "env is null");
2031 if (!g_gattObjectList)
2033 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2034 return CA_STATUS_OK;
2037 char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
2040 OIC_LOG(ERROR, TAG, "address is null");
2041 return CA_STATUS_FAILED;
2044 uint32_t length = u_arraylist_length(g_gattObjectList);
2045 for (uint32_t index = 0; index < length; index++)
2047 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2050 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2054 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2055 if (!jni_setAddress)
2057 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2058 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2059 return CA_STATUS_FAILED;
2062 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2065 OIC_LOG(ERROR, TAG, "setAddress is null");
2066 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2067 return CA_STATUS_FAILED;
2070 OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
2071 if (!strcmp(address, setAddress))
2073 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
2074 if (CA_STATUS_OK != res)
2076 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
2077 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2078 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2079 return CA_STATUS_FAILED;
2081 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2082 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2083 return CA_STATUS_OK;
2085 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2087 (*env)->ReleaseStringUTFChars(env, remote_address, address);
2089 OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
2090 return CA_STATUS_OK;
2093 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
2095 VERIFY_NON_NULL(env, TAG, "env is null");
2096 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2098 if (!CALEIsEnableBTAdapter(env))
2100 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2101 return CA_ADAPTER_NOT_ENABLED;
2104 // get BluetoothGatt.discoverServices method
2105 OIC_LOG(DEBUG, TAG, "get BluetoothGatt.discoverServices method");
2106 jmethodID jni_mid_discoverServices = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2107 "discoverServices", "()Z");
2108 if (!jni_mid_discoverServices)
2110 OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
2111 return CA_STATUS_FAILED;
2114 // call disconnect gatt method
2115 OIC_LOG(INFO, TAG, "CALL API - discoverServices");
2116 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
2119 OIC_LOG(ERROR, TAG, "discoverServices has not been started");
2120 return CA_STATUS_FAILED;
2123 return CA_STATUS_OK;
2126 static void CALEWriteCharacteristicThread(void* object)
2128 VERIFY_NON_NULL_VOID(object, TAG, "object is null");
2130 bool isAttached = false;
2132 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2135 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2136 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2140 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2146 jobject gatt = (jobject)object;
2147 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
2148 if (CA_STATUS_OK != ret)
2150 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
2155 (*g_jvm)->DetachCurrentThread(g_jvm);
2159 CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
2161 OIC_LOG(DEBUG, TAG, "CALESetValueAndWriteCharacteristic");
2163 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2164 VERIFY_NON_NULL(env, TAG, "env is null");
2166 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
2169 CALEClientSendFinish(env, gatt);
2170 return CA_STATUS_FAILED;
2173 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
2176 CALEClientSendFinish(env, gatt);
2177 return CA_STATUS_FAILED;
2180 ca_mutex_lock(g_threadSendStateMutex);
2182 if (CALEClientIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING))
2184 OIC_LOG(INFO, TAG, "current state is SENDING");
2185 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2186 ca_mutex_unlock(g_threadSendStateMutex);
2187 return CA_STATUS_OK;
2190 if (CA_STATUS_OK != CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
2193 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
2194 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2195 CALEClientSendFinish(env, gatt);
2196 ca_mutex_unlock(g_threadSendStateMutex);
2197 return CA_STATUS_FAILED;
2200 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2202 ca_mutex_unlock(g_threadSendStateMutex);
2205 jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
2206 if (!jni_obj_character)
2208 CALEClientSendFinish(env, gatt);
2209 return CA_STATUS_FAILED;
2212 CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
2213 if (CA_STATUS_OK != ret)
2215 CALEClientSendFinish(env, gatt);
2216 return CA_STATUS_FAILED;
2219 // wait for callback for write Characteristic with success to sent data
2220 OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
2221 ca_mutex_lock(g_threadWriteCharacteristicMutex);
2222 if (!g_isSignalSetFlag)
2224 OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
2225 if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
2226 g_threadWriteCharacteristicMutex,
2227 WAIT_TIME_WRITE_CHARACTERISTIC))
2229 OIC_LOG(ERROR, TAG, "there is no response. write has failed");
2230 g_isSignalSetFlag = false;
2231 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2232 return CA_STATUS_FAILED;
2235 // reset flag set by writeCharacteristic Callback
2236 g_isSignalSetFlag = false;
2237 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2239 CALEClientUpdateSendCnt(env);
2241 OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
2242 return CA_STATUS_OK;
2245 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
2247 OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
2248 VERIFY_NON_NULL(env, TAG, "env is null");
2249 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2251 jobject gattParam = (*env)->NewGlobalRef(env, gatt);
2252 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
2253 CALEWriteCharacteristicThread, (void*)gattParam))
2255 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
2256 return CA_STATUS_FAILED;
2259 OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
2260 return CA_STATUS_OK;
2263 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
2264 jobject gattCharacteristic)
2266 OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
2267 VERIFY_NON_NULL(env, TAG, "env is null");
2268 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2269 VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
2271 if (!CALEIsEnableBTAdapter(env))
2273 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2274 return CA_STATUS_FAILED;
2277 // get BluetoothGatt.write characteristic method
2278 OIC_LOG(DEBUG, TAG, "write characteristic method");
2279 jmethodID jni_mid_writeCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2280 "writeCharacteristic",
2281 "(Landroid/bluetooth/"
2282 "BluetoothGattCharacteristic;)Z");
2283 if (!jni_mid_writeCharacteristic)
2285 OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
2286 return CA_STATUS_FAILED;
2289 // call disconnect gatt method
2290 OIC_LOG(INFO, TAG, "CALL API - writeCharacteristic");
2291 jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
2292 jni_mid_writeCharacteristic,
2293 gattCharacteristic);
2296 OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
2300 OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
2301 return CA_STATUS_FAILED;
2304 return CA_STATUS_OK;
2307 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
2309 VERIFY_NON_NULL(env, TAG, "env is null");
2310 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2312 if (!CALEIsEnableBTAdapter(env))
2314 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2315 return CA_STATUS_FAILED;
2318 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
2321 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2322 return CA_STATUS_FAILED;
2325 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2326 if (!jni_obj_GattCharacteristic)
2328 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2329 return CA_STATUS_FAILED;
2332 OIC_LOG(DEBUG, TAG, "read characteristic method");
2333 jmethodID jni_mid_readCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2334 "readCharacteristic",
2335 "(Landroid/bluetooth/"
2336 "BluetoothGattCharacteristic;)Z");
2337 if (!jni_mid_readCharacteristic)
2339 OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
2340 return CA_STATUS_FAILED;
2343 // call disconnect gatt method
2344 OIC_LOG(INFO, TAG, "CALL API - readCharacteristic");
2345 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
2346 jni_obj_GattCharacteristic);
2349 OIC_LOG(DEBUG, TAG, "readCharacteristic success");
2353 OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
2354 return CA_STATUS_FAILED;
2357 return CA_STATUS_OK;
2360 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
2361 jobject characteristic)
2363 VERIFY_NON_NULL(env, TAG, "env is null");
2364 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2365 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2367 if (!CALEIsEnableBTAdapter(env))
2369 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2370 return CA_ADAPTER_NOT_ENABLED;
2373 // get BluetoothGatt.setCharacteristicNotification method
2374 OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
2375 jmethodID jni_mid_setNotification = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2376 "setCharacteristicNotification",
2377 "(Landroid/bluetooth/"
2378 "BluetoothGattCharacteristic;Z)Z");
2379 if (!jni_mid_setNotification)
2381 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2382 return CA_STATUS_FAILED;
2385 OIC_LOG(INFO, TAG, "CALL API - setCharacteristicNotification");
2386 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
2387 characteristic, JNI_TRUE);
2388 if (JNI_TRUE == ret)
2390 OIC_LOG(DEBUG, TAG, "setCharacteristicNotification success");
2394 OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed");
2395 return CA_STATUS_FAILED;
2398 return CA_STATUS_OK;
2401 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
2403 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2404 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2405 VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
2407 if (!CALEIsEnableBTAdapter(env))
2409 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2413 // get BluetoothGatt.getService method
2414 OIC_LOG(DEBUG, TAG, "BluetoothGatt.getService");
2415 jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2417 "(Ljava/util/UUID;)Landroid/bluetooth/"
2418 "BluetoothGattService;");
2419 if (!jni_mid_getService)
2421 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2425 jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2426 if (!jni_obj_service_uuid)
2428 OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
2432 // get bluetooth gatt service
2433 OIC_LOG(DEBUG, TAG, "request to get service");
2434 jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
2435 jni_obj_service_uuid);
2436 if (!jni_obj_gattService)
2438 OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
2442 // get bluetooth gatt service method
2443 jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/"
2444 "BluetoothGattService",
2445 "getCharacteristic",
2446 "(Ljava/util/UUID;)"
2447 "Landroid/bluetooth/"
2448 "BluetoothGattCharacteristic;");
2449 if (!jni_mid_getCharacteristic)
2451 OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
2455 const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
2458 OIC_LOG(ERROR, TAG, "uuid is null");
2462 jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
2463 if (!jni_obj_tx_uuid)
2465 OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
2466 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2470 OIC_LOG(DEBUG, TAG, "request to get Characteristic");
2471 jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
2472 jni_mid_getCharacteristic,
2475 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2476 return jni_obj_GattCharacteristic;
2479 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
2481 OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
2482 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2483 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2484 VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
2486 if (!CALEIsEnableBTAdapter(env))
2488 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2492 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
2495 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2499 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2500 if (!jni_obj_GattCharacteristic)
2502 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2506 jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
2507 "/BluetoothGattCharacteristic");
2508 if (!jni_cid_BTGattCharacteristic)
2510 OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
2514 OIC_LOG(DEBUG, TAG, "set value in Characteristic");
2515 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
2517 if (!jni_mid_setValue)
2519 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2523 jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
2525 if (JNI_TRUE == ret)
2527 OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
2531 OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
2536 jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
2537 "setWriteType", "(I)V");
2538 if (!jni_mid_setWriteType)
2540 OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
2544 jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
2545 "WRITE_TYPE_NO_RESPONSE", "I");
2546 if (!jni_fid_no_response)
2548 OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
2552 jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
2553 jni_fid_no_response);
2555 (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
2557 return jni_obj_GattCharacteristic;
2560 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
2562 VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
2563 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2565 if (!CALEIsEnableBTAdapter(env))
2567 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2571 jmethodID jni_mid_getValue = CAGetJNIMethodID(env, "android/bluetooth/"
2572 "BluetoothGattCharacteristic",
2573 "getValue", "()[B");
2574 if (!jni_mid_getValue)
2576 OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
2580 jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
2582 return jni_obj_data_array;
2585 CAResult_t CALEClientCreateUUIDList()
2589 OIC_LOG(ERROR, TAG, "g_jvm is null");
2590 return CA_STATUS_FAILED;
2593 bool isAttached = false;
2595 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2598 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2599 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2603 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2604 return CA_STATUS_FAILED;
2609 // create new object array
2610 jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
2611 if (!jni_cid_uuid_list)
2613 OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
2617 jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
2618 jni_cid_uuid_list, NULL);
2619 if (!jni_obj_uuid_list)
2621 OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
2626 jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2629 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
2632 (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
2634 g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
2638 (*g_jvm)->DetachCurrentThread(g_jvm);
2641 return CA_STATUS_OK;
2648 (*g_jvm)->DetachCurrentThread(g_jvm);
2650 return CA_STATUS_FAILED;
2653 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
2654 jobject characteristic)
2656 VERIFY_NON_NULL(env, TAG, "env is null");
2657 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2658 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2660 if (!CALEIsEnableBTAdapter(env))
2662 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2663 return CA_ADAPTER_NOT_ENABLED;
2666 OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
2667 jmethodID jni_mid_getDescriptor = CAGetJNIMethodID(env, "android/bluetooth/"
2668 "BluetoothGattCharacteristic",
2670 "(Ljava/util/UUID;)Landroid/bluetooth/"
2671 "BluetoothGattDescriptor;");
2672 if (!jni_mid_getDescriptor)
2674 OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
2675 return CA_STATUS_FAILED;
2678 jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
2679 if (!jni_obj_cc_uuid)
2681 OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
2682 return CA_STATUS_FAILED;
2685 OIC_LOG(DEBUG, TAG, "request to get descriptor");
2686 jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
2687 jni_mid_getDescriptor, jni_obj_cc_uuid);
2688 if (!jni_obj_descriptor)
2690 OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
2691 return CA_NOT_SUPPORTED;
2694 OIC_LOG(DEBUG, TAG, "set value in descriptor");
2695 jclass jni_cid_descriptor = (*env)->FindClass(env,
2696 "android/bluetooth/BluetoothGattDescriptor");
2697 if (!jni_cid_descriptor)
2699 OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2700 return CA_STATUS_FAILED;
2703 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2704 if (!jni_mid_setValue)
2706 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2707 return CA_STATUS_FAILED;
2710 jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2711 "ENABLE_NOTIFICATION_VALUE", "[B");
2712 if (!jni_fid_NotiValue)
2714 OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2715 return CA_STATUS_FAILED;
2718 OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2720 jboolean jni_setvalue = (*env)->CallBooleanMethod(
2721 env, jni_obj_descriptor, jni_mid_setValue,
2722 (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2725 OIC_LOG(DEBUG, TAG, "setValue success");
2729 OIC_LOG(ERROR, TAG, "setValue has failed");
2730 return CA_STATUS_FAILED;
2733 jmethodID jni_mid_writeDescriptor = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt",
2735 "(Landroid/bluetooth/"
2736 "BluetoothGattDescriptor;)Z");
2737 if (!jni_mid_writeDescriptor)
2739 OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2740 return CA_STATUS_FAILED;
2743 OIC_LOG(INFO, TAG, "CALL API - writeDescriptor");
2744 jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2745 jni_obj_descriptor);
2748 OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2752 OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2753 return CA_STATUS_FAILED;
2756 return CA_STATUS_OK;
2759 void CALEClientCreateScanDeviceList(JNIEnv *env)
2761 OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2762 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2764 ca_mutex_lock(g_deviceListMutex);
2765 // create new object array
2766 if (g_deviceList == NULL)
2768 OIC_LOG(DEBUG, TAG, "Create device list");
2770 g_deviceList = u_arraylist_create();
2772 ca_mutex_unlock(g_deviceListMutex);
2775 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2777 VERIFY_NON_NULL(device, TAG, "device is null");
2778 VERIFY_NON_NULL(env, TAG, "env is null");
2780 ca_mutex_lock(g_deviceListMutex);
2784 OIC_LOG(ERROR, TAG, "gdevice_list is null");
2785 CALEClientStopScanWithInterval();
2787 ca_mutex_unlock(g_deviceListMutex);
2788 return CA_STATUS_FAILED;
2791 jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2792 if (!jni_remoteAddress)
2794 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2795 ca_mutex_unlock(g_deviceListMutex);
2796 return CA_STATUS_FAILED;
2799 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2802 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2803 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2804 ca_mutex_unlock(g_deviceListMutex);
2805 return CA_STATUS_FAILED;
2808 if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2810 jobject gdevice = (*env)->NewGlobalRef(env, device);
2811 u_arraylist_add(g_deviceList, gdevice);
2812 ca_cond_signal(g_deviceDescCond);
2813 OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress);
2815 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2816 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2818 ca_mutex_unlock(g_deviceListMutex);
2820 return CA_STATUS_OK;
2823 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2825 VERIFY_NON_NULL_RET(env, TAG, "env is null", true);
2826 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2830 OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2834 uint32_t length = u_arraylist_length(g_deviceList);
2835 for (uint32_t index = 0; index < length; index++)
2837 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2840 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2844 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2845 if (!jni_setAddress)
2847 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2851 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2854 OIC_LOG(ERROR, TAG, "setAddress is null");
2855 (*env)->DeleteLocalRef(env, jni_setAddress);
2859 if (!strcmp(remoteAddress, setAddress))
2861 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2862 (*env)->DeleteLocalRef(env, jni_setAddress);
2866 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2867 (*env)->DeleteLocalRef(env, jni_setAddress);
2870 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress);
2875 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2877 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2878 VERIFY_NON_NULL(env, TAG, "env is null");
2880 ca_mutex_lock(g_deviceListMutex);
2884 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2885 ca_mutex_unlock(g_deviceListMutex);
2886 return CA_STATUS_FAILED;
2889 uint32_t length = u_arraylist_length(g_deviceList);
2890 for (uint32_t index = 0; index < length; index++)
2892 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2895 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2898 (*env)->DeleteGlobalRef(env, jarrayObj);
2902 OICFree(g_deviceList);
2903 g_deviceList = NULL;
2905 ca_mutex_unlock(g_deviceListMutex);
2906 return CA_STATUS_OK;
2909 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2911 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2912 VERIFY_NON_NULL(address, TAG, "address is null");
2913 VERIFY_NON_NULL(env, TAG, "env is null");
2915 ca_mutex_lock(g_deviceListMutex);
2919 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2920 ca_mutex_unlock(g_deviceListMutex);
2921 return CA_STATUS_FAILED;
2924 uint32_t length = u_arraylist_length(g_deviceList);
2925 for (uint32_t index = 0; index < length; index++)
2927 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2930 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2931 ca_mutex_unlock(g_deviceListMutex);
2932 return CA_STATUS_FAILED;
2935 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2936 if (!jni_setAddress)
2938 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2939 ca_mutex_unlock(g_deviceListMutex);
2940 return CA_STATUS_FAILED;
2943 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2946 OIC_LOG(ERROR, TAG, "setAddress is null");
2947 ca_mutex_unlock(g_deviceListMutex);
2948 return CA_STATUS_FAILED;
2951 const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2954 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2955 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2956 ca_mutex_unlock(g_deviceListMutex);
2957 return CA_STATUS_FAILED;
2960 if (!strcmp(setAddress, remoteAddress))
2962 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2963 (*env)->DeleteGlobalRef(env, jarrayObj);
2965 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2966 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2968 if (NULL == u_arraylist_remove(g_deviceList, index))
2970 OIC_LOG(ERROR, TAG, "List removal failed.");
2971 ca_mutex_unlock(g_deviceListMutex);
2972 return CA_STATUS_FAILED;
2974 ca_mutex_unlock(g_deviceListMutex);
2975 return CA_STATUS_OK;
2977 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2978 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2981 ca_mutex_unlock(g_deviceListMutex);
2982 OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2984 return CA_STATUS_OK;
2991 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2993 OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2994 VERIFY_NON_NULL(env, TAG, "env is null");
2995 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2997 ca_mutex_lock(g_gattObjectMutex);
2999 if (!g_gattObjectList)
3001 OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
3002 ca_mutex_unlock(g_gattObjectMutex);
3003 return CA_STATUS_FAILED;
3006 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3007 if (!jni_remoteAddress)
3009 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3010 ca_mutex_unlock(g_gattObjectMutex);
3011 return CA_STATUS_FAILED;
3014 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3017 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3018 ca_mutex_unlock(g_gattObjectMutex);
3019 return CA_STATUS_FAILED;
3022 OIC_LOG_V(DEBUG, TAG, "remote address : %s", remoteAddress);
3023 if (!CALEClientIsGattObjInList(env, remoteAddress))
3025 jobject newGatt = (*env)->NewGlobalRef(env, gatt);
3026 u_arraylist_add(g_gattObjectList, newGatt);
3027 OIC_LOG(INFO, TAG, "added a newGatt object to gattObjectList");
3030 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3031 ca_mutex_unlock(g_gattObjectMutex);
3032 return CA_STATUS_OK;
3035 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
3037 OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
3038 VERIFY_NON_NULL(env, TAG, "env is null");
3039 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
3041 uint32_t length = u_arraylist_length(g_gattObjectList);
3042 for (uint32_t index = 0; index < length; index++)
3045 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3048 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3052 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3053 if (!jni_setAddress)
3055 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3059 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3062 OIC_LOG(ERROR, TAG, "setAddress is null");
3066 if (!strcmp(remoteAddress, setAddress))
3068 OIC_LOG(DEBUG, TAG, "the device is already set");
3069 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3074 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3079 OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
3083 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
3085 OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
3086 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
3087 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3089 ca_mutex_lock(g_gattObjectMutex);
3090 uint32_t length = u_arraylist_length(g_gattObjectList);
3091 for (uint32_t index = 0; index < length; index++)
3093 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3096 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3097 ca_mutex_unlock(g_gattObjectMutex);
3101 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3102 if (!jni_setAddress)
3104 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3105 ca_mutex_unlock(g_gattObjectMutex);
3109 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3112 OIC_LOG(ERROR, TAG, "setAddress is null");
3113 ca_mutex_unlock(g_gattObjectMutex);
3117 if (!strcmp(remoteAddress, setAddress))
3119 OIC_LOG(DEBUG, TAG, "the device is already set");
3120 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3121 ca_mutex_unlock(g_gattObjectMutex);
3124 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3127 ca_mutex_unlock(g_gattObjectMutex);
3128 OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
3132 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
3134 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
3135 VERIFY_NON_NULL(env, TAG, "env is null");
3137 ca_mutex_lock(g_gattObjectMutex);
3138 if (!g_gattObjectList)
3140 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3141 ca_mutex_unlock(g_gattObjectMutex);
3142 return CA_STATUS_OK;
3145 uint32_t length = u_arraylist_length(g_gattObjectList);
3146 for (uint32_t index = 0; index < length; index++)
3148 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3151 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3154 (*env)->DeleteGlobalRef(env, jarrayObj);
3158 OICFree(g_gattObjectList);
3159 g_gattObjectList = NULL;
3160 OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
3161 ca_mutex_unlock(g_gattObjectMutex);
3162 return CA_STATUS_OK;
3165 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
3167 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
3168 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
3169 VERIFY_NON_NULL(env, TAG, "env is null");
3171 ca_mutex_lock(g_gattObjectMutex);
3172 if (!g_gattObjectList)
3174 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3175 ca_mutex_unlock(g_gattObjectMutex);
3176 return CA_STATUS_OK;
3179 uint32_t length = u_arraylist_length(g_gattObjectList);
3180 for (uint32_t index = 0; index < length; index++)
3182 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3185 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3186 ca_mutex_unlock(g_gattObjectMutex);
3187 return CA_STATUS_FAILED;
3190 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3191 if (!jni_setAddress)
3193 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3194 ca_mutex_unlock(g_gattObjectMutex);
3195 return CA_STATUS_FAILED;
3198 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3201 OIC_LOG(ERROR, TAG, "setAddress is null");
3202 ca_mutex_unlock(g_gattObjectMutex);
3203 return CA_STATUS_FAILED;
3206 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3207 if (!jni_remoteAddress)
3209 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3210 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3211 ca_mutex_unlock(g_gattObjectMutex);
3212 return CA_STATUS_FAILED;
3215 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3218 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3219 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3220 ca_mutex_unlock(g_gattObjectMutex);
3221 return CA_STATUS_FAILED;
3224 if (!strcmp(setAddress, remoteAddress))
3226 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3227 (*env)->DeleteGlobalRef(env, jarrayObj);
3229 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3230 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3232 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3234 OIC_LOG(ERROR, TAG, "List removal failed.");
3235 ca_mutex_unlock(g_gattObjectMutex);
3236 return CA_STATUS_FAILED;
3238 ca_mutex_unlock(g_gattObjectMutex);
3239 return CA_STATUS_OK;
3241 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3242 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3245 ca_mutex_unlock(g_gattObjectMutex);
3246 OIC_LOG(DEBUG, TAG, "there are no target object");
3247 return CA_STATUS_OK;
3250 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
3252 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
3253 VERIFY_NON_NULL(addr, TAG, "addr is null");
3254 VERIFY_NON_NULL(env, TAG, "env is null");
3256 ca_mutex_lock(g_gattObjectMutex);
3257 if (!g_gattObjectList)
3259 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3260 ca_mutex_unlock(g_gattObjectMutex);
3261 return CA_STATUS_OK;
3264 uint32_t length = u_arraylist_length(g_gattObjectList);
3265 for (uint32_t index = 0; index < length; index++)
3267 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3270 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3271 ca_mutex_unlock(g_gattObjectMutex);
3272 return CA_STATUS_FAILED;
3275 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3276 if (!jni_setAddress)
3278 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3279 ca_mutex_unlock(g_gattObjectMutex);
3280 return CA_STATUS_FAILED;
3283 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3286 OIC_LOG(ERROR, TAG, "setAddress is null");
3287 ca_mutex_unlock(g_gattObjectMutex);
3288 return CA_STATUS_FAILED;
3291 const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
3294 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3295 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3296 ca_mutex_unlock(g_gattObjectMutex);
3297 return CA_STATUS_FAILED;
3300 if (!strcmp(setAddress, remoteAddress))
3302 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3303 (*env)->DeleteGlobalRef(env, jarrayObj);
3305 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3306 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3307 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3309 OIC_LOG(ERROR, TAG, "List removal failed.");
3310 ca_mutex_unlock(g_gattObjectMutex);
3311 return CA_STATUS_FAILED;
3313 ca_mutex_unlock(g_gattObjectMutex);
3314 return CA_STATUS_OK;
3316 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3317 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3320 ca_mutex_unlock(g_gattObjectMutex);
3321 OIC_LOG(DEBUG, TAG, "there are no target object");
3322 return CA_STATUS_FAILED;
3325 jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
3327 OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice");
3329 VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
3330 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
3332 // get Bluetooth Address
3333 jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
3334 if (!jni_btTargetAddress)
3336 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3340 const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
3343 OIC_LOG(ERROR, TAG, "targetAddress is not available");
3347 // get method ID of getDevice()
3348 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3349 "getDevice", METHODID_BT_DEVICE);
3350 if (!jni_mid_getDevice)
3352 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
3353 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3357 ca_mutex_lock(g_gattObjectMutex);
3359 size_t length = u_arraylist_length(g_gattObjectList);
3360 OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length);
3361 OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
3363 for (size_t index = 0; index < length; index++)
3365 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3368 ca_mutex_unlock(g_gattObjectMutex);
3369 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3370 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3374 jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
3375 if (!jni_obj_device)
3377 ca_mutex_unlock(g_gattObjectMutex);
3378 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
3379 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3383 jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
3386 ca_mutex_unlock(g_gattObjectMutex);
3387 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3388 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3392 const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
3395 ca_mutex_unlock(g_gattObjectMutex);
3396 OIC_LOG(ERROR, TAG, "btAddress is not available");
3397 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3401 OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index);
3402 if (!strcmp(targetAddress, btAddress))
3404 OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
3407 jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3410 OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
3412 ca_mutex_unlock(g_gattObjectMutex);
3413 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3414 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3415 (*env)->DeleteLocalRef(env, jni_btAddress);
3416 (*env)->DeleteLocalRef(env, jni_obj_device);
3417 return jni_LEAddress;
3419 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3420 (*env)->DeleteLocalRef(env, jni_btAddress);
3421 (*env)->DeleteLocalRef(env, jni_obj_device);
3423 ca_mutex_unlock(g_gattObjectMutex);
3425 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3426 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress);
3434 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
3435 uint16_t target_state)
3437 VERIFY_NON_NULL(address, TAG, "address is null");
3438 VERIFY_NON_NULL(address, TAG, "state_type is null");
3439 VERIFY_NON_NULL(address, TAG, "target_state is null");
3441 if (!g_deviceStateList)
3443 OIC_LOG(ERROR, TAG, "gdevice_list is null");
3444 return CA_STATUS_FAILED;
3447 ca_mutex_lock(g_deviceStateListMutex);
3449 if (CALEClientIsDeviceInList(address))
3451 CALEState_t* curState = CALEClientGetStateInfo(address);
3454 OIC_LOG(ERROR, TAG, "curState is null");
3455 ca_mutex_unlock(g_deviceStateListMutex);
3456 return CA_STATUS_FAILED;
3461 case CA_LE_CONNECTION_STATE:
3462 curState->connectedState = target_state;
3464 case CA_LE_SEND_STATE:
3465 curState->sendState = target_state;
3470 OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
3471 curState->address, curState->connectedState, curState->sendState,
3472 curState->autoConnectFlag);
3474 else /** state is added newly **/
3476 if (strlen(address) > CA_MACADDR_SIZE)
3478 OIC_LOG(ERROR, TAG, "address is not proper");
3479 ca_mutex_unlock(g_deviceStateListMutex);
3480 return CA_STATUS_INVALID_PARAM;
3483 CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
3486 OIC_LOG(ERROR, TAG, "out of memory");
3487 ca_mutex_unlock(g_deviceStateListMutex);
3488 return CA_MEMORY_ALLOC_FAILED;
3491 OICStrcpy(newstate->address, sizeof(newstate->address), address);
3495 case CA_LE_CONNECTION_STATE:
3496 newstate->connectedState = target_state;
3497 newstate->sendState = STATE_SEND_NONE;
3499 case CA_LE_SEND_STATE:
3500 newstate->connectedState = STATE_DISCONNECTED;
3501 newstate->sendState = target_state;
3506 OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, "
3507 "conn : %d, send : %d, ACFlag : %d",
3508 newstate->address, newstate->connectedState, newstate->sendState,
3509 newstate->autoConnectFlag);
3510 u_arraylist_add(g_deviceStateList, newstate); // update new state
3512 ca_mutex_unlock(g_deviceStateListMutex);
3514 return CA_STATUS_OK;
3517 bool CALEClientIsDeviceInList(const char* remoteAddress)
3519 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3521 if (!g_deviceStateList)
3523 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3527 uint32_t length = u_arraylist_length(g_deviceStateList);
3528 for (uint32_t index = 0; index < length; index++)
3530 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3533 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3537 if (!strcmp(remoteAddress, state->address))
3539 OIC_LOG(DEBUG, TAG, "the device is already set");
3548 OIC_LOG(DEBUG, TAG, "there are no the device in list.");
3552 CAResult_t CALEClientRemoveAllDeviceState()
3554 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
3556 ca_mutex_lock(g_deviceStateListMutex);
3557 if (!g_deviceStateList)
3559 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3560 ca_mutex_unlock(g_deviceStateListMutex);
3561 return CA_STATUS_FAILED;
3564 uint32_t length = u_arraylist_length(g_deviceStateList);
3565 for (uint32_t index = 0; index < length; index++)
3567 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3570 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3576 OICFree(g_deviceStateList);
3577 g_deviceStateList = NULL;
3578 ca_mutex_unlock(g_deviceStateListMutex);
3580 return CA_STATUS_OK;
3583 CAResult_t CALEClientResetDeviceStateForAll()
3585 OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll");
3587 ca_mutex_lock(g_deviceStateListMutex);
3588 if (!g_deviceStateList)
3590 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3591 ca_mutex_unlock(g_deviceStateListMutex);
3592 return CA_STATUS_FAILED;
3595 size_t length = u_arraylist_length(g_deviceStateList);
3596 for (size_t index = 0; index < length; index++)
3598 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3601 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3605 // autoConnectFlag value will be not changed,
3606 // since it has reset only termination case.
3607 state->connectedState = STATE_DISCONNECTED;
3608 state->sendState = STATE_SEND_NONE;
3610 ca_mutex_unlock(g_deviceStateListMutex);
3612 return CA_STATUS_OK;
3615 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
3617 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
3618 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3620 if (!g_deviceStateList)
3622 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3623 return CA_STATUS_FAILED;
3626 uint32_t length = u_arraylist_length(g_deviceStateList);
3627 for (uint32_t index = 0; index < length; index++)
3629 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3632 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3636 if (!strcmp(state->address, remoteAddress))
3638 OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
3640 CALEState_t* targetState = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
3642 if (NULL == targetState)
3644 OIC_LOG(ERROR, TAG, "List removal failed.");
3645 return CA_STATUS_FAILED;
3648 OICFree(targetState);
3649 return CA_STATUS_OK;
3653 return CA_STATUS_OK;
3656 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
3658 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3660 if (!g_deviceStateList)
3662 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3666 uint32_t length = u_arraylist_length(g_deviceStateList);
3667 OIC_LOG_V(DEBUG, TAG, "length of deviceStateList : %d", length);
3668 OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
3670 for (uint32_t index = 0; index < length; index++)
3672 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3675 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3679 OIC_LOG_V(DEBUG, TAG, "state address : %s (idx: %d)", state->address, index);
3681 if (!strcmp(state->address, remoteAddress))
3683 OIC_LOG(DEBUG, TAG, "found state");
3688 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in deviceStateList", remoteAddress);
3692 bool CALEClientIsValidState(const char* remoteAddress, uint16_t state_type,
3693 uint16_t target_state)
3695 OIC_LOG_V(DEBUG, TAG, "CALEClientIsValidState : type[%d], target state[%d]",
3696 state_type, target_state);
3697 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3699 ca_mutex_lock(g_deviceStateListMutex);
3700 if (!g_deviceStateList)
3702 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3703 ca_mutex_unlock(g_deviceStateListMutex);
3707 CALEState_t* state = CALEClientGetStateInfo(remoteAddress);
3710 OIC_LOG(ERROR, TAG, "state is null");
3711 ca_mutex_unlock(g_deviceStateListMutex);
3715 uint16_t curValue = 0;
3718 case CA_LE_CONNECTION_STATE:
3719 curValue = state->connectedState;
3721 case CA_LE_SEND_STATE:
3722 curValue = state->sendState;
3728 if (target_state == curValue)
3730 ca_mutex_unlock(g_deviceStateListMutex);
3735 ca_mutex_unlock(g_deviceStateListMutex);
3739 ca_mutex_unlock(g_deviceStateListMutex);
3743 void CALEClientCreateDeviceList()
3745 OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
3747 // create new object array
3748 if (!g_gattObjectList)
3750 OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
3752 g_gattObjectList = u_arraylist_create();
3755 if (!g_deviceStateList)
3757 OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
3759 g_deviceStateList = u_arraylist_create();
3764 OIC_LOG(DEBUG, TAG, "Create g_deviceList");
3766 g_deviceList = u_arraylist_create();
3771 * Check Sent Count for remove g_sendBuffer
3773 void CALEClientUpdateSendCnt(JNIEnv *env)
3775 OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
3777 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3779 ca_mutex_lock(g_threadMutex);
3783 if (g_targetCnt <= g_currentSentCnt)
3786 g_currentSentCnt = 0;
3790 (*env)->DeleteGlobalRef(env, g_sendBuffer);
3791 g_sendBuffer = NULL;
3793 // notity the thread
3794 ca_cond_signal(g_threadCond);
3796 CALEClientSetSendFinishFlag(true);
3797 OIC_LOG(DEBUG, TAG, "set signal for send data");
3800 ca_mutex_unlock(g_threadMutex);
3803 CAResult_t CALEClientInitGattMutexVaraibles()
3805 if (NULL == g_bleReqRespClientCbMutex)
3807 g_bleReqRespClientCbMutex = ca_mutex_new();
3808 if (NULL == g_bleReqRespClientCbMutex)
3810 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3811 return CA_STATUS_FAILED;
3815 if (NULL == g_bleServerBDAddressMutex)
3817 g_bleServerBDAddressMutex = ca_mutex_new();
3818 if (NULL == g_bleServerBDAddressMutex)
3820 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3821 return CA_STATUS_FAILED;
3825 if (NULL == g_threadMutex)
3827 g_threadMutex = ca_mutex_new();
3828 if (NULL == g_threadMutex)
3830 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3831 return CA_STATUS_FAILED;
3835 if (NULL == g_threadSendMutex)
3837 g_threadSendMutex = ca_mutex_new();
3838 if (NULL == g_threadSendMutex)
3840 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3841 return CA_STATUS_FAILED;
3845 if (NULL == g_deviceListMutex)
3847 g_deviceListMutex = ca_mutex_new();
3848 if (NULL == g_deviceListMutex)
3850 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3851 return CA_STATUS_FAILED;
3855 if (NULL == g_gattObjectMutex)
3857 g_gattObjectMutex = ca_mutex_new();
3858 if (NULL == g_gattObjectMutex)
3860 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3861 return CA_STATUS_FAILED;
3865 if (NULL == g_deviceStateListMutex)
3867 g_deviceStateListMutex = ca_mutex_new();
3868 if (NULL == g_deviceStateListMutex)
3870 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3871 return CA_STATUS_FAILED;
3875 if (NULL == g_SendFinishMutex)
3877 g_SendFinishMutex = ca_mutex_new();
3878 if (NULL == g_SendFinishMutex)
3880 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3881 return CA_STATUS_FAILED;
3885 if (NULL == g_threadWriteCharacteristicMutex)
3887 g_threadWriteCharacteristicMutex = ca_mutex_new();
3888 if (NULL == g_threadWriteCharacteristicMutex)
3890 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3891 return CA_STATUS_FAILED;
3895 if (NULL == g_deviceScanRetryDelayMutex)
3897 g_deviceScanRetryDelayMutex = ca_mutex_new();
3898 if (NULL == g_deviceScanRetryDelayMutex)
3900 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3901 return CA_STATUS_FAILED;
3905 if (NULL == g_threadSendStateMutex)
3907 g_threadSendStateMutex = ca_mutex_new();
3908 if (NULL == g_threadSendStateMutex)
3910 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3911 return CA_STATUS_FAILED;
3915 if (NULL == g_threadScanIntervalMutex)
3917 g_threadScanIntervalMutex = ca_mutex_new();
3918 if (NULL == g_threadScanIntervalMutex)
3920 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3921 return CA_STATUS_FAILED;
3925 return CA_STATUS_OK;
3928 void CALEClientTerminateGattMutexVariables()
3930 ca_mutex_free(g_bleReqRespClientCbMutex);
3931 g_bleReqRespClientCbMutex = NULL;
3933 ca_mutex_free(g_bleServerBDAddressMutex);
3934 g_bleServerBDAddressMutex = NULL;
3936 ca_mutex_free(g_threadMutex);
3937 g_threadMutex = NULL;
3939 ca_mutex_free(g_threadSendMutex);
3940 g_threadSendMutex = NULL;
3942 ca_mutex_free(g_deviceListMutex);
3943 g_deviceListMutex = NULL;
3945 ca_mutex_free(g_SendFinishMutex);
3946 g_SendFinishMutex = NULL;
3948 ca_mutex_free(g_threadWriteCharacteristicMutex);
3949 g_threadWriteCharacteristicMutex = NULL;
3951 ca_mutex_free(g_deviceScanRetryDelayMutex);
3952 g_deviceScanRetryDelayMutex = NULL;
3954 ca_mutex_free(g_threadSendStateMutex);
3955 g_threadSendStateMutex = NULL;
3957 ca_mutex_free(g_threadScanIntervalMutex);
3958 g_threadScanIntervalMutex = NULL;
3961 void CALEClientSetSendFinishFlag(bool flag)
3963 OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3965 ca_mutex_lock(g_SendFinishMutex);
3966 g_isFinishedSendData = flag;
3967 ca_mutex_unlock(g_SendFinishMutex);
3974 CAResult_t CAStartLEGattClient()
3976 // init mutex for send logic
3977 if (!g_deviceDescCond)
3979 g_deviceDescCond = ca_cond_new();
3984 g_threadCond = ca_cond_new();
3987 if (!g_threadWriteCharacteristicCond)
3989 g_threadWriteCharacteristicCond = ca_cond_new();
3992 if (!g_threadScanIntervalCond)
3994 g_threadScanIntervalCond = ca_cond_new();
3997 CAResult_t ret = CALEClientStartScanWithInterval();
3998 if (CA_STATUS_OK != ret)
4000 OIC_LOG(ERROR, TAG, "CALEClientStartScanWithInterval has failed");
4004 g_isStartedLEClient = true;
4005 return CA_STATUS_OK;
4008 void CAStopLEGattClient()
4010 OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
4014 OIC_LOG(ERROR, TAG, "g_jvm is null");
4018 bool isAttached = false;
4020 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
4023 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
4024 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
4028 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
4034 CAResult_t ret = CALEClientDisconnectAll(env);
4035 if (CA_STATUS_OK != ret)
4037 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
4040 CALEClientStopScanWithInterval();
4042 ca_mutex_lock(g_threadMutex);
4043 OIC_LOG(DEBUG, TAG, "signal - connection cond");
4044 ca_cond_signal(g_threadCond);
4045 CALEClientSetSendFinishFlag(true);
4046 ca_mutex_unlock(g_threadMutex);
4048 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4049 OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
4050 ca_cond_signal(g_threadWriteCharacteristicCond);
4051 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4053 ca_mutex_lock(g_deviceScanRetryDelayMutex);
4054 OIC_LOG(DEBUG, TAG, "signal - delay cond");
4055 ca_cond_signal(g_deviceScanRetryDelayCond);
4056 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
4058 ca_mutex_lock(g_threadScanIntervalMutex);
4059 OIC_LOG(DEBUG, TAG, "signal - delay cond");
4060 ca_cond_signal(g_threadScanIntervalCond);
4061 ca_mutex_unlock(g_threadScanIntervalMutex);
4063 ca_cond_free(g_deviceDescCond);
4064 ca_cond_free(g_threadCond);
4065 ca_cond_free(g_threadWriteCharacteristicCond);
4066 ca_cond_free(g_deviceScanRetryDelayCond);
4067 ca_cond_free(g_threadScanIntervalCond);
4069 g_deviceDescCond = NULL;
4070 g_threadCond = NULL;
4071 g_threadWriteCharacteristicCond = NULL;
4072 g_deviceScanRetryDelayCond = NULL;
4073 g_threadScanIntervalCond = NULL;
4077 (*g_jvm)->DetachCurrentThread(g_jvm);
4082 CAResult_t CAInitializeLEGattClient()
4084 OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
4085 CALEClientInitialize();
4086 return CA_STATUS_OK;
4089 void CATerminateLEGattClient()
4091 OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
4092 CAStopLEGattClient();
4093 CALEClientTerminate();
4096 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t *data,
4097 uint32_t dataLen, CALETransferType_t type,
4100 OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
4101 VERIFY_NON_NULL(data, TAG, "data is null");
4102 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
4104 if (LE_UNICAST != type || position < 0)
4106 OIC_LOG(ERROR, TAG, "this request is not unicast");
4107 return CA_STATUS_INVALID_PARAM;
4110 return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
4113 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
4115 OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
4116 VERIFY_NON_NULL(data, TAG, "data is null");
4118 return CALEClientSendMulticastMessage(data, dataLen);
4121 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
4123 ca_mutex_lock(g_bleReqRespClientCbMutex);
4124 g_CABLEClientDataReceivedCallback = callback;
4125 ca_mutex_unlock(g_bleReqRespClientCbMutex);
4128 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
4130 g_threadPoolHandle = handle;
4133 CAResult_t CAGetLEAddress(char **local_address)
4135 VERIFY_NON_NULL(local_address, TAG, "local_address");
4136 OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
4137 return CA_NOT_SUPPORTED;
4140 JNIEXPORT void JNICALL
4141 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
4144 OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
4145 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4146 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4147 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4149 g_leScanCallback = (*env)->NewGlobalRef(env, callback);
4152 JNIEXPORT void JNICALL
4153 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
4156 OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
4157 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4158 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4159 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
4161 g_leGattCallback = (*env)->NewGlobalRef(env, callback);
4164 JNIEXPORT void JNICALL
4165 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
4168 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4169 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4170 VERIFY_NON_NULL_VOID(device, TAG, "device is null");
4172 CAResult_t res = CALEClientAddScanDeviceToList(env, device);
4173 if (CA_STATUS_OK != res)
4175 OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
4180 * Class: org_iotivity_ca_jar_caleinterface
4181 * Method: CALeGattConnectionStateChangeCallback
4182 * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
4184 JNIEXPORT void JNICALL
4185 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
4191 OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
4193 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4194 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4195 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4197 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
4199 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4202 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
4206 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4209 OIC_LOG(ERROR, TAG, "address is null");
4212 OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
4214 if (state_connected == newstate)
4216 OIC_LOG(DEBUG, TAG, "LE is connected");
4217 if (GATT_SUCCESS == status)
4219 CAResult_t res = CALEClientUpdateDeviceState(address,
4220 CA_LE_CONNECTION_STATE,
4222 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4223 if (CA_STATUS_OK != res)
4225 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4229 res = CALEClientAddGattobjToList(env, gatt);
4230 if (CA_STATUS_OK != res)
4232 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
4236 res = CALEClientDiscoverServices(env, gatt);
4237 if (CA_STATUS_OK != res)
4239 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
4245 OIC_LOG(INFO, TAG, "unknown status");
4246 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4249 else // STATE_DISCONNECTED == newstate
4251 OIC_LOG(DEBUG, TAG, "LE is disconnected");
4253 CAResult_t res = CALEClientUpdateDeviceState(address,
4254 CA_LE_CONNECTION_STATE,
4255 STATE_DISCONNECTED);
4256 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4257 if (CA_STATUS_OK != res)
4259 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4263 res = CALEClientGattClose(env, gatt);
4264 if (CA_STATUS_OK != res)
4266 OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
4269 if (CALECheckConnectionStateValue(status))
4271 // this state is unexpected reason to disconnect
4272 // if the reason is suitable, connection logic of the device will be destroyed.
4273 OIC_LOG(INFO, TAG, "connection logic destroy");
4278 // other reason except for gatt_success is expected to running
4279 // background connection in BT platform.
4280 OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
4281 CALEClientUpdateSendCnt(env);
4287 (*env)->DeleteGlobalRef(env, g_sendBuffer);
4288 g_sendBuffer = NULL;
4295 CALEClientSendFinish(env, gatt);
4300 * Class: org_iotivity_ca_jar_caleinterface
4301 * Method: CALeGattServicesDiscoveredCallback
4302 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
4304 JNIEXPORT void JNICALL
4305 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
4310 OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d", status);
4311 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4312 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4313 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4315 if (GATT_SUCCESS != status) // discovery error
4317 CALEClientSendFinish(env, gatt);
4321 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4324 CALEClientSendFinish(env, gatt);
4328 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4331 CALEClientSendFinish(env, gatt);
4335 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
4338 OIC_LOG(ERROR, TAG, "jni_uuid is null");
4342 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
4343 if (!jni_obj_GattCharacteristic)
4345 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
4349 CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
4350 jni_obj_GattCharacteristic);
4351 if (CA_STATUS_OK != res)
4353 OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
4357 res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
4358 if (CA_STATUS_OK != res)
4360 OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
4362 res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE);
4363 if (CA_STATUS_OK != res)
4365 OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4369 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4370 STATE_SERVICE_CONNECTED);
4371 if (CA_STATUS_OK != res)
4373 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4379 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4380 if (CA_STATUS_OK != res)
4382 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4389 res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE);
4390 if (CA_STATUS_OK != res)
4392 OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4397 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
4398 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4403 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
4404 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4405 CALEClientSendFinish(env, gatt);
4410 * Class: org_iotivity_ca_jar_caleinterface
4411 * Method: CALeGattCharacteristicWritjclasseCallback
4412 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
4414 JNIEXPORT void JNICALL
4415 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
4416 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
4418 OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
4419 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4420 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4421 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4423 // send success & signal
4424 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4430 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4436 if (GATT_SUCCESS != status) // error case
4438 OIC_LOG(ERROR, TAG, "send failure");
4441 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4442 if (CA_STATUS_OK != res)
4444 OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
4445 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4446 g_isSignalSetFlag = true;
4447 ca_cond_signal(g_threadWriteCharacteristicCond);
4448 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4450 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4452 if (CA_STATUS_OK != res)
4454 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4457 if (g_clientErrorCallback)
4459 jint length = (*env)->GetArrayLength(env, data);
4460 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
4463 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4469 OIC_LOG(DEBUG, TAG, "send success");
4470 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4471 STATE_SEND_SUCCESS);
4472 if (CA_STATUS_OK != res)
4474 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4477 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4478 OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
4479 g_isSignalSetFlag = true;
4480 ca_cond_signal(g_threadWriteCharacteristicCond);
4481 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4484 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4490 CALEClientSendFinish(env, gatt);
4495 * Class: org_iotivity_ca_jar_caleinterface
4496 * Method: CALeGattCharacteristicChangedCallback
4497 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
4499 JNIEXPORT void JNICALL
4500 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
4501 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
4503 OIC_LOG(INFO, TAG, "CALeGattCharacteristicChangedCallback");
4504 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4505 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4506 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4507 VERIFY_NON_NULL_VOID(data, TAG, "data is null");
4509 // get Byte Array and convert to uint8_t*
4510 jint length = (*env)->GetArrayLength(env, data);
4513 jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
4515 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
4516 jni_byte_responseData);
4518 uint8_t* receivedData = OICMalloc(length);
4521 OIC_LOG(ERROR, TAG, "receivedData is null");
4525 memcpy(receivedData, jni_byte_responseData, length);
4526 (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
4528 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4531 OIC_LOG(ERROR, TAG, "jni_address is null");
4532 OICFree(receivedData);
4536 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4539 OIC_LOG(ERROR, TAG, "address is null");
4540 OICFree(receivedData);
4544 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
4545 receivedData, length);
4547 uint32_t sentLength = 0;
4548 ca_mutex_lock(g_bleServerBDAddressMutex);
4549 g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
4550 ca_mutex_unlock(g_bleServerBDAddressMutex);
4552 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4556 * Class: org_iotivity_ca_jar_caleinterface
4557 * Method: CALeGattDescriptorWriteCallback
4558 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
4560 JNIEXPORT void JNICALL
4561 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
4565 OIC_LOG_V(INFO, TAG, "CALeGattDescriptorWriteCallback - status %d", status);
4566 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4567 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4568 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4570 if (GATT_SUCCESS != status) // error
4575 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4581 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4587 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4588 STATE_SERVICE_CONNECTED);
4589 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4590 if (CA_STATUS_OK != res)
4592 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4598 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4599 if (CA_STATUS_OK != res)
4601 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4610 CALEClientSendFinish(env, gatt);