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;
261 //getApplicationContext
262 jclass contextClass = (*env)->FindClass(env, CLASSPATH_CONTEXT);
265 OIC_LOG(ERROR, TAG, "Could not get context object class");
266 return CA_STATUS_FAILED;
269 jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
270 "getApplicationContext",
271 METHODID_CONTEXTNONPARAM);
272 if (!getApplicationContextMethod)
274 OIC_LOG(ERROR, TAG, "Could not get getApplicationContext method");
275 return CA_STATUS_FAILED;
278 //Create EDRJniInterface instance
279 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
280 if (!EDRJniInterface)
282 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
283 return CA_STATUS_FAILED;
286 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
287 "(Landroid/content/Context;)V");
288 if (!EDRInterfaceConstructorMethod)
290 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface constructor method");
291 return CA_STATUS_FAILED;
294 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context);
295 OIC_LOG(DEBUG, TAG, "NewObject Success");
300 static void CAEDRDestroyMutex()
302 if (g_mutexStateList)
304 ca_mutex_free(g_mutexStateList);
305 g_mutexStateList = NULL;
308 if (g_mutexObjectList)
310 ca_mutex_free(g_mutexObjectList);
311 g_mutexObjectList = NULL;
315 static CAResult_t CAEDRCreateMutex()
317 g_mutexStateList = ca_mutex_new();
318 if (!g_mutexStateList)
320 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
323 return CA_STATUS_FAILED;
326 g_mutexObjectList = ca_mutex_new();
327 if (!g_mutexObjectList)
329 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
332 return CA_STATUS_FAILED;
338 CAResult_t CAEDRInitialize()
340 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
344 CAEDRJniInitContext();
347 CAResult_t result = CAEDRCreateMutex();
348 if(CA_STATUS_OK != result)
350 OIC_LOG(ERROR, TAG, "CAEDRInitialize - Could not create mutex");
354 bool isAttached = false;
356 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
359 OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
360 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
364 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
365 return CA_STATUS_NOT_INITIALIZED;
369 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
372 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
373 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
374 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
376 (*env)->DeleteLocalRef(env, jni_address);
378 ca_mutex_lock(g_mutexStateList);
379 CAEDRNativeCreateDeviceStateList();
380 ca_mutex_unlock(g_mutexStateList);
382 ca_mutex_lock(g_mutexObjectList);
383 CAEDRNativeCreateDeviceSocketList();
384 ca_mutex_unlock(g_mutexObjectList);
388 (*g_jvm)->DetachCurrentThread(g_jvm);
393 CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
396 OIC_LOG(DEBUG, TAG, "OUT");
401 void CAEDRTerminate()
403 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
405 bool isAttached = false;
407 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
410 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
411 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
415 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
423 (*g_jvm)->DetachCurrentThread(g_jvm);
428 (*env)->DeleteGlobalRef(env, g_context);
431 CAEDRNativeSocketCloseToAll(env);
436 CAEDRNativeRemoveAllDeviceState();
437 CAEDRNativeRemoveAllDeviceSocket(env);
438 CAEDRDestroyJniInterface();
441 CAResult_t CAEDRDestroyJniInterface()
443 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
447 OIC_LOG(ERROR, TAG, "g_jvm is null");
448 return CA_STATUS_FAILED;
451 bool isAttached = false;
453 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
456 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
457 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
461 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
462 return CA_STATUS_FAILED;
467 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
468 if (!jni_EDRJniInterface)
470 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
474 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
475 "destroyEdrInterface",
477 if (!jni_EDRInterfaceDestroyMethod)
479 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
483 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
485 if ((*env)->ExceptionCheck(env))
487 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
488 (*env)->ExceptionDescribe(env);
489 (*env)->ExceptionClear(env);
493 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
497 (*g_jvm)->DetachCurrentThread(g_jvm);
506 (*g_jvm)->DetachCurrentThread(g_jvm);
509 return CA_STATUS_FAILED;
512 void CAEDRCoreJniInit()
514 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
515 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
518 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
520 VERIFY_NON_NULL(address, TAG, "address is null");
521 VERIFY_NON_NULL(data, TAG, "data is null");
523 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
527 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
529 VERIFY_NON_NULL(data, TAG, "data is null");
531 bool isAttached = false;
533 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
536 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
537 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
541 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
542 return CA_STATUS_INVALID_PARAM;
547 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
548 if(CA_STATUS_OK != result)
550 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
556 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
557 (*g_jvm)->DetachCurrentThread(g_jvm);
560 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
564 CAResult_t CAEDRGetInterfaceInfo(char **address)
566 CAEDRGetLocalAddress(address);
570 void CAEDRGetLocalAddress(char **address)
572 bool isAttached = false;
574 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
577 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
578 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
581 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
587 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
590 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
591 *address = OICStrdup(localAddress);
592 if (*address == NULL)
596 (*g_jvm)->DetachCurrentThread(g_jvm);
598 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
599 (*env)->DeleteLocalRef(env, jni_address);
603 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
604 (*env)->DeleteLocalRef(env, jni_address);
607 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
610 (*g_jvm)->DetachCurrentThread(g_jvm);
614 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
616 VERIFY_NON_NULL(address, TAG, "address is null");
617 VERIFY_NON_NULL(data, TAG, "data is null");
619 bool isAttached = false;
621 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
624 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
625 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
628 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
629 return CA_STATUS_INVALID_PARAM;
634 OIC_LOG(DEBUG, TAG, "set byteArray for data");
636 // get bonded device list
637 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
638 if (!jni_arrayPairedDevices)
640 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
643 (*g_jvm)->DetachCurrentThread(g_jvm);
645 return CA_STATUS_INVALID_PARAM;
647 // Get information from array of devices
648 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
649 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
650 METHODID_STRINGNONPARAM);
651 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
652 METHODID_STRINGNONPARAM);
654 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
655 for (jsize i = 0; i < length; i++)
657 OIC_LOG(DEBUG, TAG, "start to check device");
658 // get name, address from BT device
659 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
660 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
664 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
665 OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
666 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
667 (*env)->DeleteLocalRef(env, j_str_name);
670 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
671 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
672 (*env)->DeleteLocalRef(env, j_obj_device);
675 OIC_LOG(ERROR, TAG, "remoteAddress is null");
678 (*g_jvm)->DetachCurrentThread(g_jvm);
681 (*env)->DeleteLocalRef(env, j_str_address);
682 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
683 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
684 return CA_STATUS_INVALID_PARAM;
686 OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
689 if (!strcmp(remoteAddress, address))
691 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
692 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
693 (*env)->DeleteLocalRef(env, j_str_address);
694 if (CA_STATUS_OK != res)
696 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
697 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
702 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
703 (*env)->DeleteLocalRef(env, j_str_address);
706 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
707 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
711 (*g_jvm)->DetachCurrentThread(g_jvm);
717 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
719 VERIFY_NON_NULL(env, TAG, "env is null");
720 VERIFY_NON_NULL(data, TAG, "data is null");
722 // get bonded device list
723 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
724 if (!jni_arrayPairedDevices)
726 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
727 return CA_STATUS_INVALID_PARAM;
729 // Get information from array of devices
730 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
731 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
732 METHODID_STRINGNONPARAM);
733 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
734 METHODID_STRINGNONPARAM);
736 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
737 for (jsize i = 0; i < length; i++)
739 // get name, address from BT device
740 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
741 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
742 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
744 if (j_str_name && j_str_address)
746 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
747 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
748 if (name && remoteAddress)
750 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
752 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
753 if (CA_STATUS_OK != res)
755 OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
757 g_edrErrorHandler(remoteAddress, data, dataLen, res);
760 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
761 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
764 (*env)->DeleteLocalRef(env, j_obj_device);
765 (*env)->DeleteLocalRef(env, j_str_name);
766 (*env)->DeleteLocalRef(env, j_str_address);
769 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
770 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
775 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
778 VERIFY_NON_NULL(env, TAG, "env is null");
779 VERIFY_NON_NULL(address, TAG, "address is null");
780 VERIFY_NON_NULL(data, TAG, "data is null");
782 if (!CAEDRNativeIsEnableBTAdapter(env))
784 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
785 return CA_ADAPTER_NOT_ENABLED;
788 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
790 // connect before send data
791 OIC_LOG_V(DEBUG, TAG, "try to connect with [%s] before sending data", address);
793 CAResult_t res = CAEDRNativeConnect(env, address);
794 if (CA_STATUS_OK != res)
800 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
802 if (!((*env)->ExceptionCheck(env)))
804 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
805 if (!jni_cid_BTsocket)
807 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
808 return CA_STATUS_FAILED;
811 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
813 METHODID_OUTPUTNONPARAM);
814 if (!jni_mid_getOutputStream)
816 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
817 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
818 return CA_STATUS_FAILED;
821 OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
823 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
826 OIC_LOG(ERROR, TAG, "jni_socket is not available");
827 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
828 return CA_STATUS_FAILED;
831 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
832 jni_mid_getOutputStream);
833 if (!jni_obj_outputStream)
835 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
836 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
837 return CA_STATUS_FAILED;
840 OIC_LOG(DEBUG, TAG, "ready outputStream..");
842 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
843 if (!jni_cid_OutputStream)
845 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
846 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
847 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
848 return CA_STATUS_FAILED;
851 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
855 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
856 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
857 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
858 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
859 return CA_STATUS_FAILED;
862 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
863 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
865 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
868 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
869 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
870 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
871 (*env)->DeleteLocalRef(env, jbuf);
873 if ((*env)->ExceptionCheck(env))
875 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
876 (*env)->ExceptionDescribe(env);
877 (*env)->ExceptionClear(env);
878 return CA_STATUS_FAILED;
881 OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
882 dataLength, address);
886 (*env)->ExceptionDescribe(env);
887 (*env)->ExceptionClear(env);
888 OIC_LOG(ERROR, TAG, "error!!");
889 return CA_STATUS_FAILED;
894 OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
900 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
902 VERIFY_NON_NULL(address, TAG, "address is null");
904 if (!CAEDRNativeIsEnableBTAdapter(env))
906 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
907 return CA_ADAPTER_NOT_ENABLED;
910 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
911 if (!jni_cid_BTAdapter)
913 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
914 return CA_STATUS_FAILED;
918 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
920 METHODID_OBJECTNONPARAM);
921 if (!jni_mid_getDefaultAdapter)
923 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
924 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
925 return CA_STATUS_FAILED;
928 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
929 jni_mid_getDefaultAdapter);
930 if (!jni_obj_BTAdapter)
932 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
933 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
934 return CA_STATUS_FAILED;
937 // get remote bluetooth device
938 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
940 METHODID_BT_DEVICEPARAM);
941 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
942 if (!jni_mid_getRemoteDevice)
944 OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
945 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
946 return CA_STATUS_FAILED;
949 jstring jni_address = (*env)->NewStringUTF(env, address);
950 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
951 jni_mid_getRemoteDevice, jni_address);
952 (*env)->DeleteLocalRef(env, jni_address);
953 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
954 if (!jni_obj_remoteBTDevice)
956 OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
957 return CA_STATUS_FAILED;
960 // get create Rfcomm Socket method ID
961 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
962 if (!jni_cid_BluetoothDevice)
964 OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
965 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
966 return CA_STATUS_FAILED;
969 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
970 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
971 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
972 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
973 if (!jni_mid_createSocket)
975 OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
976 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
977 return CA_STATUS_FAILED;
981 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
984 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
985 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
986 return CA_STATUS_FAILED;
989 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
990 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
991 if (!jni_mid_fromString)
993 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
994 (*env)->DeleteLocalRef(env, jni_cid_uuid);
995 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
996 return CA_STATUS_FAILED;
999 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1002 OIC_LOG(ERROR, TAG, "jni_uuid is null");
1003 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1004 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1005 return CA_STATUS_FAILED;
1007 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1009 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1010 (*env)->DeleteLocalRef(env, jni_uuid);
1013 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1014 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1015 return CA_STATUS_FAILED;
1018 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1019 jni_mid_createSocket, jni_obj_uuid);
1020 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1021 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1022 if (!jni_obj_BTSocket)
1024 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1025 return CA_STATUS_FAILED;
1029 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1030 if (!jni_cid_BTSocket)
1032 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1033 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1034 return CA_STATUS_FAILED;
1037 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1038 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1039 if (!jni_mid_connect)
1041 OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1042 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1043 return CA_STATUS_FAILED;
1046 OIC_LOG(DEBUG, TAG, "initiating connection...");
1047 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1049 if ((*env)->ExceptionCheck(env))
1051 OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1052 (*env)->ExceptionDescribe(env);
1053 (*env)->ExceptionClear(env);
1054 return CA_STATUS_FAILED;
1057 // set socket to list
1058 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1061 OIC_LOG(ERROR, TAG, "jni_socket is null");
1062 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1063 return CA_STATUS_FAILED;
1065 ca_mutex_lock(g_mutexObjectList);
1066 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1067 (*env)->DeleteGlobalRef(env, jni_socket);
1068 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1069 ca_mutex_unlock(g_mutexObjectList);
1072 ca_mutex_lock(g_mutexStateList);
1073 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1074 ca_mutex_unlock(g_mutexStateList);
1076 OIC_LOG(DEBUG, TAG, "successfully connected");
1078 return CA_STATUS_OK;
1081 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1083 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1085 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1086 if (!jni_cid_BTSocket)
1088 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1092 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1095 OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1099 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1100 if (!jni_obj_socket)
1102 OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1106 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1108 if ((*env)->ExceptionCheck(env))
1110 OIC_LOG(ERROR, TAG, "close is Failed!!!");
1111 (*env)->ExceptionDescribe(env);
1112 (*env)->ExceptionClear(env);
1116 // remove socket to list
1117 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1120 ca_mutex_lock(g_mutexStateList);
1121 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1122 ca_mutex_unlock(g_mutexStateList);
1124 OIC_LOG_V(DEBUG, TAG, "disconnected with [%s]", address);
1127 CAResult_t CAEDRClientInitialize()
1129 CAResult_t result = CAEDRInitialize();
1133 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1135 g_edrErrorHandler = errorHandleCallback;