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
45 #define GATT_CONNECTION_PRIORITY_BALANCED 0
46 #define GATT_FAILURE 257
47 #define GATT_INSUFFICIENT_AUTHENTICATION 5
48 #define GATT_INSUFFICIENT_ENCRYPTION 15
49 #define GATT_INVALID_ATTRIBUTE_LENGTH 13
50 #define GATT_INVALID_OFFSET 7
51 #define GATT_READ_NOT_PERMITTED 2
52 #define GATT_REQUEST_NOT_SUPPORTED 6
53 #define GATT_WRITE_NOT_PERMITTED 3
55 static ca_thread_pool_t g_threadPoolHandle = NULL;
58 static u_arraylist_t *g_deviceList = NULL; // device list to have same UUID
59 static u_arraylist_t *g_gattObjectList = NULL;
60 static u_arraylist_t *g_deviceStateList = NULL;
62 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
63 static CABLEErrorHandleCallback g_clientErrorCallback;
64 static jobject g_leScanCallback = NULL;
65 static jobject g_leGattCallback = NULL;
66 static jobject g_context = NULL;
67 static jobjectArray g_uuidList = NULL;
69 // it will be prevent to start send logic when adapter has stopped.
70 static bool g_isStartedLEClient = false;
71 static bool g_isStartedScan = false;
73 static jbyteArray g_sendBuffer = NULL;
74 static uint32_t g_targetCnt = 0;
75 static uint32_t g_currentSentCnt = 0;
76 static bool g_isFinishedSendData = false;
77 static ca_mutex g_SendFinishMutex = NULL;
78 static ca_mutex g_threadMutex = NULL;
79 static ca_cond g_threadCond = NULL;
80 static ca_cond g_deviceDescCond = NULL;
82 static ca_mutex g_threadSendMutex = NULL;
83 static ca_mutex g_threadWriteCharacteristicMutex = NULL;
84 static ca_cond g_threadWriteCharacteristicCond = NULL;
85 static bool g_isSignalSetFlag = false;
87 static ca_mutex g_bleReqRespClientCbMutex = NULL;
88 static ca_mutex g_bleServerBDAddressMutex = NULL;
90 static ca_mutex g_deviceListMutex = NULL;
91 static ca_mutex g_gattObjectMutex = NULL;
92 static ca_mutex g_deviceStateListMutex = NULL;
94 static ca_mutex g_deviceScanRetryDelayMutex = NULL;
95 static ca_cond g_deviceScanRetryDelayCond = NULL;
97 static ca_mutex g_scanMutex = NULL;
98 static ca_mutex g_threadSendStateMutex = NULL;
100 static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
103 * check if retry logic for connection routine has to be stopped or not.
104 * in case of error value including this method, connection routine has to be stopped.
105 * since there is no retry logic for this error reason in this client.
106 * @param state constant value of bluetoothgatt.
107 * @return true - waiting for background connection in BT platform.
108 * false - connection routine has to be stopped.
110 static bool CALECheckConnectionStateValue(jint state)
114 case GATT_CONNECTION_PRIORITY_BALANCED:
116 case GATT_INSUFFICIENT_AUTHENTICATION:
117 case GATT_INSUFFICIENT_ENCRYPTION:
118 case GATT_INVALID_ATTRIBUTE_LENGTH:
119 case GATT_INVALID_OFFSET:
120 case GATT_READ_NOT_PERMITTED:
121 case GATT_REQUEST_NOT_SUPPORTED:
122 case GATT_WRITE_NOT_PERMITTED:
129 void CALEClientJniInit()
131 OIC_LOG(DEBUG, TAG, "CALEClientJniInit");
132 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
135 void CALEClientJNISetContext()
137 OIC_LOG(DEBUG, TAG, "CALEClientJNISetContext");
138 g_context = (jobject) CANativeJNIGetContext();
141 CAResult_t CALECreateJniInterfaceObject()
143 OIC_LOG(DEBUG, TAG, "CALECreateJniInterfaceObject");
147 OIC_LOG(ERROR, TAG, "g_context is null");
148 return CA_STATUS_FAILED;
153 OIC_LOG(ERROR, TAG, "g_jvm is null");
154 return CA_STATUS_FAILED;
157 bool isAttached = false;
159 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
162 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
163 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
167 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
168 return CA_STATUS_FAILED;
173 jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, "android/content/Context",
174 "getApplicationContext",
175 "()Landroid/content/Context;");
177 if (!mid_getApplicationContext)
179 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
180 return CA_STATUS_FAILED;
183 jobject jApplicationContext = (*env)->CallObjectMethod(env, g_context,
184 mid_getApplicationContext);
185 if (!jApplicationContext)
187 OIC_LOG(ERROR, TAG, "Could not get application context");
188 return CA_STATUS_FAILED;
191 jclass jni_LEInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
192 if (!jni_LEInterface)
194 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
198 jmethodID LeInterfaceConstructorMethod = (*env)->GetMethodID(env, jni_LEInterface, "<init>",
199 "(Landroid/content/Context;)V");
200 if (!LeInterfaceConstructorMethod)
202 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface constructor method");
206 (*env)->NewObject(env, jni_LEInterface, LeInterfaceConstructorMethod, jApplicationContext);
207 OIC_LOG(DEBUG, TAG, "Create instance for CaLeClientInterface");
211 (*g_jvm)->DetachCurrentThread(g_jvm);
220 (*g_jvm)->DetachCurrentThread(g_jvm);
223 return CA_STATUS_FAILED;
226 CAResult_t CALEClientInitialize()
228 OIC_LOG(DEBUG, TAG, "CALEClientInitialize");
234 OIC_LOG(ERROR, TAG, "g_jvm is null");
235 return CA_STATUS_FAILED;
238 bool isAttached = false;
240 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
243 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
244 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
248 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
249 return CA_STATUS_FAILED;
254 CAResult_t ret = CALECheckPlatformVersion(env, 18);
255 if (CA_STATUS_OK != ret)
257 OIC_LOG(ERROR, TAG, "it is not supported");
261 (*g_jvm)->DetachCurrentThread(g_jvm);
267 ret = CALEClientInitGattMutexVaraibles();
268 if (CA_STATUS_OK != ret)
270 OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
271 CALEClientTerminateGattMutexVariables();
275 (*g_jvm)->DetachCurrentThread(g_jvm);
281 g_deviceDescCond = ca_cond_new();
283 // init mutex for send logic
284 g_threadCond = ca_cond_new();
285 g_threadWriteCharacteristicCond = ca_cond_new();
286 g_deviceScanRetryDelayCond = ca_cond_new();
288 CALEClientCreateDeviceList();
289 CALEClientJNISetContext();
291 ret = CALEClientCreateUUIDList();
292 if (CA_STATUS_OK != ret)
294 OIC_LOG(ERROR, TAG, "CALEClientCreateUUIDList has failed");
298 (*g_jvm)->DetachCurrentThread(g_jvm);
304 ret = CALECreateJniInterfaceObject(); /* create java caleinterface instance*/
305 if (CA_STATUS_OK != ret)
307 OIC_LOG(ERROR, TAG, "CALECreateJniInterfaceObject has failed");
311 (*g_jvm)->DetachCurrentThread(g_jvm);
316 g_isStartedLEClient = true;
320 (*g_jvm)->DetachCurrentThread(g_jvm);
326 void CALEClientTerminate()
328 OIC_LOG(DEBUG, TAG, "CALEClientTerminate");
332 OIC_LOG(ERROR, TAG, "g_jvm is null");
336 bool isAttached = false;
338 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
341 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
342 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
346 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
352 if (g_leScanCallback)
354 (*env)->DeleteGlobalRef(env, g_leScanCallback);
355 g_leScanCallback = NULL;
358 if (g_leGattCallback)
360 (*env)->DeleteGlobalRef(env, g_leGattCallback);
361 g_leGattCallback = NULL;
366 (*env)->DeleteGlobalRef(env, g_sendBuffer);
372 (*env)->DeleteGlobalRef(env, g_uuidList);
376 CAResult_t ret = CALEClientRemoveAllDeviceState();
377 if (CA_STATUS_OK != ret)
379 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed");
382 ret = CALEClientRemoveAllScanDevices(env);
383 if (CA_STATUS_OK != ret)
385 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
388 ret = CALEClientRemoveAllGattObjs(env);
389 if (CA_STATUS_OK != ret)
391 OIC_LOG(ERROR, TAG, "CALEClientRemoveAllGattObjs has failed");
394 CALEClientSetScanFlag(false);
395 CALEClientSetSendFinishFlag(true);
397 CALEClientTerminateGattMutexVariables();
398 CALEClientDestroyJniInterface();
400 ca_cond_free(g_deviceDescCond);
401 ca_cond_free(g_threadCond);
402 ca_cond_free(g_threadWriteCharacteristicCond);
403 ca_cond_free(g_deviceScanRetryDelayCond);
405 g_deviceDescCond = NULL;
407 g_threadWriteCharacteristicCond = NULL;
408 g_deviceScanRetryDelayCond = NULL;
410 g_isSignalSetFlag = false;
414 (*g_jvm)->DetachCurrentThread(g_jvm);
418 CAResult_t CALEClientDestroyJniInterface()
420 OIC_LOG(DEBUG, TAG, "CALEClientDestroyJniInterface");
424 OIC_LOG(ERROR, TAG, "g_jvm is null");
425 return CA_STATUS_FAILED;
428 bool isAttached = false;
430 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
433 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
434 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
438 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
439 return CA_STATUS_FAILED;
444 jclass jni_LeInterface = (*env)->FindClass(env, "org/iotivity/ca/CaLeClientInterface");
445 if (!jni_LeInterface)
447 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface class");
451 jmethodID jni_InterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_LeInterface,
452 "destroyLeInterface",
454 if (!jni_InterfaceDestroyMethod)
456 OIC_LOG(ERROR, TAG, "Could not get CaLeClientInterface destroy method");
460 (*env)->CallStaticVoidMethod(env, jni_LeInterface, jni_InterfaceDestroyMethod);
462 if ((*env)->ExceptionCheck(env))
464 OIC_LOG(ERROR, TAG, "destroyLeInterface has failed");
465 (*env)->ExceptionDescribe(env);
466 (*env)->ExceptionClear(env);
470 OIC_LOG(DEBUG, TAG, "Destroy instance for CaLeClientInterface");
474 (*g_jvm)->DetachCurrentThread(g_jvm);
483 (*g_jvm)->DetachCurrentThread(g_jvm);
486 return CA_STATUS_FAILED;
489 void CALEClientSendFinish(JNIEnv *env, jobject gatt)
491 OIC_LOG(DEBUG, TAG, "CALEClientSendFinish");
492 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
496 CAResult_t res = CALEClientDisconnect(env, gatt);
497 if (CA_STATUS_OK != res)
499 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
502 CALEClientUpdateSendCnt(env);
505 CAResult_t CALEClientSendUnicastMessage(const char* address,
507 const uint32_t dataLen)
509 OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data);
510 VERIFY_NON_NULL(address, TAG, "address is null");
511 VERIFY_NON_NULL(data, TAG, "data is null");
513 return CALEClientSendUnicastMessageImpl(address, data, dataLen);
516 CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
517 const uint32_t dataLen)
519 OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
520 VERIFY_NON_NULL(data, TAG, "data is null");
524 OIC_LOG(ERROR, TAG, "g_jvm is null");
525 return CA_STATUS_FAILED;
528 bool isAttached = false;
530 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
533 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
534 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
538 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
539 return CA_STATUS_FAILED;
544 CAResult_t ret = CALEClientSendMulticastMessageImpl(env, data, dataLen);
545 if (CA_STATUS_OK != ret)
547 OIC_LOG(ERROR, TAG, "CALEClientSendMulticastMessageImpl has failed");
552 (*g_jvm)->DetachCurrentThread(g_jvm);
558 CAResult_t CALEClientStartUnicastServer(const char* address)
560 OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address);
562 return CA_NOT_SUPPORTED;
565 CAResult_t CALEClientStartMulticastServer()
567 OIC_LOG(DEBUG, TAG, "it is not needed in this platform");
569 return CA_NOT_SUPPORTED;
572 void CALEClientStopUnicastServer()
574 OIC_LOG(DEBUG, TAG, "CALEClientStopUnicastServer");
577 void CALEClientStopMulticastServer()
579 OIC_LOG(DEBUG, TAG, "CALEClientStopMulticastServer");
582 void CALEClientSetCallback(CAPacketReceiveCallback callback)
584 g_packetReceiveCallback = callback;
587 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
589 g_clientErrorCallback = callback;
592 CAResult_t CALEClientIsThereScannedDevices(JNIEnv *env, const char* address)
594 VERIFY_NON_NULL(env, TAG, "env");
598 return CA_STATUS_FAILED;
601 if (0 == u_arraylist_length(g_deviceList) // multicast
602 || (address && !CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
604 // Wait for LE peripherals to be discovered.
606 // Number of times to wait for discovery to complete.
607 static size_t const RETRIES = 5;
609 static uint64_t const TIMEOUT =
610 2 * MICROSECS_PER_SEC; // Microseconds
612 bool devicesDiscovered = false;
613 for (size_t i = 0; i < RETRIES; ++i)
615 OIC_LOG(DEBUG, TAG, "waiting for target device");
616 if (ca_cond_wait_for(g_deviceDescCond,
618 TIMEOUT) == CA_WAIT_SUCCESS)
620 ca_mutex_lock(g_deviceListMutex);
621 size_t scannedDeviceLen = u_arraylist_length(g_deviceList);
622 ca_mutex_unlock(g_deviceListMutex);
624 if (0 < scannedDeviceLen)
626 if (!address // multicast
627 || (address && CALEClientIsDeviceInScanDeviceList(env, address))) // unicast
629 devicesDiscovered = true;
636 OIC_LOG(INFO, TAG, "waiting..");
638 ca_mutex_lock(g_deviceScanRetryDelayMutex);
639 if (ca_cond_wait_for(g_deviceScanRetryDelayCond,
640 g_deviceScanRetryDelayMutex,
641 MICROSECS_PER_SEC) == CA_WAIT_SUCCESS)
643 OIC_LOG(INFO, TAG, "finish to waiting for target device");
644 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
647 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
650 // checking whether a target device is found while waiting for time-out.
651 if (CALEClientIsDeviceInScanDeviceList(env, address))
653 devicesDiscovered = true;
662 // time out for scanning devices
663 if (!devicesDiscovered)
665 return CA_STATUS_FAILED;
673 CAResult_t CALEClientSendUnicastMessageImpl(const char* address, const uint8_t* data,
674 const uint32_t dataLen)
676 OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl, address: %s, data: %p", address,
678 VERIFY_NON_NULL(address, TAG, "address is null");
679 VERIFY_NON_NULL(data, TAG, "data is null");
683 OIC_LOG(ERROR, TAG, "g_jvm is null");
684 return CA_STATUS_FAILED;
687 bool isAttached = false;
689 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
692 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
693 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
696 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
697 return CA_STATUS_FAILED;
702 ca_mutex_lock(g_threadSendMutex);
704 CALEClientSetSendFinishFlag(false);
706 CAResult_t ret = CALEClientIsThereScannedDevices(env, address);
707 if (CA_STATUS_OK != ret)
709 OIC_LOG(INFO, TAG, "there is no scanned device");
713 if (g_context && g_deviceList)
715 uint32_t length = u_arraylist_length(g_deviceList);
716 for (uint32_t index = 0; index < length; index++)
718 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
721 OIC_LOG(ERROR, TAG, "jarrayObj is null");
725 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
728 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
732 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
735 OIC_LOG(ERROR, TAG, "setAddress is null");
739 OIC_LOG_V(DEBUG, TAG, "remote device address is %s", setAddress);
741 if (!strcmp(setAddress, address))
743 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
744 (*env)->DeleteLocalRef(env, jni_setAddress);
746 // connect to gatt server
747 ret = CALEClientStopScan();
748 if (CA_STATUS_OK != ret)
750 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
756 (*env)->DeleteGlobalRef(env, g_sendBuffer);
759 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
760 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
761 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
763 // Target device to send message is just one.
766 ret = CALEClientSendData(env, jarrayObj);
767 if (CA_STATUS_OK != ret)
769 OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
773 OIC_LOG(INFO, TAG, "wake up");
776 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
777 (*env)->DeleteLocalRef(env, jni_setAddress);
781 OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
783 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
784 // if there is no connection state.
785 ca_mutex_lock(g_threadMutex);
786 if (!g_isFinishedSendData)
788 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
789 ca_cond_wait(g_threadCond, g_threadMutex);
790 OIC_LOG(DEBUG, TAG, "the data was sent");
792 ca_mutex_unlock(g_threadMutex);
796 (*g_jvm)->DetachCurrentThread(g_jvm);
799 // start LE Scan again
800 ret = CALEClientStartScan();
801 if (CA_STATUS_OK != ret)
803 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
804 ca_mutex_unlock(g_threadSendMutex);
808 ca_mutex_unlock(g_threadSendMutex);
809 OIC_LOG(INFO, TAG, "unicast - send logic has finished");
810 if (CALEClientIsValidState(address, CA_LE_SEND_STATE,
817 ret = CA_SEND_FAILED;
821 ret = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
823 if (CA_STATUS_OK != ret)
825 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
833 // start LE Scan again
834 ret = CALEClientStartScan();
835 if (CA_STATUS_OK != ret)
837 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
838 ca_mutex_unlock(g_threadSendMutex);
841 (*g_jvm)->DetachCurrentThread(g_jvm);
848 (*g_jvm)->DetachCurrentThread(g_jvm);
851 ca_mutex_unlock(g_threadSendMutex);
852 return CA_SEND_FAILED;
855 CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
856 const uint32_t dataLen)
858 OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
859 VERIFY_NON_NULL(data, TAG, "data is null");
860 VERIFY_NON_NULL(env, TAG, "env is null");
864 OIC_LOG(ERROR, TAG, "g_deviceList is null");
865 return CA_STATUS_FAILED;
868 ca_mutex_lock(g_threadSendMutex);
870 CALEClientSetSendFinishFlag(false);
872 OIC_LOG(DEBUG, TAG, "set byteArray for data");
875 (*env)->DeleteGlobalRef(env, g_sendBuffer);
879 CAResult_t res = CALEClientIsThereScannedDevices(env, NULL);
880 if (CA_STATUS_OK != res)
882 OIC_LOG(INFO, TAG, "there is no scanned device");
886 // connect to gatt server
887 res = CALEClientStopScan();
888 if (CA_STATUS_OK != res)
890 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
891 ca_mutex_unlock(g_threadSendMutex);
894 uint32_t length = u_arraylist_length(g_deviceList);
895 g_targetCnt = length;
897 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
898 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
899 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
901 for (uint32_t index = 0; index < length; index++)
903 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
906 OIC_LOG(ERROR, TAG, "jarrayObj is not available");
910 res = CALEClientSendData(env, jarrayObj);
911 if (res != CA_STATUS_OK)
913 OIC_LOG(ERROR, TAG, "BT device - send has failed");
917 OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
919 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
920 ca_mutex_lock(g_threadMutex);
921 if (!g_isFinishedSendData)
923 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
924 ca_cond_wait(g_threadCond, g_threadMutex);
925 OIC_LOG(DEBUG, TAG, "the data was sent");
927 ca_mutex_unlock(g_threadMutex);
929 // start LE Scan again
930 res = CALEClientStartScan();
931 if (CA_STATUS_OK != res)
933 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
934 ca_mutex_unlock(g_threadSendMutex);
938 ca_mutex_unlock(g_threadSendMutex);
939 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
943 res = CALEClientStartScan();
944 if (CA_STATUS_OK != res)
946 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
947 ca_mutex_unlock(g_threadSendMutex);
951 ca_mutex_unlock(g_threadSendMutex);
952 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
953 return CA_SEND_FAILED;
956 CAResult_t CALEClientSendData(JNIEnv *env, jobject device)
958 OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
959 VERIFY_NON_NULL(device, TAG, "device is null");
960 VERIFY_NON_NULL(env, TAG, "env is null");
962 // get BLE address from bluetooth device object.
963 char* address = NULL;
964 CALEState_t* state = NULL;
965 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, device);
968 OIC_LOG(INFO, TAG, "there is gatt object..it's not first connection");
969 address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
972 OIC_LOG(ERROR, TAG, "address is not available");
973 return CA_STATUS_FAILED;
975 ca_mutex_lock(g_deviceStateListMutex);
976 state = CALEClientGetStateInfo(address);
977 ca_mutex_unlock(g_deviceStateListMutex);
982 OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
984 // cancel previous connection request before connection
985 // if there is gatt object in g_gattObjectList.
988 jobject gatt = CALEClientGetGattObjInList(env, address);
991 CAResult_t res = CALEClientDisconnect(env, gatt);
992 if (CA_STATUS_OK != res)
994 OIC_LOG(INFO, TAG, "there is no gatt object");
997 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1000 // connection request
1001 jobject newGatt = CALEClientConnect(env, device,
1003 if (NULL == newGatt)
1005 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1006 return CA_STATUS_FAILED;
1011 if (CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1012 STATE_SERVICE_CONNECTED))
1014 OIC_LOG(INFO, TAG, "GATT has already connected");
1016 jobject gatt = CALEClientGetGattObjInList(env, address);
1019 OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
1020 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1021 return CA_STATUS_FAILED;
1024 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1025 if (CA_STATUS_OK != ret)
1027 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1028 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1031 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1033 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1036 OIC_LOG(INFO, TAG, "service connecting...");
1038 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1039 STATE_DISCONNECTED))
1041 OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
1043 // cancel previous connection request before connection
1044 // if there is gatt object in g_gattObjectList.
1047 jobject gatt = CALEClientGetGattObjInList(env, address);
1050 CAResult_t res = CALEClientDisconnect(env, gatt);
1051 if (CA_STATUS_OK != res)
1053 OIC_LOG(INFO, TAG, "there is no gatt object");
1056 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1059 OIC_LOG(DEBUG, TAG, "start to connect LE");
1060 jobject gatt = CALEClientConnect(env, device,
1061 CALEClientGetFlagFromState(env, jni_address,
1062 CA_LE_AUTO_CONNECT_FLAG));
1065 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1066 return CA_STATUS_FAILED;
1071 return CA_STATUS_OK;
1074 jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
1076 VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
1077 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1079 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
1080 "()Landroid/bluetooth/BluetoothDevice;");
1081 if (!jni_mid_getDevice)
1083 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
1087 jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
1088 if (!jni_obj_device)
1090 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
1094 jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
1097 OIC_LOG(ERROR, TAG, "jni_address is null");
1107 CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
1110 OIC_LOG(DEBUG, TAG, "Gatt Close");
1111 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1112 VERIFY_NON_NULL(env, TAG, "env is null");
1114 // get BluetoothGatt method
1115 OIC_LOG(DEBUG, TAG, "get BluetoothGatt method");
1116 jmethodID jni_mid_closeGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "close", "()V");
1117 if (!jni_mid_closeGatt)
1119 OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1120 return CA_STATUS_OK;
1123 // call disconnect gatt method
1124 OIC_LOG(DEBUG, TAG, "request to close GATT");
1125 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
1127 if ((*env)->ExceptionCheck(env))
1129 OIC_LOG(ERROR, TAG, "closeGATT has failed");
1130 (*env)->ExceptionDescribe(env);
1131 (*env)->ExceptionClear(env);
1132 return CA_STATUS_FAILED;
1135 return CA_STATUS_OK;
1138 CAResult_t CALEClientStartScan()
1140 if (!g_isStartedLEClient)
1142 OIC_LOG(ERROR, TAG, "LE client is not started");
1143 return CA_STATUS_FAILED;
1148 OIC_LOG(ERROR, TAG, "g_jvm is null");
1149 return CA_STATUS_FAILED;
1152 if (g_isStartedScan)
1154 OIC_LOG(INFO, TAG, "scanning is already started");
1155 return CA_STATUS_OK;
1158 bool isAttached = false;
1160 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1163 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1165 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1168 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1169 return CA_STATUS_FAILED;
1174 OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1176 CAResult_t ret = CA_STATUS_OK;
1177 // scan gatt server with UUID
1178 if (g_leScanCallback && g_uuidList)
1181 ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
1183 ret = CALEClientStartScanImpl(env, g_leScanCallback);
1185 if (CA_STATUS_OK != ret)
1187 if (CA_ADAPTER_NOT_ENABLED == ret)
1189 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1193 OIC_LOG(ERROR, TAG, "start scan has failed");
1200 (*g_jvm)->DetachCurrentThread(g_jvm);
1206 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
1208 VERIFY_NON_NULL(callback, TAG, "callback is null");
1209 VERIFY_NON_NULL(env, TAG, "env is null");
1211 if (!CALEIsEnableBTAdapter(env))
1213 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1214 return CA_ADAPTER_NOT_ENABLED;
1217 // get default bt adapter class
1218 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1219 if (!jni_cid_BTAdapter)
1221 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1222 return CA_STATUS_FAILED;
1225 // get remote bt adapter method
1226 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1227 "getDefaultAdapter",
1228 METHODID_OBJECTNONPARAM);
1229 if (!jni_mid_getDefaultAdapter)
1231 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1232 return CA_STATUS_FAILED;
1235 // get start le scan method
1236 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1237 "(Landroid/bluetooth/BluetoothAdapter$"
1238 "LeScanCallback;)Z");
1239 if (!jni_mid_startLeScan)
1241 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1242 return CA_STATUS_FAILED;
1245 // gat bt adapter object
1246 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1247 jni_mid_getDefaultAdapter);
1248 if (!jni_obj_BTAdapter)
1250 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1251 return CA_STATUS_FAILED;
1254 // call start le scan method
1255 OIC_LOG(INFO, TAG, "CALL API - startLeScan");
1256 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1257 jni_mid_startLeScan, callback);
1258 if (!jni_obj_startLeScan)
1260 OIC_LOG(INFO, TAG, "startLeScan has failed");
1264 OIC_LOG(DEBUG, TAG, "LeScan has started");
1265 CALEClientSetScanFlag(true);
1268 return CA_STATUS_OK;
1271 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
1273 VERIFY_NON_NULL(callback, TAG, "callback is null");
1274 VERIFY_NON_NULL(uuids, TAG, "uuids is null");
1275 VERIFY_NON_NULL(env, TAG, "env is null");
1277 if (!CALEIsEnableBTAdapter(env))
1279 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1280 return CA_ADAPTER_NOT_ENABLED;
1283 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1284 if (!jni_cid_BTAdapter)
1286 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1287 return CA_STATUS_FAILED;
1290 // get remote bt adapter method
1291 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1292 "getDefaultAdapter",
1293 METHODID_OBJECTNONPARAM);
1294 if (!jni_mid_getDefaultAdapter)
1296 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1297 return CA_STATUS_FAILED;
1300 // get start le scan method
1301 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1302 "([Ljava/util/UUID;Landroid/bluetooth/"
1303 "BluetoothAdapter$LeScanCallback;)Z");
1304 if (!jni_mid_startLeScan)
1306 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1307 return CA_STATUS_FAILED;
1310 // get bt adapter object
1311 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1312 jni_mid_getDefaultAdapter);
1313 if (!jni_obj_BTAdapter)
1315 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1316 return CA_STATUS_FAILED;
1319 // call start le scan method
1320 OIC_LOG(INFO, TAG, "CALL API - startLeScan (with UUID)");
1321 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1322 jni_mid_startLeScan, uuids, callback);
1323 if (!jni_obj_startLeScan)
1325 OIC_LOG(INFO, TAG, "startLeScan has failed");
1329 OIC_LOG(DEBUG, TAG, "LeScan has started");
1330 CALEClientSetScanFlag(true);
1333 return CA_STATUS_OK;
1336 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
1338 VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
1339 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1342 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1345 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1349 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString",
1350 "(Ljava/lang/String;)"
1351 "Ljava/util/UUID;");
1352 if (!jni_mid_fromString)
1354 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1358 jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1359 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1363 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1367 return jni_obj_uuid;
1370 CAResult_t CALEClientStopScan()
1374 OIC_LOG(ERROR, TAG, "g_jvm is null");
1375 return CA_STATUS_FAILED;
1378 if (!g_isStartedScan)
1380 OIC_LOG(INFO, TAG, "scanning is already stopped");
1381 return CA_STATUS_OK;
1384 bool isAttached = false;
1386 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1389 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1390 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1393 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1394 return CA_STATUS_FAILED;
1399 CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
1400 if (CA_STATUS_OK != ret)
1402 if (CA_ADAPTER_NOT_ENABLED == ret)
1404 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1408 OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1413 CALEClientSetScanFlag(false);
1418 (*g_jvm)->DetachCurrentThread(g_jvm);
1424 void CALEClientSetScanFlag(bool flag)
1426 ca_mutex_lock(g_scanMutex);
1427 g_isStartedScan = flag;
1428 ca_mutex_unlock(g_scanMutex);
1431 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
1433 OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
1434 VERIFY_NON_NULL(callback, TAG, "callback is null");
1435 VERIFY_NON_NULL(env, TAG, "env is null");
1437 if (!CALEIsEnableBTAdapter(env))
1439 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1440 return CA_ADAPTER_NOT_ENABLED;
1443 // get default bt adapter class
1444 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1445 if (!jni_cid_BTAdapter)
1447 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1448 return CA_STATUS_FAILED;
1451 // get remote bt adapter method
1452 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1453 "getDefaultAdapter",
1454 METHODID_OBJECTNONPARAM);
1455 if (!jni_mid_getDefaultAdapter)
1457 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1458 return CA_STATUS_FAILED;
1461 // get start le scan method
1462 jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
1463 "(Landroid/bluetooth/"
1464 "BluetoothAdapter$LeScanCallback;)V");
1465 if (!jni_mid_stopLeScan)
1467 OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
1468 return CA_STATUS_FAILED;
1471 // gat bt adapter object
1472 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1473 jni_mid_getDefaultAdapter);
1474 if (!jni_obj_BTAdapter)
1476 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1477 return CA_STATUS_FAILED;
1480 OIC_LOG(INFO, TAG, "CALL API - stopLeScan");
1481 // call start le scan method
1482 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
1483 if ((*env)->ExceptionCheck(env))
1485 OIC_LOG(ERROR, TAG, "stopLeScan has failed");
1486 (*env)->ExceptionDescribe(env);
1487 (*env)->ExceptionClear(env);
1488 return CA_STATUS_FAILED;
1491 return CA_STATUS_OK;
1494 CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, jint state_idx, jboolean flag)
1496 OIC_LOG(DEBUG, TAG, "IN - CALEClientSetFlagToState");
1497 VERIFY_NON_NULL(env, TAG, "env");
1498 VERIFY_NON_NULL(jni_address, TAG, "jni_address");
1500 ca_mutex_lock(g_deviceStateListMutex);
1502 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1505 OIC_LOG(ERROR, TAG, "address is not available");
1506 return CA_STATUS_FAILED;
1509 if (CALEClientIsDeviceInList(address))
1511 CALEState_t* curState = CALEClientGetStateInfo(address);
1514 OIC_LOG(ERROR, TAG, "curState is null");
1515 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1516 ca_mutex_unlock(g_deviceStateListMutex);
1517 return CA_STATUS_FAILED;
1519 OIC_LOG_V(INFO, TAG, "%d flag is set : %d", state_idx, flag);
1523 case CA_LE_AUTO_CONNECT_FLAG:
1524 curState->autoConnectFlag = flag;
1526 case CA_LE_DESCRIPTOR_FOUND:
1527 curState->isDescriptorFound = flag;
1534 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1535 ca_mutex_unlock(g_deviceStateListMutex);
1536 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetFlagToState");
1537 return CA_STATUS_OK;
1540 jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx)
1542 OIC_LOG(DEBUG, TAG, "IN - CALEClientGetFlagFromState");
1543 VERIFY_NON_NULL_RET(env, TAG, "env", false);
1544 VERIFY_NON_NULL_RET(jni_address, TAG, "jni_address", false);
1546 ca_mutex_lock(g_deviceStateListMutex);
1548 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1551 OIC_LOG(ERROR, TAG, "address is not available");
1552 ca_mutex_unlock(g_deviceStateListMutex);
1556 CALEState_t* curState = CALEClientGetStateInfo(address);
1557 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1560 OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false");
1561 ca_mutex_unlock(g_deviceStateListMutex);
1565 jboolean ret = JNI_FALSE;
1568 case CA_LE_AUTO_CONNECT_FLAG:
1569 ret = curState->autoConnectFlag;
1571 case CA_LE_DESCRIPTOR_FOUND:
1572 ret = curState->isDescriptorFound;
1577 ca_mutex_unlock(g_deviceStateListMutex);
1579 OIC_LOG_V(INFO, TAG, "%d flag is %d", state_idx, ret);
1580 OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetFlagFromState");
1584 jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1586 OIC_LOG(DEBUG, TAG, "CALEClientConnect");
1587 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1588 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1590 // get gatt object from Bluetooth Device object for closeProfileProxy(..)
1591 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
1594 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1597 OIC_LOG(ERROR, TAG, "address is not available");
1601 // close the gatt service
1602 jobject gatt = CALEClientGetGattObjInList(env, address);
1605 CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
1606 if (CA_STATUS_OK != res)
1608 OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
1609 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1613 // clean previous gatt object after close profile service
1614 res = CALEClientRemoveGattObjForAddr(env, jni_address);
1615 if (CA_STATUS_OK != res)
1617 OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
1618 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1622 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1625 jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
1628 OIC_LOG(DEBUG, TAG, "re-connection will be started");
1632 // add new gatt object into g_gattObjectList
1633 CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
1634 if (CA_STATUS_OK != res)
1636 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
1643 jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1645 OIC_LOG(DEBUG, TAG, "GATT CONNECT");
1646 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1647 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1649 if (!g_leGattCallback)
1651 OIC_LOG(INFO, TAG, "g_leGattCallback is null");
1655 if (!CALEIsEnableBTAdapter(env))
1657 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1661 jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1664 OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
1668 // get BluetoothDevice method
1669 OIC_LOG(DEBUG, TAG, "get BluetoothDevice method");
1670 jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
1672 "(Landroid/content/Context;ZLandroid/"
1673 "bluetooth/BluetoothGattCallback;)"
1674 "Landroid/bluetooth/BluetoothGatt;");
1675 if (!jni_mid_connectGatt)
1677 OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
1681 OIC_LOG(INFO, TAG, "CALL API - connectGatt");
1682 jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
1683 jni_mid_connectGatt,
1685 autoconnect, g_leGattCallback);
1686 if (!jni_obj_connectGatt)
1688 OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
1689 CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
1690 CALEClientUpdateSendCnt(env);
1695 OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
1697 return jni_obj_connectGatt;
1700 CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
1702 OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
1704 VERIFY_NON_NULL(env, TAG, "env is null");
1705 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1707 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1708 if (!jni_cid_BTAdapter)
1710 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
1711 return CA_STATUS_FAILED;
1714 // get remote bt adapter method
1715 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1716 "getDefaultAdapter",
1717 METHODID_OBJECTNONPARAM);
1718 if (!jni_mid_getDefaultAdapter)
1720 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1721 return CA_STATUS_FAILED;
1724 // gat bt adapter object
1725 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1726 jni_mid_getDefaultAdapter);
1727 if (!jni_obj_BTAdapter)
1729 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1730 return CA_STATUS_FAILED;
1733 // get closeProfileProxy method
1734 jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1735 "closeProfileProxy",
1736 "(ILandroid/bluetooth/"
1737 "BluetoothProfile;)V");
1738 if (!jni_mid_closeProfileProxy)
1740 OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
1741 return CA_STATUS_FAILED;
1744 jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
1745 if (!jni_cid_BTProfile)
1747 OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
1748 return CA_STATUS_FAILED;
1751 // GATT - Constant value : 7 (0x00000007)
1752 jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
1756 OIC_LOG(ERROR, TAG, "id_gatt is null");
1757 return CA_STATUS_FAILED;
1760 jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
1762 OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
1763 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
1764 if ((*env)->ExceptionCheck(env))
1766 OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
1767 (*env)->ExceptionDescribe(env);
1768 (*env)->ExceptionClear(env);
1769 return CA_STATUS_FAILED;
1772 OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
1773 return CA_STATUS_OK;
1777 CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
1779 OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1780 VERIFY_NON_NULL(env, TAG, "env is null");
1781 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1783 // get BluetoothGatt method
1784 OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
1785 jmethodID jni_mid_disconnectGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1786 "disconnect", "()V");
1787 if (!jni_mid_disconnectGatt)
1789 OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
1790 return CA_STATUS_FAILED;
1793 // call disconnect gatt method
1794 OIC_LOG(INFO, TAG, "CALL API - disconnect");
1795 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
1796 if ((*env)->ExceptionCheck(env))
1798 OIC_LOG(ERROR, TAG, "disconnect has failed");
1799 (*env)->ExceptionDescribe(env);
1800 (*env)->ExceptionClear(env);
1801 return CA_STATUS_FAILED;
1804 OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
1806 return CA_STATUS_OK;
1809 CAResult_t CALEClientDisconnectAll(JNIEnv *env)
1811 OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1812 VERIFY_NON_NULL(env, TAG, "env is null");
1814 if (!g_gattObjectList)
1816 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1817 return CA_STATUS_OK;
1820 uint32_t length = u_arraylist_length(g_gattObjectList);
1821 OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
1822 for (uint32_t index = 0; index < length; index++)
1824 OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
1825 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1828 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1831 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1832 if (CA_STATUS_OK != res)
1834 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1839 return CA_STATUS_OK;
1842 CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
1844 OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
1845 VERIFY_NON_NULL(env, TAG, "env is null");
1847 if (!g_gattObjectList)
1849 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1850 return CA_STATUS_OK;
1853 char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
1856 OIC_LOG(ERROR, TAG, "address is null");
1857 return CA_STATUS_FAILED;
1860 uint32_t length = u_arraylist_length(g_gattObjectList);
1861 for (uint32_t index = 0; index < length; index++)
1863 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1866 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1870 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
1871 if (!jni_setAddress)
1873 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1874 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1875 return CA_STATUS_FAILED;
1878 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1881 OIC_LOG(ERROR, TAG, "setAddress is null");
1882 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1883 return CA_STATUS_FAILED;
1886 OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
1887 if (!strcmp(address, setAddress))
1889 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1890 if (CA_STATUS_OK != res)
1892 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1893 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1894 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1895 return CA_STATUS_FAILED;
1897 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1898 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1899 return CA_STATUS_OK;
1901 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1903 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1905 OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
1906 return CA_STATUS_OK;
1909 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
1911 VERIFY_NON_NULL(env, TAG, "env is null");
1912 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1914 if (!CALEIsEnableBTAdapter(env))
1916 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1917 return CA_ADAPTER_NOT_ENABLED;
1920 // get BluetoothGatt.discoverServices method
1921 OIC_LOG(DEBUG, TAG, "get BluetoothGatt.discoverServices method");
1922 jmethodID jni_mid_discoverServices = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1923 "discoverServices", "()Z");
1924 if (!jni_mid_discoverServices)
1926 OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
1927 return CA_STATUS_FAILED;
1930 // call disconnect gatt method
1931 OIC_LOG(INFO, TAG, "CALL API - discoverServices");
1932 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
1935 OIC_LOG(ERROR, TAG, "discoverServices has not been started");
1936 return CA_STATUS_FAILED;
1939 return CA_STATUS_OK;
1942 static void CALEWriteCharacteristicThread(void* object)
1944 VERIFY_NON_NULL_VOID(object, TAG, "object is null");
1946 bool isAttached = false;
1948 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1951 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1952 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1956 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1962 jobject gatt = (jobject)object;
1963 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1964 if (CA_STATUS_OK != ret)
1966 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1971 (*g_jvm)->DetachCurrentThread(g_jvm);
1975 CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
1977 OIC_LOG(DEBUG, TAG, "CALESetValueAndWriteCharacteristic");
1979 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1980 VERIFY_NON_NULL(env, TAG, "env is null");
1982 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
1985 CALEClientSendFinish(env, gatt);
1986 return CA_STATUS_FAILED;
1989 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1992 CALEClientSendFinish(env, gatt);
1993 return CA_STATUS_FAILED;
1996 ca_mutex_lock(g_threadSendStateMutex);
1998 if (CALEClientIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING))
2000 OIC_LOG(INFO, TAG, "current state is SENDING");
2001 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2002 ca_mutex_unlock(g_threadSendStateMutex);
2003 return CA_STATUS_OK;
2006 if (CA_STATUS_OK != CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
2009 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
2010 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2011 CALEClientSendFinish(env, gatt);
2012 ca_mutex_unlock(g_threadSendStateMutex);
2013 return CA_STATUS_FAILED;
2016 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2018 ca_mutex_unlock(g_threadSendStateMutex);
2021 jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
2022 if (!jni_obj_character)
2024 CALEClientSendFinish(env, gatt);
2025 return CA_STATUS_FAILED;
2028 CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
2029 if (CA_STATUS_OK != ret)
2031 CALEClientSendFinish(env, gatt);
2032 return CA_STATUS_FAILED;
2035 // wait for callback for write Characteristic with success to sent data
2036 OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
2037 ca_mutex_lock(g_threadWriteCharacteristicMutex);
2038 if (!g_isSignalSetFlag)
2040 OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
2041 if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
2042 g_threadWriteCharacteristicMutex,
2043 WAIT_TIME_WRITE_CHARACTERISTIC))
2045 OIC_LOG(ERROR, TAG, "there is no response. write has failed");
2046 g_isSignalSetFlag = false;
2047 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2048 return CA_STATUS_FAILED;
2051 // reset flag set by writeCharacteristic Callback
2052 g_isSignalSetFlag = false;
2053 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2055 OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
2056 return CA_STATUS_OK;
2059 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
2061 OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
2062 VERIFY_NON_NULL(env, TAG, "env is null");
2063 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2065 jobject gattParam = (*env)->NewGlobalRef(env, gatt);
2066 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
2067 CALEWriteCharacteristicThread, (void*)gattParam))
2069 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
2070 return CA_STATUS_FAILED;
2073 OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
2074 return CA_STATUS_OK;
2077 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
2078 jobject gattCharacteristic)
2080 OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
2081 VERIFY_NON_NULL(env, TAG, "env is null");
2082 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2083 VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
2085 if (!CALEIsEnableBTAdapter(env))
2087 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2088 return CA_STATUS_FAILED;
2091 // get BluetoothGatt.write characteristic method
2092 OIC_LOG(DEBUG, TAG, "write characteristic method");
2093 jmethodID jni_mid_writeCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2094 "writeCharacteristic",
2095 "(Landroid/bluetooth/"
2096 "BluetoothGattCharacteristic;)Z");
2097 if (!jni_mid_writeCharacteristic)
2099 OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
2100 return CA_STATUS_FAILED;
2103 // call disconnect gatt method
2104 OIC_LOG(INFO, TAG, "CALL API - writeCharacteristic");
2105 jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
2106 jni_mid_writeCharacteristic,
2107 gattCharacteristic);
2110 OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
2114 OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
2115 return CA_STATUS_FAILED;
2118 return CA_STATUS_OK;
2121 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
2123 VERIFY_NON_NULL(env, TAG, "env is null");
2124 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2126 if (!CALEIsEnableBTAdapter(env))
2128 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2129 return CA_STATUS_FAILED;
2132 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
2135 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2136 return CA_STATUS_FAILED;
2139 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2140 if (!jni_obj_GattCharacteristic)
2142 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2143 return CA_STATUS_FAILED;
2146 OIC_LOG(DEBUG, TAG, "read characteristic method");
2147 jmethodID jni_mid_readCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2148 "readCharacteristic",
2149 "(Landroid/bluetooth/"
2150 "BluetoothGattCharacteristic;)Z");
2151 if (!jni_mid_readCharacteristic)
2153 OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
2154 return CA_STATUS_FAILED;
2157 // call disconnect gatt method
2158 OIC_LOG(INFO, TAG, "CALL API - readCharacteristic");
2159 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
2160 jni_obj_GattCharacteristic);
2163 OIC_LOG(DEBUG, TAG, "readCharacteristic success");
2167 OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
2168 return CA_STATUS_FAILED;
2171 return CA_STATUS_OK;
2174 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
2175 jobject characteristic)
2177 VERIFY_NON_NULL(env, TAG, "env is null");
2178 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2179 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2181 if (!CALEIsEnableBTAdapter(env))
2183 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2184 return CA_ADAPTER_NOT_ENABLED;
2187 // get BluetoothGatt.setCharacteristicNotification method
2188 OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
2189 jmethodID jni_mid_setNotification = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2190 "setCharacteristicNotification",
2191 "(Landroid/bluetooth/"
2192 "BluetoothGattCharacteristic;Z)Z");
2193 if (!jni_mid_setNotification)
2195 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2196 return CA_STATUS_FAILED;
2199 OIC_LOG(INFO, TAG, "CALL API - setCharacteristicNotification");
2200 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
2201 characteristic, JNI_TRUE);
2202 if (JNI_TRUE == ret)
2204 OIC_LOG(DEBUG, TAG, "setCharacteristicNotification success");
2208 OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed");
2209 return CA_STATUS_FAILED;
2212 return CA_STATUS_OK;
2215 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
2217 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2218 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2219 VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
2221 if (!CALEIsEnableBTAdapter(env))
2223 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2227 // get BluetoothGatt.getService method
2228 OIC_LOG(DEBUG, TAG, "BluetoothGatt.getService");
2229 jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2231 "(Ljava/util/UUID;)Landroid/bluetooth/"
2232 "BluetoothGattService;");
2233 if (!jni_mid_getService)
2235 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2239 jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2240 if (!jni_obj_service_uuid)
2242 OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
2246 // get bluetooth gatt service
2247 OIC_LOG(DEBUG, TAG, "request to get service");
2248 jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
2249 jni_obj_service_uuid);
2250 if (!jni_obj_gattService)
2252 OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
2256 // get bluetooth gatt service method
2257 jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/"
2258 "BluetoothGattService",
2259 "getCharacteristic",
2260 "(Ljava/util/UUID;)"
2261 "Landroid/bluetooth/"
2262 "BluetoothGattCharacteristic;");
2263 if (!jni_mid_getCharacteristic)
2265 OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
2269 const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
2272 OIC_LOG(ERROR, TAG, "uuid is null");
2276 jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
2277 if (!jni_obj_tx_uuid)
2279 OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
2280 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2284 OIC_LOG(DEBUG, TAG, "request to get Characteristic");
2285 jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
2286 jni_mid_getCharacteristic,
2289 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2290 return jni_obj_GattCharacteristic;
2293 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
2295 OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
2296 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2297 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2298 VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
2300 if (!CALEIsEnableBTAdapter(env))
2302 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2306 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
2309 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2313 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2314 if (!jni_obj_GattCharacteristic)
2316 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2320 jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
2321 "/BluetoothGattCharacteristic");
2322 if (!jni_cid_BTGattCharacteristic)
2324 OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
2328 OIC_LOG(DEBUG, TAG, "set value in Characteristic");
2329 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
2331 if (!jni_mid_setValue)
2333 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2337 jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
2339 if (JNI_TRUE == ret)
2341 OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
2345 OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
2350 jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
2351 "setWriteType", "(I)V");
2352 if (!jni_mid_setWriteType)
2354 OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
2358 jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
2359 "WRITE_TYPE_NO_RESPONSE", "I");
2360 if (!jni_fid_no_response)
2362 OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
2366 jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
2367 jni_fid_no_response);
2369 (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
2371 return jni_obj_GattCharacteristic;
2374 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
2376 VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
2377 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2379 if (!CALEIsEnableBTAdapter(env))
2381 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2385 jmethodID jni_mid_getValue = CAGetJNIMethodID(env, "android/bluetooth/"
2386 "BluetoothGattCharacteristic",
2387 "getValue", "()[B");
2388 if (!jni_mid_getValue)
2390 OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
2394 jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
2396 return jni_obj_data_array;
2399 CAResult_t CALEClientCreateUUIDList()
2403 OIC_LOG(ERROR, TAG, "g_jvm is null");
2404 return CA_STATUS_FAILED;
2407 bool isAttached = false;
2409 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2412 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2413 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2417 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2418 return CA_STATUS_FAILED;
2423 // create new object array
2424 jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
2425 if (!jni_cid_uuid_list)
2427 OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
2431 jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
2432 jni_cid_uuid_list, NULL);
2433 if (!jni_obj_uuid_list)
2435 OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
2440 jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2443 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
2446 (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
2448 g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
2452 (*g_jvm)->DetachCurrentThread(g_jvm);
2455 return CA_STATUS_OK;
2462 (*g_jvm)->DetachCurrentThread(g_jvm);
2464 return CA_STATUS_FAILED;
2467 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
2468 jobject characteristic)
2470 VERIFY_NON_NULL(env, TAG, "env is null");
2471 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2472 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2474 if (!CALEIsEnableBTAdapter(env))
2476 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2477 return CA_ADAPTER_NOT_ENABLED;
2480 OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
2481 jmethodID jni_mid_getDescriptor = CAGetJNIMethodID(env, "android/bluetooth/"
2482 "BluetoothGattCharacteristic",
2484 "(Ljava/util/UUID;)Landroid/bluetooth/"
2485 "BluetoothGattDescriptor;");
2486 if (!jni_mid_getDescriptor)
2488 OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
2489 return CA_STATUS_FAILED;
2492 jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
2493 if (!jni_obj_cc_uuid)
2495 OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
2496 return CA_STATUS_FAILED;
2499 OIC_LOG(DEBUG, TAG, "request to get descriptor");
2500 jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
2501 jni_mid_getDescriptor, jni_obj_cc_uuid);
2502 if (!jni_obj_descriptor)
2504 OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
2505 return CA_NOT_SUPPORTED;
2508 OIC_LOG(DEBUG, TAG, "set value in descriptor");
2509 jclass jni_cid_descriptor = (*env)->FindClass(env,
2510 "android/bluetooth/BluetoothGattDescriptor");
2511 if (!jni_cid_descriptor)
2513 OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2514 return CA_STATUS_FAILED;
2517 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2518 if (!jni_mid_setValue)
2520 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2521 return CA_STATUS_FAILED;
2524 jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2525 "ENABLE_NOTIFICATION_VALUE", "[B");
2526 if (!jni_fid_NotiValue)
2528 OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2529 return CA_STATUS_FAILED;
2532 OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2534 jboolean jni_setvalue = (*env)->CallBooleanMethod(
2535 env, jni_obj_descriptor, jni_mid_setValue,
2536 (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2539 OIC_LOG(DEBUG, TAG, "setValue success");
2543 OIC_LOG(ERROR, TAG, "setValue has failed");
2544 return CA_STATUS_FAILED;
2547 jmethodID jni_mid_writeDescriptor = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt",
2549 "(Landroid/bluetooth/"
2550 "BluetoothGattDescriptor;)Z");
2551 if (!jni_mid_writeDescriptor)
2553 OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2554 return CA_STATUS_FAILED;
2557 OIC_LOG(INFO, TAG, "CALL API - writeDescriptor");
2558 jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2559 jni_obj_descriptor);
2562 OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2566 OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2567 return CA_STATUS_FAILED;
2570 return CA_STATUS_OK;
2573 void CALEClientCreateScanDeviceList(JNIEnv *env)
2575 OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2576 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2578 ca_mutex_lock(g_deviceListMutex);
2579 // create new object array
2580 if (g_deviceList == NULL)
2582 OIC_LOG(DEBUG, TAG, "Create device list");
2584 g_deviceList = u_arraylist_create();
2586 ca_mutex_unlock(g_deviceListMutex);
2589 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2591 VERIFY_NON_NULL(device, TAG, "device is null");
2592 VERIFY_NON_NULL(env, TAG, "env is null");
2594 ca_mutex_lock(g_deviceListMutex);
2598 OIC_LOG(ERROR, TAG, "gdevice_list is null");
2600 CALEClientSetScanFlag(false);
2601 if (CA_STATUS_OK != CALEClientStopScan())
2603 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
2606 ca_mutex_unlock(g_deviceListMutex);
2607 return CA_STATUS_FAILED;
2610 jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2611 if (!jni_remoteAddress)
2613 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2614 ca_mutex_unlock(g_deviceListMutex);
2615 return CA_STATUS_FAILED;
2618 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2621 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2622 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2623 ca_mutex_unlock(g_deviceListMutex);
2624 return CA_STATUS_FAILED;
2627 if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2629 jobject gdevice = (*env)->NewGlobalRef(env, device);
2630 u_arraylist_add(g_deviceList, gdevice);
2631 ca_cond_signal(g_deviceDescCond);
2632 OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress);
2634 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2635 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2637 ca_mutex_unlock(g_deviceListMutex);
2639 return CA_STATUS_OK;
2642 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2644 VERIFY_NON_NULL_RET(env, TAG, "env is null", true);
2645 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2649 OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2653 uint32_t length = u_arraylist_length(g_deviceList);
2654 for (uint32_t index = 0; index < length; index++)
2656 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2659 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2663 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2664 if (!jni_setAddress)
2666 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2670 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2673 OIC_LOG(ERROR, TAG, "setAddress is null");
2674 (*env)->DeleteLocalRef(env, jni_setAddress);
2678 if (!strcmp(remoteAddress, setAddress))
2680 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2681 (*env)->DeleteLocalRef(env, jni_setAddress);
2685 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2686 (*env)->DeleteLocalRef(env, jni_setAddress);
2689 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress);
2694 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2696 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2697 VERIFY_NON_NULL(env, TAG, "env is null");
2699 ca_mutex_lock(g_deviceListMutex);
2703 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2704 ca_mutex_unlock(g_deviceListMutex);
2705 return CA_STATUS_FAILED;
2708 uint32_t length = u_arraylist_length(g_deviceList);
2709 for (uint32_t index = 0; index < length; index++)
2711 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2714 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2717 (*env)->DeleteGlobalRef(env, jarrayObj);
2721 OICFree(g_deviceList);
2722 g_deviceList = NULL;
2724 ca_mutex_unlock(g_deviceListMutex);
2725 return CA_STATUS_OK;
2728 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2730 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2731 VERIFY_NON_NULL(address, TAG, "address is null");
2732 VERIFY_NON_NULL(env, TAG, "env is null");
2734 ca_mutex_lock(g_deviceListMutex);
2738 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2739 ca_mutex_unlock(g_deviceListMutex);
2740 return CA_STATUS_FAILED;
2743 uint32_t length = u_arraylist_length(g_deviceList);
2744 for (uint32_t index = 0; index < length; index++)
2746 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2749 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2750 ca_mutex_unlock(g_deviceListMutex);
2751 return CA_STATUS_FAILED;
2754 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2755 if (!jni_setAddress)
2757 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2758 ca_mutex_unlock(g_deviceListMutex);
2759 return CA_STATUS_FAILED;
2762 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2765 OIC_LOG(ERROR, TAG, "setAddress is null");
2766 ca_mutex_unlock(g_deviceListMutex);
2767 return CA_STATUS_FAILED;
2770 const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2773 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2774 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2775 ca_mutex_unlock(g_deviceListMutex);
2776 return CA_STATUS_FAILED;
2779 if (!strcmp(setAddress, remoteAddress))
2781 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2782 (*env)->DeleteGlobalRef(env, jarrayObj);
2784 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2785 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2787 if (NULL == u_arraylist_remove(g_deviceList, index))
2789 OIC_LOG(ERROR, TAG, "List removal failed.");
2790 ca_mutex_unlock(g_deviceListMutex);
2791 return CA_STATUS_FAILED;
2793 ca_mutex_unlock(g_deviceListMutex);
2794 return CA_STATUS_OK;
2796 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2797 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2800 ca_mutex_unlock(g_deviceListMutex);
2801 OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2803 return CA_STATUS_OK;
2810 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2812 OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2813 VERIFY_NON_NULL(env, TAG, "env is null");
2814 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2816 ca_mutex_lock(g_gattObjectMutex);
2818 if (!g_gattObjectList)
2820 OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
2821 ca_mutex_unlock(g_gattObjectMutex);
2822 return CA_STATUS_FAILED;
2825 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2826 if (!jni_remoteAddress)
2828 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2829 ca_mutex_unlock(g_gattObjectMutex);
2830 return CA_STATUS_FAILED;
2833 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2836 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2837 ca_mutex_unlock(g_gattObjectMutex);
2838 return CA_STATUS_FAILED;
2841 OIC_LOG_V(DEBUG, TAG, "remote address : %s", remoteAddress);
2842 if (!CALEClientIsGattObjInList(env, remoteAddress))
2844 jobject newGatt = (*env)->NewGlobalRef(env, gatt);
2845 u_arraylist_add(g_gattObjectList, newGatt);
2846 OIC_LOG(INFO, TAG, "added a newGatt object to gattObjectList");
2849 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2850 ca_mutex_unlock(g_gattObjectMutex);
2851 return CA_STATUS_OK;
2854 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
2856 OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
2857 VERIFY_NON_NULL(env, TAG, "env is null");
2858 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2860 uint32_t length = u_arraylist_length(g_gattObjectList);
2861 for (uint32_t index = 0; index < length; index++)
2864 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2867 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2871 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2872 if (!jni_setAddress)
2874 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2878 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2881 OIC_LOG(ERROR, TAG, "setAddress is null");
2885 if (!strcmp(remoteAddress, setAddress))
2887 OIC_LOG(DEBUG, TAG, "the device is already set");
2888 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2893 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2898 OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
2902 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
2904 OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
2905 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2906 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2908 ca_mutex_lock(g_gattObjectMutex);
2909 uint32_t length = u_arraylist_length(g_gattObjectList);
2910 for (uint32_t index = 0; index < length; index++)
2912 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2915 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2916 ca_mutex_unlock(g_gattObjectMutex);
2920 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2921 if (!jni_setAddress)
2923 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2924 ca_mutex_unlock(g_gattObjectMutex);
2928 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2931 OIC_LOG(ERROR, TAG, "setAddress is null");
2932 ca_mutex_unlock(g_gattObjectMutex);
2936 if (!strcmp(remoteAddress, setAddress))
2938 OIC_LOG(DEBUG, TAG, "the device is already set");
2939 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2940 ca_mutex_unlock(g_gattObjectMutex);
2943 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2946 ca_mutex_unlock(g_gattObjectMutex);
2947 OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
2951 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
2953 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
2954 VERIFY_NON_NULL(env, TAG, "env is null");
2956 ca_mutex_lock(g_gattObjectMutex);
2957 if (!g_gattObjectList)
2959 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2960 ca_mutex_unlock(g_gattObjectMutex);
2961 return CA_STATUS_OK;
2964 uint32_t length = u_arraylist_length(g_gattObjectList);
2965 for (uint32_t index = 0; index < length; index++)
2967 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2970 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2973 (*env)->DeleteGlobalRef(env, jarrayObj);
2977 OICFree(g_gattObjectList);
2978 g_gattObjectList = NULL;
2979 OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
2980 ca_mutex_unlock(g_gattObjectMutex);
2981 return CA_STATUS_OK;
2984 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
2986 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
2987 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2988 VERIFY_NON_NULL(env, TAG, "env is null");
2990 ca_mutex_lock(g_gattObjectMutex);
2991 if (!g_gattObjectList)
2993 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2994 ca_mutex_unlock(g_gattObjectMutex);
2995 return CA_STATUS_OK;
2998 uint32_t length = u_arraylist_length(g_gattObjectList);
2999 for (uint32_t index = 0; index < length; index++)
3001 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3004 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3005 ca_mutex_unlock(g_gattObjectMutex);
3006 return CA_STATUS_FAILED;
3009 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3010 if (!jni_setAddress)
3012 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3013 ca_mutex_unlock(g_gattObjectMutex);
3014 return CA_STATUS_FAILED;
3017 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3020 OIC_LOG(ERROR, TAG, "setAddress is null");
3021 ca_mutex_unlock(g_gattObjectMutex);
3022 return CA_STATUS_FAILED;
3025 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3026 if (!jni_remoteAddress)
3028 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3029 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3030 ca_mutex_unlock(g_gattObjectMutex);
3031 return CA_STATUS_FAILED;
3034 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3037 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3038 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3039 ca_mutex_unlock(g_gattObjectMutex);
3040 return CA_STATUS_FAILED;
3043 if (!strcmp(setAddress, remoteAddress))
3045 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3046 (*env)->DeleteGlobalRef(env, jarrayObj);
3048 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3049 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3051 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3053 OIC_LOG(ERROR, TAG, "List removal failed.");
3054 ca_mutex_unlock(g_gattObjectMutex);
3055 return CA_STATUS_FAILED;
3057 ca_mutex_unlock(g_gattObjectMutex);
3058 return CA_STATUS_OK;
3060 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3061 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3064 ca_mutex_unlock(g_gattObjectMutex);
3065 OIC_LOG(DEBUG, TAG, "there are no target object");
3066 return CA_STATUS_OK;
3069 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
3071 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
3072 VERIFY_NON_NULL(addr, TAG, "addr is null");
3073 VERIFY_NON_NULL(env, TAG, "env is null");
3075 ca_mutex_lock(g_gattObjectMutex);
3076 if (!g_gattObjectList)
3078 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3079 ca_mutex_unlock(g_gattObjectMutex);
3080 return CA_STATUS_OK;
3083 uint32_t length = u_arraylist_length(g_gattObjectList);
3084 for (uint32_t index = 0; index < length; index++)
3086 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3089 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3090 ca_mutex_unlock(g_gattObjectMutex);
3091 return CA_STATUS_FAILED;
3094 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3095 if (!jni_setAddress)
3097 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3098 ca_mutex_unlock(g_gattObjectMutex);
3099 return CA_STATUS_FAILED;
3102 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3105 OIC_LOG(ERROR, TAG, "setAddress is null");
3106 ca_mutex_unlock(g_gattObjectMutex);
3107 return CA_STATUS_FAILED;
3110 const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
3113 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3114 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3115 ca_mutex_unlock(g_gattObjectMutex);
3116 return CA_STATUS_FAILED;
3119 if (!strcmp(setAddress, remoteAddress))
3121 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3122 (*env)->DeleteGlobalRef(env, jarrayObj);
3124 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3125 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3126 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3128 OIC_LOG(ERROR, TAG, "List removal failed.");
3129 ca_mutex_unlock(g_gattObjectMutex);
3130 return CA_STATUS_FAILED;
3132 ca_mutex_unlock(g_gattObjectMutex);
3133 return CA_STATUS_OK;
3135 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3136 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3139 ca_mutex_unlock(g_gattObjectMutex);
3140 OIC_LOG(DEBUG, TAG, "there are no target object");
3141 return CA_STATUS_FAILED;
3144 jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
3146 OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice");
3148 VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
3149 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
3151 // get Bluetooth Address
3152 jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
3153 if (!jni_btTargetAddress)
3155 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3159 const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
3162 OIC_LOG(ERROR, TAG, "targetAddress is not available");
3166 // get method ID of getDevice()
3167 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3168 "getDevice", METHODID_BT_DEVICE);
3169 if (!jni_mid_getDevice)
3171 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
3172 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3176 ca_mutex_lock(g_gattObjectMutex);
3178 size_t length = u_arraylist_length(g_gattObjectList);
3179 OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length);
3180 OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
3182 for (size_t index = 0; index < length; index++)
3184 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3187 ca_mutex_unlock(g_gattObjectMutex);
3188 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3189 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3193 jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
3194 if (!jni_obj_device)
3196 ca_mutex_unlock(g_gattObjectMutex);
3197 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
3198 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3202 jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
3205 ca_mutex_unlock(g_gattObjectMutex);
3206 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3207 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3211 const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
3214 ca_mutex_unlock(g_gattObjectMutex);
3215 OIC_LOG(ERROR, TAG, "btAddress is not available");
3216 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3220 OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index);
3221 if (!strcmp(targetAddress, btAddress))
3223 OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
3226 jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3229 OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
3231 ca_mutex_unlock(g_gattObjectMutex);
3232 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3233 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3234 (*env)->DeleteLocalRef(env, jni_btAddress);
3235 (*env)->DeleteLocalRef(env, jni_obj_device);
3236 return jni_LEAddress;
3238 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3239 (*env)->DeleteLocalRef(env, jni_btAddress);
3240 (*env)->DeleteLocalRef(env, jni_obj_device);
3242 ca_mutex_unlock(g_gattObjectMutex);
3244 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3245 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress);
3253 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
3254 uint16_t target_state)
3256 VERIFY_NON_NULL(address, TAG, "address is null");
3257 VERIFY_NON_NULL(address, TAG, "state_type is null");
3258 VERIFY_NON_NULL(address, TAG, "target_state is null");
3260 if (!g_deviceStateList)
3262 OIC_LOG(ERROR, TAG, "gdevice_list is null");
3263 return CA_STATUS_FAILED;
3266 ca_mutex_lock(g_deviceStateListMutex);
3268 if (CALEClientIsDeviceInList(address))
3270 CALEState_t* curState = CALEClientGetStateInfo(address);
3273 OIC_LOG(ERROR, TAG, "curState is null");
3274 ca_mutex_unlock(g_deviceStateListMutex);
3275 return CA_STATUS_FAILED;
3280 case CA_LE_CONNECTION_STATE:
3281 curState->connectedState = target_state;
3283 case CA_LE_SEND_STATE:
3284 curState->sendState = target_state;
3289 OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
3290 curState->address, curState->connectedState, curState->sendState,
3291 curState->autoConnectFlag);
3293 else /** state is added newly **/
3295 if (strlen(address) > CA_MACADDR_SIZE)
3297 OIC_LOG(ERROR, TAG, "address is not proper");
3298 ca_mutex_unlock(g_deviceStateListMutex);
3299 return CA_STATUS_INVALID_PARAM;
3302 CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
3305 OIC_LOG(ERROR, TAG, "out of memory");
3306 ca_mutex_unlock(g_deviceStateListMutex);
3307 return CA_MEMORY_ALLOC_FAILED;
3310 OICStrcpy(newstate->address, sizeof(newstate->address), address);
3314 case CA_LE_CONNECTION_STATE:
3315 newstate->connectedState = target_state;
3316 newstate->sendState = STATE_SEND_NONE;
3318 case CA_LE_SEND_STATE:
3319 newstate->connectedState = STATE_DISCONNECTED;
3320 newstate->sendState = target_state;
3325 OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, "
3326 "conn : %d, send : %d, ACFlag : %d",
3327 newstate->address, newstate->connectedState, newstate->sendState,
3328 newstate->autoConnectFlag);
3329 u_arraylist_add(g_deviceStateList, newstate); // update new state
3332 ca_mutex_unlock(g_deviceStateListMutex);
3334 return CA_STATUS_OK;
3337 bool CALEClientIsDeviceInList(const char* remoteAddress)
3339 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3341 if (!g_deviceStateList)
3343 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3347 uint32_t length = u_arraylist_length(g_deviceStateList);
3348 for (uint32_t index = 0; index < length; index++)
3350 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3353 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3357 if (!strcmp(remoteAddress, state->address))
3359 OIC_LOG(DEBUG, TAG, "the device is already set");
3368 OIC_LOG(DEBUG, TAG, "there are no the device in list.");
3372 CAResult_t CALEClientRemoveAllDeviceState()
3374 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
3376 ca_mutex_lock(g_deviceStateListMutex);
3377 if (!g_deviceStateList)
3379 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3380 ca_mutex_unlock(g_deviceStateListMutex);
3381 return CA_STATUS_FAILED;
3384 uint32_t length = u_arraylist_length(g_deviceStateList);
3385 for (uint32_t index = 0; index < length; index++)
3387 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3390 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3396 OICFree(g_deviceStateList);
3397 g_deviceStateList = NULL;
3398 ca_mutex_unlock(g_deviceStateListMutex);
3400 return CA_STATUS_OK;
3403 CAResult_t CALEClientResetDeviceStateForAll()
3405 OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll");
3407 ca_mutex_lock(g_deviceStateListMutex);
3408 if (!g_deviceStateList)
3410 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3411 ca_mutex_unlock(g_deviceStateListMutex);
3412 return CA_STATUS_FAILED;
3415 size_t length = u_arraylist_length(g_deviceStateList);
3416 for (size_t index = 0; index < length; index++)
3418 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3421 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3425 // autoConnectFlag value will be not changed,
3426 // since it has reset only termination case.
3427 state->connectedState = STATE_DISCONNECTED;
3428 state->sendState = STATE_SEND_NONE;
3430 ca_mutex_unlock(g_deviceStateListMutex);
3432 return CA_STATUS_OK;
3435 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
3437 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
3438 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3440 if (!g_deviceStateList)
3442 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3443 return CA_STATUS_FAILED;
3446 uint32_t length = u_arraylist_length(g_deviceStateList);
3447 for (uint32_t index = 0; index < length; index++)
3449 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3452 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3456 if (!strcmp(state->address, remoteAddress))
3458 OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
3460 CALEState_t* targetState = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
3462 if (NULL == targetState)
3464 OIC_LOG(ERROR, TAG, "List removal failed.");
3465 return CA_STATUS_FAILED;
3468 OICFree(targetState);
3469 return CA_STATUS_OK;
3473 return CA_STATUS_OK;
3476 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
3478 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3480 if (!g_deviceStateList)
3482 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3486 uint32_t length = u_arraylist_length(g_deviceStateList);
3487 OIC_LOG_V(DEBUG, TAG, "length of deviceStateList : %d", length);
3488 OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
3490 for (uint32_t index = 0; index < length; index++)
3492 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3495 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3499 OIC_LOG_V(DEBUG, TAG, "state address : %s (idx: %d)", state->address, index);
3501 if (!strcmp(state->address, remoteAddress))
3503 OIC_LOG(DEBUG, TAG, "found state");
3508 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in deviceStateList", remoteAddress);
3512 bool CALEClientIsValidState(const char* remoteAddress, uint16_t state_type,
3513 uint16_t target_state)
3515 OIC_LOG_V(DEBUG, TAG, "CALEClientIsValidState : type[%d], target state[%d]",
3516 state_type, target_state);
3517 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3519 ca_mutex_lock(g_deviceStateListMutex);
3520 if (!g_deviceStateList)
3522 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3523 ca_mutex_unlock(g_deviceStateListMutex);
3527 CALEState_t* state = CALEClientGetStateInfo(remoteAddress);
3530 OIC_LOG(ERROR, TAG, "state is null");
3531 ca_mutex_unlock(g_deviceStateListMutex);
3535 uint16_t curValue = 0;
3538 case CA_LE_CONNECTION_STATE:
3539 curValue = state->connectedState;
3541 case CA_LE_SEND_STATE:
3542 curValue = state->sendState;
3548 if (target_state == curValue)
3550 ca_mutex_unlock(g_deviceStateListMutex);
3555 ca_mutex_unlock(g_deviceStateListMutex);
3559 ca_mutex_unlock(g_deviceStateListMutex);
3563 void CALEClientCreateDeviceList()
3565 OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
3567 // create new object array
3568 if (!g_gattObjectList)
3570 OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
3572 g_gattObjectList = u_arraylist_create();
3575 if (!g_deviceStateList)
3577 OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
3579 g_deviceStateList = u_arraylist_create();
3584 OIC_LOG(DEBUG, TAG, "Create g_deviceList");
3586 g_deviceList = u_arraylist_create();
3591 * Check Sent Count for remove g_sendBuffer
3593 void CALEClientUpdateSendCnt(JNIEnv *env)
3595 OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
3597 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3599 ca_mutex_lock(g_threadMutex);
3603 if (g_targetCnt <= g_currentSentCnt)
3606 g_currentSentCnt = 0;
3610 (*env)->DeleteGlobalRef(env, g_sendBuffer);
3611 g_sendBuffer = NULL;
3613 // notity the thread
3614 ca_cond_signal(g_threadCond);
3616 CALEClientSetSendFinishFlag(true);
3617 OIC_LOG(DEBUG, TAG, "set signal for send data");
3620 ca_mutex_unlock(g_threadMutex);
3623 CAResult_t CALEClientInitGattMutexVaraibles()
3625 if (NULL == g_bleReqRespClientCbMutex)
3627 g_bleReqRespClientCbMutex = ca_mutex_new();
3628 if (NULL == g_bleReqRespClientCbMutex)
3630 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3631 return CA_STATUS_FAILED;
3635 if (NULL == g_bleServerBDAddressMutex)
3637 g_bleServerBDAddressMutex = ca_mutex_new();
3638 if (NULL == g_bleServerBDAddressMutex)
3640 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3641 return CA_STATUS_FAILED;
3645 if (NULL == g_threadMutex)
3647 g_threadMutex = ca_mutex_new();
3648 if (NULL == g_threadMutex)
3650 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3651 return CA_STATUS_FAILED;
3655 if (NULL == g_threadSendMutex)
3657 g_threadSendMutex = ca_mutex_new();
3658 if (NULL == g_threadSendMutex)
3660 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3661 return CA_STATUS_FAILED;
3665 if (NULL == g_deviceListMutex)
3667 g_deviceListMutex = ca_mutex_new();
3668 if (NULL == g_deviceListMutex)
3670 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3671 return CA_STATUS_FAILED;
3675 if (NULL == g_gattObjectMutex)
3677 g_gattObjectMutex = ca_mutex_new();
3678 if (NULL == g_gattObjectMutex)
3680 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3681 return CA_STATUS_FAILED;
3685 if (NULL == g_deviceStateListMutex)
3687 g_deviceStateListMutex = ca_mutex_new();
3688 if (NULL == g_deviceStateListMutex)
3690 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3691 return CA_STATUS_FAILED;
3695 if (NULL == g_SendFinishMutex)
3697 g_SendFinishMutex = ca_mutex_new();
3698 if (NULL == g_SendFinishMutex)
3700 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3701 return CA_STATUS_FAILED;
3705 if (NULL == g_scanMutex)
3707 g_scanMutex = ca_mutex_new();
3708 if (NULL == g_scanMutex)
3710 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3711 return CA_STATUS_FAILED;
3715 if (NULL == g_threadWriteCharacteristicMutex)
3717 g_threadWriteCharacteristicMutex = ca_mutex_new();
3718 if (NULL == g_threadWriteCharacteristicMutex)
3720 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3721 return CA_STATUS_FAILED;
3725 if (NULL == g_deviceScanRetryDelayMutex)
3727 g_deviceScanRetryDelayMutex = ca_mutex_new();
3728 if (NULL == g_deviceScanRetryDelayMutex)
3730 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3731 return CA_STATUS_FAILED;
3735 if (NULL == g_threadSendStateMutex)
3737 g_threadSendStateMutex = ca_mutex_new();
3738 if (NULL == g_threadSendStateMutex)
3740 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3741 return CA_STATUS_FAILED;
3745 return CA_STATUS_OK;
3748 void CALEClientTerminateGattMutexVariables()
3750 ca_mutex_free(g_bleReqRespClientCbMutex);
3751 g_bleReqRespClientCbMutex = NULL;
3753 ca_mutex_free(g_bleServerBDAddressMutex);
3754 g_bleServerBDAddressMutex = NULL;
3756 ca_mutex_free(g_threadMutex);
3757 g_threadMutex = NULL;
3759 ca_mutex_free(g_threadSendMutex);
3760 g_threadSendMutex = NULL;
3762 ca_mutex_free(g_deviceListMutex);
3763 g_deviceListMutex = NULL;
3765 ca_mutex_free(g_SendFinishMutex);
3766 g_SendFinishMutex = NULL;
3768 ca_mutex_free(g_scanMutex);
3771 ca_mutex_free(g_threadWriteCharacteristicMutex);
3772 g_threadWriteCharacteristicMutex = NULL;
3774 ca_mutex_free(g_deviceScanRetryDelayMutex);
3775 g_deviceScanRetryDelayMutex = NULL;
3777 ca_mutex_free(g_threadSendStateMutex);
3778 g_threadSendStateMutex = NULL;
3781 void CALEClientSetSendFinishFlag(bool flag)
3783 OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3785 ca_mutex_lock(g_SendFinishMutex);
3786 g_isFinishedSendData = flag;
3787 ca_mutex_unlock(g_SendFinishMutex);
3794 CAResult_t CAStartLEGattClient()
3796 // init mutex for send logic
3797 if (!g_deviceDescCond)
3799 g_deviceDescCond = ca_cond_new();
3804 g_threadCond = ca_cond_new();
3807 if (!g_threadWriteCharacteristicCond)
3809 g_threadWriteCharacteristicCond = ca_cond_new();
3812 CAResult_t ret = CALEClientStartScan();
3813 if (CA_STATUS_OK != ret)
3815 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
3819 g_isStartedLEClient = true;
3820 return CA_STATUS_OK;
3823 void CAStopLEGattClient()
3825 OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
3829 OIC_LOG(ERROR, TAG, "g_jvm is null");
3833 bool isAttached = false;
3835 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
3838 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
3839 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
3843 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
3849 CAResult_t ret = CALEClientDisconnectAll(env);
3850 if (CA_STATUS_OK != ret)
3852 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
3855 ret = CALEClientStopScan();
3856 if(CA_STATUS_OK != ret)
3858 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
3861 ca_mutex_lock(g_threadMutex);
3862 OIC_LOG(DEBUG, TAG, "signal - connection cond");
3863 ca_cond_signal(g_threadCond);
3864 CALEClientSetSendFinishFlag(true);
3865 ca_mutex_unlock(g_threadMutex);
3867 ca_mutex_lock(g_threadWriteCharacteristicMutex);
3868 OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
3869 ca_cond_signal(g_threadWriteCharacteristicCond);
3870 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
3872 ca_mutex_lock(g_deviceScanRetryDelayMutex);
3873 OIC_LOG(DEBUG, TAG, "signal - delay cond");
3874 ca_cond_signal(g_deviceScanRetryDelayCond);
3875 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
3877 ca_cond_free(g_deviceDescCond);
3878 ca_cond_free(g_threadCond);
3879 ca_cond_free(g_threadWriteCharacteristicCond);
3880 ca_cond_free(g_deviceScanRetryDelayCond);
3882 g_deviceDescCond = NULL;
3883 g_threadCond = NULL;
3884 g_threadWriteCharacteristicCond = NULL;
3885 g_deviceScanRetryDelayCond = NULL;
3889 (*g_jvm)->DetachCurrentThread(g_jvm);
3894 CAResult_t CAInitializeLEGattClient()
3896 OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
3897 CALEClientInitialize();
3898 return CA_STATUS_OK;
3901 void CATerminateLEGattClient()
3903 OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
3904 CAStopLEGattClient();
3905 CALEClientTerminate();
3908 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t *data,
3909 uint32_t dataLen, CALETransferType_t type,
3912 OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
3913 VERIFY_NON_NULL(data, TAG, "data is null");
3914 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3916 if (LE_UNICAST != type || position < 0)
3918 OIC_LOG(ERROR, TAG, "this request is not unicast");
3919 return CA_STATUS_INVALID_PARAM;
3922 return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
3925 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
3927 OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
3928 VERIFY_NON_NULL(data, TAG, "data is null");
3930 return CALEClientSendMulticastMessage(data, dataLen);
3933 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
3935 ca_mutex_lock(g_bleReqRespClientCbMutex);
3936 g_CABLEClientDataReceivedCallback = callback;
3937 ca_mutex_unlock(g_bleReqRespClientCbMutex);
3940 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
3942 g_threadPoolHandle = handle;
3945 CAResult_t CAGetLEAddress(char **local_address)
3947 VERIFY_NON_NULL(local_address, TAG, "local_address");
3948 OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
3949 return CA_NOT_SUPPORTED;
3952 JNIEXPORT void JNICALL
3953 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
3956 OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
3957 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3958 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3959 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3961 g_leScanCallback = (*env)->NewGlobalRef(env, callback);
3964 JNIEXPORT void JNICALL
3965 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
3968 OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
3969 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3970 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3971 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3973 g_leGattCallback = (*env)->NewGlobalRef(env, callback);
3976 JNIEXPORT void JNICALL
3977 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
3980 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3981 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3982 VERIFY_NON_NULL_VOID(device, TAG, "device is null");
3984 CAResult_t res = CALEClientAddScanDeviceToList(env, device);
3985 if (CA_STATUS_OK != res)
3987 OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
3991 static jstring CALEClientGetAddressFromGatt(JNIEnv *env, jobject gatt)
3993 OIC_LOG(DEBUG, TAG, "IN - CAManagerGetAddressFromGatt");
3995 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
3996 VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
3998 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3999 "getDevice", METHODID_BT_DEVICE);
4000 if (!jni_mid_getDevice)
4002 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
4006 jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
4007 if (!jni_obj_device)
4009 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
4013 jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
4016 OIC_LOG(ERROR, TAG, "jni_address is null");
4020 OIC_LOG(DEBUG, TAG, "OUT - CAManagerGetAddressFromGatt");
4025 * Class: org_iotivity_ca_jar_caleinterface
4026 * Method: CALeGattConnectionStateChangeCallback
4027 * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
4029 JNIEXPORT void JNICALL
4030 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
4036 OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
4038 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4039 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4040 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4042 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
4044 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4047 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
4051 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4054 OIC_LOG(ERROR, TAG, "address is null");
4057 OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
4060 if (state_connected == newstate)
4062 OIC_LOG(DEBUG, TAG, "LE is connected");
4063 if (GATT_SUCCESS == status)
4065 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, STATE_CONNECTED);
4066 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4067 if (CA_STATUS_OK != res)
4069 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4073 res = CALEClientAddGattobjToList(env, gatt);
4074 if (CA_STATUS_OK != res)
4076 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
4080 res = CALEClientDiscoverServices(env, gatt);
4081 if (CA_STATUS_OK != res)
4083 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
4089 OIC_LOG(INFO, TAG, "unknown status");
4090 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4093 else // STATE_DISCONNECTED == newstate
4095 OIC_LOG(DEBUG, TAG, "LE is disconnected");
4097 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, STATE_DISCONNECTED);
4098 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4099 if (CA_STATUS_OK != res)
4101 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4105 res = CALEClientGattClose(env, gatt);
4106 if (CA_STATUS_OK != res)
4108 OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
4111 if (GATT_ERROR == status)
4113 // when we get GATT ERROR(0x85), gatt connection can be called again.
4114 OIC_LOG(INFO, TAG, "retry gatt connect");
4116 jstring leAddress = CALEClientGetAddressFromGatt(env, gatt);
4119 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGatt has failed");
4123 jobject btObject = CALEGetRemoteDevice(env, leAddress);
4126 OIC_LOG(ERROR, TAG, "CALEGetRemoteDevice has failed");
4130 jobject newGatt = CALEClientConnect(env, btObject, JNI_TRUE);
4133 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
4141 if (CALECheckConnectionStateValue(status))
4143 // this state is unexpected reason to disconnect
4144 // if the reason is suitable, connection logic of the device will be destroyed.
4145 OIC_LOG(INFO, TAG, "connection logic destroy");
4150 // other reason except for gatt_success is expected to running
4151 // background connection in BT platform.
4152 OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
4153 CALEClientUpdateSendCnt(env);
4160 (*env)->DeleteGlobalRef(env, g_sendBuffer);
4161 g_sendBuffer = NULL;
4168 CALEClientSendFinish(env, gatt);
4173 * Class: org_iotivity_ca_jar_caleinterface
4174 * Method: CALeGattServicesDiscoveredCallback
4175 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
4177 JNIEXPORT void JNICALL
4178 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
4183 OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d", status);
4184 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4185 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4186 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4188 if (GATT_SUCCESS != status) // discovery error
4190 CALEClientSendFinish(env, gatt);
4194 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4197 CALEClientSendFinish(env, gatt);
4201 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4204 CALEClientSendFinish(env, gatt);
4208 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
4211 OIC_LOG(ERROR, TAG, "jni_uuid is null");
4215 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
4216 if (!jni_obj_GattCharacteristic)
4218 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
4222 CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
4223 jni_obj_GattCharacteristic);
4224 if (CA_STATUS_OK != res)
4226 OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
4230 res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
4231 if (CA_STATUS_OK != res)
4233 OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
4235 res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_FALSE);
4236 if (CA_STATUS_OK != res)
4238 OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4242 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4243 STATE_SERVICE_CONNECTED);
4244 if (CA_STATUS_OK != res)
4246 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4252 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4253 if (CA_STATUS_OK != res)
4255 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4262 res = CALEClientSetFlagToState(env, jni_address, CA_LE_DESCRIPTOR_FOUND, JNI_TRUE);
4263 if (CA_STATUS_OK != res)
4265 OIC_LOG(ERROR, TAG, "CALEClientSetFlagToState has failed");
4270 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
4271 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4276 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
4277 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4278 CALEClientSendFinish(env, gatt);
4283 * Class: org_iotivity_ca_jar_caleinterface
4284 * Method: CALeGattCharacteristicWritjclasseCallback
4285 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
4287 JNIEXPORT void JNICALL
4288 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
4289 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
4291 OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
4292 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4293 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4294 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4296 // send success & signal
4297 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4303 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4309 if (GATT_SUCCESS != status) // error case
4311 OIC_LOG(ERROR, TAG, "send failure");
4314 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4315 if (CA_STATUS_OK != res)
4317 OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
4318 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4319 g_isSignalSetFlag = true;
4320 ca_cond_signal(g_threadWriteCharacteristicCond);
4321 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4323 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4325 if (CA_STATUS_OK != res)
4327 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4330 if (g_clientErrorCallback)
4332 jint length = (*env)->GetArrayLength(env, data);
4333 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
4336 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4342 OIC_LOG(DEBUG, TAG, "send success");
4343 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4344 STATE_SEND_SUCCESS);
4345 if (CA_STATUS_OK != res)
4347 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4350 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4351 OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
4352 g_isSignalSetFlag = true;
4353 ca_cond_signal(g_threadWriteCharacteristicCond);
4354 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4356 CALEClientUpdateSendCnt(env);
4359 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4365 CALEClientSendFinish(env, gatt);
4370 * Class: org_iotivity_ca_jar_caleinterface
4371 * Method: CALeGattCharacteristicChangedCallback
4372 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
4374 JNIEXPORT void JNICALL
4375 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
4376 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
4378 OIC_LOG(INFO, TAG, "CALeGattCharacteristicChangedCallback");
4379 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4380 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4381 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4382 VERIFY_NON_NULL_VOID(data, TAG, "data is null");
4384 // get Byte Array and convert to uint8_t*
4385 jint length = (*env)->GetArrayLength(env, data);
4388 jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
4390 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
4391 jni_byte_responseData);
4393 uint8_t* receivedData = OICMalloc(length);
4396 OIC_LOG(ERROR, TAG, "receivedData is null");
4400 memcpy(receivedData, jni_byte_responseData, length);
4401 (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
4403 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4406 OIC_LOG(ERROR, TAG, "jni_address is null");
4407 OICFree(receivedData);
4411 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4414 OIC_LOG(ERROR, TAG, "address is null");
4415 OICFree(receivedData);
4419 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
4420 receivedData, length);
4422 uint32_t sentLength = 0;
4423 ca_mutex_lock(g_bleServerBDAddressMutex);
4424 g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
4425 ca_mutex_unlock(g_bleServerBDAddressMutex);
4427 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4431 * Class: org_iotivity_ca_jar_caleinterface
4432 * Method: CALeGattDescriptorWriteCallback
4433 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
4435 JNIEXPORT void JNICALL
4436 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
4440 OIC_LOG_V(INFO, TAG, "CALeGattDescriptorWriteCallback - status %d", status);
4441 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4442 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4443 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4445 if (GATT_SUCCESS != status) // error
4450 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4456 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4462 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4463 STATE_SERVICE_CONNECTED);
4464 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4465 if (CA_STATUS_OK != res)
4467 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4473 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4474 if (CA_STATUS_OK != res)
4476 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4485 CALEClientSendFinish(env, gatt);