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);
745 // connect to gatt server
746 ret = CALEClientStopScan();
747 if (CA_STATUS_OK != ret)
749 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
755 (*env)->DeleteGlobalRef(env, g_sendBuffer);
758 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
759 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
760 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
762 // Target device to send message is just one.
765 ret = CALEClientSendData(env, jarrayObj);
766 if (CA_STATUS_OK != ret)
768 OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
772 OIC_LOG(INFO, TAG, "wake up");
775 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
779 OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
781 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
782 // if there is no connection state.
783 ca_mutex_lock(g_threadMutex);
784 if (!g_isFinishedSendData)
786 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
787 ca_cond_wait(g_threadCond, g_threadMutex);
788 OIC_LOG(DEBUG, TAG, "the data was sent");
790 ca_mutex_unlock(g_threadMutex);
794 (*g_jvm)->DetachCurrentThread(g_jvm);
797 // start LE Scan again
798 ret = CALEClientStartScan();
799 if (CA_STATUS_OK != ret)
801 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
802 ca_mutex_unlock(g_threadSendMutex);
806 ca_mutex_unlock(g_threadSendMutex);
807 OIC_LOG(INFO, TAG, "unicast - send logic has finished");
808 if (CALEClientIsValidState(address, CA_LE_SEND_STATE,
815 ret = CA_SEND_FAILED;
819 ret = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
821 if (CA_STATUS_OK != ret)
823 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
831 // start LE Scan again
832 ret = CALEClientStartScan();
833 if (CA_STATUS_OK != ret)
835 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
836 ca_mutex_unlock(g_threadSendMutex);
839 (*g_jvm)->DetachCurrentThread(g_jvm);
846 (*g_jvm)->DetachCurrentThread(g_jvm);
849 ca_mutex_unlock(g_threadSendMutex);
850 return CA_SEND_FAILED;
853 CAResult_t CALEClientSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data,
854 const uint32_t dataLen)
856 OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
857 VERIFY_NON_NULL(data, TAG, "data is null");
858 VERIFY_NON_NULL(env, TAG, "env is null");
862 OIC_LOG(ERROR, TAG, "g_deviceList is null");
863 return CA_STATUS_FAILED;
866 ca_mutex_lock(g_threadSendMutex);
868 CALEClientSetSendFinishFlag(false);
870 OIC_LOG(DEBUG, TAG, "set byteArray for data");
873 (*env)->DeleteGlobalRef(env, g_sendBuffer);
877 CAResult_t res = CALEClientIsThereScannedDevices(env, NULL);
878 if (CA_STATUS_OK != res)
880 OIC_LOG(INFO, TAG, "there is no scanned device");
884 // connect to gatt server
885 res = CALEClientStopScan();
886 if (CA_STATUS_OK != res)
888 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
889 ca_mutex_unlock(g_threadSendMutex);
892 uint32_t length = u_arraylist_length(g_deviceList);
893 g_targetCnt = length;
895 jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
896 (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
897 g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
899 for (uint32_t index = 0; index < length; index++)
901 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
904 OIC_LOG(ERROR, TAG, "jarrayObj is not available");
908 res = CALEClientSendData(env, jarrayObj);
909 if (res != CA_STATUS_OK)
911 OIC_LOG(ERROR, TAG, "BT device - send has failed");
914 jstring jni_address = CALEGetAddressFromBTDevice(env, jarrayObj);
917 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
921 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
924 OIC_LOG(ERROR, TAG, "address is not available");
928 (*env)->ReleaseStringUTFChars(env, jni_address, address);
931 OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
933 // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
934 ca_mutex_lock(g_threadMutex);
935 if (!g_isFinishedSendData)
937 OIC_LOG(DEBUG, TAG, "waiting send finish signal");
938 ca_cond_wait(g_threadCond, g_threadMutex);
939 OIC_LOG(DEBUG, TAG, "the data was sent");
941 ca_mutex_unlock(g_threadMutex);
943 // start LE Scan again
944 res = CALEClientStartScan();
945 if (CA_STATUS_OK != res)
947 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
948 ca_mutex_unlock(g_threadSendMutex);
952 ca_mutex_unlock(g_threadSendMutex);
953 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
957 res = CALEClientStartScan();
958 if (CA_STATUS_OK != res)
960 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
961 ca_mutex_unlock(g_threadSendMutex);
965 ca_mutex_unlock(g_threadSendMutex);
966 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
967 return CA_SEND_FAILED;
970 CAResult_t CALEClientSendData(JNIEnv *env, jobject device)
972 OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
973 VERIFY_NON_NULL(device, TAG, "device is null");
974 VERIFY_NON_NULL(env, TAG, "env is null");
976 // get BLE address from bluetooth device object.
977 char* address = NULL;
978 CALEState_t* state = NULL;
979 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, device);
982 OIC_LOG(INFO, TAG, "there is gatt object..it's not first connection");
983 address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
986 OIC_LOG(ERROR, TAG, "address is not available");
987 return CA_STATUS_FAILED;
989 ca_mutex_lock(g_deviceStateListMutex);
990 state = CALEClientGetStateInfo(address);
991 ca_mutex_unlock(g_deviceStateListMutex);
996 OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
998 // cancel previous connection request before connection
999 // if there is gatt object in g_gattObjectList.
1002 jobject gatt = CALEClientGetGattObjInList(env, address);
1005 CAResult_t res = CALEClientDisconnect(env, gatt);
1006 if (CA_STATUS_OK != res)
1008 OIC_LOG(INFO, TAG, "there is no gatt object");
1011 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1014 // connection request
1015 jobject newGatt = CALEClientConnect(env, device,
1017 if (NULL == newGatt)
1019 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1020 return CA_STATUS_FAILED;
1025 if (CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1026 STATE_SERVICE_CONNECTED))
1028 OIC_LOG(INFO, TAG, "GATT has already connected");
1030 jobject gatt = CALEClientGetGattObjInList(env, address);
1033 OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
1034 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1035 return CA_STATUS_FAILED;
1038 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1039 if (CA_STATUS_OK != ret)
1041 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1042 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1045 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1047 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1050 OIC_LOG(INFO, TAG, "service connecting...");
1052 else if(CALEClientIsValidState(address, CA_LE_CONNECTION_STATE,
1053 STATE_DISCONNECTED))
1055 OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
1057 // cancel previous connection request before connection
1058 // if there is gatt object in g_gattObjectList.
1061 jobject gatt = CALEClientGetGattObjInList(env, address);
1064 CAResult_t res = CALEClientDisconnect(env, gatt);
1065 if (CA_STATUS_OK != res)
1067 OIC_LOG(INFO, TAG, "there is no gatt object");
1070 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1073 OIC_LOG(DEBUG, TAG, "start to connect LE");
1074 jobject gatt = CALEClientConnect(env, device,
1075 CALEClientGetFlagFromState(env, jni_address,
1076 CA_LE_AUTO_CONNECT_FLAG));
1079 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
1080 return CA_STATUS_FAILED;
1085 return CA_STATUS_OK;
1088 jstring CALEClientGetAddressFromGattObj(JNIEnv *env, jobject gatt)
1090 VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
1091 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1093 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
1094 "()Landroid/bluetooth/BluetoothDevice;");
1095 if (!jni_mid_getDevice)
1097 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
1101 jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
1102 if (!jni_obj_device)
1104 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
1108 jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
1111 OIC_LOG(ERROR, TAG, "jni_address is null");
1121 CAResult_t CALEClientGattClose(JNIEnv *env, jobject bluetoothGatt)
1124 OIC_LOG(DEBUG, TAG, "Gatt Close");
1125 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1126 VERIFY_NON_NULL(env, TAG, "env is null");
1128 // get BluetoothGatt method
1129 OIC_LOG(DEBUG, TAG, "get BluetoothGatt method");
1130 jmethodID jni_mid_closeGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "close", "()V");
1131 if (!jni_mid_closeGatt)
1133 OIC_LOG(ERROR, TAG, "jni_mid_closeGatt is null");
1134 return CA_STATUS_OK;
1137 // call disconnect gatt method
1138 OIC_LOG(DEBUG, TAG, "request to close GATT");
1139 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_closeGatt);
1141 if ((*env)->ExceptionCheck(env))
1143 OIC_LOG(ERROR, TAG, "closeGATT has failed");
1144 (*env)->ExceptionDescribe(env);
1145 (*env)->ExceptionClear(env);
1146 return CA_STATUS_FAILED;
1149 return CA_STATUS_OK;
1152 CAResult_t CALEClientStartScan()
1154 if (!g_isStartedLEClient)
1156 OIC_LOG(ERROR, TAG, "LE client is not started");
1157 return CA_STATUS_FAILED;
1162 OIC_LOG(ERROR, TAG, "g_jvm is null");
1163 return CA_STATUS_FAILED;
1166 if (g_isStartedScan)
1168 OIC_LOG(INFO, TAG, "scanning is already started");
1169 return CA_STATUS_OK;
1172 bool isAttached = false;
1174 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1177 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1179 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1182 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1183 return CA_STATUS_FAILED;
1188 OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1190 CAResult_t ret = CA_STATUS_OK;
1191 // scan gatt server with UUID
1192 if (g_leScanCallback && g_uuidList)
1195 ret = CALEClientStartScanWithUUIDImpl(env, g_uuidList, g_leScanCallback);
1197 ret = CALEClientStartScanImpl(env, g_leScanCallback);
1199 if (CA_STATUS_OK != ret)
1201 if (CA_ADAPTER_NOT_ENABLED == ret)
1203 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1207 OIC_LOG(ERROR, TAG, "start scan has failed");
1214 (*g_jvm)->DetachCurrentThread(g_jvm);
1220 CAResult_t CALEClientStartScanImpl(JNIEnv *env, jobject callback)
1222 VERIFY_NON_NULL(callback, TAG, "callback is null");
1223 VERIFY_NON_NULL(env, TAG, "env is null");
1225 if (!CALEIsEnableBTAdapter(env))
1227 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1228 return CA_ADAPTER_NOT_ENABLED;
1231 // get default bt adapter class
1232 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1233 if (!jni_cid_BTAdapter)
1235 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1236 return CA_STATUS_FAILED;
1239 // get remote bt adapter method
1240 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1241 "getDefaultAdapter",
1242 METHODID_OBJECTNONPARAM);
1243 if (!jni_mid_getDefaultAdapter)
1245 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1246 return CA_STATUS_FAILED;
1249 // get start le scan method
1250 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1251 "(Landroid/bluetooth/BluetoothAdapter$"
1252 "LeScanCallback;)Z");
1253 if (!jni_mid_startLeScan)
1255 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1256 return CA_STATUS_FAILED;
1259 // gat bt adapter object
1260 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1261 jni_mid_getDefaultAdapter);
1262 if (!jni_obj_BTAdapter)
1264 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1265 return CA_STATUS_FAILED;
1268 // call start le scan method
1269 OIC_LOG(INFO, TAG, "CALL API - startLeScan");
1270 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1271 jni_mid_startLeScan, callback);
1272 if (!jni_obj_startLeScan)
1274 OIC_LOG(INFO, TAG, "startLeScan has failed");
1278 OIC_LOG(DEBUG, TAG, "LeScan has started");
1279 CALEClientSetScanFlag(true);
1282 return CA_STATUS_OK;
1285 CAResult_t CALEClientStartScanWithUUIDImpl(JNIEnv *env, jobjectArray uuids, jobject callback)
1287 VERIFY_NON_NULL(callback, TAG, "callback is null");
1288 VERIFY_NON_NULL(uuids, TAG, "uuids is null");
1289 VERIFY_NON_NULL(env, TAG, "env is null");
1291 if (!CALEIsEnableBTAdapter(env))
1293 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1294 return CA_ADAPTER_NOT_ENABLED;
1297 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1298 if (!jni_cid_BTAdapter)
1300 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1301 return CA_STATUS_FAILED;
1304 // get remote bt adapter method
1305 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1306 "getDefaultAdapter",
1307 METHODID_OBJECTNONPARAM);
1308 if (!jni_mid_getDefaultAdapter)
1310 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1311 return CA_STATUS_FAILED;
1314 // get start le scan method
1315 jmethodID jni_mid_startLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "startLeScan",
1316 "([Ljava/util/UUID;Landroid/bluetooth/"
1317 "BluetoothAdapter$LeScanCallback;)Z");
1318 if (!jni_mid_startLeScan)
1320 OIC_LOG(ERROR, TAG, "startLeScan: jni_mid_startLeScan is null");
1321 return CA_STATUS_FAILED;
1324 // get bt adapter object
1325 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1326 jni_mid_getDefaultAdapter);
1327 if (!jni_obj_BTAdapter)
1329 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_obj_BTAdapter is null");
1330 return CA_STATUS_FAILED;
1333 // call start le scan method
1334 OIC_LOG(INFO, TAG, "CALL API - startLeScan (with UUID)");
1335 jboolean jni_obj_startLeScan = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter,
1336 jni_mid_startLeScan, uuids, callback);
1337 if (!jni_obj_startLeScan)
1339 OIC_LOG(INFO, TAG, "startLeScan has failed");
1343 OIC_LOG(DEBUG, TAG, "LeScan has started");
1344 CALEClientSetScanFlag(true);
1347 return CA_STATUS_OK;
1350 jobject CALEClientGetUUIDObject(JNIEnv *env, const char* uuid)
1352 VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
1353 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1356 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1359 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1363 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_uuid, "fromString",
1364 "(Ljava/lang/String;)"
1365 "Ljava/util/UUID;");
1366 if (!jni_mid_fromString)
1368 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1372 jstring jni_uuid = (*env)->NewStringUTF(env, uuid);
1373 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1377 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1381 return jni_obj_uuid;
1384 CAResult_t CALEClientStopScan()
1388 OIC_LOG(ERROR, TAG, "g_jvm is null");
1389 return CA_STATUS_FAILED;
1392 if (!g_isStartedScan)
1394 OIC_LOG(INFO, TAG, "scanning is already stopped");
1395 return CA_STATUS_OK;
1398 bool isAttached = false;
1400 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1403 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1404 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1407 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1408 return CA_STATUS_FAILED;
1413 CAResult_t ret = CALEClientStopScanImpl(env, g_leScanCallback);
1414 if (CA_STATUS_OK != ret)
1416 if (CA_ADAPTER_NOT_ENABLED == ret)
1418 OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1422 OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1427 CALEClientSetScanFlag(false);
1432 (*g_jvm)->DetachCurrentThread(g_jvm);
1438 void CALEClientSetScanFlag(bool flag)
1440 ca_mutex_lock(g_scanMutex);
1441 g_isStartedScan = flag;
1442 ca_mutex_unlock(g_scanMutex);
1445 CAResult_t CALEClientStopScanImpl(JNIEnv *env, jobject callback)
1447 OIC_LOG(DEBUG, TAG, "CALEClientStopScanImpl");
1448 VERIFY_NON_NULL(callback, TAG, "callback is null");
1449 VERIFY_NON_NULL(env, TAG, "env is null");
1451 if (!CALEIsEnableBTAdapter(env))
1453 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1454 return CA_ADAPTER_NOT_ENABLED;
1457 // get default bt adapter class
1458 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1459 if (!jni_cid_BTAdapter)
1461 OIC_LOG(ERROR, TAG, "getState From BTAdapter: jni_cid_BTAdapter is null");
1462 return CA_STATUS_FAILED;
1465 // get remote bt adapter method
1466 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1467 "getDefaultAdapter",
1468 METHODID_OBJECTNONPARAM);
1469 if (!jni_mid_getDefaultAdapter)
1471 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1472 return CA_STATUS_FAILED;
1475 // get start le scan method
1476 jmethodID jni_mid_stopLeScan = (*env)->GetMethodID(env, jni_cid_BTAdapter, "stopLeScan",
1477 "(Landroid/bluetooth/"
1478 "BluetoothAdapter$LeScanCallback;)V");
1479 if (!jni_mid_stopLeScan)
1481 OIC_LOG(ERROR, TAG, "stopLeScan: jni_mid_stopLeScan is null");
1482 return CA_STATUS_FAILED;
1485 // gat bt adapter object
1486 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1487 jni_mid_getDefaultAdapter);
1488 if (!jni_obj_BTAdapter)
1490 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1491 return CA_STATUS_FAILED;
1494 OIC_LOG(INFO, TAG, "CALL API - stopLeScan");
1495 // call start le scan method
1496 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_stopLeScan, callback);
1497 if ((*env)->ExceptionCheck(env))
1499 OIC_LOG(ERROR, TAG, "stopLeScan has failed");
1500 (*env)->ExceptionDescribe(env);
1501 (*env)->ExceptionClear(env);
1502 return CA_STATUS_FAILED;
1505 return CA_STATUS_OK;
1508 CAResult_t CALEClientSetFlagToState(JNIEnv *env, jstring jni_address, jint state_idx, jboolean flag)
1510 OIC_LOG(DEBUG, TAG, "IN - CALEClientSetFlagToState");
1511 VERIFY_NON_NULL(env, TAG, "env");
1512 VERIFY_NON_NULL(jni_address, TAG, "jni_address");
1514 ca_mutex_lock(g_deviceStateListMutex);
1516 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1519 OIC_LOG(ERROR, TAG, "address is not available");
1520 return CA_STATUS_FAILED;
1523 if (CALEClientIsDeviceInList(address))
1525 CALEState_t* curState = CALEClientGetStateInfo(address);
1528 OIC_LOG(ERROR, TAG, "curState is null");
1529 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1530 ca_mutex_unlock(g_deviceStateListMutex);
1531 return CA_STATUS_FAILED;
1533 OIC_LOG_V(INFO, TAG, "%d flag is set : %d", state_idx, flag);
1537 case CA_LE_AUTO_CONNECT_FLAG:
1538 curState->autoConnectFlag = flag;
1545 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1546 ca_mutex_unlock(g_deviceStateListMutex);
1547 OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetFlagToState");
1548 return CA_STATUS_OK;
1551 jboolean CALEClientGetFlagFromState(JNIEnv *env, jstring jni_address, jint state_idx)
1553 OIC_LOG(DEBUG, TAG, "IN - CALEClientGetFlagFromState");
1554 VERIFY_NON_NULL_RET(env, TAG, "env", false);
1555 VERIFY_NON_NULL_RET(jni_address, TAG, "jni_address", false);
1557 ca_mutex_lock(g_deviceStateListMutex);
1559 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
1562 OIC_LOG(ERROR, TAG, "address is not available");
1563 ca_mutex_unlock(g_deviceStateListMutex);
1567 CALEState_t* curState = CALEClientGetStateInfo(address);
1568 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1571 OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false");
1572 ca_mutex_unlock(g_deviceStateListMutex);
1576 jboolean ret = JNI_FALSE;
1579 case CA_LE_AUTO_CONNECT_FLAG:
1580 ret = curState->autoConnectFlag;
1585 ca_mutex_unlock(g_deviceStateListMutex);
1587 OIC_LOG_V(INFO, TAG, "%d flag is %d", state_idx, ret);
1588 OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetFlagFromState");
1592 jobject CALEClientConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1594 OIC_LOG(DEBUG, TAG, "CALEClientConnect");
1595 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1596 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1598 // get gatt object from Bluetooth Device object for closeProfileProxy(..)
1599 jstring jni_address = CALEClientGetLEAddressFromBTDevice(env, bluetoothDevice);
1602 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
1605 OIC_LOG(ERROR, TAG, "address is not available");
1609 // close the gatt service
1610 jobject gatt = CALEClientGetGattObjInList(env, address);
1613 CAResult_t res = CALEClientCloseProfileProxy(env, gatt);
1614 if (CA_STATUS_OK != res)
1616 OIC_LOG(ERROR, TAG, "CALEClientCloseProfileProxy has failed");
1617 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1621 // clean previous gatt object after close profile service
1622 res = CALEClientRemoveGattObjForAddr(env, jni_address);
1623 if (CA_STATUS_OK != res)
1625 OIC_LOG(ERROR, TAG, "CALEClientRemoveGattObjForAddr has failed");
1626 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1630 (*env)->ReleaseStringUTFChars(env, jni_address, address);
1633 jobject newGatt = CALEClientGattConnect(env, bluetoothDevice, autoconnect);
1636 OIC_LOG(DEBUG, TAG, "re-connection will be started");
1640 // add new gatt object into g_gattObjectList
1641 CAResult_t res = CALEClientAddGattobjToList(env, newGatt);
1642 if (CA_STATUS_OK != res)
1644 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
1651 jobject CALEClientGattConnect(JNIEnv *env, jobject bluetoothDevice, jboolean autoconnect)
1653 OIC_LOG(DEBUG, TAG, "GATT CONNECT");
1654 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
1655 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
1657 if (!g_leGattCallback)
1659 OIC_LOG(INFO, TAG, "g_leGattCallback is null");
1663 if (!CALEIsEnableBTAdapter(env))
1665 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1669 jstring jni_address = CALEGetAddressFromBTDevice(env, bluetoothDevice);
1672 OIC_LOG(ERROR, TAG, "bleConnect: CALEGetAddressFromBTDevice is null");
1676 // get BluetoothDevice method
1677 OIC_LOG(DEBUG, TAG, "get BluetoothDevice method");
1678 jmethodID jni_mid_connectGatt = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
1680 "(Landroid/content/Context;ZLandroid/"
1681 "bluetooth/BluetoothGattCallback;)"
1682 "Landroid/bluetooth/BluetoothGatt;");
1683 if (!jni_mid_connectGatt)
1685 OIC_LOG(ERROR, TAG, "bleConnect: jni_mid_connectGatt is null");
1689 OIC_LOG(INFO, TAG, "CALL API - connectGatt");
1690 jobject jni_obj_connectGatt = (*env)->CallObjectMethod(env, bluetoothDevice,
1691 jni_mid_connectGatt,
1693 autoconnect, g_leGattCallback);
1694 if (!jni_obj_connectGatt)
1696 OIC_LOG(ERROR, TAG, "connectGatt was failed..it will be removed");
1697 CALEClientRemoveDeviceInScanDeviceList(env, jni_address);
1698 CALEClientUpdateSendCnt(env);
1703 OIC_LOG(DEBUG, TAG, "le connecting..please wait..");
1705 return jni_obj_connectGatt;
1708 CAResult_t CALEClientCloseProfileProxy(JNIEnv *env, jobject gatt)
1710 OIC_LOG(DEBUG, TAG, "IN - CALEClientCloseProfileProxy");
1712 VERIFY_NON_NULL(env, TAG, "env is null");
1713 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1715 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
1716 if (!jni_cid_BTAdapter)
1718 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
1719 return CA_STATUS_FAILED;
1722 // get remote bt adapter method
1723 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1724 "getDefaultAdapter",
1725 METHODID_OBJECTNONPARAM);
1726 if (!jni_mid_getDefaultAdapter)
1728 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
1729 return CA_STATUS_FAILED;
1732 // gat bt adapter object
1733 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1734 jni_mid_getDefaultAdapter);
1735 if (!jni_obj_BTAdapter)
1737 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
1738 return CA_STATUS_FAILED;
1741 // get closeProfileProxy method
1742 jmethodID jni_mid_closeProfileProxy = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1743 "closeProfileProxy",
1744 "(ILandroid/bluetooth/"
1745 "BluetoothProfile;)V");
1746 if (!jni_mid_closeProfileProxy)
1748 OIC_LOG(ERROR, TAG, "jni_mid_closeProfileProxy is null");
1749 return CA_STATUS_FAILED;
1752 jclass jni_cid_BTProfile = (*env)->FindClass(env, CLASSPATH_BT_PROFILE);
1753 if (!jni_cid_BTProfile)
1755 OIC_LOG(ERROR, TAG, "jni_cid_BTProfile is null");
1756 return CA_STATUS_FAILED;
1759 // GATT - Constant value : 7 (0x00000007)
1760 jfieldID id_gatt = (*env)->GetStaticFieldID(env, jni_cid_BTProfile,
1764 OIC_LOG(ERROR, TAG, "id_gatt is null");
1765 return CA_STATUS_FAILED;
1768 jint jni_gatt = (*env)->GetStaticIntField(env, jni_cid_BTProfile, id_gatt);
1770 OIC_LOG(DEBUG, TAG, "CALL API - close the connection of the profile proxy to the Service");
1771 (*env)->CallVoidMethod(env, jni_obj_BTAdapter, jni_mid_closeProfileProxy, jni_gatt, gatt);
1772 if ((*env)->ExceptionCheck(env))
1774 OIC_LOG(ERROR, TAG, "closeProfileProxy has failed");
1775 (*env)->ExceptionDescribe(env);
1776 (*env)->ExceptionClear(env);
1777 return CA_STATUS_FAILED;
1780 OIC_LOG(DEBUG, TAG, "OUT - CALEClientCloseProfileProxy");
1781 return CA_STATUS_OK;
1785 CAResult_t CALEClientDisconnect(JNIEnv *env, jobject bluetoothGatt)
1787 OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1788 VERIFY_NON_NULL(env, TAG, "env is null");
1789 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1791 // get BluetoothGatt method
1792 OIC_LOG(DEBUG, TAG, "get gatt disconnect method");
1793 jmethodID jni_mid_disconnectGatt = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1794 "disconnect", "()V");
1795 if (!jni_mid_disconnectGatt)
1797 OIC_LOG(ERROR, TAG, "jni_mid_disconnectGatt is null");
1798 return CA_STATUS_FAILED;
1801 // call disconnect gatt method
1802 OIC_LOG(INFO, TAG, "CALL API - disconnect");
1803 (*env)->CallVoidMethod(env, bluetoothGatt, jni_mid_disconnectGatt);
1804 if ((*env)->ExceptionCheck(env))
1806 OIC_LOG(ERROR, TAG, "disconnect has failed");
1807 (*env)->ExceptionDescribe(env);
1808 (*env)->ExceptionClear(env);
1809 return CA_STATUS_FAILED;
1812 OIC_LOG(DEBUG, TAG, "disconnecting Gatt...");
1814 return CA_STATUS_OK;
1817 CAResult_t CALEClientDisconnectAll(JNIEnv *env)
1819 OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1820 VERIFY_NON_NULL(env, TAG, "env is null");
1822 if (!g_gattObjectList)
1824 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1825 return CA_STATUS_OK;
1828 uint32_t length = u_arraylist_length(g_gattObjectList);
1829 OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
1830 for (uint32_t index = 0; index < length; index++)
1832 OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
1833 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1836 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1839 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1840 if (CA_STATUS_OK != res)
1842 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1847 return CA_STATUS_OK;
1850 CAResult_t CALEClientDisconnectforAddress(JNIEnv *env, jstring remote_address)
1852 OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
1853 VERIFY_NON_NULL(env, TAG, "env is null");
1855 if (!g_gattObjectList)
1857 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1858 return CA_STATUS_OK;
1861 char* address = (char*)(*env)->GetStringUTFChars(env, remote_address, NULL);
1864 OIC_LOG(ERROR, TAG, "address is null");
1865 return CA_STATUS_FAILED;
1868 uint32_t length = u_arraylist_length(g_gattObjectList);
1869 for (uint32_t index = 0; index < length; index++)
1871 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
1874 OIC_LOG(ERROR, TAG, "jarrayObj is null");
1878 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
1879 if (!jni_setAddress)
1881 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
1882 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1883 return CA_STATUS_FAILED;
1886 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
1889 OIC_LOG(ERROR, TAG, "setAddress is null");
1890 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1891 return CA_STATUS_FAILED;
1894 OIC_LOG_V(DEBUG, TAG, "target address : %s, set address : %s", address, setAddress);
1895 if (!strcmp(address, setAddress))
1897 CAResult_t res = CALEClientDisconnect(env, jarrayObj);
1898 if (CA_STATUS_OK != res)
1900 OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1901 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1902 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1903 return CA_STATUS_FAILED;
1905 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1906 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1907 return CA_STATUS_OK;
1909 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
1911 (*env)->ReleaseStringUTFChars(env, remote_address, address);
1913 OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
1914 return CA_STATUS_OK;
1917 CAResult_t CALEClientDiscoverServices(JNIEnv *env, jobject bluetoothGatt)
1919 VERIFY_NON_NULL(env, TAG, "env is null");
1920 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
1922 if (!CALEIsEnableBTAdapter(env))
1924 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1925 return CA_ADAPTER_NOT_ENABLED;
1928 // get BluetoothGatt.discoverServices method
1929 OIC_LOG(DEBUG, TAG, "get BluetoothGatt.discoverServices method");
1930 jmethodID jni_mid_discoverServices = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
1931 "discoverServices", "()Z");
1932 if (!jni_mid_discoverServices)
1934 OIC_LOG(ERROR, TAG, "jni_mid_discoverServices is null");
1935 return CA_STATUS_FAILED;
1938 // call disconnect gatt method
1939 OIC_LOG(INFO, TAG, "CALL API - discoverServices");
1940 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_discoverServices);
1943 OIC_LOG(ERROR, TAG, "discoverServices has not been started");
1944 return CA_STATUS_FAILED;
1947 return CA_STATUS_OK;
1950 static void CALEWriteCharacteristicThread(void* object)
1952 VERIFY_NON_NULL_VOID(object, TAG, "object is null");
1954 bool isAttached = false;
1956 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
1959 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
1960 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
1964 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
1970 jobject gatt = (jobject)object;
1971 CAResult_t ret = CALESetValueAndWriteCharacteristic(env, gatt);
1972 if (CA_STATUS_OK != ret)
1974 OIC_LOG(ERROR, TAG, "CALESetValueAndWriteCharacteristic has failed");
1979 (*g_jvm)->DetachCurrentThread(g_jvm);
1983 CAResult_t CALESetValueAndWriteCharacteristic(JNIEnv* env, jobject gatt)
1985 OIC_LOG(DEBUG, TAG, "CALESetValueAndWriteCharacteristic");
1987 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
1988 VERIFY_NON_NULL(env, TAG, "env is null");
1990 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
1993 CALEClientSendFinish(env, gatt);
1994 return CA_STATUS_FAILED;
1997 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
2000 CALEClientSendFinish(env, gatt);
2001 return CA_STATUS_FAILED;
2004 ca_mutex_lock(g_threadSendStateMutex);
2006 if (CALEClientIsValidState(address, CA_LE_SEND_STATE, STATE_SENDING))
2008 OIC_LOG(INFO, TAG, "current state is SENDING");
2009 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2010 ca_mutex_unlock(g_threadSendStateMutex);
2011 return CA_STATUS_OK;
2014 if (CA_STATUS_OK != CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
2017 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
2018 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2019 CALEClientSendFinish(env, gatt);
2020 ca_mutex_unlock(g_threadSendStateMutex);
2021 return CA_STATUS_FAILED;
2024 (*env)->ReleaseStringUTFChars(env, jni_address, address);
2026 ca_mutex_unlock(g_threadSendStateMutex);
2029 jobject jni_obj_character = CALEClientCreateGattCharacteristic(env, gatt, g_sendBuffer);
2030 if (!jni_obj_character)
2032 CALEClientSendFinish(env, gatt);
2033 return CA_STATUS_FAILED;
2036 CAResult_t ret = CALEClientWriteCharacteristicImpl(env, gatt, jni_obj_character);
2037 if (CA_STATUS_OK != ret)
2039 CALEClientSendFinish(env, gatt);
2040 return CA_STATUS_FAILED;
2043 // wait for callback for write Characteristic with success to sent data
2044 OIC_LOG_V(DEBUG, TAG, "callback flag is %d", g_isSignalSetFlag);
2045 ca_mutex_lock(g_threadWriteCharacteristicMutex);
2046 if (!g_isSignalSetFlag)
2048 OIC_LOG(DEBUG, TAG, "wait for callback to notify writeCharacteristic is success");
2049 if (CA_WAIT_SUCCESS != ca_cond_wait_for(g_threadWriteCharacteristicCond,
2050 g_threadWriteCharacteristicMutex,
2051 WAIT_TIME_WRITE_CHARACTERISTIC))
2053 OIC_LOG(ERROR, TAG, "there is no response. write has failed");
2054 g_isSignalSetFlag = false;
2055 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2056 return CA_STATUS_FAILED;
2059 // reset flag set by writeCharacteristic Callback
2060 g_isSignalSetFlag = false;
2061 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
2063 OIC_LOG(INFO, TAG, "writeCharacteristic success!!");
2064 return CA_STATUS_OK;
2067 CAResult_t CALEClientWriteCharacteristic(JNIEnv *env, jobject gatt)
2069 OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
2070 VERIFY_NON_NULL(env, TAG, "env is null");
2071 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2073 jobject gattParam = (*env)->NewGlobalRef(env, gatt);
2074 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle,
2075 CALEWriteCharacteristicThread, (void*)gattParam))
2077 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
2078 return CA_STATUS_FAILED;
2081 OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
2082 return CA_STATUS_OK;
2085 CAResult_t CALEClientWriteCharacteristicImpl(JNIEnv *env, jobject bluetoothGatt,
2086 jobject gattCharacteristic)
2088 OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
2089 VERIFY_NON_NULL(env, TAG, "env is null");
2090 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2091 VERIFY_NON_NULL(gattCharacteristic, TAG, "gattCharacteristic is null");
2093 if (!CALEIsEnableBTAdapter(env))
2095 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2096 return CA_STATUS_FAILED;
2099 // get BluetoothGatt.write characteristic method
2100 OIC_LOG(DEBUG, TAG, "write characteristic method");
2101 jmethodID jni_mid_writeCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2102 "writeCharacteristic",
2103 "(Landroid/bluetooth/"
2104 "BluetoothGattCharacteristic;)Z");
2105 if (!jni_mid_writeCharacteristic)
2107 OIC_LOG(ERROR, TAG, "jni_mid_writeCharacteristic is null");
2108 return CA_STATUS_FAILED;
2111 // call disconnect gatt method
2112 OIC_LOG(INFO, TAG, "CALL API - writeCharacteristic");
2113 jboolean ret = (jboolean)(*env)->CallBooleanMethod(env, bluetoothGatt,
2114 jni_mid_writeCharacteristic,
2115 gattCharacteristic);
2118 OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
2122 OIC_LOG(ERROR, TAG, "writeCharacteristic has failed");
2123 return CA_STATUS_FAILED;
2126 return CA_STATUS_OK;
2129 CAResult_t CALEClientReadCharacteristic(JNIEnv *env, jobject bluetoothGatt)
2131 VERIFY_NON_NULL(env, TAG, "env is null");
2132 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2134 if (!CALEIsEnableBTAdapter(env))
2136 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2137 return CA_STATUS_FAILED;
2140 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
2143 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2144 return CA_STATUS_FAILED;
2147 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2148 if (!jni_obj_GattCharacteristic)
2150 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2151 return CA_STATUS_FAILED;
2154 OIC_LOG(DEBUG, TAG, "read characteristic method");
2155 jmethodID jni_mid_readCharacteristic = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2156 "readCharacteristic",
2157 "(Landroid/bluetooth/"
2158 "BluetoothGattCharacteristic;)Z");
2159 if (!jni_mid_readCharacteristic)
2161 OIC_LOG(ERROR, TAG, "jni_mid_readCharacteristic is null");
2162 return CA_STATUS_FAILED;
2165 // call disconnect gatt method
2166 OIC_LOG(INFO, TAG, "CALL API - readCharacteristic");
2167 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_readCharacteristic,
2168 jni_obj_GattCharacteristic);
2171 OIC_LOG(DEBUG, TAG, "readCharacteristic success");
2175 OIC_LOG(ERROR, TAG, "readCharacteristic has failed");
2176 return CA_STATUS_FAILED;
2179 return CA_STATUS_OK;
2182 CAResult_t CALEClientSetCharacteristicNotification(JNIEnv *env, jobject bluetoothGatt,
2183 jobject characteristic)
2185 VERIFY_NON_NULL(env, TAG, "env is null");
2186 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2187 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2189 if (!CALEIsEnableBTAdapter(env))
2191 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2192 return CA_ADAPTER_NOT_ENABLED;
2195 // get BluetoothGatt.setCharacteristicNotification method
2196 OIC_LOG(DEBUG, TAG, "CALEClientSetCharacteristicNotification");
2197 jmethodID jni_mid_setNotification = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2198 "setCharacteristicNotification",
2199 "(Landroid/bluetooth/"
2200 "BluetoothGattCharacteristic;Z)Z");
2201 if (!jni_mid_setNotification)
2203 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2204 return CA_STATUS_FAILED;
2207 OIC_LOG(INFO, TAG, "CALL API - setCharacteristicNotification");
2208 jboolean ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_setNotification,
2209 characteristic, JNI_TRUE);
2210 if (JNI_TRUE == ret)
2212 OIC_LOG(DEBUG, TAG, "setCharacteristicNotification success");
2216 OIC_LOG(ERROR, TAG, "setCharacteristicNotification has failed");
2217 return CA_STATUS_FAILED;
2220 return CA_STATUS_OK;
2223 jobject CALEClientGetGattService(JNIEnv *env, jobject bluetoothGatt, jstring characterUUID)
2225 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2226 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2227 VERIFY_NON_NULL_RET(characterUUID, TAG, "characterUUID is null", NULL);
2229 if (!CALEIsEnableBTAdapter(env))
2231 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2235 // get BluetoothGatt.getService method
2236 OIC_LOG(DEBUG, TAG, "BluetoothGatt.getService");
2237 jmethodID jni_mid_getService = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
2239 "(Ljava/util/UUID;)Landroid/bluetooth/"
2240 "BluetoothGattService;");
2241 if (!jni_mid_getService)
2243 OIC_LOG(ERROR, TAG, "jni_mid_getService is null");
2247 jobject jni_obj_service_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2248 if (!jni_obj_service_uuid)
2250 OIC_LOG(ERROR, TAG, "jni_obj_service_uuid is null");
2254 // get bluetooth gatt service
2255 OIC_LOG(DEBUG, TAG, "request to get service");
2256 jobject jni_obj_gattService = (*env)->CallObjectMethod(env, bluetoothGatt, jni_mid_getService,
2257 jni_obj_service_uuid);
2258 if (!jni_obj_gattService)
2260 OIC_LOG(ERROR, TAG, "jni_obj_gattService is null");
2264 // get bluetooth gatt service method
2265 jmethodID jni_mid_getCharacteristic = CAGetJNIMethodID(env, "android/bluetooth/"
2266 "BluetoothGattService",
2267 "getCharacteristic",
2268 "(Ljava/util/UUID;)"
2269 "Landroid/bluetooth/"
2270 "BluetoothGattCharacteristic;");
2271 if (!jni_mid_getCharacteristic)
2273 OIC_LOG(ERROR, TAG, "jni_mid_getCharacteristic is null");
2277 const char* uuid = (*env)->GetStringUTFChars(env, characterUUID, NULL);
2280 OIC_LOG(ERROR, TAG, "uuid is null");
2284 jobject jni_obj_tx_uuid = CALEClientGetUUIDObject(env, uuid);
2285 if (!jni_obj_tx_uuid)
2287 OIC_LOG(ERROR, TAG, "jni_obj_tx_uuid is null");
2288 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2292 OIC_LOG(DEBUG, TAG, "request to get Characteristic");
2293 jobject jni_obj_GattCharacteristic = (*env)->CallObjectMethod(env, jni_obj_gattService,
2294 jni_mid_getCharacteristic,
2297 (*env)->ReleaseStringUTFChars(env, characterUUID, uuid);
2298 return jni_obj_GattCharacteristic;
2301 jobject CALEClientCreateGattCharacteristic(JNIEnv *env, jobject bluetoothGatt, jbyteArray data)
2303 OIC_LOG(DEBUG, TAG, "CALEClientCreateGattCharacteristic");
2304 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2305 VERIFY_NON_NULL_RET(bluetoothGatt, TAG, "bluetoothGatt is null", NULL);
2306 VERIFY_NON_NULL_RET(data, TAG, "data is null", NULL);
2308 if (!CALEIsEnableBTAdapter(env))
2310 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2314 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_REQUEST_UUID);
2317 OIC_LOG(ERROR, TAG, "jni_uuid is null");
2321 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, bluetoothGatt, jni_uuid);
2322 if (!jni_obj_GattCharacteristic)
2324 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
2328 jclass jni_cid_BTGattCharacteristic = (*env)->FindClass(env, "android/bluetooth"
2329 "/BluetoothGattCharacteristic");
2330 if (!jni_cid_BTGattCharacteristic)
2332 OIC_LOG(ERROR, TAG, "jni_cid_BTGattCharacteristic is null");
2336 OIC_LOG(DEBUG, TAG, "set value in Characteristic");
2337 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic, "setValue",
2339 if (!jni_mid_setValue)
2341 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2345 jboolean ret = (*env)->CallBooleanMethod(env, jni_obj_GattCharacteristic, jni_mid_setValue,
2347 if (JNI_TRUE == ret)
2349 OIC_LOG(DEBUG, TAG, "the locally stored value has been set");
2353 OIC_LOG(ERROR, TAG, "the locally stored value hasn't been set");
2358 jmethodID jni_mid_setWriteType = (*env)->GetMethodID(env, jni_cid_BTGattCharacteristic,
2359 "setWriteType", "(I)V");
2360 if (!jni_mid_setWriteType)
2362 OIC_LOG(ERROR, TAG, "jni_mid_setWriteType is null");
2366 jfieldID jni_fid_no_response = (*env)->GetStaticFieldID(env, jni_cid_BTGattCharacteristic,
2367 "WRITE_TYPE_NO_RESPONSE", "I");
2368 if (!jni_fid_no_response)
2370 OIC_LOG(ERROR, TAG, "jni_fid_no_response is not available");
2374 jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTGattCharacteristic,
2375 jni_fid_no_response);
2377 (*env)->CallVoidMethod(env, jni_obj_GattCharacteristic, jni_mid_setWriteType, jni_int_val);
2379 return jni_obj_GattCharacteristic;
2382 jbyteArray CALEClientGetValueFromCharacteristic(JNIEnv *env, jobject characteristic)
2384 VERIFY_NON_NULL_RET(characteristic, TAG, "characteristic is null", NULL);
2385 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2387 if (!CALEIsEnableBTAdapter(env))
2389 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2393 jmethodID jni_mid_getValue = CAGetJNIMethodID(env, "android/bluetooth/"
2394 "BluetoothGattCharacteristic",
2395 "getValue", "()[B");
2396 if (!jni_mid_getValue)
2398 OIC_LOG(ERROR, TAG, "jni_mid_getValue is null");
2402 jbyteArray jni_obj_data_array = (*env)->CallObjectMethod(env, characteristic,
2404 return jni_obj_data_array;
2407 CAResult_t CALEClientCreateUUIDList()
2411 OIC_LOG(ERROR, TAG, "g_jvm is null");
2412 return CA_STATUS_FAILED;
2415 bool isAttached = false;
2417 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
2420 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
2421 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
2425 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
2426 return CA_STATUS_FAILED;
2431 // create new object array
2432 jclass jni_cid_uuid_list = (*env)->FindClass(env, CLASSPATH_BT_UUID);
2433 if (!jni_cid_uuid_list)
2435 OIC_LOG(ERROR, TAG, "jni_cid_uuid_list is null");
2439 jobjectArray jni_obj_uuid_list = (jobjectArray)(*env)->NewObjectArray(env, 1,
2440 jni_cid_uuid_list, NULL);
2441 if (!jni_obj_uuid_list)
2443 OIC_LOG(ERROR, TAG, "jni_obj_uuid_list is null");
2448 jobject jni_obj_uuid = CALEClientGetUUIDObject(env, OIC_GATT_SERVICE_UUID);
2451 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
2454 (*env)->SetObjectArrayElement(env, jni_obj_uuid_list, 0, jni_obj_uuid);
2456 g_uuidList = (jobjectArray)(*env)->NewGlobalRef(env, jni_obj_uuid_list);
2460 (*g_jvm)->DetachCurrentThread(g_jvm);
2463 return CA_STATUS_OK;
2470 (*g_jvm)->DetachCurrentThread(g_jvm);
2472 return CA_STATUS_FAILED;
2475 CAResult_t CALEClientSetUUIDToDescriptor(JNIEnv *env, jobject bluetoothGatt,
2476 jobject characteristic)
2478 VERIFY_NON_NULL(env, TAG, "env is null");
2479 VERIFY_NON_NULL(bluetoothGatt, TAG, "bluetoothGatt is null");
2480 VERIFY_NON_NULL(characteristic, TAG, "characteristic is null");
2482 if (!CALEIsEnableBTAdapter(env))
2484 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
2485 return CA_ADAPTER_NOT_ENABLED;
2488 OIC_LOG(DEBUG, TAG, "CALEClientSetUUIDToDescriptor");
2489 jmethodID jni_mid_getDescriptor = CAGetJNIMethodID(env, "android/bluetooth/"
2490 "BluetoothGattCharacteristic",
2492 "(Ljava/util/UUID;)Landroid/bluetooth/"
2493 "BluetoothGattDescriptor;");
2494 if (!jni_mid_getDescriptor)
2496 OIC_LOG(ERROR, TAG, "jni_mid_getDescriptor is null");
2497 return CA_STATUS_FAILED;
2500 jobject jni_obj_cc_uuid = CALEClientGetUUIDObject(env, OIC_GATT_CHARACTERISTIC_CONFIG_UUID);
2501 if (!jni_obj_cc_uuid)
2503 OIC_LOG(ERROR, TAG, "jni_obj_cc_uuid is null");
2504 return CA_STATUS_FAILED;
2507 OIC_LOG(DEBUG, TAG, "request to get descriptor");
2508 jobject jni_obj_descriptor = (*env)->CallObjectMethod(env, characteristic,
2509 jni_mid_getDescriptor, jni_obj_cc_uuid);
2510 if (!jni_obj_descriptor)
2512 OIC_LOG(INFO, TAG, "jni_obj_descriptor is null");
2513 return CA_NOT_SUPPORTED;
2516 OIC_LOG(DEBUG, TAG, "set value in descriptor");
2517 jclass jni_cid_descriptor = (*env)->FindClass(env,
2518 "android/bluetooth/BluetoothGattDescriptor");
2519 if (!jni_cid_descriptor)
2521 OIC_LOG(ERROR, TAG, "jni_cid_descriptor is null");
2522 return CA_STATUS_FAILED;
2525 jmethodID jni_mid_setValue = (*env)->GetMethodID(env, jni_cid_descriptor, "setValue", "([B)Z");
2526 if (!jni_mid_setValue)
2528 OIC_LOG(ERROR, TAG, "jni_mid_setValue is null");
2529 return CA_STATUS_FAILED;
2532 jfieldID jni_fid_NotiValue = (*env)->GetStaticFieldID(env, jni_cid_descriptor,
2533 "ENABLE_NOTIFICATION_VALUE", "[B");
2534 if (!jni_fid_NotiValue)
2536 OIC_LOG(ERROR, TAG, "jni_fid_NotiValue is null");
2537 return CA_STATUS_FAILED;
2540 OIC_LOG(DEBUG, TAG, "get ENABLE_NOTIFICATION_VALUE");
2542 jboolean jni_setvalue = (*env)->CallBooleanMethod(
2543 env, jni_obj_descriptor, jni_mid_setValue,
2544 (jbyteArray)(*env)->GetStaticObjectField(env, jni_cid_descriptor, jni_fid_NotiValue));
2547 OIC_LOG(DEBUG, TAG, "setValue success");
2551 OIC_LOG(ERROR, TAG, "setValue has failed");
2552 return CA_STATUS_FAILED;
2555 jmethodID jni_mid_writeDescriptor = CAGetJNIMethodID(env, "android/bluetooth/BluetoothGatt",
2557 "(Landroid/bluetooth/"
2558 "BluetoothGattDescriptor;)Z");
2559 if (!jni_mid_writeDescriptor)
2561 OIC_LOG(ERROR, TAG, "jni_mid_writeDescriptor is null");
2562 return CA_STATUS_FAILED;
2565 OIC_LOG(INFO, TAG, "CALL API - writeDescriptor");
2566 jboolean jni_ret = (*env)->CallBooleanMethod(env, bluetoothGatt, jni_mid_writeDescriptor,
2567 jni_obj_descriptor);
2570 OIC_LOG(DEBUG, TAG, "writeDescriptor success");
2574 OIC_LOG(ERROR, TAG, "writeDescriptor has failed");
2575 return CA_STATUS_FAILED;
2578 return CA_STATUS_OK;
2581 void CALEClientCreateScanDeviceList(JNIEnv *env)
2583 OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
2584 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
2586 ca_mutex_lock(g_deviceListMutex);
2587 // create new object array
2588 if (g_deviceList == NULL)
2590 OIC_LOG(DEBUG, TAG, "Create device list");
2592 g_deviceList = u_arraylist_create();
2594 ca_mutex_unlock(g_deviceListMutex);
2597 CAResult_t CALEClientAddScanDeviceToList(JNIEnv *env, jobject device)
2599 VERIFY_NON_NULL(device, TAG, "device is null");
2600 VERIFY_NON_NULL(env, TAG, "env is null");
2602 ca_mutex_lock(g_deviceListMutex);
2606 OIC_LOG(ERROR, TAG, "gdevice_list is null");
2608 CALEClientSetScanFlag(false);
2609 if (CA_STATUS_OK != CALEClientStopScan())
2611 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
2614 ca_mutex_unlock(g_deviceListMutex);
2615 return CA_STATUS_FAILED;
2618 jstring jni_remoteAddress = CALEGetAddressFromBTDevice(env, device);
2619 if (!jni_remoteAddress)
2621 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2622 ca_mutex_unlock(g_deviceListMutex);
2623 return CA_STATUS_FAILED;
2626 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2629 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2630 ca_mutex_unlock(g_deviceListMutex);
2631 return CA_STATUS_FAILED;
2634 if (!CALEClientIsDeviceInScanDeviceList(env, remoteAddress))
2636 jobject gdevice = (*env)->NewGlobalRef(env, device);
2637 u_arraylist_add(g_deviceList, gdevice);
2638 ca_cond_signal(g_deviceDescCond);
2639 OIC_LOG_V(DEBUG, TAG, "Added a new BT Device in deviceList [%s]", remoteAddress);
2641 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2643 ca_mutex_unlock(g_deviceListMutex);
2645 return CA_STATUS_OK;
2648 bool CALEClientIsDeviceInScanDeviceList(JNIEnv *env, const char* remoteAddress)
2650 VERIFY_NON_NULL_RET(env, TAG, "env is null", true);
2651 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2655 OIC_LOG(DEBUG, TAG, "g_deviceList is null");
2659 uint32_t length = u_arraylist_length(g_deviceList);
2660 for (uint32_t index = 0; index < length; index++)
2662 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2665 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2669 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2670 if (!jni_setAddress)
2672 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2676 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2679 OIC_LOG(ERROR, TAG, "setAddress is null");
2683 if (!strcmp(remoteAddress, setAddress))
2685 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2689 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2692 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in scanned device list", remoteAddress);
2697 CAResult_t CALEClientRemoveAllScanDevices(JNIEnv *env)
2699 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
2700 VERIFY_NON_NULL(env, TAG, "env is null");
2702 ca_mutex_lock(g_deviceListMutex);
2706 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2707 ca_mutex_unlock(g_deviceListMutex);
2708 return CA_STATUS_FAILED;
2711 uint32_t length = u_arraylist_length(g_deviceList);
2712 for (uint32_t index = 0; index < length; index++)
2714 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2717 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2720 (*env)->DeleteGlobalRef(env, jarrayObj);
2724 OICFree(g_deviceList);
2725 g_deviceList = NULL;
2727 ca_mutex_unlock(g_deviceListMutex);
2728 return CA_STATUS_OK;
2731 CAResult_t CALEClientRemoveDeviceInScanDeviceList(JNIEnv *env, jstring address)
2733 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
2734 VERIFY_NON_NULL(address, TAG, "address is null");
2735 VERIFY_NON_NULL(env, TAG, "env is null");
2737 ca_mutex_lock(g_deviceListMutex);
2741 OIC_LOG(ERROR, TAG, "g_deviceList is null");
2742 ca_mutex_unlock(g_deviceListMutex);
2743 return CA_STATUS_FAILED;
2746 uint32_t length = u_arraylist_length(g_deviceList);
2747 for (uint32_t index = 0; index < length; index++)
2749 jobject jarrayObj = (jobject) u_arraylist_get(g_deviceList, index);
2752 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2753 ca_mutex_unlock(g_deviceListMutex);
2754 return CA_STATUS_FAILED;
2757 jstring jni_setAddress = CALEGetAddressFromBTDevice(env, jarrayObj);
2758 if (!jni_setAddress)
2760 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2761 ca_mutex_unlock(g_deviceListMutex);
2762 return CA_STATUS_FAILED;
2765 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2768 OIC_LOG(ERROR, TAG, "setAddress is null");
2769 ca_mutex_unlock(g_deviceListMutex);
2770 return CA_STATUS_FAILED;
2773 const char* remoteAddress = (*env)->GetStringUTFChars(env, address, NULL);
2776 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2777 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2778 ca_mutex_unlock(g_deviceListMutex);
2779 return CA_STATUS_FAILED;
2782 if (!strcmp(setAddress, remoteAddress))
2784 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
2785 (*env)->DeleteGlobalRef(env, jarrayObj);
2787 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2788 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2790 if (NULL == u_arraylist_remove(g_deviceList, index))
2792 OIC_LOG(ERROR, TAG, "List removal failed.");
2793 ca_mutex_unlock(g_deviceListMutex);
2794 return CA_STATUS_FAILED;
2796 ca_mutex_unlock(g_deviceListMutex);
2797 return CA_STATUS_OK;
2799 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2800 (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
2803 ca_mutex_unlock(g_deviceListMutex);
2804 OIC_LOG(DEBUG, TAG, "There are no object in the device list");
2806 return CA_STATUS_OK;
2813 CAResult_t CALEClientAddGattobjToList(JNIEnv *env, jobject gatt)
2815 OIC_LOG(DEBUG, TAG, "CALEClientAddGattobjToList");
2816 VERIFY_NON_NULL(env, TAG, "env is null");
2817 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2819 ca_mutex_lock(g_gattObjectMutex);
2821 if (!g_gattObjectList)
2823 OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
2824 ca_mutex_unlock(g_gattObjectMutex);
2825 return CA_STATUS_FAILED;
2828 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
2829 if (!jni_remoteAddress)
2831 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
2832 ca_mutex_unlock(g_gattObjectMutex);
2833 return CA_STATUS_FAILED;
2836 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
2839 OIC_LOG(ERROR, TAG, "remoteAddress is null");
2840 ca_mutex_unlock(g_gattObjectMutex);
2841 return CA_STATUS_FAILED;
2844 OIC_LOG_V(DEBUG, TAG, "remote address : %s", remoteAddress);
2845 if (!CALEClientIsGattObjInList(env, remoteAddress))
2847 jobject newGatt = (*env)->NewGlobalRef(env, gatt);
2848 u_arraylist_add(g_gattObjectList, newGatt);
2849 OIC_LOG(INFO, TAG, "added a newGatt object to gattObjectList");
2852 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
2853 ca_mutex_unlock(g_gattObjectMutex);
2854 return CA_STATUS_OK;
2857 bool CALEClientIsGattObjInList(JNIEnv *env, const char* remoteAddress)
2859 OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
2860 VERIFY_NON_NULL(env, TAG, "env is null");
2861 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2863 uint32_t length = u_arraylist_length(g_gattObjectList);
2864 for (uint32_t index = 0; index < length; index++)
2867 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2870 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2874 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2875 if (!jni_setAddress)
2877 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2881 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2884 OIC_LOG(ERROR, TAG, "setAddress is null");
2888 if (!strcmp(remoteAddress, setAddress))
2890 OIC_LOG(DEBUG, TAG, "the device is already set");
2891 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2896 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2901 OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
2905 jobject CALEClientGetGattObjInList(JNIEnv *env, const char* remoteAddress)
2907 OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
2908 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
2909 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2911 ca_mutex_lock(g_gattObjectMutex);
2912 uint32_t length = u_arraylist_length(g_gattObjectList);
2913 for (uint32_t index = 0; index < length; index++)
2915 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2918 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2919 ca_mutex_unlock(g_gattObjectMutex);
2923 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
2924 if (!jni_setAddress)
2926 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
2927 ca_mutex_unlock(g_gattObjectMutex);
2931 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
2934 OIC_LOG(ERROR, TAG, "setAddress is null");
2935 ca_mutex_unlock(g_gattObjectMutex);
2939 if (!strcmp(remoteAddress, setAddress))
2941 OIC_LOG(DEBUG, TAG, "the device is already set");
2942 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2943 ca_mutex_unlock(g_gattObjectMutex);
2946 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
2949 ca_mutex_unlock(g_gattObjectMutex);
2950 OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
2954 CAResult_t CALEClientRemoveAllGattObjs(JNIEnv *env)
2956 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
2957 VERIFY_NON_NULL(env, TAG, "env is null");
2959 ca_mutex_lock(g_gattObjectMutex);
2960 if (!g_gattObjectList)
2962 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2963 ca_mutex_unlock(g_gattObjectMutex);
2964 return CA_STATUS_OK;
2967 uint32_t length = u_arraylist_length(g_gattObjectList);
2968 for (uint32_t index = 0; index < length; index++)
2970 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
2973 OIC_LOG(ERROR, TAG, "jarrayObj is null");
2976 (*env)->DeleteGlobalRef(env, jarrayObj);
2980 OICFree(g_gattObjectList);
2981 g_gattObjectList = NULL;
2982 OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
2983 ca_mutex_unlock(g_gattObjectMutex);
2984 return CA_STATUS_OK;
2987 CAResult_t CALEClientRemoveGattObj(JNIEnv *env, jobject gatt)
2989 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
2990 VERIFY_NON_NULL(gatt, TAG, "gatt is null");
2991 VERIFY_NON_NULL(env, TAG, "env is null");
2993 ca_mutex_lock(g_gattObjectMutex);
2994 if (!g_gattObjectList)
2996 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2997 ca_mutex_unlock(g_gattObjectMutex);
2998 return CA_STATUS_OK;
3001 uint32_t length = u_arraylist_length(g_gattObjectList);
3002 for (uint32_t index = 0; index < length; index++)
3004 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3007 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3008 ca_mutex_unlock(g_gattObjectMutex);
3009 return CA_STATUS_FAILED;
3012 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3013 if (!jni_setAddress)
3015 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3016 ca_mutex_unlock(g_gattObjectMutex);
3017 return CA_STATUS_FAILED;
3020 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3023 OIC_LOG(ERROR, TAG, "setAddress is null");
3024 ca_mutex_unlock(g_gattObjectMutex);
3025 return CA_STATUS_FAILED;
3028 jstring jni_remoteAddress = CALEClientGetAddressFromGattObj(env, gatt);
3029 if (!jni_remoteAddress)
3031 OIC_LOG(ERROR, TAG, "jni_remoteAddress is null");
3032 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3033 ca_mutex_unlock(g_gattObjectMutex);
3034 return CA_STATUS_FAILED;
3037 const char* remoteAddress = (*env)->GetStringUTFChars(env, jni_remoteAddress, NULL);
3040 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3041 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3042 ca_mutex_unlock(g_gattObjectMutex);
3043 return CA_STATUS_FAILED;
3046 if (!strcmp(setAddress, remoteAddress))
3048 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3049 (*env)->DeleteGlobalRef(env, jarrayObj);
3051 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3052 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3054 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3056 OIC_LOG(ERROR, TAG, "List removal failed.");
3057 ca_mutex_unlock(g_gattObjectMutex);
3058 return CA_STATUS_FAILED;
3060 ca_mutex_unlock(g_gattObjectMutex);
3061 return CA_STATUS_OK;
3063 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3064 (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
3067 ca_mutex_unlock(g_gattObjectMutex);
3068 OIC_LOG(DEBUG, TAG, "there are no target object");
3069 return CA_STATUS_OK;
3072 CAResult_t CALEClientRemoveGattObjForAddr(JNIEnv *env, jstring addr)
3074 OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
3075 VERIFY_NON_NULL(addr, TAG, "addr is null");
3076 VERIFY_NON_NULL(env, TAG, "env is null");
3078 ca_mutex_lock(g_gattObjectMutex);
3079 if (!g_gattObjectList)
3081 OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
3082 ca_mutex_unlock(g_gattObjectMutex);
3083 return CA_STATUS_OK;
3086 uint32_t length = u_arraylist_length(g_gattObjectList);
3087 for (uint32_t index = 0; index < length; index++)
3089 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3092 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3093 ca_mutex_unlock(g_gattObjectMutex);
3094 return CA_STATUS_FAILED;
3097 jstring jni_setAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3098 if (!jni_setAddress)
3100 OIC_LOG(ERROR, TAG, "jni_setAddress is null");
3101 ca_mutex_unlock(g_gattObjectMutex);
3102 return CA_STATUS_FAILED;
3105 const char* setAddress = (*env)->GetStringUTFChars(env, jni_setAddress, NULL);
3108 OIC_LOG(ERROR, TAG, "setAddress is null");
3109 ca_mutex_unlock(g_gattObjectMutex);
3110 return CA_STATUS_FAILED;
3113 const char* remoteAddress = (*env)->GetStringUTFChars(env, addr, NULL);
3116 OIC_LOG(ERROR, TAG, "remoteAddress is null");
3117 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3118 ca_mutex_unlock(g_gattObjectMutex);
3119 return CA_STATUS_FAILED;
3122 if (!strcmp(setAddress, remoteAddress))
3124 OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
3125 (*env)->DeleteGlobalRef(env, jarrayObj);
3127 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3128 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3129 if (NULL == u_arraylist_remove(g_gattObjectList, index))
3131 OIC_LOG(ERROR, TAG, "List removal failed.");
3132 ca_mutex_unlock(g_gattObjectMutex);
3133 return CA_STATUS_FAILED;
3135 ca_mutex_unlock(g_gattObjectMutex);
3136 return CA_STATUS_OK;
3138 (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
3139 (*env)->ReleaseStringUTFChars(env, addr, remoteAddress);
3142 ca_mutex_unlock(g_gattObjectMutex);
3143 OIC_LOG(DEBUG, TAG, "there are no target object");
3144 return CA_STATUS_FAILED;
3147 jstring CALEClientGetLEAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
3149 OIC_LOG(DEBUG, TAG, "CALEClientGetLEAddressFromBTDevice");
3151 VERIFY_NON_NULL_RET(env, TAG, "env", NULL);
3152 VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice", NULL);
3154 // get Bluetooth Address
3155 jstring jni_btTargetAddress = CALEGetAddressFromBTDevice(env, bluetoothDevice);
3156 if (!jni_btTargetAddress)
3158 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3162 const char* targetAddress = (*env)->GetStringUTFChars(env, jni_btTargetAddress, NULL);
3165 OIC_LOG(ERROR, TAG, "targetAddress is not available");
3169 // get method ID of getDevice()
3170 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
3171 "getDevice", METHODID_BT_DEVICE);
3172 if (!jni_mid_getDevice)
3174 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
3175 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3179 ca_mutex_lock(g_gattObjectMutex);
3181 size_t length = u_arraylist_length(g_gattObjectList);
3182 OIC_LOG_V(DEBUG, TAG, "length of gattObjectList : %d", length);
3183 OIC_LOG_V(DEBUG, TAG, "targetAddress : %s", targetAddress);
3185 for (size_t index = 0; index < length; index++)
3187 jobject jarrayObj = (jobject) u_arraylist_get(g_gattObjectList, index);
3190 ca_mutex_unlock(g_gattObjectMutex);
3191 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3192 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3196 jobject jni_obj_device = (*env)->CallObjectMethod(env, jarrayObj, jni_mid_getDevice);
3197 if (!jni_obj_device)
3199 ca_mutex_unlock(g_gattObjectMutex);
3200 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
3201 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3205 jstring jni_btAddress = CALEGetAddressFromBTDevice(env, jni_obj_device);
3208 ca_mutex_unlock(g_gattObjectMutex);
3209 OIC_LOG(ERROR, TAG, "CALEGetAddressFromBTDevice has failed");
3210 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3214 const char* btAddress = (*env)->GetStringUTFChars(env, jni_btAddress, NULL);
3217 ca_mutex_unlock(g_gattObjectMutex);
3218 OIC_LOG(ERROR, TAG, "btAddress is not available");
3219 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3223 OIC_LOG_V(DEBUG, TAG, "btAddress : %s (idx: %d)", btAddress, index);
3224 if (!strcmp(targetAddress, btAddress))
3226 OIC_LOG(DEBUG, TAG, "Found Gatt object from BT device");
3229 jstring jni_LEAddress = CALEClientGetAddressFromGattObj(env, jarrayObj);
3232 OIC_LOG(ERROR, TAG, "jni_LEAddress is null");
3234 ca_mutex_unlock(g_gattObjectMutex);
3235 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3236 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3237 (*env)->DeleteLocalRef(env, jni_btAddress);
3238 (*env)->DeleteLocalRef(env, jni_obj_device);
3239 return jni_LEAddress;
3241 (*env)->ReleaseStringUTFChars(env, jni_btAddress, btAddress);
3242 (*env)->DeleteLocalRef(env, jni_btAddress);
3243 (*env)->DeleteLocalRef(env, jni_obj_device);
3245 ca_mutex_unlock(g_gattObjectMutex);
3247 (*env)->ReleaseStringUTFChars(env, jni_btTargetAddress, targetAddress);
3248 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in gattObjectList", targetAddress);
3256 CAResult_t CALEClientUpdateDeviceState(const char* address, uint16_t state_type,
3257 uint16_t target_state)
3259 VERIFY_NON_NULL(address, TAG, "address is null");
3260 VERIFY_NON_NULL(address, TAG, "state_type is null");
3261 VERIFY_NON_NULL(address, TAG, "target_state is null");
3263 if (!g_deviceStateList)
3265 OIC_LOG(ERROR, TAG, "gdevice_list is null");
3266 return CA_STATUS_FAILED;
3269 ca_mutex_lock(g_deviceStateListMutex);
3271 if (CALEClientIsDeviceInList(address))
3273 CALEState_t* curState = CALEClientGetStateInfo(address);
3276 OIC_LOG(ERROR, TAG, "curState is null");
3277 ca_mutex_unlock(g_deviceStateListMutex);
3278 return CA_STATUS_FAILED;
3283 case CA_LE_CONNECTION_STATE:
3284 curState->connectedState = target_state;
3286 case CA_LE_SEND_STATE:
3287 curState->sendState = target_state;
3292 OIC_LOG_V(INFO, TAG, "update state - addr : %s, conn : %d, send : %d, ACFlag : %d",
3293 curState->address, curState->connectedState, curState->sendState,
3294 curState->autoConnectFlag);
3296 else /** state is added newly **/
3298 if (strlen(address) > CA_MACADDR_SIZE)
3300 OIC_LOG(ERROR, TAG, "address is not proper");
3301 ca_mutex_unlock(g_deviceStateListMutex);
3302 return CA_STATUS_INVALID_PARAM;
3305 CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
3308 OIC_LOG(ERROR, TAG, "out of memory");
3309 ca_mutex_unlock(g_deviceStateListMutex);
3310 return CA_MEMORY_ALLOC_FAILED;
3313 OICStrcpy(newstate->address, sizeof(newstate->address), address);
3317 case CA_LE_CONNECTION_STATE:
3318 newstate->connectedState = target_state;
3319 newstate->sendState = STATE_SEND_NONE;
3321 case CA_LE_SEND_STATE:
3322 newstate->connectedState = STATE_DISCONNECTED;
3323 newstate->sendState = target_state;
3328 OIC_LOG_V(INFO, TAG, "add a new state to List - addr : %s, "
3329 "conn : %d, send : %d, ACFlag : %d",
3330 newstate->address, newstate->connectedState, newstate->sendState,
3331 newstate->autoConnectFlag);
3332 u_arraylist_add(g_deviceStateList, newstate); // update new state
3335 ca_mutex_unlock(g_deviceStateListMutex);
3337 return CA_STATUS_OK;
3340 bool CALEClientIsDeviceInList(const char* remoteAddress)
3342 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3344 if (!g_deviceStateList)
3346 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3350 uint32_t length = u_arraylist_length(g_deviceStateList);
3351 for (uint32_t index = 0; index < length; index++)
3353 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3356 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3360 if (!strcmp(remoteAddress, state->address))
3362 OIC_LOG(DEBUG, TAG, "the device is already set");
3371 OIC_LOG(DEBUG, TAG, "there are no the device in list.");
3375 CAResult_t CALEClientRemoveAllDeviceState()
3377 OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
3379 ca_mutex_lock(g_deviceStateListMutex);
3380 if (!g_deviceStateList)
3382 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3383 ca_mutex_unlock(g_deviceStateListMutex);
3384 return CA_STATUS_FAILED;
3387 uint32_t length = u_arraylist_length(g_deviceStateList);
3388 for (uint32_t index = 0; index < length; index++)
3390 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3393 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3399 OICFree(g_deviceStateList);
3400 g_deviceStateList = NULL;
3401 ca_mutex_unlock(g_deviceStateListMutex);
3403 return CA_STATUS_OK;
3406 CAResult_t CALEClientResetDeviceStateForAll()
3408 OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll");
3410 ca_mutex_lock(g_deviceStateListMutex);
3411 if (!g_deviceStateList)
3413 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3414 ca_mutex_unlock(g_deviceStateListMutex);
3415 return CA_STATUS_FAILED;
3418 size_t length = u_arraylist_length(g_deviceStateList);
3419 for (size_t index = 0; index < length; index++)
3421 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3424 OIC_LOG(ERROR, TAG, "jarrayObj is null");
3428 // autoConnectFlag value will be not changed,
3429 // since it has reset only termination case.
3430 state->connectedState = STATE_DISCONNECTED;
3431 state->sendState = STATE_SEND_NONE;
3433 ca_mutex_unlock(g_deviceStateListMutex);
3435 return CA_STATUS_OK;
3438 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
3440 OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
3441 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3443 if (!g_deviceStateList)
3445 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3446 return CA_STATUS_FAILED;
3449 uint32_t length = u_arraylist_length(g_deviceStateList);
3450 for (uint32_t index = 0; index < length; index++)
3452 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3455 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3459 if (!strcmp(state->address, remoteAddress))
3461 OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
3463 CALEState_t* targetState = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
3465 if (NULL == targetState)
3467 OIC_LOG(ERROR, TAG, "List removal failed.");
3468 return CA_STATUS_FAILED;
3471 OICFree(targetState);
3472 return CA_STATUS_OK;
3476 return CA_STATUS_OK;
3479 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
3481 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
3483 if (!g_deviceStateList)
3485 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3489 uint32_t length = u_arraylist_length(g_deviceStateList);
3490 OIC_LOG_V(DEBUG, TAG, "length of deviceStateList : %d", length);
3491 OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
3493 for (uint32_t index = 0; index < length; index++)
3495 CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
3498 OIC_LOG(ERROR, TAG, "CALEState_t object is null");
3502 OIC_LOG_V(DEBUG, TAG, "state address : %s (idx: %d)", state->address, index);
3504 if (!strcmp(state->address, remoteAddress))
3506 OIC_LOG(DEBUG, TAG, "found state");
3511 OIC_LOG_V(DEBUG, TAG, "[%s] doesn't exist in deviceStateList", remoteAddress);
3515 bool CALEClientIsValidState(const char* remoteAddress, uint16_t state_type,
3516 uint16_t target_state)
3518 OIC_LOG_V(DEBUG, TAG, "CALEClientIsValidState : type[%d], target state[%d]",
3519 state_type, target_state);
3520 VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
3522 ca_mutex_lock(g_deviceStateListMutex);
3523 if (!g_deviceStateList)
3525 OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
3526 ca_mutex_unlock(g_deviceStateListMutex);
3530 CALEState_t* state = CALEClientGetStateInfo(remoteAddress);
3533 OIC_LOG(ERROR, TAG, "state is null");
3534 ca_mutex_unlock(g_deviceStateListMutex);
3538 uint16_t curValue = 0;
3541 case CA_LE_CONNECTION_STATE:
3542 curValue = state->connectedState;
3544 case CA_LE_SEND_STATE:
3545 curValue = state->sendState;
3551 if (target_state == curValue)
3553 ca_mutex_unlock(g_deviceStateListMutex);
3558 ca_mutex_unlock(g_deviceStateListMutex);
3562 ca_mutex_unlock(g_deviceStateListMutex);
3566 void CALEClientCreateDeviceList()
3568 OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
3570 // create new object array
3571 if (!g_gattObjectList)
3573 OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
3575 g_gattObjectList = u_arraylist_create();
3578 if (!g_deviceStateList)
3580 OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
3582 g_deviceStateList = u_arraylist_create();
3587 OIC_LOG(DEBUG, TAG, "Create g_deviceList");
3589 g_deviceList = u_arraylist_create();
3594 * Check Sent Count for remove g_sendBuffer
3596 void CALEClientUpdateSendCnt(JNIEnv *env)
3598 OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
3600 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3602 ca_mutex_lock(g_threadMutex);
3606 if (g_targetCnt <= g_currentSentCnt)
3609 g_currentSentCnt = 0;
3613 (*env)->DeleteGlobalRef(env, g_sendBuffer);
3614 g_sendBuffer = NULL;
3616 // notity the thread
3617 ca_cond_signal(g_threadCond);
3619 CALEClientSetSendFinishFlag(true);
3620 OIC_LOG(DEBUG, TAG, "set signal for send data");
3623 ca_mutex_unlock(g_threadMutex);
3626 CAResult_t CALEClientInitGattMutexVaraibles()
3628 if (NULL == g_bleReqRespClientCbMutex)
3630 g_bleReqRespClientCbMutex = ca_mutex_new();
3631 if (NULL == g_bleReqRespClientCbMutex)
3633 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3634 return CA_STATUS_FAILED;
3638 if (NULL == g_bleServerBDAddressMutex)
3640 g_bleServerBDAddressMutex = ca_mutex_new();
3641 if (NULL == g_bleServerBDAddressMutex)
3643 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3644 return CA_STATUS_FAILED;
3648 if (NULL == g_threadMutex)
3650 g_threadMutex = ca_mutex_new();
3651 if (NULL == g_threadMutex)
3653 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3654 return CA_STATUS_FAILED;
3658 if (NULL == g_threadSendMutex)
3660 g_threadSendMutex = ca_mutex_new();
3661 if (NULL == g_threadSendMutex)
3663 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3664 return CA_STATUS_FAILED;
3668 if (NULL == g_deviceListMutex)
3670 g_deviceListMutex = ca_mutex_new();
3671 if (NULL == g_deviceListMutex)
3673 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3674 return CA_STATUS_FAILED;
3678 if (NULL == g_gattObjectMutex)
3680 g_gattObjectMutex = ca_mutex_new();
3681 if (NULL == g_gattObjectMutex)
3683 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3684 return CA_STATUS_FAILED;
3688 if (NULL == g_deviceStateListMutex)
3690 g_deviceStateListMutex = ca_mutex_new();
3691 if (NULL == g_deviceStateListMutex)
3693 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3694 return CA_STATUS_FAILED;
3698 if (NULL == g_SendFinishMutex)
3700 g_SendFinishMutex = ca_mutex_new();
3701 if (NULL == g_SendFinishMutex)
3703 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3704 return CA_STATUS_FAILED;
3708 if (NULL == g_scanMutex)
3710 g_scanMutex = ca_mutex_new();
3711 if (NULL == g_scanMutex)
3713 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3714 return CA_STATUS_FAILED;
3718 if (NULL == g_threadWriteCharacteristicMutex)
3720 g_threadWriteCharacteristicMutex = ca_mutex_new();
3721 if (NULL == g_threadWriteCharacteristicMutex)
3723 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3724 return CA_STATUS_FAILED;
3728 if (NULL == g_deviceScanRetryDelayMutex)
3730 g_deviceScanRetryDelayMutex = ca_mutex_new();
3731 if (NULL == g_deviceScanRetryDelayMutex)
3733 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3734 return CA_STATUS_FAILED;
3738 if (NULL == g_threadSendStateMutex)
3740 g_threadSendStateMutex = ca_mutex_new();
3741 if (NULL == g_threadSendStateMutex)
3743 OIC_LOG(ERROR, TAG, "ca_mutex_new has failed");
3744 return CA_STATUS_FAILED;
3748 return CA_STATUS_OK;
3751 void CALEClientTerminateGattMutexVariables()
3753 ca_mutex_free(g_bleReqRespClientCbMutex);
3754 g_bleReqRespClientCbMutex = NULL;
3756 ca_mutex_free(g_bleServerBDAddressMutex);
3757 g_bleServerBDAddressMutex = NULL;
3759 ca_mutex_free(g_threadMutex);
3760 g_threadMutex = NULL;
3762 ca_mutex_free(g_threadSendMutex);
3763 g_threadSendMutex = NULL;
3765 ca_mutex_free(g_deviceListMutex);
3766 g_deviceListMutex = NULL;
3768 ca_mutex_free(g_SendFinishMutex);
3769 g_SendFinishMutex = NULL;
3771 ca_mutex_free(g_scanMutex);
3774 ca_mutex_free(g_threadWriteCharacteristicMutex);
3775 g_threadWriteCharacteristicMutex = NULL;
3777 ca_mutex_free(g_deviceScanRetryDelayMutex);
3778 g_deviceScanRetryDelayMutex = NULL;
3780 ca_mutex_free(g_threadSendStateMutex);
3781 g_threadSendStateMutex = NULL;
3784 void CALEClientSetSendFinishFlag(bool flag)
3786 OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
3788 ca_mutex_lock(g_SendFinishMutex);
3789 g_isFinishedSendData = flag;
3790 ca_mutex_unlock(g_SendFinishMutex);
3797 CAResult_t CAStartLEGattClient()
3799 // init mutex for send logic
3800 if (!g_deviceDescCond)
3802 g_deviceDescCond = ca_cond_new();
3807 g_threadCond = ca_cond_new();
3810 if (!g_threadWriteCharacteristicCond)
3812 g_threadWriteCharacteristicCond = ca_cond_new();
3815 CAResult_t ret = CALEClientStartScan();
3816 if (CA_STATUS_OK != ret)
3818 OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
3822 g_isStartedLEClient = true;
3823 return CA_STATUS_OK;
3826 void CAStopLEGattClient()
3828 OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
3832 OIC_LOG(ERROR, TAG, "g_jvm is null");
3836 bool isAttached = false;
3838 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
3841 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
3842 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
3846 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
3852 CAResult_t ret = CALEClientDisconnectAll(env);
3853 if (CA_STATUS_OK != ret)
3855 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
3858 ret = CALEClientStopScan();
3859 if(CA_STATUS_OK != ret)
3861 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
3864 ca_mutex_lock(g_threadMutex);
3865 OIC_LOG(DEBUG, TAG, "signal - connection cond");
3866 ca_cond_signal(g_threadCond);
3867 CALEClientSetSendFinishFlag(true);
3868 ca_mutex_unlock(g_threadMutex);
3870 ca_mutex_lock(g_threadWriteCharacteristicMutex);
3871 OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
3872 ca_cond_signal(g_threadWriteCharacteristicCond);
3873 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
3875 ca_mutex_lock(g_deviceScanRetryDelayMutex);
3876 OIC_LOG(DEBUG, TAG, "signal - delay cond");
3877 ca_cond_signal(g_deviceScanRetryDelayCond);
3878 ca_mutex_unlock(g_deviceScanRetryDelayMutex);
3880 ca_cond_free(g_deviceDescCond);
3881 ca_cond_free(g_threadCond);
3882 ca_cond_free(g_threadWriteCharacteristicCond);
3883 ca_cond_free(g_deviceScanRetryDelayCond);
3885 g_deviceDescCond = NULL;
3886 g_threadCond = NULL;
3887 g_threadWriteCharacteristicCond = NULL;
3888 g_deviceScanRetryDelayCond = NULL;
3892 (*g_jvm)->DetachCurrentThread(g_jvm);
3897 CAResult_t CAInitializeLEGattClient()
3899 OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
3900 CALEClientInitialize();
3901 return CA_STATUS_OK;
3904 void CATerminateLEGattClient()
3906 OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
3907 CAStopLEGattClient();
3908 CALEClientTerminate();
3911 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress, const uint8_t *data,
3912 uint32_t dataLen, CALETransferType_t type,
3915 OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
3916 VERIFY_NON_NULL(data, TAG, "data is null");
3917 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
3919 if (LE_UNICAST != type || position < 0)
3921 OIC_LOG(ERROR, TAG, "this request is not unicast");
3922 return CA_STATUS_INVALID_PARAM;
3925 return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
3928 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
3930 OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
3931 VERIFY_NON_NULL(data, TAG, "data is null");
3933 return CALEClientSendMulticastMessage(data, dataLen);
3936 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
3938 ca_mutex_lock(g_bleReqRespClientCbMutex);
3939 g_CABLEClientDataReceivedCallback = callback;
3940 ca_mutex_unlock(g_bleReqRespClientCbMutex);
3943 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
3945 g_threadPoolHandle = handle;
3948 CAResult_t CAGetLEAddress(char **local_address)
3950 VERIFY_NON_NULL(local_address, TAG, "local_address");
3951 OIC_LOG(INFO, TAG, "CAGetLEAddress is not support");
3952 return CA_NOT_SUPPORTED;
3955 JNIEXPORT void JNICALL
3956 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterLeScanCallback(JNIEnv *env, jobject obj,
3959 OIC_LOG(DEBUG, TAG, "CaLeRegisterLeScanCallback");
3960 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3961 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3962 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3964 g_leScanCallback = (*env)->NewGlobalRef(env, callback);
3967 JNIEXPORT void JNICALL
3968 Java_org_iotivity_ca_CaLeClientInterface_caLeRegisterGattCallback(JNIEnv *env, jobject obj,
3971 OIC_LOG(DEBUG, TAG, "CaLeRegisterGattCallback");
3972 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3973 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3974 VERIFY_NON_NULL_VOID(callback, TAG, "callback is null");
3976 g_leGattCallback = (*env)->NewGlobalRef(env, callback);
3979 JNIEXPORT void JNICALL
3980 Java_org_iotivity_ca_CaLeClientInterface_caLeScanCallback(JNIEnv *env, jobject obj,
3983 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
3984 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
3985 VERIFY_NON_NULL_VOID(device, TAG, "device is null");
3987 CAResult_t res = CALEClientAddScanDeviceToList(env, device);
3988 if (CA_STATUS_OK != res)
3990 OIC_LOG_V(ERROR, TAG, "CALEClientAddScanDeviceToList has failed : %d", res);
3994 static jstring CALEClientGetAddressFromGatt(JNIEnv *env, jobject gatt)
3996 OIC_LOG(DEBUG, TAG, "IN - CAManagerGetAddressFromGatt");
3998 VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
3999 VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
4001 jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT,
4002 "getDevice", METHODID_BT_DEVICE);
4003 if (!jni_mid_getDevice)
4005 OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
4009 jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
4010 if (!jni_obj_device)
4012 OIC_LOG(ERROR, TAG, "jni_obj_device is null");
4016 jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
4019 OIC_LOG(ERROR, TAG, "jni_address is null");
4023 OIC_LOG(DEBUG, TAG, "OUT - CAManagerGetAddressFromGatt");
4028 * Class: org_iotivity_ca_jar_caleinterface
4029 * Method: CALeGattConnectionStateChangeCallback
4030 * Signature: (Landroid/bluetooth/BluetoothGatt;II)V
4032 JNIEXPORT void JNICALL
4033 Java_org_iotivity_ca_CaLeClientInterface_caLeGattConnectionStateChangeCallback(JNIEnv *env,
4039 OIC_LOG_V(INFO, TAG, "CALeGattConnectionStateChangeCallback - status %d, newstate %d", status,
4041 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4042 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4043 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4045 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
4047 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4050 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGattObj has failed");
4054 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4057 OIC_LOG(ERROR, TAG, "address is null");
4060 OIC_LOG_V(DEBUG, TAG, "CALeGattConnectionStateChangeCallback - address [%s]", address);
4063 if (state_connected == newstate)
4065 OIC_LOG(DEBUG, TAG, "LE is connected");
4066 if (GATT_SUCCESS == status)
4068 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, STATE_CONNECTED);
4069 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4070 if (CA_STATUS_OK != res)
4072 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4076 res = CALEClientAddGattobjToList(env, gatt);
4077 if (CA_STATUS_OK != res)
4079 OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
4083 res = CALEClientDiscoverServices(env, gatt);
4084 if (CA_STATUS_OK != res)
4086 OIC_LOG(ERROR, TAG, "CALEClientDiscoverServices has failed");
4092 OIC_LOG(INFO, TAG, "unknown status");
4093 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4096 else // STATE_DISCONNECTED == newstate
4098 OIC_LOG(DEBUG, TAG, "LE is disconnected");
4100 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE, STATE_DISCONNECTED);
4101 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4102 if (CA_STATUS_OK != res)
4104 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4108 res = CALEClientGattClose(env, gatt);
4109 if (CA_STATUS_OK != res)
4111 OIC_LOG(ERROR, TAG, "CALEClientGattClose has failed");
4114 if (GATT_ERROR == status)
4116 // when we get GATT ERROR(0x85), gatt connection can be called again.
4117 OIC_LOG(INFO, TAG, "retry gatt connect");
4119 jstring leAddress = CALEClientGetAddressFromGatt(env, gatt);
4122 OIC_LOG(ERROR, TAG, "CALEClientGetAddressFromGatt has failed");
4126 jobject btObject = CALEGetRemoteDevice(env, leAddress);
4129 OIC_LOG(ERROR, TAG, "CALEGetRemoteDevice has failed");
4133 jobject newGatt = CALEClientConnect(env, btObject, JNI_TRUE);
4136 OIC_LOG(ERROR, TAG, "CALEClientConnect has failed");
4144 if (CALECheckConnectionStateValue(status))
4146 // this state is unexpected reason to disconnect
4147 // if the reason is suitable, connection logic of the device will be destroyed.
4148 OIC_LOG(INFO, TAG, "connection logic destroy");
4153 // other reason except for gatt_success is expected to running
4154 // background connection in BT platform.
4155 OIC_LOG(INFO, TAG, "unknown status or manual disconnected state");
4156 CALEClientUpdateSendCnt(env);
4163 (*env)->DeleteGlobalRef(env, g_sendBuffer);
4164 g_sendBuffer = NULL;
4171 CALEClientSendFinish(env, gatt);
4176 * Class: org_iotivity_ca_jar_caleinterface
4177 * Method: CALeGattServicesDiscoveredCallback
4178 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
4180 JNIEXPORT void JNICALL
4181 Java_org_iotivity_ca_CaLeClientInterface_caLeGattServicesDiscoveredCallback(JNIEnv *env,
4186 OIC_LOG_V(INFO, TAG, "CALeGattServicesDiscoveredCallback - status %d: ", status);
4187 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4188 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4189 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4191 if (0 != status) // discovery error
4193 CALEClientSendFinish(env, gatt);
4197 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4200 CALEClientSendFinish(env, gatt);
4204 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4207 CALEClientSendFinish(env, gatt);
4211 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_GATT_CHARACTERISTIC_RESPONSE_UUID);
4214 OIC_LOG(ERROR, TAG, "jni_uuid is null");
4218 jobject jni_obj_GattCharacteristic = CALEClientGetGattService(env, gatt, jni_uuid);
4219 if (!jni_obj_GattCharacteristic)
4221 OIC_LOG(ERROR, TAG, "jni_obj_GattCharacteristic is null");
4225 CAResult_t res = CALEClientSetCharacteristicNotification(env, gatt,
4226 jni_obj_GattCharacteristic);
4227 if (CA_STATUS_OK != res)
4229 OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
4233 res = CALEClientSetUUIDToDescriptor(env, gatt, jni_obj_GattCharacteristic);
4234 if (CA_STATUS_OK != res)
4236 OIC_LOG_V(INFO, TAG, "Descriptor is not found : %d", res);
4238 res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4239 STATE_SERVICE_CONNECTED);
4240 if (CA_STATUS_OK != res)
4242 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4248 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4249 if (CA_STATUS_OK != res)
4251 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4257 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
4258 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4263 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
4264 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4265 CALEClientSendFinish(env, gatt);
4270 * Class: org_iotivity_ca_jar_caleinterface
4271 * Method: CALeGattCharacteristicWritjclasseCallback
4272 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;I)V
4274 JNIEXPORT void JNICALL
4275 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicWriteCallback(
4276 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data, jint status)
4278 OIC_LOG_V(INFO, TAG, "CALeGattCharacteristicWriteCallback - status : %d", status);
4279 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4280 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4281 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4283 // send success & signal
4284 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4290 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4296 if (GATT_SUCCESS != status) // error case
4298 OIC_LOG(ERROR, TAG, "send failure");
4301 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4302 if (CA_STATUS_OK != res)
4304 OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
4305 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4306 g_isSignalSetFlag = true;
4307 ca_cond_signal(g_threadWriteCharacteristicCond);
4308 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4310 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4312 if (CA_STATUS_OK != res)
4314 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4317 if (g_clientErrorCallback)
4319 jint length = (*env)->GetArrayLength(env, data);
4320 g_clientErrorCallback(address, data, length, CA_SEND_FAILED);
4323 CALEClientSendFinish(env, gatt);
4329 OIC_LOG(DEBUG, TAG, "send success");
4330 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_SEND_STATE,
4331 STATE_SEND_SUCCESS);
4332 if (CA_STATUS_OK != res)
4334 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4337 ca_mutex_lock(g_threadWriteCharacteristicMutex);
4338 OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
4339 g_isSignalSetFlag = true;
4340 ca_cond_signal(g_threadWriteCharacteristicCond);
4341 ca_mutex_unlock(g_threadWriteCharacteristicMutex);
4343 CALEClientUpdateSendCnt(env);
4346 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4352 CALEClientSendFinish(env, gatt);
4357 * Class: org_iotivity_ca_jar_caleinterface
4358 * Method: CALeGattCharacteristicChangedCallback
4359 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattCharacteristic;)V
4361 JNIEXPORT void JNICALL
4362 Java_org_iotivity_ca_CaLeClientInterface_caLeGattCharacteristicChangedCallback(
4363 JNIEnv *env, jobject obj, jobject gatt, jbyteArray data)
4365 OIC_LOG(INFO, TAG, "CALeGattCharacteristicChangedCallback");
4366 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4367 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4368 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4369 VERIFY_NON_NULL_VOID(data, TAG, "data is null");
4371 // get Byte Array and convert to uint8_t*
4372 jint length = (*env)->GetArrayLength(env, data);
4375 jbyte *jni_byte_responseData = (jbyte*) (*env)->GetByteArrayElements(env, data, &isCopy);
4377 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - raw data received : %p",
4378 jni_byte_responseData);
4380 uint8_t* receivedData = OICMalloc(length);
4383 OIC_LOG(ERROR, TAG, "receivedData is null");
4387 memcpy(receivedData, jni_byte_responseData, length);
4388 (*env)->ReleaseByteArrayElements(env, data, jni_byte_responseData, JNI_ABORT);
4390 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4393 OIC_LOG(ERROR, TAG, "jni_address is null");
4394 OICFree(receivedData);
4398 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4401 OIC_LOG(ERROR, TAG, "address is null");
4402 OICFree(receivedData);
4406 OIC_LOG_V(DEBUG, TAG, "CALeGattCharacteristicChangedCallback - data. : %p, %d",
4407 receivedData, length);
4409 uint32_t sentLength = 0;
4410 ca_mutex_lock(g_bleServerBDAddressMutex);
4411 g_CABLEClientDataReceivedCallback(address, receivedData, length, &sentLength);
4412 ca_mutex_unlock(g_bleServerBDAddressMutex);
4414 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4418 * Class: org_iotivity_ca_jar_caleinterface
4419 * Method: CALeGattDescriptorWriteCallback
4420 * Signature: (Landroid/bluetooth/BluetoothGatt;Landroid/bluetooth/BluetoothGattDescriptor;I)V
4422 JNIEXPORT void JNICALL
4423 Java_org_iotivity_ca_CaLeClientInterface_caLeGattDescriptorWriteCallback(JNIEnv *env, jobject obj,
4427 OIC_LOG_V(INFO, TAG, "CALeGattDescriptorWriteCallback - status %d: ", status);
4428 VERIFY_NON_NULL_VOID(env, TAG, "env is null");
4429 VERIFY_NON_NULL_VOID(obj, TAG, "obj is null");
4430 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt is null");
4432 if (GATT_SUCCESS != status) // error
4437 jstring jni_address = CALEClientGetAddressFromGattObj(env, gatt);
4443 const char* address = (*env)->GetStringUTFChars(env, jni_address, NULL);
4446 CAResult_t res = CALEClientUpdateDeviceState(address, CA_LE_CONNECTION_STATE,
4447 STATE_SERVICE_CONNECTED);
4448 if (CA_STATUS_OK != res)
4450 OIC_LOG(ERROR, TAG, "CALEClientUpdateDeviceState has failed");
4451 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4455 (*env)->ReleaseStringUTFChars(env, jni_address, address);
4459 CAResult_t res = CALEClientWriteCharacteristic(env, gatt);
4460 if (CA_STATUS_OK != res)
4462 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
4471 CALEClientSendFinish(env, gatt);