1 /******************************************************************
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 ******************************************************************/
25 #include "caedrinterface.h"
26 #include "caedrutils.h"
27 #include "caedrclient.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "cathreadpool.h" /* for thread pool */
33 #include "uarraylist.h"
34 #include "caadapterutils.h"
35 #include "caremotehandler.h"
38 #define TAG PCF("CA_EDR_CLIENT")
40 static const char METHODID_CONTEXTNONPARAM[] = "()Landroid/content/Context;";
41 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
42 static const char METHODID_OUTPUTNONPARAM[] = "()Ljava/io/OutputStream;";
43 static const char METHODID_STRINGNONPARAM[] = "()Ljava/lang/String;";
44 static const char METHODID_BT_DEVICEPARAM[] =
45 "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;";
46 static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter";
47 static const char CLASSPATH_BT_DEVICE[] = "android/bluetooth/BluetoothDevice";
48 static const char CLASSPATH_BT_INTERFACE[] = "org/iotivity/ca/CaEdrInterface";
49 static const char CLASSPATH_BT_SOCKET[] = "android/bluetooth/BluetoothSocket";
50 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
51 static const char CLASSPATH_CONTEXT[] = "android/content/Context";
52 static const char CLASSPATH_OUTPUT[] = "java/io/OutputStream";
54 static ca_thread_pool_t g_threadPoolHandle = NULL;
57 static jobject g_context;
60 * @var g_mutexUnicastServer
61 * @brief Mutex to synchronize unicast server
63 static ca_mutex g_mutexUnicastServer = NULL;
67 * @brief Flag to control the Receive Unicast Data Thread
69 static bool g_stopUnicast = false;
72 * @var g_mutexMulticastServer
73 * @brief Mutex to synchronize secure multicast server
75 static ca_mutex g_mutexMulticastServer = NULL;
78 * @var g_stopMulticast
79 * @brief Flag to control the Receive Multicast Data Thread
81 static bool g_stopMulticast = false;
85 * @brief Flag to control the Accept Thread
87 static bool g_stopAccept = false;
90 * @var g_mutexStateList
91 * @brief Mutex to synchronize device state list
93 static ca_mutex g_mutexStateList = NULL;
96 * @var g_mutexObjectList
97 * @brief Mutex to synchronize device object list
99 static ca_mutex g_mutexObjectList = NULL;
102 * @var g_edrErrorHandler
103 * @brief Error callback to update error in EDR
105 static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
107 typedef struct send_data
115 @brief Thread context information for unicast, multicast and secured unicast server
120 CAAdapterServerType_t type;
121 } CAAdapterReceiveThreadContext_t;
126 } CAAdapterAcceptThreadContext_t;
129 * implement for BT-EDR adapter common method
131 CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
133 OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
137 OIC_LOG(ERROR, TAG, "endpoint info is null");
138 return CA_STATUS_FAILED;
141 int32_t netInfoSize = 1;
143 char *macAddress = NULL;
144 CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
145 OIC_LOG_V(ERROR, TAG, "address : %s", macAddress);
146 if (NULL == macAddress)
148 OIC_LOG(ERROR, TAG, "mac address is null");
150 return CA_STATUS_FAILED;
152 if (CA_STATUS_OK != ret)
154 OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
160 // Create local endpoint using util function
161 CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
163 if (NULL == endpoint)
165 OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
167 return CA_STATUS_FAILED;
170 // copy unicast server information
171 CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
174 OIC_LOG(ERROR, TAG, "Invalid input..");
176 CAFreeEndpoint(endpoint);
177 return CA_MEMORY_ALLOC_FAILED;
179 *netInfo = *endpoint;
183 CAFreeEndpoint(endpoint);
185 OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
189 void CAEDRClientTerminate()
191 OIC_LOG(DEBUG, TAG, "IN");
193 OIC_LOG(DEBUG, TAG, "OUT");
196 CAResult_t CAEDRManagerReadData(void)
198 OIC_LOG(DEBUG, TAG, "IN");
200 OIC_LOG(DEBUG, TAG, "OUT");
201 return CA_NOT_SUPPORTED;
204 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
207 OIC_LOG(DEBUG, TAG, "IN");
209 CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
210 OIC_LOG(DEBUG, TAG, "OUT");
214 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
216 OIC_LOG(DEBUG, TAG, "IN");
218 CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
219 OIC_LOG(DEBUG, TAG, "OUT");
223 // It will be updated when android EDR support is added
224 void CAEDRClientUnsetCallbacks(void)
226 OIC_LOG(DEBUG, TAG, "IN");
228 OIC_LOG(DEBUG, TAG, "OUT");
231 // It will be updated when android EDR support is added
232 void CAEDRClientDisconnectAll(void)
234 OIC_LOG(DEBUG, TAG, "IN");
236 OIC_LOG(DEBUG, TAG, "OUT");
239 CAResult_t CAEDRGetAdapterEnableState(bool *state)
241 OIC_LOG(DEBUG, TAG, "IN");
244 OIC_LOG(ERROR, TAG, "g_jvm is null");
245 return CA_STATUS_INVALID_PARAM;
247 bool isAttached = false;
249 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
252 OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
253 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
257 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
258 return CA_STATUS_INVALID_PARAM;
262 jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
274 (*g_jvm)->DetachCurrentThread(g_jvm);
277 OIC_LOG(DEBUG, TAG, "OUT");
281 void CAEDRJniInitContext()
283 OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
285 g_context = (jobject) CANativeJNIGetContext();
288 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
291 OIC_LOG(DEBUG, TAG, "[EDRCore] CAEDRCreateJNIInterfaceObject");
293 if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
295 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get JNIEnv pointer");
296 return CA_STATUS_FAILED;
299 //getApplicationContext
300 jclass contextClass = (*env)->FindClass(env, CLASSPATH_CONTEXT);
303 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get context object class");
304 return CA_STATUS_FAILED;
307 jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
308 "getApplicationContext",
309 METHODID_CONTEXTNONPARAM);
310 if (!getApplicationContextMethod)
312 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get getApplicationContext method");
313 return CA_STATUS_FAILED;
316 //Create EDRJniInterface instance
317 jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
318 if (!EDRJniInterface)
320 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get CaEdrInterface class");
321 return CA_STATUS_FAILED;
324 jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
325 "(Landroid/content/Context;)V");
326 if (!EDRInterfaceConstructorMethod)
328 OIC_LOG(ERROR, TAG, "[EDRCore] Could not get CaEdrInterface constructor method");
329 return CA_STATUS_FAILED;
332 (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context);
333 OIC_LOG(DEBUG, TAG, "[EDRCore] NewObject Success");
339 static void CAEDRDestroyMutex()
341 OIC_LOG(DEBUG, TAG, "IN");
343 if (g_mutexUnicastServer)
345 ca_mutex_free(g_mutexUnicastServer);
346 g_mutexUnicastServer = NULL;
349 if (g_mutexMulticastServer)
351 ca_mutex_free(g_mutexMulticastServer);
352 g_mutexMulticastServer = NULL;
355 if (g_mutexStateList)
357 ca_mutex_free(g_mutexStateList);
358 g_mutexStateList = NULL;
361 if (g_mutexObjectList)
363 ca_mutex_free(g_mutexObjectList);
364 g_mutexObjectList = NULL;
366 OIC_LOG(DEBUG, TAG, "OUT");
369 static CAResult_t CAEDRCreateMutex()
371 OIC_LOG(DEBUG, TAG, "IN");
373 g_mutexUnicastServer = ca_mutex_new();
374 if (!g_mutexUnicastServer)
376 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
377 return CA_STATUS_FAILED;
380 g_mutexMulticastServer = ca_mutex_new();
381 if (!g_mutexMulticastServer)
383 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
386 return CA_STATUS_FAILED;
389 g_mutexStateList = ca_mutex_new();
390 if (!g_mutexStateList)
392 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
395 return CA_STATUS_FAILED;
398 g_mutexObjectList = ca_mutex_new();
399 if (!g_mutexObjectList)
401 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
404 return CA_STATUS_FAILED;
407 OIC_LOG(DEBUG, TAG, "OUT");
411 void CAEDRInitialize(ca_thread_pool_t handle)
413 OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
415 g_threadPoolHandle = handle;
419 CAEDRJniInitContext();
424 bool isAttached = false;
426 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
429 OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
430 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
434 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
439 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
442 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
443 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
444 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
447 ca_mutex_lock(g_mutexStateList);
448 CAEDRNativeCreateDeviceStateList();
449 ca_mutex_unlock(g_mutexStateList);
451 ca_mutex_lock(g_mutexObjectList);
452 CAEDRNativeCreateDeviceSocketList();
453 ca_mutex_unlock(g_mutexObjectList);
457 (*g_jvm)->DetachCurrentThread(g_jvm);
462 CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
465 OIC_LOG(DEBUG, TAG, "OUT");
468 void CAEDRTerminate()
470 OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
472 bool isAttached = false;
474 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
477 OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
478 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
482 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
489 g_stopMulticast = true;
490 g_stopUnicast = true;
494 (*g_jvm)->DetachCurrentThread(g_jvm);
499 (*env)->DeleteGlobalRef(env, g_context);
502 CAEDRNativeSocketCloseToAll(env);
507 CAEDRNativeRemoveAllDeviceState();
508 CAEDRNativeRemoveAllDeviceSocket(env);
511 void CAEDRCoreJniInit()
513 OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
514 g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
517 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
519 OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessage(%s, %s)", address, data);
521 CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
525 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
527 OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data);
529 bool isAttached = false;
531 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
534 OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
535 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
539 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
540 return CA_STATUS_INVALID_PARAM;
545 CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
546 if(CA_STATUS_OK != result)
548 OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
552 OIC_LOG(DEBUG, TAG, "sent data");
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 OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl, address: %s, data: %s", address, data);
618 bool isAttached = false;
620 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
623 OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
624 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
627 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
628 return CA_STATUS_INVALID_PARAM;
633 OIC_LOG(DEBUG, TAG, "[EDR][Native] set byteArray for data");
635 // get bonded device list
636 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
637 if (!jni_arrayPairedDevices)
639 OIC_LOG(ERROR, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
642 (*g_jvm)->DetachCurrentThread(g_jvm);
644 return CA_STATUS_INVALID_PARAM;
646 // Get information from array of devices
647 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
648 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
649 METHODID_STRINGNONPARAM);
650 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
651 METHODID_STRINGNONPARAM);
653 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
655 for (i = 0; i < length; i++)
657 OIC_LOG(DEBUG, TAG, "[EDR][Native] 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, "[EDR][Native] getBondedDevices: ~~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 OIC_LOG_V(DEBUG, TAG,
673 "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
677 OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
680 (*g_jvm)->DetachCurrentThread(g_jvm);
683 (*env)->DeleteLocalRef(env, j_str_address);
684 (*env)->DeleteLocalRef(env, j_obj_device);
685 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
686 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
687 return CA_STATUS_INVALID_PARAM;
691 OIC_LOG(ERROR, TAG, "[EDR][Native] address is null");
694 (*g_jvm)->DetachCurrentThread(g_jvm);
696 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
697 (*env)->DeleteLocalRef(env, j_str_address);
698 (*env)->DeleteLocalRef(env, j_obj_device);
699 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
700 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
701 return CA_STATUS_INVALID_PARAM;
704 if (!strcmp(remoteAddress, address))
706 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
707 if (CA_STATUS_OK != res)
709 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
710 (*env)->DeleteLocalRef(env, j_str_address);
711 (*env)->DeleteLocalRef(env, j_obj_device);
712 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
713 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
717 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
718 (*env)->DeleteLocalRef(env, j_str_address);
719 (*env)->DeleteLocalRef(env, j_obj_device);
722 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
723 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
727 (*g_jvm)->DetachCurrentThread(g_jvm);
733 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
735 OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
737 // get bonded device list
738 jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
739 if (!jni_arrayPairedDevices)
741 OIC_LOG(ERROR, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
742 return CA_STATUS_INVALID_PARAM;
744 // Get information from array of devices
745 jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
746 jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
747 METHODID_STRINGNONPARAM);
748 jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
749 METHODID_STRINGNONPARAM);
751 jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
753 for (i = 0; i < length; i++)
755 // get name, address from BT device
756 jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
757 jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
761 const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
762 OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name);
763 (*env)->ReleaseStringUTFChars(env, j_str_name, name);
764 (*env)->DeleteLocalRef(env, j_str_name);
767 jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
768 const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
769 OIC_LOG_V(DEBUG, TAG,
770 "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
773 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
774 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
775 (*env)->DeleteLocalRef(env, j_str_address);
776 if (CA_STATUS_OK != res)
778 OIC_LOG_V(ERROR, TAG, "CASendMulticastMessageImpl, failed to send message to : %s",
780 g_edrErrorHandler(remoteAddress, data, dataLen, res);
785 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
786 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
794 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
797 OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData logic start : %s, %d", data, dataLength);
799 if (!CAEDRNativeIsEnableBTAdapter(env))
801 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
802 return CA_STATUS_INVALID_PARAM;
805 if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
807 // connect before send data
808 OIC_LOG(DEBUG, TAG, "[EDR][Native] connect before send data");
812 OIC_LOG(ERROR, TAG, "[EDR][Native] remote address is empty");
813 return CA_STATUS_INVALID_PARAM;
817 CAResult_t res = CAEDRNativeConnect(env, address);
818 if (CA_STATUS_OK != res)
825 if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
827 if (!((*env)->ExceptionCheck(env)))
829 jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
830 if (!jni_cid_BTsocket)
832 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_BTsocket is null");
833 return CA_STATUS_FAILED;
836 jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
838 METHODID_OUTPUTNONPARAM);
839 if (!jni_mid_getOutputStream)
841 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_getOutputStream is null");
842 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
843 return CA_STATUS_FAILED;
846 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Get MethodID for i/o stream");
848 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
851 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_socket is not available");
852 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
853 return CA_STATUS_FAILED;
856 jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
857 jni_mid_getOutputStream);
858 if (!jni_obj_outputStream)
860 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_obj_outputStream is null");
861 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
862 return CA_STATUS_FAILED;
865 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: ready outputStream..");
867 jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
868 if (!jni_cid_OutputStream)
870 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_OutputStream is null");
871 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
872 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
873 return CA_STATUS_FAILED;
876 jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
880 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_write is null");
881 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
882 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
883 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
884 return CA_STATUS_FAILED;
888 jbuf = (*env)->NewByteArray(env, dataLength);
889 (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
891 (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
894 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
895 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
896 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
897 (*env)->DeleteLocalRef(env, jbuf);
899 if ((*env)->ExceptionCheck(env))
901 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: Write Error!!!");
902 (*env)->ExceptionDescribe(env);
903 (*env)->ExceptionClear(env);
904 return CA_STATUS_FAILED;
907 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Write Success");
911 (*env)->ExceptionDescribe(env);
912 (*env)->ExceptionClear(env);
913 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: error!!");
914 return CA_STATUS_FAILED;
919 OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: BT connection is not completed!!");
925 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
927 OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect..");
929 if (!CAEDRNativeIsEnableBTAdapter(env))
931 OIC_LOG(ERROR, TAG, "BT adpater is not enable");
932 return CA_STATUS_INVALID_PARAM;
935 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
936 if (!jni_cid_BTAdapter)
938 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BTAdapter is null");
939 return CA_STATUS_FAILED;
943 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
945 METHODID_OBJECTNONPARAM);
946 if (!jni_mid_getDefaultAdapter)
948 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getDefaultAdapter is null");
949 return CA_STATUS_FAILED;
952 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
953 jni_mid_getDefaultAdapter);
954 if (!jni_obj_BTAdapter)
956 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTAdapter is null");
957 return CA_STATUS_FAILED;
960 // get remote bluetooth device
961 jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
963 METHODID_BT_DEVICEPARAM);
964 if (!jni_mid_getRemoteDevice)
966 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getRemoteDevice is null");
967 return CA_STATUS_FAILED;
970 jstring jni_address = (*env)->NewStringUTF(env, address);
971 jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
972 jni_mid_getRemoteDevice, jni_address);
973 if (!jni_obj_remoteBTDevice)
975 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_remoteBTDevice is null");
976 return CA_STATUS_FAILED;
979 // get create Rfcomm Socket method ID
980 jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
981 if (!jni_cid_BluetoothDevice)
983 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BluetoothDevice is null");
984 return CA_STATUS_FAILED;
987 jmethodID jni_mid_createSocket = (*env)->GetMethodID(
988 env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
989 "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
990 if (!jni_mid_createSocket)
992 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_createSocket is null");
993 return CA_STATUS_FAILED;
997 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1000 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_uuid is null");
1001 return CA_STATUS_FAILED;
1004 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
1005 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
1006 if (!jni_mid_fromString)
1008 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_fromString is null");
1009 return CA_STATUS_FAILED;
1012 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1015 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_uuid is null");
1016 return CA_STATUS_FAILED;
1018 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1022 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_uuid is null");
1023 return CA_STATUS_FAILED;
1026 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1027 jni_mid_createSocket, jni_obj_uuid);
1028 if (!jni_obj_BTSocket)
1030 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTSocket is null");
1031 return CA_STATUS_FAILED;
1035 jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1036 if (!jni_cid_BTSocket)
1038 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BTSocket is null");
1039 return CA_STATUS_FAILED;
1042 jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1043 if (!jni_mid_connect)
1045 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_connect is null");
1046 return CA_STATUS_FAILED;
1049 OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: initiating connection...");
1050 (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1052 if ((*env)->ExceptionCheck(env))
1054 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: Connect is Failed!!!");
1055 (*env)->ExceptionDescribe(env);
1056 (*env)->ExceptionClear(env);
1057 return CA_STATUS_FAILED;
1060 // set socket to list
1061 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1064 OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_socket is null");
1065 return CA_STATUS_FAILED;
1067 ca_mutex_lock(g_mutexObjectList);
1068 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
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, "[EDR][Native] btConnect: connected");
1078 return CA_STATUS_OK;
1081 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1084 jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1085 if (!jni_cid_BTSocket)
1087 OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_cid_BTSocket is null");
1091 jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1094 OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_mid_close is null");
1098 jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1099 if (!jni_obj_socket)
1101 OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_obj_socket is not available");
1105 (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1107 if ((*env)->ExceptionCheck(env))
1109 OIC_LOG(ERROR, TAG, "[EDR][Native] close: close is Failed!!!");
1110 (*env)->ExceptionDescribe(env);
1111 (*env)->ExceptionClear(env);
1115 // remove socket to list
1116 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1119 ca_mutex_lock(g_mutexStateList);
1120 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1121 ca_mutex_unlock(g_mutexStateList);
1123 OIC_LOG(DEBUG, TAG, "[EDR][Native] close: disconnected");
1126 void CAEDRInitializeClient(ca_thread_pool_t handle)
1128 OIC_LOG(DEBUG, TAG, "IN");
1129 CAEDRInitialize(handle);
1130 OIC_LOG(DEBUG, TAG, "OUT");
1133 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1135 g_edrErrorHandler = errorHandleCallback;