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"
37 #define TAG PCF("OIC_CA_EDR_CLIENT")
39 static const char METHODID_CONTEXTNONPARAM[] = "()Landroid/content/Context;";
40 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
41 static const char METHODID_OUTPUTNONPARAM[] = "()Ljava/io/OutputStream;";
42 static const char METHODID_STRINGNONPARAM[] = "()Ljava/lang/String;";
43 static const char METHODID_BT_DEVICEPARAM[] =
44 "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;";
45 static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter";
46 static const char CLASSPATH_BT_DEVICE[] = "android/bluetooth/BluetoothDevice";
47 static const char CLASSPATH_BT_INTERFACE[] = "org/iotivity/ca/CaEdrInterface";
48 static const char CLASSPATH_BT_SOCKET[] = "android/bluetooth/BluetoothSocket";
49 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
50 static const char CLASSPATH_CONTEXT[] = "android/content/Context";
51 static const char CLASSPATH_OUTPUT[] = "java/io/OutputStream";
54 static jobject g_context;
57 * @var g_mutexUnicastServer
58 * @brief Mutex to synchronize unicast server
60 static ca_mutex g_mutexUnicastServer = NULL;
64 * @brief Flag to control the Receive Unicast Data Thread
66 static bool g_stopUnicast = false;
69 * @var g_mutexMulticastServer
70 * @brief Mutex to synchronize secure multicast server
72 static ca_mutex g_mutexMulticastServer = NULL;
75 * @var g_stopMulticast
76 * @brief Flag to control the Receive Multicast Data Thread
78 static bool g_stopMulticast = false;
82 * @brief Flag to control the Accept Thread
84 static bool g_stopAccept = false;
87 * @var g_mutexStateList
88 * @brief Mutex to synchronize device state list
90 static ca_mutex g_mutexStateList = NULL;
93 * @var g_mutexObjectList
94 * @brief Mutex to synchronize device object list
96 static ca_mutex g_mutexObjectList = NULL;
99 * @var g_edrErrorHandler
100 * @brief Error callback to update error in EDR
102 static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
104 typedef struct send_data
112 @brief Thread context information for unicast, multicast and secured unicast server
117 CAAdapterServerType_t type;
118 } CAAdapterReceiveThreadContext_t;
123 } CAAdapterAcceptThreadContext_t;
126 * implement for BT-EDR adapter common method
128 CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
130 OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
134 OIC_LOG(ERROR, TAG, "endpoint info is null");
135 return CA_STATUS_INVALID_PARAM;
138 char *macAddress = NULL;
139 CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
140 if (CA_STATUS_OK != ret)
142 OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
149 OIC_LOG(ERROR, TAG, "mac address is null");
150 return CA_STATUS_FAILED;
152 OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
154 // Create local endpoint using util function
155 CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
157 if (NULL == endpoint)
159 OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
161 return CA_STATUS_FAILED;
164 // copy unicast server information
165 int32_t netInfoSize = 1;
166 CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
169 OIC_LOG(ERROR, TAG, "Invalid input..");
171 CAFreeEndpoint(endpoint);
172 return CA_MEMORY_ALLOC_FAILED;
174 *netInfo = *endpoint;
178 CAFreeEndpoint(endpoint);
180 OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
184 void CAEDRClientTerminate()
186 OIC_LOG(DEBUG, TAG, "IN");
188 OIC_LOG(DEBUG, TAG, "OUT");
191 CAResult_t CAEDRManagerReadData()
193 OIC_LOG(DEBUG, TAG, "IN");
195 OIC_LOG(DEBUG, TAG, "OUT");
196 return CA_NOT_SUPPORTED;
199 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
202 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
203 VERIFY_NON_NULL(data, TAG, "data is null");
205 CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
209 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
211 VERIFY_NON_NULL(data, TAG, "data is null");
213 CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
217 // It will be updated when android EDR support is added
218 void CAEDRClientUnsetCallbacks()
220 OIC_LOG(DEBUG, TAG, "IN");
222 OIC_LOG(DEBUG, TAG, "OUT");
225 // It will be updated when android EDR support is added
226 void CAEDRClientDisconnectAll()
228 OIC_LOG(DEBUG, TAG, "IN");
230 OIC_LOG(DEBUG, TAG, "OUT");
233 CAResult_t CAEDRGetAdapterEnableState(bool *state)
235 VERIFY_NON_NULL(state, TAG, "state is null");
239 OIC_LOG(ERROR, TAG, "g_jvm is null");
240 return CA_STATUS_INVALID_PARAM;
242 bool isAttached = false;
244 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
247 OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
248 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
252 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
253 return CA_STATUS_INVALID_PARAM;
259 jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
267 (*g_jvm)->DetachCurrentThread(g_jvm);
273 void CAEDRJniInitContext()
275 OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
277 g_context = (jobject) CANativeJNIGetContext();
280 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
283 OIC_LOG(DEBUG, TAG, "CAEDRCreateJNIInterfaceObject");
285 if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
287 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
288 return CA_STATUS_FAILED;
291 //getApplicationContext
292 jclass contextClass = (*env)->FindClass(env, CLASSPATH_CONTEXT);
295 OIC_LOG(ERROR, TAG, "Could not get context object class");
296 return CA_STATUS_FAILED;
299 jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
300 "getApplicationContext",
301 METHODID_CONTEXTNONPARAM);
302 if (!getApplicationContextMethod)
304 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
305 return CA_STATUS_FAILED;
308 //Create EDRJniInterface instance
309 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
310 if (!EDRJniInterface)
312 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
313 return CA_STATUS_FAILED;
316 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
317 "(Landroid/content/Context;)V");
318 if (!EDRInterfaceConstructorMethod)
320 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method");
321 return CA_STATUS_FAILED;
324 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context);
325 OIC_LOG(DEBUG, TAG, "NewObject Success");
330 static void CAEDRDestroyMutex()
332 if (g_mutexUnicastServer)
334 ca_mutex_free(g_mutexUnicastServer);
335 g_mutexUnicastServer = NULL;
338 if (g_mutexMulticastServer)
340 ca_mutex_free(g_mutexMulticastServer);
341 g_mutexMulticastServer = NULL;
344 if (g_mutexStateList)
346 ca_mutex_free(g_mutexStateList);
347 g_mutexStateList = NULL;
350 if (g_mutexObjectList)
352 ca_mutex_free(g_mutexObjectList);
353 g_mutexObjectList = NULL;
357 static CAResult_t CAEDRCreateMutex()
359 g_mutexUnicastServer = ca_mutex_new();
360 if (!g_mutexUnicastServer)
362 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
363 return CA_STATUS_FAILED;
366 g_mutexMulticastServer = ca_mutex_new();
367 if (!g_mutexMulticastServer)
369 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
372 return CA_STATUS_FAILED;
375 g_mutexStateList = ca_mutex_new();
376 if (!g_mutexStateList)
378 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
381 return CA_STATUS_FAILED;
384 g_mutexObjectList = ca_mutex_new();
385 if (!g_mutexObjectList)
387 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
390 return CA_STATUS_FAILED;
396 CAResult_t CAEDRInitialize()
398 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
402 CAEDRJniInitContext();
405 CAResult_t result = CAEDRCreateMutex();
406 if(CA_STATUS_OK != result)
408 OIC_LOG(ERROR, TAG, "CAEDRInitialize - Could not create mutex");
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");
423 return CA_STATUS_NOT_INITIALIZED;
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");
459 void CAEDRTerminate()
461 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
463 bool isAttached = false;
465 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
468 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
469 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
473 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
480 g_stopMulticast = true;
481 g_stopUnicast = true;
485 (*g_jvm)->DetachCurrentThread(g_jvm);
490 (*env)->DeleteGlobalRef(env, g_context);
493 CAEDRNativeSocketCloseToAll(env);
498 CAEDRNativeRemoveAllDeviceState();
499 CAEDRNativeRemoveAllDeviceSocket(env);
500 CAEDRDestroyJniInterface();
503 CAResult_t CAEDRDestroyJniInterface()
505 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
509 OIC_LOG(ERROR, TAG, "g_jvm is null");
510 return CA_STATUS_FAILED;
513 bool isAttached = false;
515 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
518 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
519 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
523 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
524 return CA_STATUS_FAILED;
529 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
530 if (!jni_EDRJniInterface)
532 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
536 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
537 "destroyEdrInterface",
539 if (!jni_EDRInterfaceDestroyMethod)
541 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
545 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
547 if ((*env)->ExceptionCheck(env))
549 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
550 (*env)->ExceptionDescribe(env);
551 (*env)->ExceptionClear(env);
555 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
559 (*g_jvm)->DetachCurrentThread(g_jvm);
568 (*g_jvm)->DetachCurrentThread(g_jvm);
571 return CA_STATUS_FAILED;
574 void CAEDRCoreJniInit()
576 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
577 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
580 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
582 VERIFY_NON_NULL(address, TAG, "address is null");
583 VERIFY_NON_NULL(data, TAG, "data is null");
585 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
589 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
591 VERIFY_NON_NULL(data, TAG, "data is null");
593 bool isAttached = false;
595 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
598 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
599 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
603 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
604 return CA_STATUS_INVALID_PARAM;
609 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
610 if(CA_STATUS_OK != result)
612 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
616 OIC_LOG(DEBUG, TAG, "sent data");
620 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
621 (*g_jvm)->DetachCurrentThread(g_jvm);
624 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
628 CAResult_t CAEDRGetInterfaceInfo(char **address)
630 CAEDRGetLocalAddress(address);
634 void CAEDRGetLocalAddress(char **address)
636 bool isAttached = false;
638 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
641 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
642 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
645 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
651 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
654 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
655 *address = OICStrdup(localAddress);
656 if (*address == NULL)
660 (*g_jvm)->DetachCurrentThread(g_jvm);
662 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
663 (*env)->DeleteLocalRef(env, jni_address);
667 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
668 (*env)->DeleteLocalRef(env, jni_address);
671 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
674 (*g_jvm)->DetachCurrentThread(g_jvm);
678 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
680 VERIFY_NON_NULL(address, TAG, "address is null");
681 VERIFY_NON_NULL(data, TAG, "data is null");
683 bool isAttached = false;
685 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
688 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
689 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
692 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
693 return CA_STATUS_INVALID_PARAM;
698 OIC_LOG(DEBUG, TAG, "set byteArray for data");
700 // get bonded device list
701 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
702 if (!jni_arrayPairedDevices)
704 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
707 (*g_jvm)->DetachCurrentThread(g_jvm);
709 return CA_STATUS_INVALID_PARAM;
711 // Get information from array of devices
712 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
713 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
714 METHODID_STRINGNONPARAM);
715 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
716 METHODID_STRINGNONPARAM);
718 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
719 for (jsize i = 0; i < length; i++)
721 OIC_LOG(DEBUG, TAG, "start to check device");
722 // get name, address from BT device
723 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
724 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
728 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
729 OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
730 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
731 (*env)->DeleteLocalRef(env, j_str_name);
734 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
735 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
736 (*env)->DeleteLocalRef(env, j_obj_device);
739 OIC_LOG(ERROR, TAG, "remoteAddress is null");
742 (*g_jvm)->DetachCurrentThread(g_jvm);
745 (*env)->DeleteLocalRef(env, j_str_address);
746 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
747 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
748 return CA_STATUS_INVALID_PARAM;
750 OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
753 if (!strcmp(remoteAddress, address))
755 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
756 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
757 (*env)->DeleteLocalRef(env, j_str_address);
758 if (CA_STATUS_OK != res)
760 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
761 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
766 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
767 (*env)->DeleteLocalRef(env, j_str_address);
770 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
771 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
775 (*g_jvm)->DetachCurrentThread(g_jvm);
781 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
783 VERIFY_NON_NULL(env, TAG, "env is null");
784 VERIFY_NON_NULL(data, TAG, "data is null");
786 // get bonded device list
787 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
788 if (!jni_arrayPairedDevices)
790 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
791 return CA_STATUS_INVALID_PARAM;
793 // Get information from array of devices
794 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
795 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
796 METHODID_STRINGNONPARAM);
797 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
798 METHODID_STRINGNONPARAM);
800 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
801 for (jsize i = 0; i < length; i++)
803 // get name, address from BT device
804 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
805 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
806 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
808 if (j_str_name && j_str_address)
810 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
811 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
812 if (name && remoteAddress)
814 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
816 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
817 if (CA_STATUS_OK != res)
819 OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
821 g_edrErrorHandler(remoteAddress, data, dataLen, res);
824 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
825 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
828 (*env)->DeleteLocalRef(env, j_obj_device);
829 (*env)->DeleteLocalRef(env, j_str_name);
830 (*env)->DeleteLocalRef(env, j_str_address);
833 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
834 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
839 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
842 VERIFY_NON_NULL(env, TAG, "env is null");
843 VERIFY_NON_NULL(address, TAG, "address is null");
844 VERIFY_NON_NULL(data, TAG, "data is null");
846 if (!CAEDRNativeIsEnableBTAdapter(env))
848 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
849 return CA_ADAPTER_NOT_ENABLED;
852 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
854 // connect before send data
855 OIC_LOG(DEBUG, TAG, "connect before send data");
857 CAResult_t res = CAEDRNativeConnect(env, address);
858 if (CA_STATUS_OK != res)
864 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
866 if (!((*env)->ExceptionCheck(env)))
868 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
869 if (!jni_cid_BTsocket)
871 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
872 return CA_STATUS_FAILED;
875 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
877 METHODID_OUTPUTNONPARAM);
878 if (!jni_mid_getOutputStream)
880 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
881 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
882 return CA_STATUS_FAILED;
885 OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
887 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
890 OIC_LOG(ERROR, TAG, "jni_socket is not available");
891 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
892 return CA_STATUS_FAILED;
895 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
896 jni_mid_getOutputStream);
897 if (!jni_obj_outputStream)
899 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
900 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
901 return CA_STATUS_FAILED;
904 OIC_LOG(DEBUG, TAG, "ready outputStream..");
906 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
907 if (!jni_cid_OutputStream)
909 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
910 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
911 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
912 return CA_STATUS_FAILED;
915 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
919 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
920 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
921 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
922 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
923 return CA_STATUS_FAILED;
926 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
927 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
929 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
932 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
933 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
934 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
935 (*env)->DeleteLocalRef(env, jbuf);
937 if ((*env)->ExceptionCheck(env))
939 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
940 (*env)->ExceptionDescribe(env);
941 (*env)->ExceptionClear(env);
942 return CA_STATUS_FAILED;
945 OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
946 dataLength, address);
950 (*env)->ExceptionDescribe(env);
951 (*env)->ExceptionClear(env);
952 OIC_LOG(ERROR, TAG, "error!!");
953 return CA_STATUS_FAILED;
958 OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
964 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
966 VERIFY_NON_NULL(address, TAG, "address is null");
967 OIC_LOG(DEBUG, TAG, "btConnect..");
969 if (!CAEDRNativeIsEnableBTAdapter(env))
971 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
972 return CA_ADAPTER_NOT_ENABLED;
975 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
976 if (!jni_cid_BTAdapter)
978 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
979 return CA_STATUS_FAILED;
983 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
985 METHODID_OBJECTNONPARAM);
986 if (!jni_mid_getDefaultAdapter)
988 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
989 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
990 return CA_STATUS_FAILED;
993 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
994 jni_mid_getDefaultAdapter);
995 if (!jni_obj_BTAdapter)
997 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
998 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
999 return CA_STATUS_FAILED;
1002 // get remote bluetooth device
1003 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1005 METHODID_BT_DEVICEPARAM);
1006 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1007 if (!jni_mid_getRemoteDevice)
1009 OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
1010 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1011 return CA_STATUS_FAILED;
1014 jstring jni_address = (*env)->NewStringUTF(env, address);
1015 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
1016 jni_mid_getRemoteDevice, jni_address);
1017 (*env)->DeleteLocalRef(env, jni_address);
1018 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1019 if (!jni_obj_remoteBTDevice)
1021 OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
1022 return CA_STATUS_FAILED;
1025 // get create Rfcomm Socket method ID
1026 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
1027 if (!jni_cid_BluetoothDevice)
1029 OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
1030 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1031 return CA_STATUS_FAILED;
1034 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
1035 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
1036 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
1037 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
1038 if (!jni_mid_createSocket)
1040 OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
1041 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1042 return CA_STATUS_FAILED;
1046 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1049 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1050 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1051 return CA_STATUS_FAILED;
1054 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
1055 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
1056 if (!jni_mid_fromString)
1058 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1059 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1060 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1061 return CA_STATUS_FAILED;
1064 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1067 OIC_LOG(ERROR, TAG, "jni_uuid is null");
1068 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1069 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1070 return CA_STATUS_FAILED;
1072 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1074 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1075 (*env)->DeleteLocalRef(env, jni_uuid);
1078 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1079 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1080 return CA_STATUS_FAILED;
1083 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1084 jni_mid_createSocket, jni_obj_uuid);
1085 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1086 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1087 if (!jni_obj_BTSocket)
1089 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1090 return CA_STATUS_FAILED;
1094 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1095 if (!jni_cid_BTSocket)
1097 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1098 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1099 return CA_STATUS_FAILED;
1102 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1103 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1104 if (!jni_mid_connect)
1106 OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1107 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1108 return CA_STATUS_FAILED;
1111 OIC_LOG(DEBUG, TAG, "initiating connection...");
1112 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1114 if ((*env)->ExceptionCheck(env))
1116 OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1117 (*env)->ExceptionDescribe(env);
1118 (*env)->ExceptionClear(env);
1119 return CA_STATUS_FAILED;
1122 // set socket to list
1123 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1126 OIC_LOG(ERROR, TAG, "jni_socket is null");
1127 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1128 return CA_STATUS_FAILED;
1130 ca_mutex_lock(g_mutexObjectList);
1131 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1132 (*env)->DeleteGlobalRef(env, jni_socket);
1133 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1134 ca_mutex_unlock(g_mutexObjectList);
1137 ca_mutex_lock(g_mutexStateList);
1138 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1139 ca_mutex_unlock(g_mutexStateList);
1141 OIC_LOG(DEBUG, TAG, "connected");
1143 return CA_STATUS_OK;
1146 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1148 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1150 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1151 if (!jni_cid_BTSocket)
1153 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1157 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1160 OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1164 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1165 if (!jni_obj_socket)
1167 OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1171 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1173 if ((*env)->ExceptionCheck(env))
1175 OIC_LOG(ERROR, TAG, "close is Failed!!!");
1176 (*env)->ExceptionDescribe(env);
1177 (*env)->ExceptionClear(env);
1181 // remove socket to list
1182 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1185 ca_mutex_lock(g_mutexStateList);
1186 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1187 ca_mutex_unlock(g_mutexStateList);
1189 OIC_LOG(DEBUG, TAG, "disconnected");
1192 CAResult_t CAEDRClientInitialize()
1194 CAResult_t result = CAEDRInitialize();
1198 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1200 g_edrErrorHandler = errorHandleCallback;