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);
432 CAEDRNativeSocketCloseToAll(env);
437 CAEDRNativeRemoveAllDeviceState();
438 CAEDRNativeRemoveAllDeviceSocket(env);
439 CAEDRDestroyJniInterface();
442 CAResult_t CAEDRDestroyJniInterface()
444 OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
448 OIC_LOG(ERROR, TAG, "g_jvm is null");
449 return CA_STATUS_FAILED;
452 bool isAttached = false;
454 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
457 OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
458 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
462 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
463 return CA_STATUS_FAILED;
468 jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
469 if (!jni_EDRJniInterface)
471 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
475 jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
476 "destroyEdrInterface",
478 if (!jni_EDRInterfaceDestroyMethod)
480 OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
484 (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
486 if ((*env)->ExceptionCheck(env))
488 OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
489 (*env)->ExceptionDescribe(env);
490 (*env)->ExceptionClear(env);
494 OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
498 (*g_jvm)->DetachCurrentThread(g_jvm);
507 (*g_jvm)->DetachCurrentThread(g_jvm);
510 return CA_STATUS_FAILED;
513 void CAEDRCoreJniInit()
515 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
516 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
519 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
521 VERIFY_NON_NULL(address, TAG, "address is null");
522 VERIFY_NON_NULL(data, TAG, "data is null");
524 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
528 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
530 VERIFY_NON_NULL(data, TAG, "data is null");
532 bool isAttached = false;
534 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
537 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
538 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
542 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
543 return CA_STATUS_INVALID_PARAM;
548 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
549 if(CA_STATUS_OK != result)
551 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
557 OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
558 (*g_jvm)->DetachCurrentThread(g_jvm);
561 OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
565 CAResult_t CAEDRGetInterfaceInfo(char **address)
567 CAEDRGetLocalAddress(address);
571 void CAEDRGetLocalAddress(char **address)
573 bool isAttached = false;
575 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
578 OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
579 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
582 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
588 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
591 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
592 *address = OICStrdup(localAddress);
593 if (*address == NULL)
597 (*g_jvm)->DetachCurrentThread(g_jvm);
599 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
600 (*env)->DeleteLocalRef(env, jni_address);
604 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
605 (*env)->DeleteLocalRef(env, jni_address);
608 OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
611 (*g_jvm)->DetachCurrentThread(g_jvm);
615 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
617 VERIFY_NON_NULL(address, TAG, "address is null");
618 VERIFY_NON_NULL(data, TAG, "data is null");
620 bool isAttached = false;
622 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
625 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
626 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
629 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
630 return CA_STATUS_INVALID_PARAM;
635 OIC_LOG(DEBUG, TAG, "set byteArray for data");
637 // get bonded device list
638 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
639 if (!jni_arrayPairedDevices)
641 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
644 (*g_jvm)->DetachCurrentThread(g_jvm);
646 return CA_STATUS_INVALID_PARAM;
648 // Get information from array of devices
649 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
650 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
651 METHODID_STRINGNONPARAM);
652 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
653 METHODID_STRINGNONPARAM);
655 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
656 for (jsize i = 0; i < length; i++)
658 OIC_LOG(DEBUG, TAG, "start to check device");
659 // get name, address from BT device
660 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
661 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
665 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
666 OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
667 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
668 (*env)->DeleteLocalRef(env, j_str_name);
671 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
672 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
673 (*env)->DeleteLocalRef(env, j_obj_device);
676 OIC_LOG(ERROR, TAG, "remoteAddress is null");
679 (*g_jvm)->DetachCurrentThread(g_jvm);
682 (*env)->DeleteLocalRef(env, j_str_address);
683 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
684 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
685 return CA_STATUS_INVALID_PARAM;
687 OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
690 if (!strcmp(remoteAddress, address))
692 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
693 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
694 (*env)->DeleteLocalRef(env, j_str_address);
695 if (CA_STATUS_OK != res)
697 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
698 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
703 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
704 (*env)->DeleteLocalRef(env, j_str_address);
707 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
708 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
712 (*g_jvm)->DetachCurrentThread(g_jvm);
718 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
720 VERIFY_NON_NULL(env, TAG, "env is null");
721 VERIFY_NON_NULL(data, TAG, "data is null");
723 // get bonded device list
724 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
725 if (!jni_arrayPairedDevices)
727 OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
728 return CA_STATUS_INVALID_PARAM;
730 // Get information from array of devices
731 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
732 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
733 METHODID_STRINGNONPARAM);
734 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
735 METHODID_STRINGNONPARAM);
737 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
738 for (jsize i = 0; i < length; i++)
740 // get name, address from BT device
741 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
742 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
743 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
745 if (j_str_name && j_str_address)
747 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
748 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
749 if (name && remoteAddress)
751 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
753 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
754 if (CA_STATUS_OK != res)
756 OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
758 g_edrErrorHandler(remoteAddress, data, dataLen, res);
761 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
762 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
765 (*env)->DeleteLocalRef(env, j_obj_device);
766 (*env)->DeleteLocalRef(env, j_str_name);
767 (*env)->DeleteLocalRef(env, j_str_address);
770 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
771 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
776 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
779 VERIFY_NON_NULL(env, TAG, "env is null");
780 VERIFY_NON_NULL(address, TAG, "address is null");
781 VERIFY_NON_NULL(data, TAG, "data is null");
783 if (!CAEDRNativeIsEnableBTAdapter(env))
785 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
786 return CA_ADAPTER_NOT_ENABLED;
789 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
791 // connect before send data
792 OIC_LOG_V(DEBUG, TAG, "try to connect with [%s] before sending data", address);
794 CAResult_t res = CAEDRNativeConnect(env, address);
795 if (CA_STATUS_OK != res)
801 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
803 if (!((*env)->ExceptionCheck(env)))
805 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
806 if (!jni_cid_BTsocket)
808 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
809 return CA_STATUS_FAILED;
812 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
814 METHODID_OUTPUTNONPARAM);
815 if (!jni_mid_getOutputStream)
817 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
818 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
819 return CA_STATUS_FAILED;
822 OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
824 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
827 OIC_LOG(ERROR, TAG, "jni_socket is not available");
828 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
829 return CA_STATUS_FAILED;
832 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
833 jni_mid_getOutputStream);
834 if (!jni_obj_outputStream)
836 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
837 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
838 return CA_STATUS_FAILED;
841 OIC_LOG(DEBUG, TAG, "ready outputStream..");
843 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
844 if (!jni_cid_OutputStream)
846 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
847 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
848 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
849 return CA_STATUS_FAILED;
852 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
856 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
857 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
858 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
859 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
860 return CA_STATUS_FAILED;
863 jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
864 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
866 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
869 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
870 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
871 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
872 (*env)->DeleteLocalRef(env, jbuf);
874 if ((*env)->ExceptionCheck(env))
876 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
877 (*env)->ExceptionDescribe(env);
878 (*env)->ExceptionClear(env);
879 return CA_STATUS_FAILED;
882 OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
883 dataLength, address);
887 (*env)->ExceptionDescribe(env);
888 (*env)->ExceptionClear(env);
889 OIC_LOG(ERROR, TAG, "error!!");
890 return CA_STATUS_FAILED;
895 OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
901 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
903 VERIFY_NON_NULL(address, TAG, "address is null");
905 if (!CAEDRNativeIsEnableBTAdapter(env))
907 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
908 return CA_ADAPTER_NOT_ENABLED;
911 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
912 if (!jni_cid_BTAdapter)
914 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
915 return CA_STATUS_FAILED;
919 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
921 METHODID_OBJECTNONPARAM);
922 if (!jni_mid_getDefaultAdapter)
924 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
925 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
926 return CA_STATUS_FAILED;
929 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
930 jni_mid_getDefaultAdapter);
931 if (!jni_obj_BTAdapter)
933 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
934 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
935 return CA_STATUS_FAILED;
938 // get remote bluetooth device
939 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
941 METHODID_BT_DEVICEPARAM);
942 (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
943 if (!jni_mid_getRemoteDevice)
945 OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
946 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
947 return CA_STATUS_FAILED;
950 jstring jni_address = (*env)->NewStringUTF(env, address);
951 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
952 jni_mid_getRemoteDevice, jni_address);
953 (*env)->DeleteLocalRef(env, jni_address);
954 (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
955 if (!jni_obj_remoteBTDevice)
957 OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
958 return CA_STATUS_FAILED;
961 // get create Rfcomm Socket method ID
962 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
963 if (!jni_cid_BluetoothDevice)
965 OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
966 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
967 return CA_STATUS_FAILED;
970 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
971 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
972 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
973 (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
974 if (!jni_mid_createSocket)
976 OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
977 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
978 return CA_STATUS_FAILED;
982 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
985 OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
986 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
987 return CA_STATUS_FAILED;
990 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
991 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
992 if (!jni_mid_fromString)
994 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
995 (*env)->DeleteLocalRef(env, jni_cid_uuid);
996 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
997 return CA_STATUS_FAILED;
1000 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1003 OIC_LOG(ERROR, TAG, "jni_uuid is null");
1004 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1005 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1006 return CA_STATUS_FAILED;
1008 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1010 (*env)->DeleteLocalRef(env, jni_cid_uuid);
1011 (*env)->DeleteLocalRef(env, jni_uuid);
1014 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1015 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1016 return CA_STATUS_FAILED;
1019 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1020 jni_mid_createSocket, jni_obj_uuid);
1021 (*env)->DeleteLocalRef(env, jni_obj_uuid);
1022 (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1023 if (!jni_obj_BTSocket)
1025 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1026 return CA_STATUS_FAILED;
1030 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1031 if (!jni_cid_BTSocket)
1033 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1034 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1035 return CA_STATUS_FAILED;
1038 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1039 (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1040 if (!jni_mid_connect)
1042 OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1043 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1044 return CA_STATUS_FAILED;
1047 OIC_LOG(DEBUG, TAG, "initiating connection...");
1048 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1050 if ((*env)->ExceptionCheck(env))
1052 OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1053 (*env)->ExceptionDescribe(env);
1054 (*env)->ExceptionClear(env);
1055 return CA_STATUS_FAILED;
1058 // set socket to list
1059 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1062 OIC_LOG(ERROR, TAG, "jni_socket is null");
1063 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1064 return CA_STATUS_FAILED;
1066 ca_mutex_lock(g_mutexObjectList);
1067 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1068 (*env)->DeleteGlobalRef(env, jni_socket);
1069 (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1070 ca_mutex_unlock(g_mutexObjectList);
1073 ca_mutex_lock(g_mutexStateList);
1074 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1075 ca_mutex_unlock(g_mutexStateList);
1077 OIC_LOG(DEBUG, TAG, "successfully connected");
1079 return CA_STATUS_OK;
1082 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1084 VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1086 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1087 if (!jni_cid_BTSocket)
1089 OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1093 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1096 OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1100 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1101 if (!jni_obj_socket)
1103 OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1107 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1109 if ((*env)->ExceptionCheck(env))
1111 OIC_LOG(ERROR, TAG, "close is Failed!!!");
1112 (*env)->ExceptionDescribe(env);
1113 (*env)->ExceptionClear(env);
1117 // remove socket to list
1118 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1121 ca_mutex_lock(g_mutexStateList);
1122 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1123 ca_mutex_unlock(g_mutexStateList);
1125 OIC_LOG_V(DEBUG, TAG, "disconnected with [%s]", address);
1128 CAResult_t CAEDRClientInitialize()
1130 CAResult_t result = CAEDRInitialize();
1134 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1136 g_edrErrorHandler = errorHandleCallback;