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 "caedrserver.h"
29 #include "oic_malloc.h"
30 #include "cathreadpool.h" /* for thread pool */
32 #include "uarraylist.h"
33 #include "caadapterutils.h"
34 #include "org_iotivity_ca_CaEdrInterface.h"
35 #include "oic_string.h"
37 #define TAG PCF("OIC_CA_EDR_SERVER")
39 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
40 static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter";
41 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
43 static ca_thread_pool_t g_threadPoolHandle = NULL;
48 * Maximum CoAP over TCP header length
49 * to know the total data length.
51 #define EDR_MAX_HEADER_LEN 6
54 * server socket instance.
56 static jobject g_serverSocketObject = NULL;
59 * Mutex to synchronize unicast server.
61 static ca_mutex g_mutexUnicastServer = NULL;
64 * Flag to control the Receive Unicast Data Thread.
66 static bool g_stopUnicast = false;
69 * Mutex to synchronize secure multicast server.
71 static ca_mutex g_mutexMulticastServer = NULL;
74 * Flag to control the Receive Multicast Data Thread.
76 static bool g_stopMulticast = false;
79 * Mutex to synchronize accept server.
81 static ca_mutex g_mutexAcceptServer = NULL;
84 * Flag to control the Accept Thread.
86 static bool g_stopAccept = false;
89 * Mutex to synchronize server socket.
91 static ca_mutex g_mutexServerSocket = NULL;
93 static jobject g_serverSocket = NULL;
96 * Mutex to synchronize device state list.
98 static ca_mutex g_mutexStateList = NULL;
101 * Mutex to synchronize device object list.
103 static ca_mutex g_mutexObjectList = NULL;
106 * Thread context information for unicast, multicast and secured unicast server.
111 CAAdapterServerType_t type;
112 } CAAdapterReceiveThreadContext_t;
117 } CAAdapterAcceptThreadContext_t;
120 * Maintains the callback to be notified when data received from remote
123 static CAEDRDataReceivedCallback g_edrPacketReceivedCallback = NULL;
125 static void CAReceiveHandler(void *data)
127 OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler..");
129 VERIFY_NON_NULL_VOID(data, TAG, "Invalid thread context");
131 bool isAttached = false;
133 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
136 OIC_LOG(DEBUG, TAG, "CAReceiveHandler - Could not get JNIEnv pointer");
137 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
141 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
147 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) data;
149 while (true != *(ctx->stopFlag))
151 if (!CAEDRNativeIsEnableBTAdapter(env))
153 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
157 // if new socket object is added in socket list after below logic is ran.
158 // new socket will be started to read after next while loop
159 uint32_t length = CAEDRGetSocketListLength();
162 for (uint32_t idx = 0; idx < length; idx++)
164 CAEDRNativeReadData(env, idx);
171 (*g_jvm)->DetachCurrentThread(g_jvm);
176 OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
179 static void CAAcceptHandler(void *data)
181 OIC_LOG(DEBUG, TAG, "AcceptThread start");
183 VERIFY_NON_NULL_VOID(data, TAG, "CAAcceptHandler: data is null");
185 bool isAttached = false;
187 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
190 OIC_LOG(DEBUG, TAG, "CAAcceptHandler - Could not get JNIEnv pointer");
191 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
195 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
201 jobject jni_obj_BTServerSocket = CAEDRNativeListen(env);
202 if (!jni_obj_BTServerSocket)
204 OIC_LOG(ERROR, TAG, "AcceptThread: jni_obj_BTServerSocket is null");
208 (*g_jvm)->DetachCurrentThread(g_jvm);
214 ca_mutex_lock(g_mutexServerSocket);
215 g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
216 ca_mutex_unlock(g_mutexServerSocket);
218 CAAdapterAcceptThreadContext_t *ctx = (CAAdapterAcceptThreadContext_t *) data;
220 // it should be initialized for restart accept thread
221 ca_mutex_lock(g_mutexAcceptServer);
222 g_stopAccept = false;
223 ca_mutex_unlock(g_mutexAcceptServer);
225 while (true != *(ctx->stopFlag))
227 OIC_LOG(DEBUG, TAG, "AcceptThread running");
229 // when BT state is changed with Off. its thread will be stopped
230 if (!CAEDRNativeIsEnableBTAdapter(env))
232 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
233 ca_mutex_lock(g_mutexAcceptServer);
235 ca_mutex_unlock(g_mutexAcceptServer);
236 ca_mutex_lock(g_mutexServerSocket);
237 g_serverSocket = NULL;
238 ca_mutex_unlock(g_mutexServerSocket);
242 CAEDRNativeAccept(env, g_serverSocket);
248 (*g_jvm)->DetachCurrentThread(g_jvm);
253 OIC_LOG(DEBUG, TAG, "AcceptThread finish");
259 * implement for adapter common method.
261 CAResult_t CAEDRServerStart()
263 if (!g_threadPoolHandle)
265 return CA_STATUS_NOT_INITIALIZED;
268 CAEDRServerStartAcceptThread();
269 CAResult_t res = CAEDRStartUnicastServer(false);
270 if (CA_STATUS_OK != res)
272 OIC_LOG(ERROR, TAG, "CAEDRStartUnicastServer failed");
274 return CA_STATUS_FAILED;
280 CAResult_t CAEDRServerStop()
282 CAEDRStopUnicastServer();
283 CAEDRStopMulticastServer();
285 ca_mutex_lock(g_mutexAcceptServer);
287 ca_mutex_unlock(g_mutexAcceptServer);
291 OIC_LOG(DEBUG, TAG, "g_jvm is null");
292 return CA_STATUS_FAILED;
295 bool isAttached = false;
297 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
300 OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
301 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
305 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
306 return CA_STATUS_FAILED;
311 CAEDRNatvieCloseServerTask(env);
315 (*g_jvm)->DetachCurrentThread(g_jvm);
321 void CAEDRSetPacketReceivedCallback(CAEDRDataReceivedCallback packetReceivedCallback)
323 g_edrPacketReceivedCallback = packetReceivedCallback;
326 static void CAEDRServerDestroyMutex()
328 if (g_mutexUnicastServer)
330 ca_mutex_free(g_mutexUnicastServer);
331 g_mutexUnicastServer = NULL;
334 if (g_mutexMulticastServer)
336 ca_mutex_free(g_mutexMulticastServer);
337 g_mutexMulticastServer = NULL;
340 if (g_mutexAcceptServer)
342 ca_mutex_free(g_mutexAcceptServer);
343 g_mutexAcceptServer = NULL;
346 if (g_mutexServerSocket)
348 ca_mutex_free(g_mutexServerSocket);
349 g_mutexServerSocket = NULL;
352 if (g_mutexStateList)
354 ca_mutex_free(g_mutexStateList);
355 g_mutexStateList = NULL;
358 if (g_mutexObjectList)
360 ca_mutex_free(g_mutexObjectList);
361 g_mutexObjectList = NULL;
365 static CAResult_t CAEDRServerCreateMutex()
367 g_mutexUnicastServer = ca_mutex_new();
368 if (!g_mutexUnicastServer)
370 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
371 return CA_STATUS_FAILED;
374 g_mutexMulticastServer = ca_mutex_new();
375 if (!g_mutexMulticastServer)
377 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
379 CAEDRServerDestroyMutex();
380 return CA_STATUS_FAILED;
383 g_mutexAcceptServer = ca_mutex_new();
384 if (!g_mutexAcceptServer)
386 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
388 CAEDRServerDestroyMutex();
389 return CA_STATUS_FAILED;
392 g_mutexServerSocket = ca_mutex_new();
393 if (!g_mutexServerSocket)
395 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
397 CAEDRServerDestroyMutex();
398 return CA_STATUS_FAILED;
401 g_mutexStateList = ca_mutex_new();
402 if (!g_mutexStateList)
404 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
406 CAEDRServerDestroyMutex();
407 return CA_STATUS_FAILED;
410 g_mutexObjectList = ca_mutex_new();
411 if (!g_mutexObjectList)
413 OIC_LOG(ERROR, TAG, "Failed to created mutex!");
415 CAEDRServerDestroyMutex();
416 return CA_STATUS_FAILED;
422 void CAEDRServerJniInit()
424 OIC_LOG(DEBUG, TAG, "CAEDRServerJniInit");
425 g_jvm = CANativeJNIGetJavaVM();
428 CAResult_t CAEDRServerInitialize(ca_thread_pool_t handle)
430 OIC_LOG(DEBUG, TAG, "CAEDRServerInitialize");
431 VERIFY_NON_NULL(handle, TAG, "handle is NULL");
432 g_threadPoolHandle = handle;
433 CAEDRServerJniInit();
436 CAResult_t result = CAEDRServerCreateMutex();
440 CAResult_t CAEDRServerStartAcceptThread()
442 bool isAttached = false;
444 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
447 OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
448 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
452 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
453 return CA_STATUS_FAILED;
458 jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
461 const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
462 OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
463 (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
466 ca_mutex_lock(g_mutexStateList);
467 CAEDRNativeCreateDeviceStateList();
468 ca_mutex_unlock(g_mutexStateList);
470 ca_mutex_lock(g_mutexObjectList);
471 CAEDRNativeCreateDeviceSocketList();
472 ca_mutex_unlock(g_mutexObjectList);
476 (*g_jvm)->DetachCurrentThread(g_jvm);
479 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
480 sizeof(CAAdapterReceiveThreadContext_t));
483 OIC_LOG(ERROR, TAG, "Out of memory!");
484 return CA_MEMORY_ALLOC_FAILED;
487 ctx->stopFlag = &g_stopAccept;
488 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAAcceptHandler, (void *) ctx))
490 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
491 OICFree((void *) ctx);
492 return CA_STATUS_FAILED;
498 void CAEDRServerTerminate()
500 OIC_LOG(DEBUG, TAG, "CAEDRServerTerminate");
506 bool isAttached = false;
508 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
511 OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
512 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
516 OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
522 CAEDRNativeSocketCloseToAll(env);
526 (*g_jvm)->DetachCurrentThread(g_jvm);
529 CAEDRNativeRemoveAllDeviceState();
530 CAEDRNativeRemoveAllDeviceSocket(env);
533 CAEDRServerDestroyMutex();
536 CAResult_t CAEDRStartUnicastServer(bool isSecured)
538 OIC_LOG(DEBUG, TAG, "CAEDRStartUnicastServer");
540 ca_mutex_lock(g_mutexUnicastServer);
543 * The task to listen for data from unicast is added to the thread pool.
544 * This is a blocking call is made where we try to receive some data..
545 * We will keep waiting until some data is received.
546 * This task will be terminated when thread pool is freed on stopping the adapters.
547 * Thread context will be freed by thread on exit.
549 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
550 sizeof(CAAdapterReceiveThreadContext_t));
553 OIC_LOG(ERROR, TAG, "Out of memory!");
554 ca_mutex_unlock(g_mutexUnicastServer);
555 return CA_MEMORY_ALLOC_FAILED;
558 ctx->stopFlag = &g_stopUnicast;
559 ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
560 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *) ctx))
562 OIC_LOG(ERROR, TAG, "Failed to create read thread!");
563 ca_mutex_unlock(g_mutexUnicastServer);
564 OICFree((void *) ctx);
565 return CA_STATUS_FAILED;
567 ca_mutex_unlock(g_mutexUnicastServer);
569 OIC_LOG(DEBUG, TAG, "OUT");
573 CAResult_t CAEDRStartMulticastServer()
575 OIC_LOG(DEBUG, TAG, "CAEDRStartMulticastServer");
577 ca_mutex_lock(g_mutexMulticastServer);
580 * The task to listen to data from multicast socket is added to the thread pool.
581 * This is a blocking call is made where we try to receive some data.
582 * We will keep waiting until some data is received.
583 * This task will be terminated when thread pool is freed on stopping the adapters.
584 * Thread context will be freed by thread on exit.
586 CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
587 sizeof(CAAdapterReceiveThreadContext_t));
590 OIC_LOG(ERROR, TAG, "Out of memory!");
591 ca_mutex_unlock(g_mutexMulticastServer);
593 return CA_MEMORY_ALLOC_FAILED;
596 ctx->stopFlag = &g_stopMulticast;
597 ctx->type = CA_MULTICAST_SERVER;
599 g_stopMulticast = false;
600 if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *) ctx))
602 OIC_LOG(ERROR, TAG, "thread_pool_add_task failed!");
604 g_stopMulticast = true;
605 ca_mutex_unlock(g_mutexMulticastServer);
606 OICFree((void *) ctx);
608 return CA_STATUS_FAILED;
610 ca_mutex_unlock(g_mutexMulticastServer);
612 OIC_LOG(DEBUG, TAG, "OUT");
616 CAResult_t CAEDRStopUnicastServer()
618 OIC_LOG(DEBUG, TAG, "CAEDRStopUnicastServer");
620 ca_mutex_lock(g_mutexUnicastServer);
621 g_stopUnicast = true;
622 ca_mutex_unlock(g_mutexUnicastServer);
627 CAResult_t CAEDRStopMulticastServer()
629 OIC_LOG(DEBUG, TAG, "CAEDRStopMulticastServer");
631 ca_mutex_lock(g_mutexMulticastServer);
632 g_stopMulticast = true;
633 ca_mutex_unlock(g_mutexMulticastServer);
635 OIC_LOG(INFO, TAG, "Multicast server stopped");
640 CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
642 if ((*env)->ExceptionCheck(env))
644 (*env)->ExceptionDescribe(env);
645 (*env)->ExceptionClear(env);
646 OIC_LOG(ERROR, TAG, "env error!!");
647 return CA_STATUS_FAILED;
650 // check whether this socket object is connected or not.
651 jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(id);
654 return CA_STATUS_INVALID_PARAM;
657 // check it whether is still connected or not through google api
658 jboolean ret = CAEDRIsConnectedForSocket(env, jni_obj_socket);
661 OIC_LOG(ERROR, TAG, "it is not connected yet.");
663 // remove socket to list
664 CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
665 return CA_STATUS_FAILED;
668 // start to read through InputStream
669 jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
670 if (!jni_cid_BTsocket)
672 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
673 return CA_STATUS_FAILED;
675 jmethodID jni_mid_getInputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
677 "()Ljava/io/InputStream;");
679 jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
680 jni_mid_getInputStream);
681 if (!jni_obj_inputStream)
683 OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null");
684 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
685 return CA_STATUS_FAILED;
688 jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
689 if (!jni_cid_InputStream)
691 OIC_LOG(ERROR, TAG, "jni_cid_InputStream is null");
692 (*env)->DeleteLocalRef(env, jni_obj_inputStream);
693 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
694 return CA_STATUS_FAILED;
697 jmethodID jni_mid_available = (*env)->GetMethodID(env, jni_cid_InputStream,
699 if (!jni_mid_available)
701 OIC_LOG(ERROR, TAG, "jni_mid_available is null");
705 jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available);
707 CAConnectedDeviceInfo_t *deviceInfo = NULL;
710 jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket);
711 if (!jni_str_address)
713 OIC_LOG(ERROR, TAG, "jni_str_address is null");
717 const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL);
720 OIC_LOG(ERROR, TAG, "address is null");
721 (*env)->DeleteLocalRef(env, jni_str_address);
725 OIC_LOG_V(DEBUG, TAG, "get InputStream..%d, %s", id, address);
726 jmethodID jni_mid_read = (*env)->GetMethodID(env, jni_cid_InputStream,
730 OIC_LOG(ERROR, TAG, "jni_mid_read is null");
731 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
732 (*env)->DeleteLocalRef(env, jni_str_address);
736 deviceInfo = (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address);
739 OIC_LOG(ERROR, TAG, "failed to get device info from list");
740 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
741 (*env)->DeleteLocalRef(env, jni_str_address);
745 jint bufSize = (deviceInfo->totalDataLen == 0) ?
746 EDR_MAX_HEADER_LEN : deviceInfo->totalDataLen;
747 if (!deviceInfo->recvData)
749 deviceInfo->recvData = OICCalloc(1, bufSize);
750 if (!deviceInfo->recvData)
752 OIC_LOG(ERROR, TAG, "out of memory");
753 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
754 (*env)->DeleteLocalRef(env, jni_str_address);
759 jbyteArray jbuf = (*env)->NewByteArray(env, (jint) bufSize - deviceInfo->recvDataLen);
762 OIC_LOG(ERROR, TAG, "jbuf is null");
763 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
764 (*env)->DeleteLocalRef(env, jni_str_address);
768 jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read,
770 (jint) bufSize - deviceInfo->recvDataLen);
773 OIC_LOG(ERROR, TAG, "recvLen is -1");
774 (*env)->DeleteLocalRef(env, jbuf);
775 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
776 (*env)->DeleteLocalRef(env, jni_str_address);
780 jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
783 OIC_LOG(ERROR, TAG, "buf is null");
784 (*env)->DeleteLocalRef(env, jbuf);
785 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
786 (*env)->DeleteLocalRef(env, jni_str_address);
789 memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen);
790 deviceInfo->recvDataLen += recvLen;
792 OIC_LOG(DEBUG, TAG, "read something from InputStream");
794 if (!deviceInfo->totalDataLen)
796 coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
797 ((unsigned char *) deviceInfo->recvData)[0] >> 4);
798 size_t headerLen = coap_get_tcp_header_length_for_transport(transport);
799 if (deviceInfo->recvData && deviceInfo->recvDataLen >= headerLen)
801 deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData,
802 deviceInfo->recvDataLen);
803 OIC_LOG_V(DEBUG, TAG, "total data length [%d] bytes", deviceInfo->totalDataLen);
805 uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen);
808 OIC_LOG(ERROR, TAG, "out of memory");
809 (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
810 (*env)->DeleteLocalRef(env, jbuf);
811 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
812 (*env)->DeleteLocalRef(env, jni_str_address);
815 deviceInfo->recvData = newBuf;
819 if (deviceInfo->totalDataLen == deviceInfo->recvDataLen)
821 if ((*env)->ExceptionCheck(env))
823 OIC_LOG(ERROR, TAG, "read Error!!!");
824 (*env)->ExceptionDescribe(env);
825 (*env)->ExceptionClear(env);
827 // update state to disconnect
828 // the socket will be close next read thread routine
829 ca_mutex_lock(g_mutexStateList);
830 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
831 ca_mutex_unlock(g_mutexStateList);
833 (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
834 (*env)->DeleteLocalRef(env, jbuf);
835 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
836 (*env)->DeleteLocalRef(env, jni_str_address);
840 if (g_edrPacketReceivedCallback)
842 OIC_LOG_V(DEBUG, TAG,"data will be sent to callback routine: \
843 %s, %d", deviceInfo->recvData, deviceInfo->recvDataLen);
845 uint32_t sentLength = 0;
846 g_edrPacketReceivedCallback(address, (void*) deviceInfo->recvData,
847 deviceInfo->recvDataLen, &sentLength);
849 OICFree(deviceInfo->recvData);
850 deviceInfo->recvData = NULL;
851 deviceInfo->recvDataLen = 0;
852 deviceInfo->totalDataLen = 0;
855 (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
856 (*env)->DeleteLocalRef(env, jbuf);
857 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
858 (*env)->DeleteLocalRef(env, jni_str_address);
860 (*env)->DeleteLocalRef(env, jni_cid_InputStream);
861 (*env)->DeleteLocalRef(env, jni_obj_inputStream);
862 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
867 (*env)->DeleteLocalRef(env, jni_cid_InputStream);
868 (*env)->DeleteLocalRef(env, jni_obj_inputStream);
869 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
871 return CA_STATUS_FAILED;
874 jboolean CAEDRIsConnectedForSocket(JNIEnv *env, jobject socket)
878 OIC_LOG(ERROR, TAG, "socket is null");
882 jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
883 if (!jni_cid_BTsocket)
885 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
889 jmethodID jni_mid_isConnected = (*env)->GetMethodID(env, jni_cid_BTsocket, "isConnected",
891 if (!jni_mid_isConnected)
893 OIC_LOG(ERROR, TAG, "jni_mid_isConnected is null.");
894 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
898 jboolean jni_isConnected = (*env)->CallBooleanMethod(env, socket, jni_mid_isConnected);
900 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
902 return jni_isConnected;
905 void CANativeStartListenTask(JNIEnv *env)
907 jobject jni_obj_BTServerSocket = CAEDRNativeListen(env);
908 if (!jni_obj_BTServerSocket)
910 OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
914 ca_mutex_lock(g_mutexServerSocket);
915 g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
916 ca_mutex_unlock(g_mutexServerSocket);
919 jobject CAEDRNativeListen(JNIEnv *env)
921 OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - IN");
923 if (!CAEDRNativeIsEnableBTAdapter(env))
925 OIC_LOG(INFO, TAG, "BT adapter is not enabled");
929 jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
930 if (!jni_cid_BTAdapter)
932 OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
937 jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
939 METHODID_OBJECTNONPARAM);
940 if (!jni_mid_getDefaultAdapter)
942 OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
946 jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
947 jni_mid_getDefaultAdapter);
948 if (!jni_obj_BTAdapter)
950 OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
954 // get listen method ID
955 jmethodID jni_mid_listen = (*env)->GetMethodID(
956 env, jni_cid_BTAdapter, "listenUsingInsecureRfcommWithServiceRecord",
957 "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;");
960 OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
963 // listenUsingInsecureRfcommWithServiceRecord / listenUsingRfcommWithServiceRecord
965 jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
968 OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
972 jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
973 env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
974 if (!jni_mid_fromString)
976 OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
980 jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
983 OIC_LOG(ERROR, TAG, "jni_uuid is null");
986 jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
990 OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
995 jstring jni_name = (*env)->NewStringUTF(env, "BluetoothTestSecure");
998 OIC_LOG(ERROR, TAG, "jni_name is null");
1001 jobject jni_obj_BTServerSocket = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_listen,
1002 jni_name, jni_obj_uuid);
1003 if (!jni_obj_BTServerSocket)
1005 OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
1009 g_serverSocketObject = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
1011 OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - OUT");
1013 return jni_obj_BTServerSocket;
1016 void CAEDRNativeAccept(JNIEnv *env, jobject serverSocketObject)
1018 OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - IN");
1020 if (NULL != serverSocketObject)
1022 jclass jni_cid_BTServerSocket = (*env)->FindClass(
1023 env, "android/bluetooth/BluetoothServerSocket");
1024 if (!jni_cid_BTServerSocket)
1026 OIC_LOG(ERROR, TAG, "jni_cid_BTServerSocket is null");
1030 jmethodID jni_mid_accept = (*env)->GetMethodID(env, jni_cid_BTServerSocket, "accept",
1031 "()Landroid/bluetooth/BluetoothSocket;");
1032 if (!jni_mid_accept)
1034 OIC_LOG(ERROR, TAG, "jni_mid_accept is null");
1038 OIC_LOG(DEBUG, TAG, "initiating accept...");
1040 jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, serverSocketObject,
1042 if (!jni_obj_BTSocket)
1044 OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1046 if ((*env)->ExceptionCheck(env))
1048 OIC_LOG(ERROR, TAG, "socket might closed or timeout!!!");
1049 (*env)->ExceptionDescribe(env);
1050 (*env)->ExceptionClear(env);
1055 // get remote address
1056 jstring j_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_BTSocket);
1059 OIC_LOG(ERROR, TAG, "j_str_address is null");
1063 const char* address = (*env)->GetStringUTFChars(env, j_str_address, NULL);
1064 OIC_LOG_V(DEBUG, TAG, "address is %s", address);
1066 // set socket to list
1067 jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1068 ca_mutex_lock(g_mutexObjectList);
1069 CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1070 ca_mutex_unlock(g_mutexObjectList);
1072 OIC_LOG(DEBUG, TAG, "Accepted!!");
1075 ca_mutex_lock(g_mutexStateList);
1076 CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1077 ca_mutex_unlock(g_mutexStateList);
1079 (*env)->ReleaseStringUTFChars(env, j_str_address, address);
1080 (*env)->DeleteLocalRef(env, j_str_address);
1084 OIC_LOG(DEBUG, TAG, "serverSocket is close previously");
1087 OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - OUT");
1091 * InputStream & BluetoothServerSocket will be close for Terminating.
1093 void CAEDRNatvieCloseServerTask(JNIEnv* env)
1097 OIC_LOG(DEBUG, TAG, "Accept Resource will be close");
1099 jclass jni_cid_BTServerSocket = (*env)->FindClass(
1100 env, "android/bluetooth/BluetoothServerSocket");
1101 if (!jni_cid_BTServerSocket)
1103 OIC_LOG(ERROR, TAG, "jni_cid_BTServerSocket is null");
1107 jmethodID jni_mid_accept = (*env)->GetMethodID(env, jni_cid_BTServerSocket, "close", "()V");
1108 if (!jni_mid_accept)
1110 OIC_LOG(ERROR, TAG, "jni_mid_accept is null");
1113 (*env)->CallVoidMethod(env, g_serverSocket, jni_mid_accept);
1114 (*env)->DeleteGlobalRef(env, g_serverSocket);
1115 g_serverSocket = NULL;
1117 OIC_LOG(DEBUG, TAG, "close accept obj");