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_mutexStateList
58 * @brief Mutex to synchronize device state list
60 static ca_mutex g_mutexStateList = NULL;
63 * @var g_mutexObjectList
64 * @brief Mutex to synchronize device object list
66 static ca_mutex g_mutexObjectList = NULL;
69 * @var g_edrErrorHandler
70 * @brief Error callback to update error in EDR
72 static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
74 typedef struct send_data
82 @brief Thread context information for unicast, multicast and secured unicast server
87 CAAdapterServerType_t type;
88 } CAAdapterReceiveThreadContext_t;
93 } CAAdapterAcceptThreadContext_t;
96 * implement for BT-EDR adapter common method
98 CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
100 OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
104 OIC_LOG(ERROR, TAG, "endpoint info is null");
105 return CA_STATUS_INVALID_PARAM;
108 char *macAddress = NULL;
109 CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
110 if (CA_STATUS_OK != ret)
112 OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
119 OIC_LOG(ERROR, TAG, "mac address is null");
120 return CA_STATUS_FAILED;
122 OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
124 // Create local endpoint using util function
125 CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
127 if (NULL == endpoint)
129 OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
131 return CA_STATUS_FAILED;
134 // copy unicast server information
135 int32_t netInfoSize = 1;
136 CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
139 OIC_LOG(ERROR, TAG, "Invalid input..");
141 CAFreeEndpoint(endpoint);
142 return CA_MEMORY_ALLOC_FAILED;
144 *netInfo = *endpoint;
148 CAFreeEndpoint(endpoint);
150 OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
154 void CAEDRClientTerminate()
156 OIC_LOG(DEBUG, TAG, "IN");
158 OIC_LOG(DEBUG, TAG, "OUT");
161 CAResult_t CAEDRManagerReadData()
163 OIC_LOG(DEBUG, TAG, "IN");
165 OIC_LOG(DEBUG, TAG, "OUT");
166 return CA_NOT_SUPPORTED;
169 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
172 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
173 VERIFY_NON_NULL(data, TAG, "data is null");
175 CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
179 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
181 VERIFY_NON_NULL(data, TAG, "data is null");
183 CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
187 // It will be updated when android EDR support is added
188 void CAEDRClientUnsetCallbacks()
190 OIC_LOG(DEBUG, TAG, "IN");
192 OIC_LOG(DEBUG, TAG, "OUT");
195 // It will be updated when android EDR support is added
196 void CAEDRClientDisconnectAll()
198 OIC_LOG(DEBUG, TAG, "IN");
200 OIC_LOG(DEBUG, TAG, "OUT");
203 CAResult_t CAEDRGetAdapterEnableState(bool *state)
205 VERIFY_NON_NULL(state, TAG, "state is null");
209 OIC_LOG(ERROR, TAG, "g_jvm is null");
210 return CA_STATUS_INVALID_PARAM;
212 bool isAttached = false;
214 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
217 OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
218 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
222 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
223 return CA_STATUS_INVALID_PARAM;
229 jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
237 (*g_jvm)->DetachCurrentThread(g_jvm);
243 void CAEDRJniInitContext()
245 OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
247 g_context = (jobject) CANativeJNIGetContext();
250 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
253 OIC_LOG(DEBUG, TAG, "CAEDRCreateJNIInterfaceObject");
255 if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
257 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
258 return CA_STATUS_FAILED;
262 jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, CLASSPATH_CONTEXT,
263 "getApplicationContext",
264 METHODID_CONTEXTNONPARAM);
265 if (!mid_getApplicationContext)
267 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
268 return CA_STATUS_FAILED;
271 jobject jApplicationContext = (*env)->CallObjectMethod(env, context,
272 mid_getApplicationContext);
273 if (!jApplicationContext)
275 OIC_LOG(ERROR, TAG, "Could not get application context");
276 return CA_STATUS_FAILED;
279 //Create EDRJniInterface instance
280 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
281 if (!EDRJniInterface)
283 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
284 return CA_STATUS_FAILED;
287 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
288 "(Landroid/content/Context;)V");
289 if (!EDRInterfaceConstructorMethod)
291 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method");
292 return CA_STATUS_FAILED;
295 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, jApplicationContext);
296 OIC_LOG(DEBUG, TAG, "NewObject Success");
301 static void CAEDRDestroyMutex()
303 if (g_mutexStateList)
305 ca_mutex_free(g_mutexStateList);
306 g_mutexStateList = NULL;
309 if (g_mutexObjectList)
311 ca_mutex_free(g_mutexObjectList);
312 g_mutexObjectList = NULL;
316 static CAResult_t CAEDRCreateMutex()
318 g_mutexStateList = ca_mutex_new();
319 if (!g_mutexStateList)
321 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
324 return CA_STATUS_FAILED;
327 g_mutexObjectList = ca_mutex_new();
328 if (!g_mutexObjectList)
330 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
333 return CA_STATUS_FAILED;
339 CAResult_t CAEDRInitialize()
341 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
345 CAEDRJniInitContext();
348 CAResult_t result = CAEDRCreateMutex();
349 if(CA_STATUS_OK != result)
351 OIC_LOG(ERROR, TAG, "CAEDRInitialize - Could not create mutex");
355 bool isAttached = false;
357 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
360 OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
361 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
365 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
366 return CA_STATUS_NOT_INITIALIZED;
370 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
373 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
374 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
375 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
377 (*env)->DeleteLocalRef(env, jni_address);
379 ca_mutex_lock(g_mutexStateList);
380 CAEDRNativeCreateDeviceStateList();
381 ca_mutex_unlock(g_mutexStateList);
383 ca_mutex_lock(g_mutexObjectList);
384 CAEDRNativeCreateDeviceSocketList();
385 ca_mutex_unlock(g_mutexObjectList);
389 (*g_jvm)->DetachCurrentThread(g_jvm);
394 CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
397 OIC_LOG(DEBUG, TAG, "OUT");
402 void CAEDRTerminate()
404 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
406 bool isAttached = false;
408 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
411 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
412 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
416 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
424 (*g_jvm)->DetachCurrentThread(g_jvm);
429 (*env)->DeleteGlobalRef(env, g_context);
433 CAEDRNativeSocketCloseToAll(env);
438 CAEDRNativeRemoveAllDeviceState();
439 CAEDRNativeRemoveAllDeviceSocket(env);
440 CAEDRDestroyJniInterface();
443 CAResult_t CAEDRDestroyJniInterface()
445 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
449 OIC_LOG(ERROR, TAG, "g_jvm is null");
450 return CA_STATUS_FAILED;
453 bool isAttached = false;
455 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
458 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
459 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
463 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
464 return CA_STATUS_FAILED;
469 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
470 if (!jni_EDRJniInterface)
472 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
476 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
477 "destroyEdrInterface",
479 if (!jni_EDRInterfaceDestroyMethod)
481 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
485 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
487 if ((*env)->ExceptionCheck(env))
489 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
490 (*env)->ExceptionDescribe(env);
491 (*env)->ExceptionClear(env);
495 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
499 (*g_jvm)->DetachCurrentThread(g_jvm);
508 (*g_jvm)->DetachCurrentThread(g_jvm);
511 return CA_STATUS_FAILED;
514 void CAEDRCoreJniInit()
516 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
517 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
520 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
522 VERIFY_NON_NULL(address, TAG, "address is null");
523 VERIFY_NON_NULL(data, TAG, "data is null");
525 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
529 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
531 VERIFY_NON_NULL(data, TAG, "data is null");
533 bool isAttached = false;
535 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
538 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
539 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
543 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
544 return CA_STATUS_INVALID_PARAM;
549 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
550 if(CA_STATUS_OK != result)
552 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
558 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
559 (*g_jvm)->DetachCurrentThread(g_jvm);
562 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
566 CAResult_t CAEDRGetInterfaceInfo(char **address)
568 CAEDRGetLocalAddress(address);
572 void CAEDRGetLocalAddress(char **address)
574 bool isAttached = false;
576 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
579 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
580 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
583 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
589 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
592 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
593 *address = OICStrdup(localAddress);
594 if (*address == NULL)
598 (*g_jvm)->DetachCurrentThread(g_jvm);
600 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
601 (*env)->DeleteLocalRef(env, jni_address);
605 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
606 (*env)->DeleteLocalRef(env, jni_address);
609 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
612 (*g_jvm)->DetachCurrentThread(g_jvm);
616 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
618 VERIFY_NON_NULL(address, TAG, "address is null");
619 VERIFY_NON_NULL(data, TAG, "data is null");
621 bool isAttached = false;
623 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
626 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
627 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
630 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
631 return CA_STATUS_INVALID_PARAM;
636 OIC_LOG(DEBUG, TAG, "set byteArray for data");
638 // get bonded device list
639 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
640 if (!jni_arrayPairedDevices)
642 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
645 (*g_jvm)->DetachCurrentThread(g_jvm);
647 return CA_STATUS_INVALID_PARAM;
649 // Get information from array of devices
650 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
651 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
652 METHODID_STRINGNONPARAM);
653 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
654 METHODID_STRINGNONPARAM);
656 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
657 for (jsize i = 0; i < length; i++)
659 OIC_LOG(DEBUG, TAG, "start to check device");
660 // get name, address from BT device
661 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
662 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
666 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
667 OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
668 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
669 (*env)->DeleteLocalRef(env, j_str_name);
672 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
673 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
674 (*env)->DeleteLocalRef(env, j_obj_device);
677 OIC_LOG(ERROR, TAG, "remoteAddress is null");
680 (*g_jvm)->DetachCurrentThread(g_jvm);
683 (*env)->DeleteLocalRef(env, j_str_address);
684 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
685 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
686 return CA_STATUS_INVALID_PARAM;
688 OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
691 if (!strcmp(remoteAddress, address))
693 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
694 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
695 (*env)->DeleteLocalRef(env, j_str_address);
696 if (CA_STATUS_OK != res)
698 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
699 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
704 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
705 (*env)->DeleteLocalRef(env, j_str_address);
708 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
709 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
713 (*g_jvm)->DetachCurrentThread(g_jvm);
719 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
721 VERIFY_NON_NULL(env, TAG, "env is null");
722 VERIFY_NON_NULL(data, TAG, "data is null");
724 // get bonded device list
725 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
726 if (!jni_arrayPairedDevices)
728 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
729 return CA_STATUS_INVALID_PARAM;
731 // Get information from array of devices
732 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
733 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
734 METHODID_STRINGNONPARAM);
735 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
736 METHODID_STRINGNONPARAM);
738 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
739 for (jsize i = 0; i < length; i++)
741 // get name, address from BT device
742 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
743 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
744 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
746 if (j_str_name && j_str_address)
748 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
749 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
750 if (name && remoteAddress)
752 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
754 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
755 if (CA_STATUS_OK != res)
757 OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
759 g_edrErrorHandler(remoteAddress, data, dataLen, res);
762 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
763 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
766 (*env)->DeleteLocalRef(env, j_obj_device);
767 (*env)->DeleteLocalRef(env, j_str_name);
768 (*env)->DeleteLocalRef(env, j_str_address);
771 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
772 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
777 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
780 VERIFY_NON_NULL(env, TAG, "env is null");
781 VERIFY_NON_NULL(address, TAG, "address is null");
782 VERIFY_NON_NULL(data, TAG, "data is null");
784 if (!CAEDRNativeIsEnableBTAdapter(env))
786 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
787 return CA_ADAPTER_NOT_ENABLED;
790 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
792 // connect before send data
793 OIC_LOG_V(DEBUG, TAG, "try to connect with [%s] before sending data", address);
795 CAResult_t res = CAEDRNativeConnect(env, address);
796 if (CA_STATUS_OK != res)
802 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
804 if (!((*env)->ExceptionCheck(env)))
806 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
807 if (!jni_cid_BTsocket)
809 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
810 return CA_STATUS_FAILED;
813 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
815 METHODID_OUTPUTNONPARAM);
816 if (!jni_mid_getOutputStream)
818 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
819 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
820 return CA_STATUS_FAILED;
823 OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
825 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
828 OIC_LOG(ERROR, TAG, "jni_socket is not available");
829 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
830 return CA_STATUS_FAILED;
833 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
834 jni_mid_getOutputStream);
835 if (!jni_obj_outputStream)
837 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
838 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
839 return CA_STATUS_FAILED;
842 OIC_LOG(DEBUG, TAG, "ready outputStream..");
844 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
845 if (!jni_cid_OutputStream)
847 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
848 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
849 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
850 return CA_STATUS_FAILED;
853 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
857 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
858 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
859 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
860 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
861 return CA_STATUS_FAILED;
864 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
865 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
867 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
870 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
871 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
872 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
873 (*env)->DeleteLocalRef(env, jbuf);
875 if ((*env)->ExceptionCheck(env))
877 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
878 (*env)->ExceptionDescribe(env);
879 (*env)->ExceptionClear(env);
880 return CA_STATUS_FAILED;
883 OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
884 dataLength, address);
888 (*env)->ExceptionDescribe(env);
889 (*env)->ExceptionClear(env);
890 OIC_LOG(ERROR, TAG, "error!!");
891 return CA_STATUS_FAILED;
896 OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
902 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
904 VERIFY_NON_NULL(address, TAG, "address is null");
906 if (!CAEDRNativeIsEnableBTAdapter(env))
908 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
909 return CA_ADAPTER_NOT_ENABLED;
912 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
913 if (!jni_cid_BTAdapter)
915 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
916 return CA_STATUS_FAILED;
920 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
922 METHODID_OBJECTNONPARAM);
923 if (!jni_mid_getDefaultAdapter)
925 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
926 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
927 return CA_STATUS_FAILED;
930 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
931 jni_mid_getDefaultAdapter);
932 if (!jni_obj_BTAdapter)
934 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
935 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
936 return CA_STATUS_FAILED;
939 // get remote bluetooth device
940 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
942 METHODID_BT_DEVICEPARAM);
943 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
944 if (!jni_mid_getRemoteDevice)
946 OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
947 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
948 return CA_STATUS_FAILED;
951 jstring jni_address = (*env)->NewStringUTF(env, address);
952 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
953 jni_mid_getRemoteDevice, jni_address);
954 (*env)->DeleteLocalRef(env, jni_address);
955 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
956 if (!jni_obj_remoteBTDevice)
958 OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
959 return CA_STATUS_FAILED;
962 // get create Rfcomm Socket method ID
963 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
964 if (!jni_cid_BluetoothDevice)
966 OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
967 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
968 return CA_STATUS_FAILED;
971 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
972 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
973 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
974 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
975 if (!jni_mid_createSocket)
977 OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
978 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
979 return CA_STATUS_FAILED;
983 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
986 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
987 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
988 return CA_STATUS_FAILED;
991 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
992 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
993 if (!jni_mid_fromString)
995 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
996 (*env)->DeleteLocalRef(env, jni_cid_uuid);
997 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
998 return CA_STATUS_FAILED;
1001 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1004 OIC_LOG(ERROR, TAG, "jni_uuid is null");
1005 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1006 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1007 return CA_STATUS_FAILED;
1009 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1011 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1012 (*env)->DeleteLocalRef(env, jni_uuid);
1015 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1016 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1017 return CA_STATUS_FAILED;
1020 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1021 jni_mid_createSocket, jni_obj_uuid);
1022 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1023 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1024 if (!jni_obj_BTSocket)
1026 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1027 return CA_STATUS_FAILED;
1031 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1032 if (!jni_cid_BTSocket)
1034 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1035 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1036 return CA_STATUS_FAILED;
1039 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1040 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1041 if (!jni_mid_connect)
1043 OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1044 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1045 return CA_STATUS_FAILED;
1048 OIC_LOG(DEBUG, TAG, "initiating connection...");
1049 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1051 if ((*env)->ExceptionCheck(env))
1053 OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1054 (*env)->ExceptionDescribe(env);
1055 (*env)->ExceptionClear(env);
1056 return CA_STATUS_FAILED;
1059 // set socket to list
1060 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1063 OIC_LOG(ERROR, TAG, "jni_socket is null");
1064 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1065 return CA_STATUS_FAILED;
1067 ca_mutex_lock(g_mutexObjectList);
1068 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1069 (*env)->DeleteGlobalRef(env, jni_socket);
1070 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1071 ca_mutex_unlock(g_mutexObjectList);
1074 ca_mutex_lock(g_mutexStateList);
1075 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1076 ca_mutex_unlock(g_mutexStateList);
1078 OIC_LOG(DEBUG, TAG, "successfully connected");
1080 return CA_STATUS_OK;
1083 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1085 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1087 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1088 if (!jni_cid_BTSocket)
1090 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1094 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1097 OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1101 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1102 if (!jni_obj_socket)
1104 OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1108 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1110 if ((*env)->ExceptionCheck(env))
1112 OIC_LOG(ERROR, TAG, "close is Failed!!!");
1113 (*env)->ExceptionDescribe(env);
1114 (*env)->ExceptionClear(env);
1118 // remove socket to list
1119 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1122 ca_mutex_lock(g_mutexStateList);
1123 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1124 ca_mutex_unlock(g_mutexStateList);
1126 OIC_LOG_V(DEBUG, TAG, "disconnected with [%s]", address);
1129 CAResult_t CAEDRClientInitialize()
1131 CAResult_t result = CAEDRInitialize();
1135 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1137 g_edrErrorHandler = errorHandleCallback;