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));
1066 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1067 return CA_STATUS_FAILED;
1072 return CA_STATUS_OK;
1075 jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
1077 VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
1078 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1080 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
1081 "()Landroid/bluetooth/BluetoothDevice;");
1082 if (!jni_mid_getDevice)
1084 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
1088 jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
1089 if (!jni_obj_device)
1091 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
1095 jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
1098 OIC_LOG(ERROR, TAG, "jni_address is null");
1108 CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
1111 OIC_LOG(DEBUG, TAG, "Gatt Close");
1112 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1113 VERIFY_NON_NULL(env, TAG, "env is null");
1115 // get BluetoothGatt method
1116 OIC_LOG(DEBUG, TAG, "get BluetoothGatt method");
1117 jmethodID jni_mid_closeGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "close", "()V");
1118 if (!jni_mid_closeGatt)
1120 OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1121 return CA_STATUS_OK;
1124 // call disconnect gatt method
1125 OIC_LOG(DEBUG, TAG, "request to close GATT");
1126 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
1128 if ((*env)->ExceptionCheck(env))
1130 OIC_LOG(ERROR, TAG, "closeGATT has failed");
1131 (*env)->ExceptionDescribe(env);
1132 (*env)->ExceptionClear(env);
1133 return CA_STATUS_FAILED;
1136 return CA_STATUS_OK;
1139 CAResult_t CALEClientStartScan()
1141 if (!g_isStartedLEClient)
1143 OIC_LOG(ERROR, TAG, "LE client is not started");
1144 return CA_STATUS_FAILED;
1149 OIC_LOG(ERROR, TAG, "g_jvm is null");
1150 return CA_STATUS_FAILED;
1153 if (g_isStartedScan)
1155 OIC_LOG(INFO, TAG, "scanning is already started");
1156 return CA_STATUS_OK;
1159 bool isAttached = false;
1161 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1164 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1166 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1169 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1170 return CA_STATUS_FAILED;
1175 OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1177 CAResult_t ret = CA_STATUS_OK;
1178 // scan gatt server with UUID
1179 if (g_leScanCallback && g_uuidList)
1182 ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
1184 ret = CALEClientStartScanImpl(env, g_leScanCallback);
1186 if (CA_STATUS_OK != ret)
1188 if (CA_ADAPTER_NOT_ENABLED == ret)
1190 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1194 OIC_LOG(ERROR, TAG, "start scan has failed");
1201 (*g_jvm)->DetachCurrentThread(g_jvm);
1207 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
1209 VERIFY_NON_NULL(callback, TAG, "callback is null");
1210 VERIFY_NON_NULL(env, TAG, "env is null");
1212 if (!CALEIsEnableBTAdapter(env))
1214 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1215 return CA_ADAPTER_NOT_ENABLED;
1218 // get default bt adapter class
1219 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1220 if (!jni_cid_BTAdapter)
1222 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1223 return CA_STATUS_FAILED;
1226 // get remote bt adapter method
1227 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1228 "getDefaultAdapter",
1229 METHODID_OBJECTNONPARAM);
1230 if (!jni_mid_getDefaultAdapter)
1232 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1233 return CA_STATUS_FAILED;
1236 // get start le scan method
1237 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1238 "(Landroid/bluetooth/BluetoothAdapter$"
1239 "LeScanCallback;)Z");
1240 if (!jni_mid_startLeScan)
1242 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1243 return CA_STATUS_FAILED;
1246 // gat bt adapter object
1247 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1248 jni_mid_getDefaultAdapter);
1249 if (!jni_obj_BTAdapter)
1251 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1252 return CA_STATUS_FAILED;
1255 // call start le scan method
1256 OIC_LOG(INFO, TAG, "CALL API - startLeScan");
1257 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1258 jni_mid_startLeScan, callback);
1259 if (!jni_obj_startLeScan)
1261 OIC_LOG(INFO, TAG, "startLeScan has failed");
1265 OIC_LOG(DEBUG, TAG, "LeScan has started");
1266 CALEClientSetScanFlag(true);
1269 return CA_STATUS_OK;
1272 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
1274 VERIFY_NON_NULL(callback, TAG, "callback is null");
1275 VERIFY_NON_NULL(uuids, TAG, "uuids is null");
1276 VERIFY_NON_NULL(env, TAG, "env is null");
1278 if (!CALEIsEnableBTAdapter(env))
1280 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1281 return CA_ADAPTER_NOT_ENABLED;
1284 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1285 if (!jni_cid_BTAdapter)
1287 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1288 return CA_STATUS_FAILED;
1291 // get remote bt adapter method
1292 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1293 "getDefaultAdapter",
1294 METHODID_OBJECTNONPARAM);
1295 if (!jni_mid_getDefaultAdapter)
1297 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1298 return CA_STATUS_FAILED;
1301 // get start le scan method
1302 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1303 "([Ljava/util/UUID;Landroid/bluetooth/"
1304 "BluetoothAdapter$LeScanCallback;)Z");
1305 if (!jni_mid_startLeScan)
1307 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1308 return CA_STATUS_FAILED;
1311 // get bt adapter object
1312 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1313 jni_mid_getDefaultAdapter);
1314 if (!jni_obj_BTAdapter)
1316 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1317 return CA_STATUS_FAILED;
1320 // call start le scan method
1321 OIC_LOG(INFO, TAG, "CALL API - startLeScan (with UUID)");
1322 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1323 jni_mid_startLeScan, uuids, callback);
1324 if (!jni_obj_startLeScan)
1326 OIC_LOG(INFO, TAG, "startLeScan has failed");
1330 OIC_LOG(DEBUG, TAG, "LeScan has started");
1331 CALEClientSetScanFlag(true);
1334 return CA_STATUS_OK;
1337 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
1339 VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
1340 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1343 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1346 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1350 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString",
1351 "(Ljava/lang/String;)"
1352 "Ljava/util/UUID;");
1353 if (!jni_mid_fromString)
1355 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1359 jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1360 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1364 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1368 return jni_obj_uuid;
1371 CAResult_t CALEClientStopScan()
1375 OIC_LOG(ERROR, TAG, "g_jvm is null");
1376 return CA_STATUS_FAILED;
1379 if (!g_isStartedScan)
1381 OIC_LOG(INFO, TAG, "scanning is already stopped");
1382 return CA_STATUS_OK;
1385 bool isAttached = false;
1387 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1390 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1391 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1394 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1395 return CA_STATUS_FAILED;
1400 CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
1401 if (CA_STATUS_OK != ret)
1403 if (CA_ADAPTER_NOT_ENABLED == ret)
1405 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1409 OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1414 CALEClientSetScanFlag(false);
1419 (*g_jvm)->DetachCurrentThread(g_jvm);
1425 void CALEClientSetScanFlag(bool flag)
1427 ca_mutex_lock(g_scanMutex);
1428 g_isStartedScan = flag;
1429 ca_mutex_unlock(g_scanMutex);
1432 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
1434 OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
1435 VERIFY_NON_NULL(callback, TAG, "callback is null");
1436 VERIFY_NON_NULL(env, TAG, "env is null");
1438 if (!CALEIsEnableBTAdapter(env))
1440 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1441 return CA_ADAPTER_NOT_ENABLED;
1444 // get default bt adapter class
1445 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1446 if (!jni_cid_BTAdapter)
1448 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1449 return CA_STATUS_FAILED;
1452 // get remote bt adapter method
1453 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1454 "getDefaultAdapter",
1455 METHODID_OBJECTNONPARAM);
1456 if (!jni_mid_getDefaultAdapter)
1458 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1459 return CA_STATUS_FAILED;
1462 // get start le scan method
1463 jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
1464 "(Landroid/bluetooth/"
1465 "BluetoothAdapter$LeScanCallback;)V");
1466 if (!jni_mid_stopLeScan)
1468 OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
1469 return CA_STATUS_FAILED;
1472 // gat bt adapter object
1473 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1474 jni_mid_getDefaultAdapter);
1475 if (!jni_obj_BTAdapter)
1477 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1478 return CA_STATUS_FAILED;
1481 OIC_LOG(INFO, TAG, "CALL API - stopLeScan");
1482 // call start le scan method
1483 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
1484 if ((*env)->ExceptionCheck(env))
1486 OIC_LOG(ERROR, TAG, "stopLeScan has failed");
1487 (*env)->ExceptionDescribe(env);
1488 (*env)->ExceptionClear(env);
1489 return CA_STATUS_FAILED;
1492 return CA_STATUS_OK;
1495 CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, jint state_idx, jboolean flag)
1497 OIC_LOG(DEBUG, TAG, "IN - CALEClientSetFlagToState");
1498 VERIFY_NON_NULL(env, TAG, "env");
1499 VERIFY_NON_NULL(jni_address, TAG, "jni_address");
1501 ca_mutex_lock(g_deviceStateListMutex);
1503 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1506 OIC_LOG(ERROR, TAG, "address is not available");
1507 return CA_STATUS_FAILED;
1510 if (CALEClientIsDeviceInList(address))
1512 CALEState_t* curState = CALEClientGetStateInfo(address);
1515 OIC_LOG(ERROR, TAG, "curState is null");
1516 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1517 ca_mutex_unlock(g_deviceStateListMutex);
1518 return CA_STATUS_FAILED;
1520 OIC_LOG_V(INFO, TAG, "%d flag is set : %d", state_idx, flag);
1524 case CA_LE_AUTO_CONNECT_FLAG:
1525 curState->autoConnectFlag = flag;
1527 case CA_LE_DESCRIPTOR_FOUND:
1528 curState->isDescriptorFound = flag;
1535 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1536 ca_mutex_unlock(g_deviceStateListMutex);
1537 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetFlagToState");
1538 return CA_STATUS_OK;
1541 jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx)
1543 OIC_LOG(DEBUG, TAG, "IN - CALEClientGetFlagFromState");
1544 VERIFY_NON_NULL_RET(env, TAG, "env", false);
1545 VERIFY_NON_NULL_RET(jni_address, TAG, "jni_address", false);
1547 ca_mutex_lock(g_deviceStateListMutex);
1549 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1552 OIC_LOG(ERROR, TAG, "address is not available");
1553 ca_mutex_unlock(g_deviceStateListMutex);
1557 CALEState_t* curState = CALEClientGetStateInfo(address);
1558 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1561 OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false");
1562 ca_mutex_unlock(g_deviceStateListMutex);
1566 jboolean ret = JNI_FALSE;
1569 case CA_LE_AUTO_CONNECT_FLAG:
1570 ret = curState->autoConnectFlag;
1572 case CA_LE_DESCRIPTOR_FOUND:
1573 ret = curState->isDescriptorFound;
1578 ca_mutex_unlock(g_deviceStateListMutex);
1580 OIC_LOG_V(INFO, TAG, "%d flag is %d", state_idx, ret);
1581 OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetFlagFromState");
1585 jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1587 OIC_LOG(DEBUG, TAG, "CALEClientConnect");
1588 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1589 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1591 // get gatt object from Bluetooth Device object for closeProfileProxy(..)
1592 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
1595 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1598 OIC_LOG(ERROR, TAG, "address is not available");
1602 // close the gatt service
1603 jobject gatt = CALEClientGetGattObjInList(env, address);
1606 CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
1607 if (CA_STATUS_OK != res)
1609 OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
1610 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1614 // clean previous gatt object after close profile service
1615 res = CALEClientRemoveGattObjForAddr(env, jni_address);
1616 if (CA_STATUS_OK != res)
1618 OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
1619 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1623 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1626 jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
1629 OIC_LOG(DEBUG, TAG, "re-connection will be started");
1633 // add new gatt object into g_gattObjectList
1634 CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
1635 if (CA_STATUS_OK != res)
1637 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
1644 jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1646 OIC_LOG(DEBUG, TAG, "GATT CONNECT");
1647 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1648 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1650 if (!g_leGattCallback)
1652 OIC_LOG(INFO, TAG, "g_leGattCallback is null");
1656 if (!CALEIsEnableBTAdapter(env))
1658 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1662 jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1665 OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
1669 // get BluetoothDevice method
1670 OIC_LOG(DEBUG, TAG, "get BluetoothDevice method");
1671 jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
1673 "(Landroid/content/Context;ZLandroid/"
1674 "bluetooth/BluetoothGattCallback;)"
1675 "Landroid/bluetooth/BluetoothGatt;");
1676 if (!jni_mid_connectGatt)
1678 OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
1682 OIC_LOG(INFO, TAG, "CALL API - connectGatt");
1683 jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
1684 jni_mid_connectGatt,
1686 autoconnect, g_leGattCallback);
1687 if (!jni_obj_connectGatt)
1689 OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
1690 CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
1691 CALEClientUpdateSendCnt(env);
1696 OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
1698 return jni_obj_connectGatt;
1701 CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
1703 OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
1705 VERIFY_NON_NULL(env, TAG, "env is null");
1706 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1708 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1709 if (!jni_cid_BTAdapter)
1711 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
1712 return CA_STATUS_FAILED;
1715 // get remote bt adapter method
1716 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1717 "getDefaultAdapter",
1718 METHODID_OBJECTNONPARAM);
1719 if (!jni_mid_getDefaultAdapter)
1721 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1722 return CA_STATUS_FAILED;
1725 // gat bt adapter object
1726 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1727 jni_mid_getDefaultAdapter);
1728 if (!jni_obj_BTAdapter)
1730 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1731 return CA_STATUS_FAILED;
1734 // get closeProfileProxy method
1735 jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1736 "closeProfileProxy",
1737 "(ILandroid/bluetooth/"
1738 "BluetoothProfile;)V");
1739 if (!jni_mid_closeProfileProxy)
1741 OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
1742 return CA_STATUS_FAILED;
1745 jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
1746 if (!jni_cid_BTProfile)
1748 OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
1749 return CA_STATUS_FAILED;
1752 // GATT - Constant value : 7 (0x00000007)
1753 jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
1757 OIC_LOG(ERROR, TAG, "id_gatt is null");
1758 return CA_STATUS_FAILED;
1761 jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
1763 OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
1764 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
1765 if ((*env)->ExceptionCheck(env))
1767 OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
1768 (*env)->ExceptionDescribe(env);
1769 (*env)->ExceptionClear(env);
1770 return CA_STATUS_FAILED;
1773 OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
1774 return CA_STATUS_OK;
1778 CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
1780 OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1781 VERIFY_NON_NULL(env, TAG, "env is null");
1782 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1784 // get BluetoothGatt method
1785 OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
1786 jmethodID jni_mid_disconnectGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1787 "disconnect", "()V");
1788 if (!jni_mid_disconnectGatt)
1790 OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
1791 return CA_STATUS_FAILED;
1794 // call disconnect gatt method
1795 OIC_LOG(INFO, TAG, "CALL API - disconnect");
1796 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
1797 if ((*env)->ExceptionCheck(env))
1799 OIC_LOG(ERROR, TAG, "disconnect has failed");
1800 (*env)->ExceptionDescribe(env);
1801 (*env)->ExceptionClear(env);
1802 return CA_STATUS_FAILED;
1805 OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
1807 return CA_STATUS_OK;
1810 CAResult_t CALEClientDisconnectAll(JNIEnv *env)
1812 OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1813 VERIFY_NON_NULL(env, TAG, "env is null");
1815 if (!g_gattObjectList)
1817 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1818 return CA_STATUS_OK;
1821 uint32_t length = u_arraylist_length(g_gattObjectList);
1822 OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
1823 for (uint32_t index = 0; index < length; index++)
1825 OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
1826 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1829 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1832 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1833 if (CA_STATUS_OK != res)
1835 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1840 return CA_STATUS_OK;
1843 CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
1845 OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
1846 VERIFY_NON_NULL(env, TAG, "env is null");
1848 if (!g_gattObjectList)
1850 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1851 return CA_STATUS_OK;
1854 char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
1857 OIC_LOG(ERROR, TAG, "address is null");
1858 return CA_STATUS_FAILED;
1861 uint32_t length = u_arraylist_length(g_gattObjectList);
1862 for (uint32_t index = 0; index < length; index++)
1864 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1867 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1871 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
1872 if (!jni_setAddress)
1874 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1875 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1876 return CA_STATUS_FAILED;
1879 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1882 OIC_LOG(ERROR, TAG, "setAddress is null");
1883 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1884 return CA_STATUS_FAILED;
1887 OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
1888 if (!strcmp(address, setAddress))
1890 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1891 if (CA_STATUS_OK != res)
1893 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1894 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1895 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1896 return CA_STATUS_FAILED;
1898 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1899 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1900 return CA_STATUS_OK;
1902 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1904 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1906 OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
1907 return CA_STATUS_OK;
1910 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
1912 VERIFY_NON_NULL(env, TAG, "env is null");
1913 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1915 if (!CALEIsEnableBTAdapter(env))
1917 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1918 return CA_ADAPTER_NOT_ENABLED;
1921 // get BluetoothGatt.discoverServices method
1922 OIC_LOG(DEBUG, TAG, "get BluetoothGatt.discoverServices method");
1923 jmethodID jni_mid_discoverServices = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1924 "discoverServices", "()Z");
1925 if (!jni_mid_discoverServices)
1927 OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
1928 return CA_STATUS_FAILED;
1931 // call disconnect gatt method
1932 OIC_LOG(INFO, TAG, "CALL API - discoverServices");
1933 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
1936 OIC_LOG(ERROR, TAG, "discoverServices has not been started");
1937 return CA_STATUS_FAILED;
1940 return CA_STATUS_OK;
1943 static void CALEWriteCharacteristicThread(void* object)
1945 VERIFY_NON_NULL_VOID(object, TAG, "object is null");
1947 bool isAttached = false;
1949 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1952 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1953 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1957 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1963 jobject gatt = (jobject)object;
1964 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1965 if (CA_STATUS_OK != ret)
1967 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1972 (*g_jvm)->DetachCurrentThread(g_jvm);
1976 CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
1978 OIC_LOG(DEBUG, TAG, "CALESetValueAndWriteCharacteristic");
1980 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1981 VERIFY_NON_NULL(env, TAG, "env is null");
1983 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
1986 CALEClientSendFinish(env, gatt);
1987 return CA_STATUS_FAILED;
1990 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1993 CALEClientSendFinish(env, gatt);
1994 return CA_STATUS_FAILED;
1997 ca_mutex_lock(g_threadSendStateMutex);
1999 if (CALEClientIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING))
2001 OIC_LOG(INFO, TAG, "current state is SENDING");
2002 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2003 ca_mutex_unlock(g_threadSendStateMutex);
2004 return CA_STATUS_OK;
2007 if (CA_STATUS_OK != CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
2010 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
2011 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2012 CALEClientSendFinish(env, gatt);
2013 ca_mutex_unlock(g_threadSendStateMutex);
2014 return CA_STATUS_FAILED;
2017 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2019 ca_mutex_unlock(g_threadSendStateMutex);
2022 jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
2023 if (!jni_obj_character)
2025 CALEClientSendFinish(env, gatt);
2026 return CA_STATUS_FAILED;
2029 CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
2030 if (CA_STATUS_OK != ret)
2032 CALEClientSendFinish(env, gatt);
2033 return CA_STATUS_FAILED;
2036 // wait for callback for write Characteristic with success to sent data
2037 OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
2038 ca_mutex_lock(g_threadWriteCharacteristicMutex);
2039 if (!g_isSignalSetFlag)
2041 OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
2042 if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
2043 g_threadWriteCharacteristicMutex,
2044 WAIT_TIME_WRITE_CHARACTERISTIC))
2046 OIC_LOG(ERROR, TAG, "there is no response. write has failed");
2047 g_isSignalSetFlag = false;
2048 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2049 return CA_STATUS_FAILED;
2052 // reset flag set by writeCharacteristic Callback
2053 g_isSignalSetFlag = false;
2054 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2056 OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
2057 return CA_STATUS_OK;
2060 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
2062 OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
2063 VERIFY_NON_NULL(env, TAG, "env is null");
2064 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2066 jobject gattParam = (*env)->NewGlobalRef(env, gatt);
2067 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
2068 CALEWriteCharacteristicThread, (void*)gattParam))
2070 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
2071 return CA_STATUS_FAILED;
2074 OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
2075 return CA_STATUS_OK;
2078 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
2079 jobject gattCharacteristic)
2081 OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
2082 VERIFY_NON_NULL(env, TAG, "env is null");
2083 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2084 VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
2086 if (!CALEIsEnableBTAdapter(env))
2088 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2089 return CA_STATUS_FAILED;
2092 // get BluetoothGatt.write characteristic method
2093 OIC_LOG(DEBUG, TAG, "write characteristic method");
2094 jmethodID jni_mid_writeCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2095 "writeCharacteristic",
2096 "(Landroid/bluetooth/"
2097 "BluetoothGattCharacteristic;)Z");
2098 if (!jni_mid_writeCharacteristic)
2100 OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
2101 return CA_STATUS_FAILED;
2104 // call disconnect gatt method
2105 OIC_LOG(INFO, TAG, "CALL API - writeCharacteristic");
2106 jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
2107 jni_mid_writeCharacteristic,
2108 gattCharacteristic);
2111 OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
2115 OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
2116 return CA_STATUS_FAILED;
2119 return CA_STATUS_OK;
2122 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
2124 VERIFY_NON_NULL(env, TAG, "env is null");
2125 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2127 if (!CALEIsEnableBTAdapter(env))
2129 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2130 return CA_STATUS_FAILED;
2133 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
2136 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2137 return CA_STATUS_FAILED;
2140 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2141 if (!jni_obj_GattCharacteristic)
2143 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2144 return CA_STATUS_FAILED;
2147 OIC_LOG(DEBUG, TAG, "read characteristic method");
2148 jmethodID jni_mid_readCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2149 "readCharacteristic",
2150 "(Landroid/bluetooth/"
2151 "BluetoothGattCharacteristic;)Z");
2152 if (!jni_mid_readCharacteristic)
2154 OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
2155 return CA_STATUS_FAILED;
2158 // call disconnect gatt method
2159 OIC_LOG(INFO, TAG, "CALL API - readCharacteristic");
2160 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
2161 jni_obj_GattCharacteristic);
2164 OIC_LOG(DEBUG, TAG, "readCharacteristic success");
2168 OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
2169 return CA_STATUS_FAILED;
2172 return CA_STATUS_OK;
2175 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
2176 jobject characteristic)
2178 VERIFY_NON_NULL(env, TAG, "env is null");
2179 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2180 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2182 if (!CALEIsEnableBTAdapter(env))
2184 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2185 return CA_ADAPTER_NOT_ENABLED;
2188 // get BluetoothGatt.setCharacteristicNotification method
2189 OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
2190 jmethodID jni_mid_setNotification = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2191 "setCharacteristicNotification",
2192 "(Landroid/bluetooth/"
2193 "BluetoothGattCharacteristic;Z)Z");
2194 if (!jni_mid_setNotification)
2196 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2197 return CA_STATUS_FAILED;
2200 OIC_LOG(INFO, TAG, "CALL API - setCharacteristicNotification");
2201 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
2202 characteristic, JNI_TRUE);
2203 if (JNI_TRUE == ret)
2205 OIC_LOG(DEBUG, TAG, "setCharacteristicNotification success");
2209 OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed");
2210 return CA_STATUS_FAILED;
2213 return CA_STATUS_OK;
2216 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
2218 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2219 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2220 VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
2222 if (!CALEIsEnableBTAdapter(env))
2224 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2228 // get BluetoothGatt.getService method
2229 OIC_LOG(DEBUG, TAG, "BluetoothGatt.getService");
2230 jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2232 "(Ljava/util/UUID;)Landroid/bluetooth/"
2233 "BluetoothGattService;");
2234 if (!jni_mid_getService)
2236 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2240 jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2241 if (!jni_obj_service_uuid)
2243 OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
2247 // get bluetooth gatt service
2248 OIC_LOG(DEBUG, TAG, "request to get service");
2249 jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
2250 jni_obj_service_uuid);
2251 if (!jni_obj_gattService)
2253 OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
2257 // get bluetooth gatt service method
2258 jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/"
2259 "BluetoothGattService",
2260 "getCharacteristic",
2261 "(Ljava/util/UUID;)"
2262 "Landroid/bluetooth/"
2263 "BluetoothGattCharacteristic;");
2264 if (!jni_mid_getCharacteristic)
2266 OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
2270 const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
2273 OIC_LOG(ERROR, TAG, "uuid is null");
2277 jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
2278 if (!jni_obj_tx_uuid)
2280 OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
2281 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2285 OIC_LOG(DEBUG, TAG, "request to get Characteristic");
2286 jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
2287 jni_mid_getCharacteristic,
2290 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2291 return jni_obj_GattCharacteristic;
2294 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
2296 OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
2297 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2298 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2299 VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
2301 if (!CALEIsEnableBTAdapter(env))
2303 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2307 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
2310 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2314 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2315 if (!jni_obj_GattCharacteristic)
2317 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2321 jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
2322 "/BluetoothGattCharacteristic");
2323 if (!jni_cid_BTGattCharacteristic)
2325 OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
2329 OIC_LOG(DEBUG, TAG, "set value in Characteristic");
2330 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
2332 if (!jni_mid_setValue)
2334 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2338 jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
2340 if (JNI_TRUE == ret)
2342 OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
2346 OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
2351 jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
2352 "setWriteType", "(I)V");
2353 if (!jni_mid_setWriteType)
2355 OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
2359 jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
2360 "WRITE_TYPE_NO_RESPONSE", "I");
2361 if (!jni_fid_no_response)
2363 OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
2367 jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
2368 jni_fid_no_response);
2370 (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
2372 return jni_obj_GattCharacteristic;
2375 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
2377 VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
2378 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2380 if (!CALEIsEnableBTAdapter(env))
2382 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2386 jmethodID jni_mid_getValue = CAGetJNIMethodID(env, "android/bluetooth/"
2387 "BluetoothGattCharacteristic",
2388 "getValue", "()[B");
2389 if (!jni_mid_getValue)
2391 OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
2395 jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
2397 return jni_obj_data_array;
2400 CAResult_t CALEClientCreateUUIDList()
2404 OIC_LOG(ERROR, TAG, "g_jvm is null");
2405 return CA_STATUS_FAILED;
2408 bool isAttached = false;
2410 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2413 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2414 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2418 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2419 return CA_STATUS_FAILED;
2424 // create new object array
2425 jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
2426 if (!jni_cid_uuid_list)
2428 OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
2432 jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
2433 jni_cid_uuid_list, NULL);
2434 if (!jni_obj_uuid_list)
2436 OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
2441 jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2444 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
2447 (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
2449 g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
2453 (*g_jvm)->DetachCurrentThread(g_jvm);
2456 return CA_STATUS_OK;
2463 (*g_jvm)->DetachCurrentThread(g_jvm);
2465 return CA_STATUS_FAILED;
2468 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
2469 jobject characteristic)
2471 VERIFY_NON_NULL(env, TAG, "env is null");
2472 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2473 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2475 if (!CALEIsEnableBTAdapter(env))
2477 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2478 return CA_ADAPTER_NOT_ENABLED;
2481 OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
2482 jmethodID jni_mid_getDescriptor = CAGetJNIMethodID(env, "android/bluetooth/"
2483 "BluetoothGattCharacteristic",
2485 "(Ljava/util/UUID;)Landroid/bluetooth/"
2486 "BluetoothGattDescriptor;");
2487 if (!jni_mid_getDescriptor)
2489 OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
2490 return CA_STATUS_FAILED;
2493 jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
2494 if (!jni_obj_cc_uuid)
2496 OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
2497 return CA_STATUS_FAILED;
2500 OIC_LOG(DEBUG, TAG, "request to get descriptor");
2501 jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
2502 jni_mid_getDescriptor, jni_obj_cc_uuid);
2503 if (!jni_obj_descriptor)
2505 OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
2506 return CA_NOT_SUPPORTED;
2509 OIC_LOG(DEBUG, TAG, "set value in descriptor");
2510 jclass jni_cid_descriptor = (*env)->FindClass(env,
2511 "android/bluetooth/BluetoothGattDescriptor");
2512 if (!jni_cid_descriptor)
2514 OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2515 return CA_STATUS_FAILED;
2518 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2519 if (!jni_mid_setValue)
2521 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2522 return CA_STATUS_FAILED;
2525 jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2526 "ENABLE_NOTIFICATION_VALUE", "[B");
2527 if (!jni_fid_NotiValue)
2529 OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2530 return CA_STATUS_FAILED;
2533 OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2535 jboolean jni_setvalue = (*env)->CallBooleanMethod(
2536 env, jni_obj_descriptor, jni_mid_setValue,
2537 (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2540 OIC_LOG(DEBUG, TAG, "setValue success");
2544 OIC_LOG(ERROR, TAG, "setValue has failed");
2545 return CA_STATUS_FAILED;
2548 jmethodID jni_mid_writeDescriptor = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt",
2550 "(Landroid/bluetooth/"
2551 "BluetoothGattDescriptor;)Z");
2552 if (!jni_mid_writeDescriptor)
2554 OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2555 return CA_STATUS_FAILED;
2558 OIC_LOG(INFO, TAG, "CALL API - writeDescriptor");
2559 jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2560 jni_obj_descriptor);
2563 OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2567 OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2568 return CA_STATUS_FAILED;
2571 return CA_STATUS_OK;
2574 void CALEClientCreateScanDeviceList(JNIEnv *env)
2576 OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2577 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2579 ca_mutex_lock(g_deviceListMutex);
2580 // create new object array
2581 if (g_deviceList == NULL)
2583 OIC_LOG(DEBUG, TAG, "Create device list");
2585 g_deviceList = u_arraylist_create();
2587 ca_mutex_unlock(g_deviceListMutex);
2590 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2592 VERIFY_NON_NULL(device, TAG, "device is null");
2593 VERIFY_NON_NULL(env, TAG, "env is null");
2595 ca_mutex_lock(g_deviceListMutex);
2599 OIC_LOG(ERROR, TAG, "gdevice_list is null");
2601 CALEClientSetScanFlag(false);
2602 if (CA_STATUS_OK != CALEClientStopScan())
2604 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
2607 ca_mutex_unlock(g_deviceListMutex);
2608 return CA_STATUS_FAILED;
2611 jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2612 if (!jni_remoteAddress)
2614 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2615 ca_mutex_unlock(g_deviceListMutex);
2616 return CA_STATUS_FAILED;
2619 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2622 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2623 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2624 ca_mutex_unlock(g_deviceListMutex);
2625 return CA_STATUS_FAILED;
2628 if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2630 jobject gdevice = (*env)->NewGlobalRef(env, device);
2631 u_arraylist_add(g_deviceList, gdevice);
2632 ca_cond_signal(g_deviceDescCond);
2633 OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress);
2635 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2636 (*env)->DeleteLocalRef(env, jni_remoteAddress);
2638 ca_mutex_unlock(g_deviceListMutex);
2640 return CA_STATUS_OK;
2643 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2645 VERIFY_NON_NULL_RET(env, TAG, "env is null", true);
2646 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2650 OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2654 uint32_t length = u_arraylist_length(g_deviceList);
2655 for (uint32_t index = 0; index < length; index++)
2657 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2660 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2664 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2665 if (!jni_setAddress)
2667 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2671 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2674 OIC_LOG(ERROR, TAG, "setAddress is null");
2675 (*env)->DeleteLocalRef(env, jni_setAddress);
2679 if (!strcmp(remoteAddress, setAddress))
2681 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2682 (*env)->DeleteLocalRef(env, jni_setAddress);
2686 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2687 (*env)->DeleteLocalRef(env, jni_setAddress);
2690 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress);
2695 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2697 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2698 VERIFY_NON_NULL(env, TAG, "env is null");
2700 ca_mutex_lock(g_deviceListMutex);
2704 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2705 ca_mutex_unlock(g_deviceListMutex);
2706 return CA_STATUS_FAILED;
2709 uint32_t length = u_arraylist_length(g_deviceList);
2710 for (uint32_t index = 0; index < length; index++)
2712 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2715 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2718 (*env)->DeleteGlobalRef(env, jarrayObj);
2722 OICFree(g_deviceList);
2723 g_deviceList = NULL;
2725 ca_mutex_unlock(g_deviceListMutex);
2726 return CA_STATUS_OK;
2729 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2731 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2732 VERIFY_NON_NULL(address, TAG, "address is null");
2733 VERIFY_NON_NULL(env, TAG, "env is null");
2735 ca_mutex_lock(g_deviceListMutex);
2739 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2740 ca_mutex_unlock(g_deviceListMutex);
2741 return CA_STATUS_FAILED;
2744 uint32_t length = u_arraylist_length(g_deviceList);
2745 for (uint32_t index = 0; index < length; index++)
2747 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2750 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2751 ca_mutex_unlock(g_deviceListMutex);
2752 return CA_STATUS_FAILED;
2755 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2756 if (!jni_setAddress)
2758 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2759 ca_mutex_unlock(g_deviceListMutex);
2760 return CA_STATUS_FAILED;
2763 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2766 OIC_LOG(ERROR, TAG, "setAddress is null");
2767 ca_mutex_unlock(g_deviceListMutex);
2768 return CA_STATUS_FAILED;
2771 const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2774 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2775 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2776 ca_mutex_unlock(g_deviceListMutex);
2777 return CA_STATUS_FAILED;
2780 if (!strcmp(setAddress, remoteAddress))
2782 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2783 (*env)->DeleteGlobalRef(env, jarrayObj);
2785 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2786 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2788 if (NULL == u_arraylist_remove(g_deviceList, index))
2790 OIC_LOG(ERROR, TAG, "List removal failed.");
2791 ca_mutex_unlock(g_deviceListMutex);
2792 return CA_STATUS_FAILED;
2794 ca_mutex_unlock(g_deviceListMutex);
2795 return CA_STATUS_OK;
2797 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2798 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2801 ca_mutex_unlock(g_deviceListMutex);
2802 OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2804 return CA_STATUS_OK;
2811 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2813 OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2814 VERIFY_NON_NULL(env, TAG, "env is null");
2815 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2817 ca_mutex_lock(g_gattObjectMutex);
2819 if (!g_gattObjectList)
2821 OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
2822 ca_mutex_unlock(g_gattObjectMutex);
2823 return CA_STATUS_FAILED;
2826 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2827 if (!jni_remoteAddress)
2829 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2830 ca_mutex_unlock(g_gattObjectMutex);
2831 return CA_STATUS_FAILED;
2834 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2837 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2838 ca_mutex_unlock(g_gattObjectMutex);
2839 return CA_STATUS_FAILED;
2842 OIC_LOG_V(DEBUG, TAG, "remote address : %s", remoteAddress);
2843 if (!CALEClientIsGattObjInList(env, remoteAddress))
2845 jobject newGatt = (*env)->NewGlobalRef(env, gatt);
2846 u_arraylist_add(g_gattObjectList, newGatt);
2847 OIC_LOG(INFO, TAG, "added a newGatt object to gattObjectList");
2850 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2851 ca_mutex_unlock(g_gattObjectMutex);
2852 return CA_STATUS_OK;
2855 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
2857 OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
2858 VERIFY_NON_NULL(env, TAG, "env is null");
2859 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2861 uint32_t length = u_arraylist_length(g_gattObjectList);
2862 for (uint32_t index = 0; index < length; index++)
2865 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2868 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2872 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2873 if (!jni_setAddress)
2875 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2879 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2882 OIC_LOG(ERROR, TAG, "setAddress is null");
2886 if (!strcmp(remoteAddress, setAddress))
2888 OIC_LOG(DEBUG, TAG, "the device is already set");
2889 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2894 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2899 OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
2903 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
2905 OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
2906 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2907 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2909 ca_mutex_lock(g_gattObjectMutex);
2910 uint32_t length = u_arraylist_length(g_gattObjectList);
2911 for (uint32_t index = 0; index < length; index++)
2913 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2916 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2917 ca_mutex_unlock(g_gattObjectMutex);
2921 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2922 if (!jni_setAddress)
2924 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2925 ca_mutex_unlock(g_gattObjectMutex);
2929 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2932 OIC_LOG(ERROR, TAG, "setAddress is null");
2933 ca_mutex_unlock(g_gattObjectMutex);
2937 if (!strcmp(remoteAddress, setAddress))
2939 OIC_LOG(DEBUG, TAG, "the device is already set");
2940 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2941 ca_mutex_unlock(g_gattObjectMutex);
2944 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2947 ca_mutex_unlock(g_gattObjectMutex);
2948 OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
2952 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
2954 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
2955 VERIFY_NON_NULL(env, TAG, "env is null");
2957 ca_mutex_lock(g_gattObjectMutex);
2958 if (!g_gattObjectList)
2960 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2961 ca_mutex_unlock(g_gattObjectMutex);
2962 return CA_STATUS_OK;
2965 uint32_t length = u_arraylist_length(g_gattObjectList);
2966 for (uint32_t index = 0; index < length; index++)
2968 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2971 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2974 (*env)->DeleteGlobalRef(env, jarrayObj);
2978 OICFree(g_gattObjectList);
2979 g_gattObjectList = NULL;
2980 OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
2981 ca_mutex_unlock(g_gattObjectMutex);
2982 return CA_STATUS_OK;
2985 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
2987 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
2988 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2989 VERIFY_NON_NULL(env, TAG, "env is null");
2991 ca_mutex_lock(g_gattObjectMutex);
2992 if (!g_gattObjectList)
2994 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2995 ca_mutex_unlock(g_gattObjectMutex);
2996 return CA_STATUS_OK;
2999 uint32_t length = u_arraylist_length(g_gattObjectList);
3000 for (uint32_t index = 0; index < length; index++)
3002 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3005 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3006 ca_mutex_unlock(g_gattObjectMutex);
3007 return CA_STATUS_FAILED;
3010 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3011 if (!jni_setAddress)
3013 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3014 ca_mutex_unlock(g_gattObjectMutex);
3015 return CA_STATUS_FAILED;
3018 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3021 OIC_LOG(ERROR, TAG, "setAddress is null");
3022 ca_mutex_unlock(g_gattObjectMutex);
3023 return CA_STATUS_FAILED;
3026 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3027 if (!jni_remoteAddress)
3029 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3030 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3031 ca_mutex_unlock(g_gattObjectMutex);
3032 return CA_STATUS_FAILED;
3035 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3038 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3039 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3040 ca_mutex_unlock(g_gattObjectMutex);
3041 return CA_STATUS_FAILED;
3044 if (!strcmp(setAddress, remoteAddress))
3046 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3047 (*env)->DeleteGlobalRef(env, jarrayObj);
3049 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3050 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3052 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3054 OIC_LOG(ERROR, TAG, "List removal failed.");
3055 ca_mutex_unlock(g_gattObjectMutex);
3056 return CA_STATUS_FAILED;
3058 ca_mutex_unlock(g_gattObjectMutex);
3059 return CA_STATUS_OK;
3061 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3062 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3065 ca_mutex_unlock(g_gattObjectMutex);
3066 OIC_LOG(DEBUG, TAG, "there are no target object");
3067 return CA_STATUS_OK;
3070 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
3072 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
3073 VERIFY_NON_NULL(addr, TAG, "addr is null");
3074 VERIFY_NON_NULL(env, TAG, "env is null");
3076 ca_mutex_lock(g_gattObjectMutex);
3077 if (!g_gattObjectList)
3079 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3080 ca_mutex_unlock(g_gattObjectMutex);
3081 return CA_STATUS_OK;
3084 uint32_t length = u_arraylist_length(g_gattObjectList);
3085 for (uint32_t index = 0; index < length; index++)
3087 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3090 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3091 ca_mutex_unlock(g_gattObjectMutex);
3092 return CA_STATUS_FAILED;
3095 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3096 if (!jni_setAddress)
3098 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3099 ca_mutex_unlock(g_gattObjectMutex);
3100 return CA_STATUS_FAILED;
3103 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3106 OIC_LOG(ERROR, TAG, "setAddress is null");
3107 ca_mutex_unlock(g_gattObjectMutex);
3108 return CA_STATUS_FAILED;
3111 const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
3114 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3115 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3116 ca_mutex_unlock(g_gattObjectMutex);
3117 return CA_STATUS_FAILED;
3120 if (!strcmp(setAddress, remoteAddress))
3122 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3123 (*env)->DeleteGlobalRef(env, jarrayObj);
3125 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3126 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3127 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3129 OIC_LOG(ERROR, TAG, "List removal failed.");
3130 ca_mutex_unlock(g_gattObjectMutex);
3131 return CA_STATUS_FAILED;
3133 ca_mutex_unlock(g_gattObjectMutex);
3134 return CA_STATUS_OK;
3136 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3137 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3140 ca_mutex_unlock(g_gattObjectMutex);
3141 OIC_LOG(DEBUG, TAG, "there are no target object");
3142 return CA_STATUS_FAILED;
3145 jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
3147 OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice");
3149 VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
3150 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
3152 // get Bluetooth Address
3153 jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
3154 if (!jni_btTargetAddress)
3156 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3160 const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
3163 OIC_LOG(ERROR, TAG, "targetAddress is not available");
3167 // get method ID of getDevice()
3168 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3169 "getDevice", METHODID_BT_DEVICE);
3170 if (!jni_mid_getDevice)
3172 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
3173 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3177 ca_mutex_lock(g_gattObjectMutex);
3179 size_t length = u_arraylist_length(g_gattObjectList);
3180 OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length);
3181 OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
3183 for (size_t index = 0; index < length; index++)
3185 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3188 ca_mutex_unlock(g_gattObjectMutex);
3189 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3190 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3194 jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
3195 if (!jni_obj_device)
3197 ca_mutex_unlock(g_gattObjectMutex);
3198 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
3199 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3203 jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
3206 ca_mutex_unlock(g_gattObjectMutex);
3207 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3208 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3212 const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
3215 ca_mutex_unlock(g_gattObjectMutex);
3216 OIC_LOG(ERROR, TAG, "btAddress is not available");
3217 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3221 OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index);
3222 if (!strcmp(targetAddress, btAddress))
3224 OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
3227 jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3230 OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
3232 ca_mutex_unlock(g_gattObjectMutex);
3233 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3234 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3235 (*env)->DeleteLocalRef(env, jni_btAddress);
3236 (*env)->DeleteLocalRef(env, jni_obj_device);
3237 return jni_LEAddress;
3239 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3240 (*env)->DeleteLocalRef(env, jni_btAddress);
3241 (*env)->DeleteLocalRef(env, jni_obj_device);
3243 ca_mutex_unlock(g_gattObjectMutex);
3245 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3246 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress);
3254 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
3255 uint16_t target_state)
3257 VERIFY_NON_NULL(address, TAG, "address is null");
3258 VERIFY_NON_NULL(address, TAG, "state_type is null");
3259 VERIFY_NON_NULL(address, TAG, "target_state is null");
3261 if (!g_deviceStateList)
3263 OIC_LOG(ERROR, TAG, "gdevice_list is null");
3264 return CA_STATUS_FAILED;
3267 ca_mutex_lock(g_deviceStateListMutex);
3269 if (CALEClientIsDeviceInList(address))
3271 CALEState_t* curState = CALEClientGetStateInfo(address);
3274 OIC_LOG(ERROR, TAG, "curState is null");
3275 ca_mutex_unlock(g_deviceStateListMutex);
3276 return CA_STATUS_FAILED;
3281 case CA_LE_CONNECTION_STATE:
3282 curState->connectedState = target_state;
3284 case CA_LE_SEND_STATE:
3285 curState->sendState = target_state;
3290 OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
3291 curState->address, curState->connectedState, curState->sendState,
3292 curState->autoConnectFlag);
3294 else /** state is added newly **/
3296 if (strlen(address) > CA_MACADDR_SIZE)
3298 OIC_LOG(ERROR, TAG, "address is not proper");
3299 ca_mutex_unlock(g_deviceStateListMutex);
3300 return CA_STATUS_INVALID_PARAM;
3303 CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
3306 OIC_LOG(ERROR, TAG, "out of memory");
3307 ca_mutex_unlock(g_deviceStateListMutex);
3308 return CA_MEMORY_ALLOC_FAILED;
3311 OICStrcpy(newstate->address, sizeof(newstate->address), address);
3315 case CA_LE_CONNECTION_STATE:
3316 newstate->connectedState = target_state;
3317 newstate->sendState = STATE_SEND_NONE;
3319 case CA_LE_SEND_STATE:
3320 newstate->connectedState = STATE_DISCONNECTED;
3321 newstate->sendState = target_state;
3326 OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, "
3327 "conn : %d, send : %d, ACFlag : %d",
3328 newstate->address, newstate->connectedState, newstate->sendState,
3329 newstate->autoConnectFlag);
3330 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);