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 oc_mutex g_mutexStateList = NULL;
63 * @var g_mutexObjectList
64 * @brief Mutex to synchronize device object list
66 static oc_mutex g_mutexObjectList = NULL;
69 * @var g_edrErrorHandler
70 * @brief Error callback to update error in EDR
72 static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
75 * implement for BT-EDR adapter common method
77 CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
79 OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
83 OIC_LOG(ERROR, TAG, "endpoint info is null");
84 return CA_STATUS_INVALID_PARAM;
87 char *macAddress = NULL;
88 CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
89 if (CA_STATUS_OK != ret)
91 OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
98 OIC_LOG(ERROR, TAG, "mac address is null");
99 return CA_STATUS_FAILED;
101 OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
103 // Create local endpoint using util function
104 CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
106 if (NULL == endpoint)
108 OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
110 return CA_STATUS_FAILED;
113 // copy unicast server information
114 int32_t netInfoSize = 1;
115 CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
118 OIC_LOG(ERROR, TAG, "Invalid input..");
120 CAFreeEndpoint(endpoint);
121 return CA_MEMORY_ALLOC_FAILED;
123 *netInfo = *endpoint;
127 CAFreeEndpoint(endpoint);
129 OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
133 void CAEDRClientTerminate()
135 OIC_LOG(DEBUG, TAG, "IN");
137 OIC_LOG(DEBUG, TAG, "OUT");
140 CAResult_t CAEDRManagerReadData()
142 OIC_LOG(DEBUG, TAG, "IN");
144 OIC_LOG(DEBUG, TAG, "OUT");
145 return CA_NOT_SUPPORTED;
148 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
151 VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
152 VERIFY_NON_NULL(data, TAG, "data is null");
154 CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
158 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
160 VERIFY_NON_NULL(data, TAG, "data is null");
162 CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
166 // It will be updated when android EDR support is added
167 void CAEDRClientUnsetCallbacks()
169 OIC_LOG(DEBUG, TAG, "IN");
171 OIC_LOG(DEBUG, TAG, "OUT");
174 // It will be updated when android EDR support is added
175 void CAEDRClientDisconnectAll()
177 OIC_LOG(DEBUG, TAG, "IN");
179 OIC_LOG(DEBUG, TAG, "OUT");
182 CAResult_t CAEDRGetAdapterEnableState(bool *state)
184 VERIFY_NON_NULL(state, TAG, "state is null");
188 OIC_LOG(ERROR, TAG, "g_jvm is null");
189 return CA_STATUS_INVALID_PARAM;
191 bool isAttached = false;
193 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
196 OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
197 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
201 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
202 return CA_STATUS_INVALID_PARAM;
208 jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
216 (*g_jvm)->DetachCurrentThread(g_jvm);
222 void CAEDRJniInitContext()
224 OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
226 g_context = (jobject) CANativeJNIGetContext();
229 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
232 OIC_LOG(DEBUG, TAG, "CAEDRCreateJNIInterfaceObject");
234 if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
236 OIC_LOG(ERROR, TAG, "Could not get JNIEnv pointer");
237 return CA_STATUS_FAILED;
241 jmethodID mid_getApplicationContext = CAGetJNIMethodID(env, CLASSPATH_CONTEXT,
242 "getApplicationContext",
243 METHODID_CONTEXTNONPARAM);
244 if (!mid_getApplicationContext)
246 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
247 return CA_STATUS_FAILED;
250 jobject jApplicationContext = (*env)->CallObjectMethod(env, context,
251 mid_getApplicationContext);
252 if (!jApplicationContext)
254 OIC_LOG(ERROR, TAG, "Could not get application context");
255 return CA_STATUS_FAILED;
258 //Create EDRJniInterface instance
259 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
260 if (!EDRJniInterface)
262 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
263 return CA_STATUS_FAILED;
266 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
267 "(Landroid/content/Context;)V");
268 if (!EDRInterfaceConstructorMethod)
270 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method");
271 return CA_STATUS_FAILED;
274 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, jApplicationContext);
275 OIC_LOG(DEBUG, TAG, "NewObject Success");
280 static void CAEDRDestroyMutex()
282 if (g_mutexStateList)
284 oc_mutex_free(g_mutexStateList);
285 g_mutexStateList = NULL;
288 if (g_mutexObjectList)
290 oc_mutex_free(g_mutexObjectList);
291 g_mutexObjectList = NULL;
295 static CAResult_t CAEDRCreateMutex()
297 g_mutexStateList = oc_mutex_new();
298 if (!g_mutexStateList)
300 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
303 return CA_STATUS_FAILED;
306 g_mutexObjectList = oc_mutex_new();
307 if (!g_mutexObjectList)
309 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
312 return CA_STATUS_FAILED;
318 CAResult_t CAEDRInitialize()
320 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
324 CAEDRJniInitContext();
327 CAResult_t result = CAEDRCreateMutex();
328 if(CA_STATUS_OK != result)
330 OIC_LOG(ERROR, TAG, "CAEDRInitialize - Could not create mutex");
334 bool isAttached = false;
336 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
339 OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
340 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
344 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
345 return CA_STATUS_NOT_INITIALIZED;
349 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
352 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
353 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
354 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
356 (*env)->DeleteLocalRef(env, jni_address);
358 oc_mutex_lock(g_mutexStateList);
359 CAEDRNativeCreateDeviceStateList();
360 oc_mutex_unlock(g_mutexStateList);
362 oc_mutex_lock(g_mutexObjectList);
363 CAEDRNativeCreateDeviceSocketList();
364 oc_mutex_unlock(g_mutexObjectList);
368 (*g_jvm)->DetachCurrentThread(g_jvm);
373 CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
376 OIC_LOG(DEBUG, TAG, "OUT");
381 void CAEDRTerminate()
383 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
385 bool isAttached = false;
387 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
390 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
391 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
395 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
403 (*g_jvm)->DetachCurrentThread(g_jvm);
408 (*env)->DeleteGlobalRef(env, g_context);
412 CAEDRNativeSocketCloseToAll(env);
417 CAEDRNativeRemoveAllDeviceState();
418 CAEDRNativeRemoveAllDeviceSocket(env);
419 CAEDRDestroyJniInterface();
422 CAResult_t CAEDRDestroyJniInterface()
424 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
428 OIC_LOG(ERROR, TAG, "g_jvm is null");
429 return CA_STATUS_FAILED;
432 bool isAttached = false;
434 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
437 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
438 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
442 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
443 return CA_STATUS_FAILED;
448 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
449 if (!jni_EDRJniInterface)
451 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
455 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
456 "destroyEdrInterface",
458 if (!jni_EDRInterfaceDestroyMethod)
460 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
464 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
466 if ((*env)->ExceptionCheck(env))
468 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
469 (*env)->ExceptionDescribe(env);
470 (*env)->ExceptionClear(env);
474 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
478 (*g_jvm)->DetachCurrentThread(g_jvm);
487 (*g_jvm)->DetachCurrentThread(g_jvm);
490 return CA_STATUS_FAILED;
493 void CAEDRCoreJniInit()
495 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
496 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
499 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
501 VERIFY_NON_NULL(address, TAG, "address is null");
502 VERIFY_NON_NULL(data, TAG, "data is null");
504 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
508 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
510 VERIFY_NON_NULL(data, TAG, "data is null");
512 bool isAttached = false;
514 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
517 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
518 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
522 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
523 return CA_STATUS_INVALID_PARAM;
528 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
529 if(CA_STATUS_OK != result)
531 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
537 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
538 (*g_jvm)->DetachCurrentThread(g_jvm);
541 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
545 CAResult_t CAEDRGetInterfaceInfo(char **address)
547 CAEDRGetLocalAddress(address);
551 void CAEDRGetLocalAddress(char **address)
553 bool isAttached = false;
555 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
558 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
559 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
562 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
568 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
571 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
572 *address = OICStrdup(localAddress);
573 if (*address == NULL)
577 (*g_jvm)->DetachCurrentThread(g_jvm);
579 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
580 (*env)->DeleteLocalRef(env, jni_address);
584 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
585 (*env)->DeleteLocalRef(env, jni_address);
588 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
591 (*g_jvm)->DetachCurrentThread(g_jvm);
595 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
597 VERIFY_NON_NULL(address, TAG, "address is null");
598 VERIFY_NON_NULL(data, TAG, "data is null");
600 bool isAttached = false;
602 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
605 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
606 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
609 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
610 return CA_STATUS_INVALID_PARAM;
615 OIC_LOG(DEBUG, TAG, "set byteArray for data");
617 // get bonded device list
618 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
619 if (!jni_arrayPairedDevices)
621 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
624 (*g_jvm)->DetachCurrentThread(g_jvm);
626 return CA_STATUS_INVALID_PARAM;
628 // Get information from array of devices
629 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
630 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
631 METHODID_STRINGNONPARAM);
632 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
633 METHODID_STRINGNONPARAM);
635 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
636 for (jsize i = 0; i < length; i++)
638 OIC_LOG(DEBUG, TAG, "start to check device");
639 // get name, address from BT device
640 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
641 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
645 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
646 OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
647 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
648 (*env)->DeleteLocalRef(env, j_str_name);
651 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
652 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
653 (*env)->DeleteLocalRef(env, j_obj_device);
656 OIC_LOG(ERROR, TAG, "remoteAddress is null");
659 (*g_jvm)->DetachCurrentThread(g_jvm);
662 (*env)->DeleteLocalRef(env, j_str_address);
663 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
664 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
665 return CA_STATUS_INVALID_PARAM;
667 OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
670 if (!strcmp(remoteAddress, address))
672 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
673 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
674 (*env)->DeleteLocalRef(env, j_str_address);
675 if (CA_STATUS_OK != res)
677 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
678 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
683 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
684 (*env)->DeleteLocalRef(env, j_str_address);
687 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
688 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
692 (*g_jvm)->DetachCurrentThread(g_jvm);
698 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
700 VERIFY_NON_NULL(env, TAG, "env is null");
701 VERIFY_NON_NULL(data, TAG, "data is null");
703 // get bonded device list
704 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
705 if (!jni_arrayPairedDevices)
707 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
708 return CA_STATUS_INVALID_PARAM;
710 // Get information from array of devices
711 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
712 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
713 METHODID_STRINGNONPARAM);
714 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
715 METHODID_STRINGNONPARAM);
717 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
718 for (jsize i = 0; i < length; i++)
720 // get name, address from BT device
721 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
722 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
723 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
725 if (j_str_name && j_str_address)
727 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
728 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
729 if (name && remoteAddress)
731 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
733 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
734 if (CA_STATUS_OK != res)
736 OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
738 g_edrErrorHandler(remoteAddress, data, dataLen, res);
741 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
742 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
745 (*env)->DeleteLocalRef(env, j_obj_device);
746 (*env)->DeleteLocalRef(env, j_str_name);
747 (*env)->DeleteLocalRef(env, j_str_address);
750 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
751 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
756 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
759 VERIFY_NON_NULL(env, TAG, "env is null");
760 VERIFY_NON_NULL(address, TAG, "address is null");
761 VERIFY_NON_NULL(data, TAG, "data is null");
763 if (!CAEDRNativeIsEnableBTAdapter(env))
765 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
766 return CA_ADAPTER_NOT_ENABLED;
769 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
771 // connect before send data
772 OIC_LOG_V(DEBUG, TAG, "try to connect with [%s] before sending data", address);
774 CAResult_t res = CAEDRNativeConnect(env, address);
775 if (CA_STATUS_OK != res)
781 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
783 if (!((*env)->ExceptionCheck(env)))
785 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
786 if (!jni_cid_BTsocket)
788 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
789 return CA_STATUS_FAILED;
792 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
794 METHODID_OUTPUTNONPARAM);
795 if (!jni_mid_getOutputStream)
797 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
798 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
799 return CA_STATUS_FAILED;
802 OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
804 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
807 OIC_LOG(ERROR, TAG, "jni_socket is not available");
808 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
809 return CA_STATUS_FAILED;
812 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
813 jni_mid_getOutputStream);
814 if (!jni_obj_outputStream)
816 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
817 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
818 return CA_STATUS_FAILED;
821 OIC_LOG(DEBUG, TAG, "ready outputStream..");
823 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
824 if (!jni_cid_OutputStream)
826 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
827 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
828 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
829 return CA_STATUS_FAILED;
832 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
836 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
837 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
838 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
839 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
840 return CA_STATUS_FAILED;
843 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
844 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
846 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
849 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
850 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
851 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
852 (*env)->DeleteLocalRef(env, jbuf);
854 if ((*env)->ExceptionCheck(env))
856 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
857 (*env)->ExceptionDescribe(env);
858 (*env)->ExceptionClear(env);
859 return CA_STATUS_FAILED;
862 OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
863 dataLength, address);
867 (*env)->ExceptionDescribe(env);
868 (*env)->ExceptionClear(env);
869 OIC_LOG(ERROR, TAG, "error!!");
870 return CA_STATUS_FAILED;
875 OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
881 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
883 VERIFY_NON_NULL(address, TAG, "address is null");
885 if (!CAEDRNativeIsEnableBTAdapter(env))
887 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
888 return CA_ADAPTER_NOT_ENABLED;
891 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
892 if (!jni_cid_BTAdapter)
894 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
895 return CA_STATUS_FAILED;
899 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
901 METHODID_OBJECTNONPARAM);
902 if (!jni_mid_getDefaultAdapter)
904 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
905 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
906 return CA_STATUS_FAILED;
909 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
910 jni_mid_getDefaultAdapter);
911 if (!jni_obj_BTAdapter)
913 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
914 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
915 return CA_STATUS_FAILED;
918 // get remote bluetooth device
919 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
921 METHODID_BT_DEVICEPARAM);
922 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
923 if (!jni_mid_getRemoteDevice)
925 OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
926 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
927 return CA_STATUS_FAILED;
930 jstring jni_address = (*env)->NewStringUTF(env, address);
931 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
932 jni_mid_getRemoteDevice, jni_address);
933 (*env)->DeleteLocalRef(env, jni_address);
934 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
935 if (!jni_obj_remoteBTDevice)
937 OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
938 return CA_STATUS_FAILED;
941 // get create Rfcomm Socket method ID
942 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
943 if (!jni_cid_BluetoothDevice)
945 OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
946 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
947 return CA_STATUS_FAILED;
950 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
951 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
952 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
953 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
954 if (!jni_mid_createSocket)
956 OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
957 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
958 return CA_STATUS_FAILED;
962 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
965 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
966 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
967 return CA_STATUS_FAILED;
970 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
971 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
972 if (!jni_mid_fromString)
974 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
975 (*env)->DeleteLocalRef(env, jni_cid_uuid);
976 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
977 return CA_STATUS_FAILED;
980 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
983 OIC_LOG(ERROR, TAG, "jni_uuid is null");
984 (*env)->DeleteLocalRef(env, jni_cid_uuid);
985 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
986 return CA_STATUS_FAILED;
988 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
990 (*env)->DeleteLocalRef(env, jni_cid_uuid);
991 (*env)->DeleteLocalRef(env, jni_uuid);
994 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
995 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
996 return CA_STATUS_FAILED;
999 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1000 jni_mid_createSocket, jni_obj_uuid);
1001 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1002 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1003 if (!jni_obj_BTSocket)
1005 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1006 return CA_STATUS_FAILED;
1010 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1011 if (!jni_cid_BTSocket)
1013 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1014 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1015 return CA_STATUS_FAILED;
1018 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1019 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1020 if (!jni_mid_connect)
1022 OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1023 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1024 return CA_STATUS_FAILED;
1027 OIC_LOG(DEBUG, TAG, "initiating connection...");
1028 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1030 if ((*env)->ExceptionCheck(env))
1032 OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1033 (*env)->ExceptionDescribe(env);
1034 (*env)->ExceptionClear(env);
1035 return CA_STATUS_FAILED;
1038 // set socket to list
1039 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1042 OIC_LOG(ERROR, TAG, "jni_socket is null");
1043 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1044 return CA_STATUS_FAILED;
1046 oc_mutex_lock(g_mutexObjectList);
1047 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1048 (*env)->DeleteGlobalRef(env, jni_socket);
1049 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1050 oc_mutex_unlock(g_mutexObjectList);
1053 oc_mutex_lock(g_mutexStateList);
1054 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1055 oc_mutex_unlock(g_mutexStateList);
1057 OIC_LOG(DEBUG, TAG, "successfully connected");
1059 return CA_STATUS_OK;
1062 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1064 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1066 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1067 if (!jni_cid_BTSocket)
1069 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1073 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1076 OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1080 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1081 if (!jni_obj_socket)
1083 OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1087 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1089 if ((*env)->ExceptionCheck(env))
1091 OIC_LOG(ERROR, TAG, "close is Failed!!!");
1092 (*env)->ExceptionDescribe(env);
1093 (*env)->ExceptionClear(env);
1097 // remove socket to list
1098 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1101 oc_mutex_lock(g_mutexStateList);
1102 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1103 oc_mutex_unlock(g_mutexStateList);
1105 OIC_LOG_V(DEBUG, TAG, "disconnected with [%s]", address);
1108 CAResult_t CAEDRClientInitialize()
1110 CAResult_t result = CAEDRInitialize();
1114 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1116 g_edrErrorHandler = errorHandleCallback;