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 ******************************************************************/
25 #include "caedrinterface.h"
26 #include "caedrutils.h"
27 #include "caedrclient.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "cathreadpool.h" /* for thread pool */
33 #include "uarraylist.h"
34 #include "caadapterutils.h"
35 #include "caremotehandler.h"
38 #define TAG PCF("OIC_CA_EDR_CLIENT")
40 static const char METHODID_CONTEXTNONPARAM[] = "()Landroid/content/Context;";
41 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
42 static const char METHODID_OUTPUTNONPARAM[] = "()Ljava/io/OutputStream;";
43 static const char METHODID_STRINGNONPARAM[] = "()Ljava/lang/String;";
44 static const char METHODID_BT_DEVICEPARAM[] =
45 "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;";
46 static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter";
47 static const char CLASSPATH_BT_DEVICE[] = "android/bluetooth/BluetoothDevice";
48 static const char CLASSPATH_BT_INTERFACE[] = "org/iotivity/ca/CaEdrInterface";
49 static const char CLASSPATH_BT_SOCKET[] = "android/bluetooth/BluetoothSocket";
50 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
51 static const char CLASSPATH_CONTEXT[] = "android/content/Context";
52 static const char CLASSPATH_OUTPUT[] = "java/io/OutputStream";
54 static ca_thread_pool_t g_threadPoolHandle = NULL;
57 static jobject g_context;
60 * @var g_mutexUnicastServer
61 * @brief Mutex to synchronize unicast server
63 static ca_mutex g_mutexUnicastServer = NULL;
67 * @brief Flag to control the Receive Unicast Data Thread
69 static bool g_stopUnicast = false;
72 * @var g_mutexMulticastServer
73 * @brief Mutex to synchronize secure multicast server
75 static ca_mutex g_mutexMulticastServer = NULL;
78 * @var g_stopMulticast
79 * @brief Flag to control the Receive Multicast Data Thread
81 static bool g_stopMulticast = false;
85 * @brief Flag to control the Accept Thread
87 static bool g_stopAccept = false;
90 * @var g_mutexStateList
91 * @brief Mutex to synchronize device state list
93 static ca_mutex g_mutexStateList = NULL;
96 * @var g_mutexObjectList
97 * @brief Mutex to synchronize device object list
99 static ca_mutex g_mutexObjectList = NULL;
102 * @var g_edrErrorHandler
103 * @brief Error callback to update error in EDR
105 static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
107 typedef struct send_data
115 @brief Thread context information for unicast, multicast and secured unicast server
120 CAAdapterServerType_t type;
121 } CAAdapterReceiveThreadContext_t;
126 } CAAdapterAcceptThreadContext_t;
129 * implement for BT-EDR adapter common method
131 CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
133 OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
137 OIC_LOG(ERROR, TAG, "endpoint info is null");
138 return CA_STATUS_INVALID_PARAM;
141 char *macAddress = NULL;
142 CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
143 if (CA_STATUS_OK != ret)
145 OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
152 OIC_LOG(ERROR, TAG, "mac address is null");
153 return CA_STATUS_FAILED;
155 OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
157 // Create local endpoint using util function
158 CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
160 if (NULL == endpoint)
162 OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
164 return CA_STATUS_FAILED;
167 // copy unicast server information
168 int32_t netInfoSize = 1;
169 CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
172 OIC_LOG(ERROR, TAG, "Invalid input..");
174 CAFreeEndpoint(endpoint);
175 return CA_MEMORY_ALLOC_FAILED;
177 *netInfo = *endpoint;
181 CAFreeEndpoint(endpoint);
183 OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
187 void CAEDRClientTerminate()
189 OIC_LOG(DEBUG, TAG, "IN");
191 OIC_LOG(DEBUG, TAG, "OUT");
194 CAResult_t CAEDRManagerReadData()
196 OIC_LOG(DEBUG, TAG, "IN");
198 OIC_LOG(DEBUG, TAG, "OUT");
199 return CA_NOT_SUPPORTED;
202 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
205 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
206 VERIFY_NON_NULL(data, TAG, "data is null");
208 CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
212 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
214 VERIFY_NON_NULL(data, TAG, "data is null");
216 CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
220 // It will be updated when android EDR support is added
221 void CAEDRClientUnsetCallbacks()
223 OIC_LOG(DEBUG, TAG, "IN");
225 OIC_LOG(DEBUG, TAG, "OUT");
228 // It will be updated when android EDR support is added
229 void CAEDRClientDisconnectAll()
231 OIC_LOG(DEBUG, TAG, "IN");
233 OIC_LOG(DEBUG, TAG, "OUT");
236 CAResult_t CAEDRGetAdapterEnableState(bool *state)
238 VERIFY_NON_NULL(state, TAG, "state is null");
242 OIC_LOG(ERROR, TAG, "g_jvm is null");
243 return CA_STATUS_INVALID_PARAM;
245 bool isAttached = false;
247 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
250 OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
251 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
255 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
256 return CA_STATUS_INVALID_PARAM;
262 jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
270 (*g_jvm)->DetachCurrentThread(g_jvm);
276 void CAEDRJniInitContext()
278 OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
280 g_context = (jobject) CANativeJNIGetContext();
283 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
286 OIC_LOG(DEBUG, TAG, "CAEDRCreateJNIInterfaceObject");
288 if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
290 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
291 return CA_STATUS_FAILED;
294 //getApplicationContext
295 jclass contextClass = (*env)->FindClass(env, CLASSPATH_CONTEXT);
298 OIC_LOG(ERROR, TAG, "Could not get context object class");
299 return CA_STATUS_FAILED;
302 jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
303 "getApplicationContext",
304 METHODID_CONTEXTNONPARAM);
305 if (!getApplicationContextMethod)
307 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
308 return CA_STATUS_FAILED;
311 //Create EDRJniInterface instance
312 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
313 if (!EDRJniInterface)
315 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
316 return CA_STATUS_FAILED;
319 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
320 "(Landroid/content/Context;)V");
321 if (!EDRInterfaceConstructorMethod)
323 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method");
324 return CA_STATUS_FAILED;
327 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context);
328 OIC_LOG(DEBUG, TAG, "NewObject Success");
333 static void CAEDRDestroyMutex()
335 if (g_mutexUnicastServer)
337 ca_mutex_free(g_mutexUnicastServer);
338 g_mutexUnicastServer = NULL;
341 if (g_mutexMulticastServer)
343 ca_mutex_free(g_mutexMulticastServer);
344 g_mutexMulticastServer = NULL;
347 if (g_mutexStateList)
349 ca_mutex_free(g_mutexStateList);
350 g_mutexStateList = NULL;
353 if (g_mutexObjectList)
355 ca_mutex_free(g_mutexObjectList);
356 g_mutexObjectList = NULL;
360 static CAResult_t CAEDRCreateMutex()
362 g_mutexUnicastServer = ca_mutex_new();
363 if (!g_mutexUnicastServer)
365 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
366 return CA_STATUS_FAILED;
369 g_mutexMulticastServer = ca_mutex_new();
370 if (!g_mutexMulticastServer)
372 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
375 return CA_STATUS_FAILED;
378 g_mutexStateList = ca_mutex_new();
379 if (!g_mutexStateList)
381 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
384 return CA_STATUS_FAILED;
387 g_mutexObjectList = ca_mutex_new();
388 if (!g_mutexObjectList)
390 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
393 return CA_STATUS_FAILED;
399 void CAEDRInitialize(ca_thread_pool_t handle)
401 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
403 g_threadPoolHandle = handle;
407 CAEDRJniInitContext();
412 bool isAttached = false;
414 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
417 OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
418 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
422 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
427 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
430 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
431 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
432 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
434 (*env)->DeleteLocalRef(env, jni_address);
436 ca_mutex_lock(g_mutexStateList);
437 CAEDRNativeCreateDeviceStateList();
438 ca_mutex_unlock(g_mutexStateList);
440 ca_mutex_lock(g_mutexObjectList);
441 CAEDRNativeCreateDeviceSocketList();
442 ca_mutex_unlock(g_mutexObjectList);
446 (*g_jvm)->DetachCurrentThread(g_jvm);
451 CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
454 OIC_LOG(DEBUG, TAG, "OUT");
457 void CAEDRTerminate()
459 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
461 bool isAttached = false;
463 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
466 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
467 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
471 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
478 g_stopMulticast = true;
479 g_stopUnicast = true;
483 (*g_jvm)->DetachCurrentThread(g_jvm);
488 (*env)->DeleteGlobalRef(env, g_context);
491 CAEDRNativeSocketCloseToAll(env);
496 CAEDRNativeRemoveAllDeviceState();
497 CAEDRNativeRemoveAllDeviceSocket(env);
498 CAEDRDestroyJniInterface();
501 CAResult_t CAEDRDestroyJniInterface()
503 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
507 OIC_LOG(ERROR, TAG, "g_jvm is null");
508 return CA_STATUS_FAILED;
511 bool isAttached = false;
513 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
516 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
517 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
521 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
522 return CA_STATUS_FAILED;
527 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
528 if (!jni_EDRJniInterface)
530 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
534 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
535 "destroyEdrInterface",
537 if (!jni_EDRInterfaceDestroyMethod)
539 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
543 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
545 if ((*env)->ExceptionCheck(env))
547 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
548 (*env)->ExceptionDescribe(env);
549 (*env)->ExceptionClear(env);
553 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
557 (*g_jvm)->DetachCurrentThread(g_jvm);
566 (*g_jvm)->DetachCurrentThread(g_jvm);
569 return CA_STATUS_FAILED;
572 void CAEDRCoreJniInit()
574 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
575 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
578 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
580 VERIFY_NON_NULL(address, TAG, "address is null");
581 VERIFY_NON_NULL(data, TAG, "data is null");
583 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
587 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
589 VERIFY_NON_NULL(data, TAG, "data is null");
591 bool isAttached = false;
593 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
596 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
597 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
601 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
602 return CA_STATUS_INVALID_PARAM;
607 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
608 if(CA_STATUS_OK != result)
610 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
614 OIC_LOG(DEBUG, TAG, "sent data");
618 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
619 (*g_jvm)->DetachCurrentThread(g_jvm);
622 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
626 CAResult_t CAEDRGetInterfaceInfo(char **address)
628 CAEDRGetLocalAddress(address);
632 void CAEDRGetLocalAddress(char **address)
634 bool isAttached = false;
636 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
639 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
640 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
643 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
649 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
652 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
653 *address = OICStrdup(localAddress);
654 if (*address == NULL)
658 (*g_jvm)->DetachCurrentThread(g_jvm);
660 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
661 (*env)->DeleteLocalRef(env, jni_address);
665 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
666 (*env)->DeleteLocalRef(env, jni_address);
669 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
672 (*g_jvm)->DetachCurrentThread(g_jvm);
676 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
678 VERIFY_NON_NULL(address, TAG, "address is null");
679 VERIFY_NON_NULL(data, TAG, "data is null");
681 bool isAttached = false;
683 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
686 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
687 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
690 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
691 return CA_STATUS_INVALID_PARAM;
696 OIC_LOG(DEBUG, TAG, "set byteArray for data");
698 // get bonded device list
699 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
700 if (!jni_arrayPairedDevices)
702 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
705 (*g_jvm)->DetachCurrentThread(g_jvm);
707 return CA_STATUS_INVALID_PARAM;
709 // Get information from array of devices
710 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
711 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
712 METHODID_STRINGNONPARAM);
713 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
714 METHODID_STRINGNONPARAM);
716 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
717 for (jsize i = 0; i < length; i++)
719 OIC_LOG(DEBUG, TAG, "start to check device");
720 // get name, address from BT device
721 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
722 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
726 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
727 OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
728 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
729 (*env)->DeleteLocalRef(env, j_str_name);
732 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
733 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
734 (*env)->DeleteLocalRef(env, j_obj_device);
737 OIC_LOG(ERROR, TAG, "remoteAddress is null");
740 (*g_jvm)->DetachCurrentThread(g_jvm);
743 (*env)->DeleteLocalRef(env, j_str_address);
744 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
745 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
746 return CA_STATUS_INVALID_PARAM;
748 OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
751 if (!strcmp(remoteAddress, address))
753 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
754 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
755 (*env)->DeleteLocalRef(env, j_str_address);
756 if (CA_STATUS_OK != res)
758 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
759 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
764 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
765 (*env)->DeleteLocalRef(env, j_str_address);
768 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
769 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
773 (*g_jvm)->DetachCurrentThread(g_jvm);
779 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
781 VERIFY_NON_NULL(env, TAG, "env is null");
782 VERIFY_NON_NULL(data, TAG, "data is null");
784 // get bonded device list
785 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
786 if (!jni_arrayPairedDevices)
788 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
789 return CA_STATUS_INVALID_PARAM;
791 // Get information from array of devices
792 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
793 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
794 METHODID_STRINGNONPARAM);
795 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
796 METHODID_STRINGNONPARAM);
798 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
799 for (jsize i = 0; i < length; i++)
801 // get name, address from BT device
802 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
803 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
804 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
806 if (j_str_name && j_str_address)
808 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
809 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
810 if (name && remoteAddress)
812 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
814 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
815 if (CA_STATUS_OK != res)
817 OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
819 g_edrErrorHandler(remoteAddress, data, dataLen, res);
822 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
823 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
826 (*env)->DeleteLocalRef(env, j_obj_device);
827 (*env)->DeleteLocalRef(env, j_str_name);
828 (*env)->DeleteLocalRef(env, j_str_address);
831 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
832 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
837 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
840 VERIFY_NON_NULL(env, TAG, "env is null");
841 VERIFY_NON_NULL(address, TAG, "address is null");
842 VERIFY_NON_NULL(data, TAG, "data is null");
844 if (!CAEDRNativeIsEnableBTAdapter(env))
846 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
847 return CA_STATUS_INVALID_PARAM;
850 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
852 // connect before send data
853 OIC_LOG(DEBUG, TAG, "connect before send data");
855 CAResult_t res = CAEDRNativeConnect(env, address);
856 if (CA_STATUS_OK != res)
862 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
864 if (!((*env)->ExceptionCheck(env)))
866 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
867 if (!jni_cid_BTsocket)
869 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
870 return CA_STATUS_FAILED;
873 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
875 METHODID_OUTPUTNONPARAM);
876 if (!jni_mid_getOutputStream)
878 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
879 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
880 return CA_STATUS_FAILED;
883 OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
885 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
888 OIC_LOG(ERROR, TAG, "jni_socket is not available");
889 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
890 return CA_STATUS_FAILED;
893 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
894 jni_mid_getOutputStream);
895 if (!jni_obj_outputStream)
897 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
898 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
899 return CA_STATUS_FAILED;
902 OIC_LOG(DEBUG, TAG, "ready outputStream..");
904 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
905 if (!jni_cid_OutputStream)
907 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
908 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
909 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
910 return CA_STATUS_FAILED;
913 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
917 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
918 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
919 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
920 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
921 return CA_STATUS_FAILED;
924 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
925 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
927 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
930 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
931 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
932 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
933 (*env)->DeleteLocalRef(env, jbuf);
935 if ((*env)->ExceptionCheck(env))
937 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
938 (*env)->ExceptionDescribe(env);
939 (*env)->ExceptionClear(env);
940 return CA_STATUS_FAILED;
943 OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %ld bytes, to %s",
944 dataLength, address);
948 (*env)->ExceptionDescribe(env);
949 (*env)->ExceptionClear(env);
950 OIC_LOG(ERROR, TAG, "error!!");
951 return CA_STATUS_FAILED;
956 OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
962 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
964 VERIFY_NON_NULL(address, TAG, "address is null");
965 OIC_LOG(DEBUG, TAG, "btConnect..");
967 if (!CAEDRNativeIsEnableBTAdapter(env))
969 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
970 return CA_STATUS_INVALID_PARAM;
973 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
974 if (!jni_cid_BTAdapter)
976 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
977 return CA_STATUS_FAILED;
981 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
983 METHODID_OBJECTNONPARAM);
984 if (!jni_mid_getDefaultAdapter)
986 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
987 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
988 return CA_STATUS_FAILED;
991 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
992 jni_mid_getDefaultAdapter);
993 if (!jni_obj_BTAdapter)
995 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
996 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
997 return CA_STATUS_FAILED;
1000 // get remote bluetooth device
1001 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1003 METHODID_BT_DEVICEPARAM);
1004 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1005 if (!jni_mid_getRemoteDevice)
1007 OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
1008 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1009 return CA_STATUS_FAILED;
1012 jstring jni_address = (*env)->NewStringUTF(env, address);
1013 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
1014 jni_mid_getRemoteDevice, jni_address);
1015 (*env)->DeleteLocalRef(env, jni_address);
1016 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1017 if (!jni_obj_remoteBTDevice)
1019 OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
1020 return CA_STATUS_FAILED;
1023 // get create Rfcomm Socket method ID
1024 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
1025 if (!jni_cid_BluetoothDevice)
1027 OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
1028 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1029 return CA_STATUS_FAILED;
1032 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
1033 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
1034 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
1035 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
1036 if (!jni_mid_createSocket)
1038 OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
1039 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1040 return CA_STATUS_FAILED;
1044 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1047 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1048 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1049 return CA_STATUS_FAILED;
1052 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
1053 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
1054 if (!jni_mid_fromString)
1056 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1057 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1058 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1059 return CA_STATUS_FAILED;
1062 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1065 OIC_LOG(ERROR, TAG, "jni_uuid is null");
1066 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1067 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1068 return CA_STATUS_FAILED;
1070 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1072 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1073 (*env)->DeleteLocalRef(env, jni_uuid);
1076 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1077 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1078 return CA_STATUS_FAILED;
1081 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1082 jni_mid_createSocket, jni_obj_uuid);
1083 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1084 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1085 if (!jni_obj_BTSocket)
1087 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1088 return CA_STATUS_FAILED;
1092 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1093 if (!jni_cid_BTSocket)
1095 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1096 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1097 return CA_STATUS_FAILED;
1100 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1101 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1102 if (!jni_mid_connect)
1104 OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1105 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1106 return CA_STATUS_FAILED;
1109 OIC_LOG(DEBUG, TAG, "initiating connection...");
1110 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1112 if ((*env)->ExceptionCheck(env))
1114 OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1115 (*env)->ExceptionDescribe(env);
1116 (*env)->ExceptionClear(env);
1117 return CA_STATUS_FAILED;
1120 // set socket to list
1121 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1124 OIC_LOG(ERROR, TAG, "jni_socket is null");
1125 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1126 return CA_STATUS_FAILED;
1128 ca_mutex_lock(g_mutexObjectList);
1129 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1130 (*env)->DeleteGlobalRef(env, jni_socket);
1131 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1132 ca_mutex_unlock(g_mutexObjectList);
1135 ca_mutex_lock(g_mutexStateList);
1136 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1137 ca_mutex_unlock(g_mutexStateList);
1139 OIC_LOG(DEBUG, TAG, "connected");
1141 return CA_STATUS_OK;
1144 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1146 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1148 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1149 if (!jni_cid_BTSocket)
1151 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1155 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1158 OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1162 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1163 if (!jni_obj_socket)
1165 OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1169 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1171 if ((*env)->ExceptionCheck(env))
1173 OIC_LOG(ERROR, TAG, "close is Failed!!!");
1174 (*env)->ExceptionDescribe(env);
1175 (*env)->ExceptionClear(env);
1179 // remove socket to list
1180 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1183 ca_mutex_lock(g_mutexStateList);
1184 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1185 ca_mutex_unlock(g_mutexStateList);
1187 OIC_LOG(DEBUG, TAG, "disconnected");
1190 void CAEDRInitializeClient(ca_thread_pool_t handle)
1192 CAEDRInitialize(handle);
1195 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1197 g_edrErrorHandler = errorHandleCallback;