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("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");
207 OIC_LOG(DEBUG, TAG, "IN");
209 CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
210 OIC_LOG(DEBUG, TAG, "OUT");
214 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
216 VERIFY_NON_NULL(data, TAG, "data is null");
217 OIC_LOG(DEBUG, TAG, "IN");
219 CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
220 OIC_LOG(DEBUG, TAG, "OUT");
224 // It will be updated when android EDR support is added
225 void CAEDRClientUnsetCallbacks()
227 OIC_LOG(DEBUG, TAG, "IN");
229 OIC_LOG(DEBUG, TAG, "OUT");
232 // It will be updated when android EDR support is added
233 void CAEDRClientDisconnectAll()
235 OIC_LOG(DEBUG, TAG, "IN");
237 OIC_LOG(DEBUG, TAG, "OUT");
240 CAResult_t CAEDRGetAdapterEnableState(bool *state)
242 OIC_LOG(DEBUG, TAG, "IN");
245 OIC_LOG(ERROR, TAG, "g_jvm is null");
246 return CA_STATUS_INVALID_PARAM;
248 bool isAttached = false;
250 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
253 OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
254 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
258 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
259 return CA_STATUS_INVALID_PARAM;
263 jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
275 (*g_jvm)->DetachCurrentThread(g_jvm);
278 OIC_LOG(DEBUG, TAG, "OUT");
282 void CAEDRJniInitContext()
284 OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
286 g_context = (jobject) CANativeJNIGetContext();
289 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
292 OIC_LOG(DEBUG, TAG, "[EDRCore] CAEDRCreateJNIInterfaceObject");
294 if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
296 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get JNIEnv pointer");
297 return CA_STATUS_FAILED;
300 //getApplicationContext
301 jclass contextClass = (*env)->FindClass(env, CLASSPATH_CONTEXT);
304 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get context object class");
305 return CA_STATUS_FAILED;
308 jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
309 "getApplicationContext",
310 METHODID_CONTEXTNONPARAM);
311 if (!getApplicationContextMethod)
313 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get getApplicationContext method");
314 return CA_STATUS_FAILED;
317 //Create EDRJniInterface instance
318 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
319 if (!EDRJniInterface)
321 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get CaEdrInterface class");
322 return CA_STATUS_FAILED;
325 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
326 "(Landroid/content/Context;)V");
327 if (!EDRInterfaceConstructorMethod)
329 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get CaEdrInterface constructor method");
330 return CA_STATUS_FAILED;
333 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context);
334 OIC_LOG(DEBUG, TAG, "[EDRCore] NewObject Success");
340 static void CAEDRDestroyMutex()
342 OIC_LOG(DEBUG, TAG, "IN");
344 if (g_mutexUnicastServer)
346 ca_mutex_free(g_mutexUnicastServer);
347 g_mutexUnicastServer = NULL;
350 if (g_mutexMulticastServer)
352 ca_mutex_free(g_mutexMulticastServer);
353 g_mutexMulticastServer = NULL;
356 if (g_mutexStateList)
358 ca_mutex_free(g_mutexStateList);
359 g_mutexStateList = NULL;
362 if (g_mutexObjectList)
364 ca_mutex_free(g_mutexObjectList);
365 g_mutexObjectList = NULL;
367 OIC_LOG(DEBUG, TAG, "OUT");
370 static CAResult_t CAEDRCreateMutex()
372 OIC_LOG(DEBUG, TAG, "IN");
374 g_mutexUnicastServer = ca_mutex_new();
375 if (!g_mutexUnicastServer)
377 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
378 return CA_STATUS_FAILED;
381 g_mutexMulticastServer = ca_mutex_new();
382 if (!g_mutexMulticastServer)
384 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
387 return CA_STATUS_FAILED;
390 g_mutexStateList = ca_mutex_new();
391 if (!g_mutexStateList)
393 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
396 return CA_STATUS_FAILED;
399 g_mutexObjectList = ca_mutex_new();
400 if (!g_mutexObjectList)
402 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
405 return CA_STATUS_FAILED;
408 OIC_LOG(DEBUG, TAG, "OUT");
412 void CAEDRInitialize(ca_thread_pool_t handle)
414 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
416 g_threadPoolHandle = handle;
420 CAEDRJniInitContext();
425 bool isAttached = false;
427 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
430 OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
431 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
435 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
440 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
443 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
444 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
445 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
448 ca_mutex_lock(g_mutexStateList);
449 CAEDRNativeCreateDeviceStateList();
450 ca_mutex_unlock(g_mutexStateList);
452 ca_mutex_lock(g_mutexObjectList);
453 CAEDRNativeCreateDeviceSocketList();
454 ca_mutex_unlock(g_mutexObjectList);
458 (*g_jvm)->DetachCurrentThread(g_jvm);
463 CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
466 OIC_LOG(DEBUG, TAG, "OUT");
469 void CAEDRTerminate()
471 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
473 bool isAttached = false;
475 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
478 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
479 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
483 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
490 g_stopMulticast = true;
491 g_stopUnicast = true;
495 (*g_jvm)->DetachCurrentThread(g_jvm);
500 (*env)->DeleteGlobalRef(env, g_context);
503 CAEDRNativeSocketCloseToAll(env);
508 CAEDRNativeRemoveAllDeviceState();
509 CAEDRNativeRemoveAllDeviceSocket(env);
510 CAEDRDestroyJniInterface();
513 CAResult_t CAEDRDestroyJniInterface()
515 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
519 OIC_LOG(ERROR, TAG, "g_jvm is null");
520 return CA_STATUS_FAILED;
523 bool isAttached = false;
525 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
528 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
529 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
533 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
534 return CA_STATUS_FAILED;
539 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
540 if (!jni_EDRJniInterface)
542 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
546 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
547 "destroyEdrInterface",
549 if (!jni_EDRInterfaceDestroyMethod)
551 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
555 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
557 if ((*env)->ExceptionCheck(env))
559 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
560 (*env)->ExceptionDescribe(env);
561 (*env)->ExceptionClear(env);
565 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
569 (*g_jvm)->DetachCurrentThread(g_jvm);
578 (*g_jvm)->DetachCurrentThread(g_jvm);
581 return CA_STATUS_FAILED;
584 void CAEDRCoreJniInit()
586 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
587 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
590 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
592 VERIFY_NON_NULL(address, TAG, "address is null");
593 VERIFY_NON_NULL(data, TAG, "data is null");
595 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
599 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
601 VERIFY_NON_NULL(data, TAG, "data is null");
602 OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data);
604 bool isAttached = false;
606 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
609 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
610 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
614 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
615 return CA_STATUS_INVALID_PARAM;
620 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
621 if(CA_STATUS_OK != result)
623 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
627 OIC_LOG(DEBUG, TAG, "sent data");
631 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
632 (*g_jvm)->DetachCurrentThread(g_jvm);
635 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
639 CAResult_t CAEDRGetInterfaceInfo(char **address)
641 CAEDRGetLocalAddress(address);
645 void CAEDRGetLocalAddress(char **address)
647 bool isAttached = false;
649 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
652 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
653 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
656 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
662 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
665 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
666 *address = OICStrdup(localAddress);
667 if (*address == NULL)
671 (*g_jvm)->DetachCurrentThread(g_jvm);
673 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
674 (*env)->DeleteLocalRef(env, jni_address);
678 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
679 (*env)->DeleteLocalRef(env, jni_address);
682 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
685 (*g_jvm)->DetachCurrentThread(g_jvm);
689 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
691 VERIFY_NON_NULL(address, TAG, "address is null");
692 VERIFY_NON_NULL(data, TAG, "data is null");
693 OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl, address: %s, data: %s", address, data);
695 bool isAttached = false;
697 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
700 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
701 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
704 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
705 return CA_STATUS_INVALID_PARAM;
710 OIC_LOG(DEBUG, TAG, "[EDR][Native] set byteArray for data");
712 // get bonded device list
713 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
714 if (!jni_arrayPairedDevices)
716 OIC_LOG(ERROR, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
719 (*g_jvm)->DetachCurrentThread(g_jvm);
721 return CA_STATUS_INVALID_PARAM;
723 // Get information from array of devices
724 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
725 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
726 METHODID_STRINGNONPARAM);
727 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
728 METHODID_STRINGNONPARAM);
730 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
731 for (jsize i = 0; i < length; i++)
733 OIC_LOG(DEBUG, TAG, "[EDR][Native] start to check device");
734 // get name, address from BT device
735 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
736 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
740 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
741 OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name);
742 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
743 (*env)->DeleteLocalRef(env, j_str_name);
746 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
747 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
748 (*env)->DeleteLocalRef(env, j_obj_device);
751 OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
754 (*g_jvm)->DetachCurrentThread(g_jvm);
757 (*env)->DeleteLocalRef(env, j_str_address);
758 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
759 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
760 return CA_STATUS_INVALID_PARAM;
762 OIC_LOG_V(DEBUG, TAG,
763 "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
766 if (!strcmp(remoteAddress, address))
768 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
769 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
770 (*env)->DeleteLocalRef(env, j_str_address);
771 if (CA_STATUS_OK != res)
773 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
774 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
779 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
780 (*env)->DeleteLocalRef(env, j_str_address);
783 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
784 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
788 (*g_jvm)->DetachCurrentThread(g_jvm);
794 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
796 VERIFY_NON_NULL(data, TAG, "data is null");
797 OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
799 // get bonded device list
800 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
801 if (!jni_arrayPairedDevices)
803 OIC_LOG(ERROR, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
804 return CA_STATUS_INVALID_PARAM;
806 // Get information from array of devices
807 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
808 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
809 METHODID_STRINGNONPARAM);
810 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
811 METHODID_STRINGNONPARAM);
813 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
814 for (jsize i = 0; i < length; i++)
816 // get name, address from BT device
817 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
818 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
822 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
823 OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name);
824 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
825 (*env)->DeleteLocalRef(env, j_str_name);
828 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
829 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
830 (*env)->DeleteLocalRef(env, j_obj_device);
831 OIC_LOG_V(DEBUG, TAG,
832 "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
835 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
836 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
837 (*env)->DeleteLocalRef(env, j_str_address);
838 if (CA_STATUS_OK != res)
840 OIC_LOG_V(ERROR, TAG, "CASendMulticastMessageImpl, failed to send message to : %s",
842 g_edrErrorHandler(remoteAddress, data, dataLen, res);
847 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
848 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
856 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
859 VERIFY_NON_NULL(address, TAG, "address is null");
860 VERIFY_NON_NULL(data, TAG, "data is null");
861 OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData logic start : %s, %d", data, dataLength);
863 if (!CAEDRNativeIsEnableBTAdapter(env))
865 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
866 return CA_STATUS_INVALID_PARAM;
869 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
871 // connect before send data
872 OIC_LOG(DEBUG, TAG, "[EDR][Native] connect before send data");
874 CAResult_t res = CAEDRNativeConnect(env, address);
875 if (CA_STATUS_OK != res)
881 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
883 if (!((*env)->ExceptionCheck(env)))
885 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
886 if (!jni_cid_BTsocket)
888 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_BTsocket is null");
889 return CA_STATUS_FAILED;
892 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
894 METHODID_OUTPUTNONPARAM);
895 if (!jni_mid_getOutputStream)
897 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_getOutputStream is null");
898 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
899 return CA_STATUS_FAILED;
902 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Get MethodID for i/o stream");
904 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
907 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_socket is not available");
908 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
909 return CA_STATUS_FAILED;
912 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
913 jni_mid_getOutputStream);
914 if (!jni_obj_outputStream)
916 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_obj_outputStream is null");
917 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
918 return CA_STATUS_FAILED;
921 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: ready outputStream..");
923 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
924 if (!jni_cid_OutputStream)
926 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_OutputStream is null");
927 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
928 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
929 return CA_STATUS_FAILED;
932 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
936 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_write is null");
937 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
938 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
939 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
940 return CA_STATUS_FAILED;
943 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
944 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
946 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
949 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
950 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
951 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
952 (*env)->DeleteLocalRef(env, jbuf);
954 if ((*env)->ExceptionCheck(env))
956 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: Write Error!!!");
957 (*env)->ExceptionDescribe(env);
958 (*env)->ExceptionClear(env);
959 return CA_STATUS_FAILED;
962 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Write Success");
966 (*env)->ExceptionDescribe(env);
967 (*env)->ExceptionClear(env);
968 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: error!!");
969 return CA_STATUS_FAILED;
974 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: BT connection is not completed!!");
980 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
982 VERIFY_NON_NULL(address, TAG, "address is null");
983 OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect..");
985 if (!CAEDRNativeIsEnableBTAdapter(env))
987 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
988 return CA_STATUS_INVALID_PARAM;
991 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
992 if (!jni_cid_BTAdapter)
994 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BTAdapter is null");
995 return CA_STATUS_FAILED;
999 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
1000 "getDefaultAdapter",
1001 METHODID_OBJECTNONPARAM);
1002 if (!jni_mid_getDefaultAdapter)
1004 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getDefaultAdapter is null");
1005 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1006 return CA_STATUS_FAILED;
1009 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
1010 jni_mid_getDefaultAdapter);
1011 if (!jni_obj_BTAdapter)
1013 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTAdapter is null");
1014 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1015 return CA_STATUS_FAILED;
1018 // get remote bluetooth device
1019 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1021 METHODID_BT_DEVICEPARAM);
1022 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1023 if (!jni_mid_getRemoteDevice)
1025 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getRemoteDevice is null");
1026 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1027 return CA_STATUS_FAILED;
1030 jstring jni_address = (*env)->NewStringUTF(env, address);
1031 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
1032 jni_mid_getRemoteDevice, jni_address);
1033 (*env)->DeleteLocalRef(env, jni_address);
1034 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1035 if (!jni_obj_remoteBTDevice)
1037 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_remoteBTDevice is null");
1038 return CA_STATUS_FAILED;
1041 // get create Rfcomm Socket method ID
1042 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
1043 if (!jni_cid_BluetoothDevice)
1045 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BluetoothDevice is null");
1046 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1047 return CA_STATUS_FAILED;
1050 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
1051 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
1052 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
1053 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
1054 if (!jni_mid_createSocket)
1056 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_createSocket is null");
1057 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1058 return CA_STATUS_FAILED;
1062 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1065 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_uuid is null");
1066 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1067 return CA_STATUS_FAILED;
1070 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
1071 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
1072 if (!jni_mid_fromString)
1074 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_fromString is null");
1075 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1076 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1077 return CA_STATUS_FAILED;
1080 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1083 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_uuid is null");
1084 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1085 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1086 return CA_STATUS_FAILED;
1088 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1090 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1091 (*env)->DeleteLocalRef(env, jni_uuid);
1094 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_uuid is null");
1095 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1096 return CA_STATUS_FAILED;
1099 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1100 jni_mid_createSocket, jni_obj_uuid);
1101 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1102 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1103 if (!jni_obj_BTSocket)
1105 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTSocket is null");
1106 return CA_STATUS_FAILED;
1110 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1111 if (!jni_cid_BTSocket)
1113 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BTSocket is null");
1114 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1115 return CA_STATUS_FAILED;
1118 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1119 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1120 if (!jni_mid_connect)
1122 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_connect is null");
1123 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1124 return CA_STATUS_FAILED;
1127 OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: initiating connection...");
1128 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1130 if ((*env)->ExceptionCheck(env))
1132 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: Connect is Failed!!!");
1133 (*env)->ExceptionDescribe(env);
1134 (*env)->ExceptionClear(env);
1135 return CA_STATUS_FAILED;
1138 // set socket to list
1139 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1142 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_socket is null");
1143 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1144 return CA_STATUS_FAILED;
1146 ca_mutex_lock(g_mutexObjectList);
1147 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1148 (*env)->DeleteGlobalRef(env, jni_socket);
1149 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1150 ca_mutex_unlock(g_mutexObjectList);
1153 ca_mutex_lock(g_mutexStateList);
1154 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1155 ca_mutex_unlock(g_mutexStateList);
1157 OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: connected");
1159 return CA_STATUS_OK;
1162 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1164 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1166 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1167 if (!jni_cid_BTSocket)
1169 OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_cid_BTSocket is null");
1173 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1176 OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_mid_close is null");
1180 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1181 if (!jni_obj_socket)
1183 OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_obj_socket is not available");
1187 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1189 if ((*env)->ExceptionCheck(env))
1191 OIC_LOG(ERROR, TAG, "[EDR][Native] close: close is Failed!!!");
1192 (*env)->ExceptionDescribe(env);
1193 (*env)->ExceptionClear(env);
1197 // remove socket to list
1198 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1201 ca_mutex_lock(g_mutexStateList);
1202 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1203 ca_mutex_unlock(g_mutexStateList);
1205 OIC_LOG(DEBUG, TAG, "[EDR][Native] close: disconnected");
1208 void CAEDRInitializeClient(ca_thread_pool_t handle)
1210 OIC_LOG(DEBUG, TAG, "IN");
1211 CAEDRInitialize(handle);
1212 OIC_LOG(DEBUG, TAG, "OUT");
1215 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1217 g_edrErrorHandler = errorHandleCallback;