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";
55 static jobject g_context;
58 * @var g_mutexUnicastServer
59 * @brief Mutex to synchronize unicast server
61 static ca_mutex g_mutexUnicastServer = NULL;
65 * @brief Flag to control the Receive Unicast Data Thread
67 static bool g_stopUnicast = false;
70 * @var g_mutexMulticastServer
71 * @brief Mutex to synchronize secure multicast server
73 static ca_mutex g_mutexMulticastServer = NULL;
76 * @var g_stopMulticast
77 * @brief Flag to control the Receive Multicast Data Thread
79 static bool g_stopMulticast = false;
83 * @brief Flag to control the Accept Thread
85 static bool g_stopAccept = false;
88 * @var g_mutexStateList
89 * @brief Mutex to synchronize device state list
91 static ca_mutex g_mutexStateList = NULL;
94 * @var g_mutexObjectList
95 * @brief Mutex to synchronize device object list
97 static ca_mutex g_mutexObjectList = NULL;
100 * @var g_edrErrorHandler
101 * @brief Error callback to update error in EDR
103 static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
105 typedef struct send_data
113 @brief Thread context information for unicast, multicast and secured unicast server
118 CAAdapterServerType_t type;
119 } CAAdapterReceiveThreadContext_t;
124 } CAAdapterAcceptThreadContext_t;
127 * implement for BT-EDR adapter common method
129 CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
131 OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
135 OIC_LOG(ERROR, TAG, "endpoint info is null");
136 return CA_STATUS_INVALID_PARAM;
139 char *macAddress = NULL;
140 CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
141 if (CA_STATUS_OK != ret)
143 OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
150 OIC_LOG(ERROR, TAG, "mac address is null");
151 return CA_STATUS_FAILED;
153 OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
155 // Create local endpoint using util function
156 CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
158 if (NULL == endpoint)
160 OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
162 return CA_STATUS_FAILED;
165 // copy unicast server information
166 int32_t netInfoSize = 1;
167 CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
170 OIC_LOG(ERROR, TAG, "Invalid input..");
172 CAFreeEndpoint(endpoint);
173 return CA_MEMORY_ALLOC_FAILED;
175 *netInfo = *endpoint;
179 CAFreeEndpoint(endpoint);
181 OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
185 void CAEDRClientTerminate()
187 OIC_LOG(DEBUG, TAG, "IN");
189 OIC_LOG(DEBUG, TAG, "OUT");
192 CAResult_t CAEDRManagerReadData()
194 OIC_LOG(DEBUG, TAG, "IN");
196 OIC_LOG(DEBUG, TAG, "OUT");
197 return CA_NOT_SUPPORTED;
200 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
203 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
204 VERIFY_NON_NULL(data, TAG, "data is null");
206 CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
210 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
212 VERIFY_NON_NULL(data, TAG, "data is null");
214 CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
218 // It will be updated when android EDR support is added
219 void CAEDRClientUnsetCallbacks()
221 OIC_LOG(DEBUG, TAG, "IN");
223 OIC_LOG(DEBUG, TAG, "OUT");
226 // It will be updated when android EDR support is added
227 void CAEDRClientDisconnectAll()
229 OIC_LOG(DEBUG, TAG, "IN");
231 OIC_LOG(DEBUG, TAG, "OUT");
234 CAResult_t CAEDRGetAdapterEnableState(bool *state)
236 VERIFY_NON_NULL(state, TAG, "state is null");
240 OIC_LOG(ERROR, TAG, "g_jvm is null");
241 return CA_STATUS_INVALID_PARAM;
243 bool isAttached = false;
245 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
248 OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
249 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
253 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
254 return CA_STATUS_INVALID_PARAM;
260 jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
268 (*g_jvm)->DetachCurrentThread(g_jvm);
274 void CAEDRJniInitContext()
276 OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
278 g_context = (jobject) CANativeJNIGetContext();
281 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
284 OIC_LOG(DEBUG, TAG, "CAEDRCreateJNIInterfaceObject");
286 if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
288 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
289 return CA_STATUS_FAILED;
292 //getApplicationContext
293 jclass contextClass = (*env)->FindClass(env, CLASSPATH_CONTEXT);
296 OIC_LOG(ERROR, TAG, "Could not get context object class");
297 return CA_STATUS_FAILED;
300 jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
301 "getApplicationContext",
302 METHODID_CONTEXTNONPARAM);
303 if (!getApplicationContextMethod)
305 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
306 return CA_STATUS_FAILED;
309 //Create EDRJniInterface instance
310 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
311 if (!EDRJniInterface)
313 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
314 return CA_STATUS_FAILED;
317 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
318 "(Landroid/content/Context;)V");
319 if (!EDRInterfaceConstructorMethod)
321 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method");
322 return CA_STATUS_FAILED;
325 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context);
326 OIC_LOG(DEBUG, TAG, "NewObject Success");
331 static void CAEDRDestroyMutex()
333 if (g_mutexUnicastServer)
335 ca_mutex_free(g_mutexUnicastServer);
336 g_mutexUnicastServer = NULL;
339 if (g_mutexMulticastServer)
341 ca_mutex_free(g_mutexMulticastServer);
342 g_mutexMulticastServer = NULL;
345 if (g_mutexStateList)
347 ca_mutex_free(g_mutexStateList);
348 g_mutexStateList = NULL;
351 if (g_mutexObjectList)
353 ca_mutex_free(g_mutexObjectList);
354 g_mutexObjectList = NULL;
358 static CAResult_t CAEDRCreateMutex()
360 g_mutexUnicastServer = ca_mutex_new();
361 if (!g_mutexUnicastServer)
363 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
364 return CA_STATUS_FAILED;
367 g_mutexMulticastServer = ca_mutex_new();
368 if (!g_mutexMulticastServer)
370 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
373 return CA_STATUS_FAILED;
376 g_mutexStateList = ca_mutex_new();
377 if (!g_mutexStateList)
379 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
382 return CA_STATUS_FAILED;
385 g_mutexObjectList = ca_mutex_new();
386 if (!g_mutexObjectList)
388 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
391 return CA_STATUS_FAILED;
397 CAResult_t CAEDRInitialize()
399 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
403 CAEDRJniInitContext();
406 CAResult_t result = CAEDRCreateMutex();
407 if(CA_STATUS_OK != result)
409 OIC_LOG(ERROR, TAG, "CAEDRInitialize - Could not create mutex");
413 bool isAttached = false;
415 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
418 OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
419 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
423 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
424 return CA_STATUS_NOT_INITIALIZED;
428 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
431 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
432 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
433 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
435 (*env)->DeleteLocalRef(env, jni_address);
437 ca_mutex_lock(g_mutexStateList);
438 CAEDRNativeCreateDeviceStateList();
439 ca_mutex_unlock(g_mutexStateList);
441 ca_mutex_lock(g_mutexObjectList);
442 CAEDRNativeCreateDeviceSocketList();
443 ca_mutex_unlock(g_mutexObjectList);
447 (*g_jvm)->DetachCurrentThread(g_jvm);
452 CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
455 OIC_LOG(DEBUG, TAG, "OUT");
460 void CAEDRTerminate()
462 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
464 bool isAttached = false;
466 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
469 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
470 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
474 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
481 g_stopMulticast = true;
482 g_stopUnicast = true;
486 (*g_jvm)->DetachCurrentThread(g_jvm);
491 (*env)->DeleteGlobalRef(env, g_context);
494 CAEDRNativeSocketCloseToAll(env);
499 CAEDRNativeRemoveAllDeviceState();
500 CAEDRNativeRemoveAllDeviceSocket(env);
501 CAEDRDestroyJniInterface();
504 CAResult_t CAEDRDestroyJniInterface()
506 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
510 OIC_LOG(ERROR, TAG, "g_jvm is null");
511 return CA_STATUS_FAILED;
514 bool isAttached = false;
516 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
519 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
520 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
524 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
525 return CA_STATUS_FAILED;
530 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
531 if (!jni_EDRJniInterface)
533 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
537 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
538 "destroyEdrInterface",
540 if (!jni_EDRInterfaceDestroyMethod)
542 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
546 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
548 if ((*env)->ExceptionCheck(env))
550 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
551 (*env)->ExceptionDescribe(env);
552 (*env)->ExceptionClear(env);
556 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
560 (*g_jvm)->DetachCurrentThread(g_jvm);
569 (*g_jvm)->DetachCurrentThread(g_jvm);
572 return CA_STATUS_FAILED;
575 void CAEDRCoreJniInit()
577 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
578 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
581 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
583 VERIFY_NON_NULL(address, TAG, "address is null");
584 VERIFY_NON_NULL(data, TAG, "data is null");
586 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
590 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
592 VERIFY_NON_NULL(data, TAG, "data is null");
594 bool isAttached = false;
596 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
599 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
600 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
604 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
605 return CA_STATUS_INVALID_PARAM;
610 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
611 if(CA_STATUS_OK != result)
613 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
617 OIC_LOG(DEBUG, TAG, "sent data");
621 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
622 (*g_jvm)->DetachCurrentThread(g_jvm);
625 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
629 CAResult_t CAEDRGetInterfaceInfo(char **address)
631 CAEDRGetLocalAddress(address);
635 void CAEDRGetLocalAddress(char **address)
637 bool isAttached = false;
639 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
642 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
643 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
646 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
652 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
655 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
656 *address = OICStrdup(localAddress);
657 if (*address == NULL)
661 (*g_jvm)->DetachCurrentThread(g_jvm);
663 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
664 (*env)->DeleteLocalRef(env, jni_address);
668 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
669 (*env)->DeleteLocalRef(env, jni_address);
672 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
675 (*g_jvm)->DetachCurrentThread(g_jvm);
679 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
681 VERIFY_NON_NULL(address, TAG, "address is null");
682 VERIFY_NON_NULL(data, TAG, "data is null");
684 bool isAttached = false;
686 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
689 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
690 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
693 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
694 return CA_STATUS_INVALID_PARAM;
699 OIC_LOG(DEBUG, TAG, "set byteArray for data");
701 // get bonded device list
702 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
703 if (!jni_arrayPairedDevices)
705 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
708 (*g_jvm)->DetachCurrentThread(g_jvm);
710 return CA_STATUS_INVALID_PARAM;
712 // Get information from array of devices
713 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
714 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
715 METHODID_STRINGNONPARAM);
716 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
717 METHODID_STRINGNONPARAM);
719 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
720 for (jsize i = 0; i < length; i++)
722 OIC_LOG(DEBUG, TAG, "start to check device");
723 // get name, address from BT device
724 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
725 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
729 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
730 OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
731 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
732 (*env)->DeleteLocalRef(env, j_str_name);
735 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
736 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
737 (*env)->DeleteLocalRef(env, j_obj_device);
740 OIC_LOG(ERROR, TAG, "remoteAddress is null");
743 (*g_jvm)->DetachCurrentThread(g_jvm);
746 (*env)->DeleteLocalRef(env, j_str_address);
747 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
748 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
749 return CA_STATUS_INVALID_PARAM;
751 OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
754 if (!strcmp(remoteAddress, address))
756 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
757 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
758 (*env)->DeleteLocalRef(env, j_str_address);
759 if (CA_STATUS_OK != res)
761 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
762 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
767 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
768 (*env)->DeleteLocalRef(env, j_str_address);
771 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
772 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
776 (*g_jvm)->DetachCurrentThread(g_jvm);
782 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
784 VERIFY_NON_NULL(env, TAG, "env is null");
785 VERIFY_NON_NULL(data, TAG, "data is null");
787 // get bonded device list
788 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
789 if (!jni_arrayPairedDevices)
791 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
792 return CA_STATUS_INVALID_PARAM;
794 // Get information from array of devices
795 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
796 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
797 METHODID_STRINGNONPARAM);
798 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
799 METHODID_STRINGNONPARAM);
801 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
802 for (jsize i = 0; i < length; i++)
804 // get name, address from BT device
805 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
806 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
807 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
809 if (j_str_name && j_str_address)
811 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
812 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
813 if (name && remoteAddress)
815 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
817 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
818 if (CA_STATUS_OK != res)
820 OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
822 g_edrErrorHandler(remoteAddress, data, dataLen, res);
825 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
826 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
829 (*env)->DeleteLocalRef(env, j_obj_device);
830 (*env)->DeleteLocalRef(env, j_str_name);
831 (*env)->DeleteLocalRef(env, j_str_address);
834 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
835 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
840 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
843 VERIFY_NON_NULL(env, TAG, "env is null");
844 VERIFY_NON_NULL(address, TAG, "address is null");
845 VERIFY_NON_NULL(data, TAG, "data is null");
847 if (!CAEDRNativeIsEnableBTAdapter(env))
849 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
850 return CA_STATUS_INVALID_PARAM;
853 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
855 // connect before send data
856 OIC_LOG(DEBUG, TAG, "connect before send data");
858 CAResult_t res = CAEDRNativeConnect(env, address);
859 if (CA_STATUS_OK != res)
865 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
867 if (!((*env)->ExceptionCheck(env)))
869 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
870 if (!jni_cid_BTsocket)
872 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
873 return CA_STATUS_FAILED;
876 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
878 METHODID_OUTPUTNONPARAM);
879 if (!jni_mid_getOutputStream)
881 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
882 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
883 return CA_STATUS_FAILED;
886 OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
888 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
891 OIC_LOG(ERROR, TAG, "jni_socket is not available");
892 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
893 return CA_STATUS_FAILED;
896 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
897 jni_mid_getOutputStream);
898 if (!jni_obj_outputStream)
900 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
901 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
902 return CA_STATUS_FAILED;
905 OIC_LOG(DEBUG, TAG, "ready outputStream..");
907 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
908 if (!jni_cid_OutputStream)
910 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
911 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
912 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
913 return CA_STATUS_FAILED;
916 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
920 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
921 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
922 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
923 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
924 return CA_STATUS_FAILED;
927 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
928 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
930 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
933 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
934 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
935 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
936 (*env)->DeleteLocalRef(env, jbuf);
938 if ((*env)->ExceptionCheck(env))
940 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
941 (*env)->ExceptionDescribe(env);
942 (*env)->ExceptionClear(env);
943 return CA_STATUS_FAILED;
946 OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
947 dataLength, address);
951 (*env)->ExceptionDescribe(env);
952 (*env)->ExceptionClear(env);
953 OIC_LOG(ERROR, TAG, "error!!");
954 return CA_STATUS_FAILED;
959 OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
965 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
967 VERIFY_NON_NULL(address, TAG, "address is null");
968 OIC_LOG(DEBUG, TAG, "btConnect..");
970 if (!CAEDRNativeIsEnableBTAdapter(env))
972 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
973 return CA_STATUS_INVALID_PARAM;
976 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
977 if (!jni_cid_BTAdapter)
979 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
980 return CA_STATUS_FAILED;
984 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
986 METHODID_OBJECTNONPARAM);
987 if (!jni_mid_getDefaultAdapter)
989 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
990 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
991 return CA_STATUS_FAILED;
994 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
995 jni_mid_getDefaultAdapter);
996 if (!jni_obj_BTAdapter)
998 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
999 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1000 return CA_STATUS_FAILED;
1003 // get remote bluetooth device
1004 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1006 METHODID_BT_DEVICEPARAM);
1007 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1008 if (!jni_mid_getRemoteDevice)
1010 OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
1011 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1012 return CA_STATUS_FAILED;
1015 jstring jni_address = (*env)->NewStringUTF(env, address);
1016 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
1017 jni_mid_getRemoteDevice, jni_address);
1018 (*env)->DeleteLocalRef(env, jni_address);
1019 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1020 if (!jni_obj_remoteBTDevice)
1022 OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
1023 return CA_STATUS_FAILED;
1026 // get create Rfcomm Socket method ID
1027 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
1028 if (!jni_cid_BluetoothDevice)
1030 OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
1031 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1032 return CA_STATUS_FAILED;
1035 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
1036 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
1037 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
1038 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
1039 if (!jni_mid_createSocket)
1041 OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
1042 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1043 return CA_STATUS_FAILED;
1047 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1050 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1051 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1052 return CA_STATUS_FAILED;
1055 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
1056 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
1057 if (!jni_mid_fromString)
1059 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1060 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1061 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1062 return CA_STATUS_FAILED;
1065 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1068 OIC_LOG(ERROR, TAG, "jni_uuid is null");
1069 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1070 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1071 return CA_STATUS_FAILED;
1073 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1075 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1076 (*env)->DeleteLocalRef(env, jni_uuid);
1079 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1080 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1081 return CA_STATUS_FAILED;
1084 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1085 jni_mid_createSocket, jni_obj_uuid);
1086 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1087 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1088 if (!jni_obj_BTSocket)
1090 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1091 return CA_STATUS_FAILED;
1095 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1096 if (!jni_cid_BTSocket)
1098 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1099 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1100 return CA_STATUS_FAILED;
1103 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1104 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1105 if (!jni_mid_connect)
1107 OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1108 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1109 return CA_STATUS_FAILED;
1112 OIC_LOG(DEBUG, TAG, "initiating connection...");
1113 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1115 if ((*env)->ExceptionCheck(env))
1117 OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1118 (*env)->ExceptionDescribe(env);
1119 (*env)->ExceptionClear(env);
1120 return CA_STATUS_FAILED;
1123 // set socket to list
1124 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1127 OIC_LOG(ERROR, TAG, "jni_socket is null");
1128 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1129 return CA_STATUS_FAILED;
1131 ca_mutex_lock(g_mutexObjectList);
1132 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1133 (*env)->DeleteGlobalRef(env, jni_socket);
1134 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1135 ca_mutex_unlock(g_mutexObjectList);
1138 ca_mutex_lock(g_mutexStateList);
1139 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1140 ca_mutex_unlock(g_mutexStateList);
1142 OIC_LOG(DEBUG, TAG, "connected");
1144 return CA_STATUS_OK;
1147 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1149 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1151 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1152 if (!jni_cid_BTSocket)
1154 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1158 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1161 OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1165 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1166 if (!jni_obj_socket)
1168 OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1172 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1174 if ((*env)->ExceptionCheck(env))
1176 OIC_LOG(ERROR, TAG, "close is Failed!!!");
1177 (*env)->ExceptionDescribe(env);
1178 (*env)->ExceptionClear(env);
1182 // remove socket to list
1183 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1186 ca_mutex_lock(g_mutexStateList);
1187 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1188 ca_mutex_unlock(g_mutexStateList);
1190 OIC_LOG(DEBUG, TAG, "disconnected");
1193 CAResult_t CAEDRClientInitialize()
1195 CAResult_t result = CAEDRInitialize();
1199 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1201 g_edrErrorHandler = errorHandleCallback;