0a54f98edb3f95b5eddd36beed755b1a0fda2183
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_edr_adapter / android / caedrserver.c
1 /* ****************************************************************
2  *
3  * Copyright 2014 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  ******************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <jni.h>
24
25 #include "caedrinterface.h"
26 #include "caedrutils.h"
27 #include "caedrserver.h"
28 #include "logger.h"
29 #include "oic_malloc.h"
30 #include "cathreadpool.h" /* for thread pool */
31 #include "camutex.h"
32 #include "uarraylist.h"
33 #include "caadapterutils.h"
34 #include "org_iotivity_ca_CaEdrInterface.h"
35 #include "oic_string.h"
36
37 #define TAG PCF("OIC_CA_EDR_SERVER")
38
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";
42 static const char CLASSPATH_BT_SERVER_SOCKET[] = "android/bluetooth/BluetoothServerSocket";
43 static const char CLASSPATH_BT_SOCKET[] = "android/bluetooth/BluetoothSocket";
44
45 static ca_thread_pool_t g_threadPoolHandle = NULL;
46
47 static JavaVM *g_jvm;
48
49 /**
50  * Maximum CoAP over TCP header length
51  * to know the total data length.
52  */
53 #define EDR_MAX_HEADER_LEN  6
54
55 /**
56  * server socket instance.
57  */
58 static jobject g_serverSocketObject = NULL;
59
60 /**
61  * Mutex to synchronize receive server.
62  */
63 static ca_mutex g_mutexReceiveServer = NULL;
64
65 /**
66  * Flag to control the Receive Unicast Data Thread.
67  */
68 static bool g_stopUnicast = false;
69
70 /**
71  * Mutex to synchronize accept server.
72  */
73 static ca_mutex g_mutexAcceptServer = NULL;
74
75 /**
76  * Flag to control the Accept Thread.
77  */
78 static bool g_stopAccept = false;
79
80 /**
81  * Mutex to synchronize server socket.
82  */
83 static ca_mutex g_mutexServerSocket = NULL;
84
85 /**
86  * Flag to control the server socket.
87  */
88 static jobject g_serverSocket = NULL;
89
90 /**
91  * Mutex to synchronize device state list.
92  */
93 static ca_mutex g_mutexStateList = NULL;
94
95 /**
96  * Mutex to synchronize device object list.
97  */
98 static ca_mutex g_mutexObjectList = NULL;
99
100 /**
101  * Thread context information for unicast, multicast and secured unicast server.
102  */
103 typedef struct
104 {
105     bool *stopFlag;
106     CAAdapterServerType_t type;
107 } CAAdapterReceiveThreadContext_t;
108
109 typedef struct
110 {
111     bool *stopFlag;
112 } CAAdapterAcceptThreadContext_t;
113
114 /**
115  * Maintains the callback to be notified when data received from remote
116  * Bluetooth device.
117  */
118 static CAEDRDataReceivedCallback g_edrPacketReceivedCallback = NULL;
119
120 static void CAReceiveHandler(void *data)
121 {
122     OIC_LOG(DEBUG, TAG, "IN - CAReceiveHandler..");
123     // Input validation
124     VERIFY_NON_NULL_VOID(data, TAG, "Invalid thread context");
125
126     bool isAttached = false;
127     JNIEnv* env;
128     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
129     if (JNI_OK != res)
130     {
131         OIC_LOG(DEBUG, TAG, "CAReceiveHandler - Could not get JNIEnv pointer");
132         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
133
134         if (JNI_OK != res)
135         {
136             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
137             return;
138         }
139         isAttached = true;
140     }
141
142     CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) data;
143
144     while (true != *(ctx->stopFlag))
145     {
146         if (!CAEDRNativeIsEnableBTAdapter(env))
147         {
148             OIC_LOG(INFO, TAG, "BT adapter is not enabled");
149             break;
150         }
151
152         // if new socket object is added in socket list after below logic is ran.
153         // new socket will be started to read after next while loop
154         uint32_t length = CAEDRGetSocketListLength();
155         if (0 != length)
156         {
157             for (uint32_t idx = 0; idx < length; idx++)
158             {
159                 CAEDRNativeReadData(env, idx);
160             }
161         }
162     }
163
164     if (isAttached)
165     {
166         (*g_jvm)->DetachCurrentThread(g_jvm);
167     }
168
169     OICFree(ctx);
170
171     OIC_LOG(DEBUG, TAG, "OUT - CAReceiveHandler");
172 }
173
174 static void CAAcceptHandler(void *data)
175 {
176     OIC_LOG(DEBUG, TAG, "AcceptThread start");
177
178     VERIFY_NON_NULL_VOID(data, TAG, "data is null");
179
180     bool isAttached = false;
181     JNIEnv* env;
182     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
183     if (JNI_OK != res)
184     {
185         OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
186         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
187
188         if (JNI_OK != res)
189         {
190             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
191             return;
192         }
193         isAttached = true;
194     }
195
196     jobject jni_obj_BTServerSocket = CAEDRNativeListen(env);
197     if (!jni_obj_BTServerSocket)
198     {
199         OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
200
201         if (isAttached)
202         {
203             (*g_jvm)->DetachCurrentThread(g_jvm);
204         }
205
206         return;
207     }
208
209     ca_mutex_lock(g_mutexServerSocket);
210     g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
211     ca_mutex_unlock(g_mutexServerSocket);
212
213     CAAdapterAcceptThreadContext_t *ctx = (CAAdapterAcceptThreadContext_t *) data;
214
215     // it should be initialized for restart accept thread
216     ca_mutex_lock(g_mutexAcceptServer);
217     g_stopAccept = false;
218     ca_mutex_unlock(g_mutexAcceptServer);
219
220     while (true != *(ctx->stopFlag))
221     {
222         // when BT state is changed with Off. its thread will be stopped
223         if (!CAEDRNativeIsEnableBTAdapter(env))
224         {
225             OIC_LOG(INFO, TAG, "BT adapter is not enabled");
226             ca_mutex_lock(g_mutexAcceptServer);
227             g_stopAccept = true;
228             ca_mutex_unlock(g_mutexAcceptServer);
229             ca_mutex_lock(g_mutexServerSocket);
230             g_serverSocket = NULL;
231             ca_mutex_unlock(g_mutexServerSocket);
232         }
233         else
234         {
235             CAEDRNativeAccept(env, g_serverSocket);
236         }
237     }
238
239     if (isAttached)
240     {
241         (*g_jvm)->DetachCurrentThread(g_jvm);
242     }
243
244     OICFree(ctx);
245
246     OIC_LOG(DEBUG, TAG, "AcceptThread finish");
247
248     return;
249 }
250
251 /**
252  * implement for adapter common method.
253  */
254 CAResult_t CAEDRServerStart()
255 {
256     if (!g_threadPoolHandle)
257     {
258         return CA_STATUS_NOT_INITIALIZED;
259     }
260
261     CAResult_t res = CAEDRServerStartAcceptThread();
262     if (CA_STATUS_OK == res)
263     {
264         res = CAEDRStartReceiveThread(false);
265         if (CA_STATUS_OK != res)
266         {
267             OIC_LOG(ERROR, TAG, "failed to start receive thread");
268             CAEDRServerStop();
269             return CA_STATUS_FAILED;
270         }
271     }
272
273     return res;
274 }
275
276 CAResult_t CAEDRServerStop()
277 {
278     CAEDRStopReceiveThread();
279
280     ca_mutex_lock(g_mutexAcceptServer);
281     g_stopAccept = true;
282     ca_mutex_unlock(g_mutexAcceptServer);
283
284     if (!g_jvm)
285     {
286         OIC_LOG(DEBUG, TAG, "g_jvm is null");
287         return CA_STATUS_FAILED;
288     }
289
290     bool isAttached = false;
291     JNIEnv* env;
292     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
293     if (JNI_OK != res)
294     {
295         OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
296         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
297
298         if (JNI_OK != res)
299         {
300             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
301             return CA_STATUS_FAILED;
302         }
303         isAttached = true;
304     }
305
306     CAEDRNatvieCloseServerTask(env);
307
308     if (isAttached)
309     {
310         (*g_jvm)->DetachCurrentThread(g_jvm);
311     }
312
313     return CA_STATUS_OK;
314 }
315
316 void CAEDRSetPacketReceivedCallback(CAEDRDataReceivedCallback packetReceivedCallback)
317 {
318     g_edrPacketReceivedCallback = packetReceivedCallback;
319 }
320
321 static void CAEDRServerDestroyMutex()
322 {
323     if (g_mutexReceiveServer)
324     {
325         ca_mutex_free(g_mutexReceiveServer);
326         g_mutexReceiveServer = NULL;
327     }
328
329     if (g_mutexAcceptServer)
330     {
331         ca_mutex_free(g_mutexAcceptServer);
332         g_mutexAcceptServer = NULL;
333     }
334
335     if (g_mutexServerSocket)
336     {
337         ca_mutex_free(g_mutexServerSocket);
338         g_mutexServerSocket = NULL;
339     }
340
341     if (g_mutexStateList)
342     {
343         ca_mutex_free(g_mutexStateList);
344         g_mutexStateList = NULL;
345     }
346
347     if (g_mutexObjectList)
348     {
349         ca_mutex_free(g_mutexObjectList);
350         g_mutexObjectList = NULL;
351     }
352 }
353
354 static CAResult_t CAEDRServerCreateMutex()
355 {
356     g_mutexReceiveServer = ca_mutex_new();
357     if (!g_mutexReceiveServer)
358     {
359         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
360         return CA_STATUS_FAILED;
361     }
362
363     g_mutexAcceptServer = ca_mutex_new();
364     if (!g_mutexAcceptServer)
365     {
366         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
367
368         CAEDRServerDestroyMutex();
369         return CA_STATUS_FAILED;
370     }
371
372     g_mutexServerSocket = ca_mutex_new();
373     if (!g_mutexServerSocket)
374     {
375         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
376
377         CAEDRServerDestroyMutex();
378         return CA_STATUS_FAILED;
379     }
380
381     g_mutexStateList = ca_mutex_new();
382     if (!g_mutexStateList)
383     {
384         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
385
386         CAEDRServerDestroyMutex();
387         return CA_STATUS_FAILED;
388     }
389
390     g_mutexObjectList = ca_mutex_new();
391     if (!g_mutexObjectList)
392     {
393         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
394
395         CAEDRServerDestroyMutex();
396         return CA_STATUS_FAILED;
397     }
398
399     return CA_STATUS_OK;
400 }
401
402 void CAEDRServerJniInit()
403 {
404     OIC_LOG(DEBUG, TAG, "CAEDRServerJniInit");
405     g_jvm = CANativeJNIGetJavaVM();
406 }
407
408 CAResult_t CAEDRServerInitialize(ca_thread_pool_t handle)
409 {
410     OIC_LOG(DEBUG, TAG, "CAEDRServerInitialize");
411     VERIFY_NON_NULL(handle, TAG, "handle is NULL");
412
413     g_threadPoolHandle = handle;
414     CAEDRServerJniInit();
415
416     return CAEDRServerCreateMutex();
417 }
418
419 CAResult_t CAEDRServerStartAcceptThread()
420 {
421     bool isAttached = false;
422     JNIEnv* env;
423     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
424     if (JNI_OK != res)
425     {
426         OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
427         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
428
429         if (JNI_OK != res)
430         {
431             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
432             return CA_STATUS_FAILED;
433         }
434         isAttached = true;
435     }
436
437     jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
438     if (jni_address)
439     {
440         const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
441         OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
442         (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
443     }
444
445     ca_mutex_lock(g_mutexStateList);
446     CAEDRNativeCreateDeviceStateList();
447     ca_mutex_unlock(g_mutexStateList);
448
449     ca_mutex_lock(g_mutexObjectList);
450     CAEDRNativeCreateDeviceSocketList();
451     ca_mutex_unlock(g_mutexObjectList);
452
453     if (isAttached)
454     {
455         (*g_jvm)->DetachCurrentThread(g_jvm);
456     }
457
458     CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
459             sizeof(CAAdapterReceiveThreadContext_t));
460     if (!ctx)
461     {
462         OIC_LOG(ERROR, TAG, "Out of memory!");
463         return CA_MEMORY_ALLOC_FAILED;
464     }
465
466     ctx->stopFlag = &g_stopAccept;
467     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAAcceptHandler, (void *) ctx))
468     {
469         OIC_LOG(ERROR, TAG, "Failed to create read thread!");
470         OICFree((void *) ctx);
471         return CA_STATUS_FAILED;
472     }
473
474     return CA_STATUS_OK;
475 }
476
477 void CAEDRServerTerminate()
478 {
479     OIC_LOG(DEBUG, TAG, "CAEDRServerTerminate");
480
481     if (!g_jvm)
482     {
483         return;
484     }
485     bool isAttached = false;
486     JNIEnv* env;
487     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
488     if (JNI_OK != res)
489     {
490         OIC_LOG(DEBUG, TAG, "Could not get JNIEnv pointer");
491         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
492
493         if (JNI_OK != res)
494         {
495             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
496             return;
497         }
498         isAttached = true;
499     }
500
501     CAEDRNativeSocketCloseToAll(env);
502
503     if (isAttached)
504     {
505         (*g_jvm)->DetachCurrentThread(g_jvm);
506     }
507
508     CAEDRNativeRemoveAllDeviceState();
509     CAEDRNativeRemoveAllDeviceSocket(env);
510
511     // delete mutex
512     CAEDRServerDestroyMutex();
513 }
514
515 CAResult_t CAEDRStartReceiveThread(bool isSecured)
516 {
517     OIC_LOG(DEBUG, TAG, "CAEDRStartReceiveThread");
518
519     ca_mutex_lock(g_mutexReceiveServer);
520
521     /**
522      * The task to listen for data from unicast is added to the thread pool.
523      * This is a blocking call is made where we try to receive some data..
524      * We will keep waiting until some data is received.
525      * This task will be terminated when thread pool is freed on stopping the adapters.
526      * Thread context will be freed by thread on exit.
527      */
528     CAAdapterReceiveThreadContext_t *ctx = (CAAdapterReceiveThreadContext_t *) OICMalloc(
529             sizeof(CAAdapterReceiveThreadContext_t));
530     if (!ctx)
531     {
532         OIC_LOG(ERROR, TAG, "Out of memory!");
533         ca_mutex_unlock(g_mutexReceiveServer);
534         return CA_MEMORY_ALLOC_FAILED;
535     }
536
537     g_stopUnicast = false;
538     ctx->stopFlag = &g_stopUnicast;
539     ctx->type = isSecured ? CA_SECURED_UNICAST_SERVER : CA_UNICAST_SERVER;
540     if (CA_STATUS_OK != ca_thread_pool_add_task(g_threadPoolHandle, CAReceiveHandler, (void *) ctx))
541     {
542         OIC_LOG(ERROR, TAG, "Failed to create read thread!");
543         ca_mutex_unlock(g_mutexReceiveServer);
544         OICFree((void *) ctx);
545         return CA_STATUS_FAILED;
546     }
547     ca_mutex_unlock(g_mutexReceiveServer);
548
549     OIC_LOG(DEBUG, TAG, "OUT");
550     return CA_STATUS_OK;
551 }
552
553 CAResult_t CAEDRStopReceiveThread()
554 {
555     OIC_LOG(DEBUG, TAG, "CAEDRStopReceiveThread");
556
557     ca_mutex_lock(g_mutexReceiveServer);
558     g_stopUnicast = true;
559     ca_mutex_unlock(g_mutexReceiveServer);
560
561     return CA_STATUS_OK;
562 }
563
564 CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
565 {
566     if ((*env)->ExceptionCheck(env))
567     {
568         (*env)->ExceptionDescribe(env);
569         (*env)->ExceptionClear(env);
570         OIC_LOG(ERROR, TAG, "env error!!");
571         return CA_STATUS_FAILED;
572     }
573
574     // check whether this socket object is connected or not.
575     jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(id);
576     if (!jni_obj_socket)
577     {
578         return CA_STATUS_INVALID_PARAM;
579     }
580
581     // start to read through InputStream
582     jmethodID jni_mid_getInputStream = CAGetJNIMethodID(env,
583                                                         CLASSPATH_BT_SOCKET,
584                                                         "getInputStream",
585                                                         "()Ljava/io/InputStream;");
586
587     jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
588                                                            jni_mid_getInputStream);
589     if (!jni_obj_inputStream)
590     {
591         OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null");
592         return CA_STATUS_FAILED;
593     }
594
595     jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
596     if (!jni_cid_InputStream)
597     {
598         OIC_LOG(ERROR, TAG, "jni_cid_InputStream is null");
599         (*env)->DeleteLocalRef(env, jni_obj_inputStream);
600         return CA_STATUS_FAILED;
601     }
602
603     jmethodID jni_mid_available = (*env)->GetMethodID(env, jni_cid_InputStream,
604                                                       "available", "()I");
605     if (!jni_mid_available)
606     {
607         OIC_LOG(ERROR, TAG, "jni_mid_available is null");
608         goto exit;
609     }
610
611     jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available);
612
613     CAConnectedDeviceInfo_t *deviceInfo = NULL;
614     if (0 < available)
615     {
616         jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket);
617         if (!jni_str_address)
618         {
619             OIC_LOG(ERROR, TAG, "jni_str_address is null");
620             goto exit;
621         }
622
623         const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL);
624         if (!address)
625         {
626             OIC_LOG(ERROR, TAG, "address is null");
627             (*env)->DeleteLocalRef(env, jni_str_address);
628             goto exit;
629         }
630
631         OIC_LOG_V(DEBUG, TAG, "get InputStream..%d, %s", id, address);
632         jmethodID jni_mid_read = (*env)->GetMethodID(env, jni_cid_InputStream,
633                                                      "read", "([BII)I");
634         if (!jni_mid_read)
635         {
636             OIC_LOG(ERROR, TAG, "jni_mid_read is null");
637             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
638             (*env)->DeleteLocalRef(env, jni_str_address);
639             goto exit;
640         }
641
642         deviceInfo = (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address);
643         if (!deviceInfo)
644         {
645             OIC_LOG(ERROR, TAG, "failed to get device info from list");
646             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
647             (*env)->DeleteLocalRef(env, jni_str_address);
648             goto exit;
649         }
650
651         jint bufSize = (deviceInfo->totalDataLen == 0) ?
652                 EDR_MAX_HEADER_LEN : deviceInfo->totalDataLen;
653         if (!deviceInfo->recvData)
654         {
655             deviceInfo->recvData = OICCalloc(1, bufSize);
656             if (!deviceInfo->recvData)
657             {
658                 OIC_LOG(ERROR, TAG, "out of memory");
659                 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
660                 (*env)->DeleteLocalRef(env, jni_str_address);
661                 goto exit;
662             }
663         }
664
665         jbyteArray jbuf = (*env)->NewByteArray(env, (jint) bufSize - deviceInfo->recvDataLen);
666         if (!jbuf)
667         {
668             OIC_LOG(ERROR, TAG, "jbuf is null");
669             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
670             (*env)->DeleteLocalRef(env, jni_str_address);
671             goto exit;
672         }
673
674         jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read,
675                                              jbuf, (jint) 0,
676                                              (jint) bufSize - deviceInfo->recvDataLen);
677         if (-1 == recvLen)
678         {
679             OIC_LOG(ERROR, TAG, "recvLen is -1");
680             (*env)->DeleteLocalRef(env, jbuf);
681             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
682             (*env)->DeleteLocalRef(env, jni_str_address);
683             goto exit;
684         }
685
686         jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
687         if (!buf)
688         {
689             OIC_LOG(ERROR, TAG, "buf is null");
690             (*env)->DeleteLocalRef(env, jbuf);
691             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
692             (*env)->DeleteLocalRef(env, jni_str_address);
693             goto exit;
694         }
695         memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen);
696         deviceInfo->recvDataLen += recvLen;
697
698         OIC_LOG(DEBUG, TAG, "read something from InputStream");
699
700         if (!deviceInfo->totalDataLen)
701         {
702             coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
703                     ((unsigned char *) deviceInfo->recvData)[0] >> 4);
704             size_t headerLen = coap_get_tcp_header_length_for_transport(transport);
705             if (deviceInfo->recvData && deviceInfo->recvDataLen >= headerLen)
706             {
707                 deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData,
708                                                                          deviceInfo->recvDataLen);
709                 OIC_LOG_V(DEBUG, TAG, "total data length [%d] bytes", deviceInfo->totalDataLen);
710
711                 uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen);
712                 if (!newBuf)
713                 {
714                     OIC_LOG(ERROR, TAG, "out of memory");
715                     (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
716                     (*env)->DeleteLocalRef(env, jbuf);
717                     (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
718                     (*env)->DeleteLocalRef(env, jni_str_address);
719                     goto exit;
720                 }
721                 deviceInfo->recvData = newBuf;
722             }
723         }
724
725         if (deviceInfo->totalDataLen == deviceInfo->recvDataLen)
726         {
727             if ((*env)->ExceptionCheck(env))
728             {
729                 OIC_LOG(ERROR, TAG, "read Error!!!");
730                 (*env)->ExceptionDescribe(env);
731                 (*env)->ExceptionClear(env);
732
733                 // update state to disconnect
734                 // the socket will be close next read thread routine
735                 ca_mutex_lock(g_mutexStateList);
736                 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
737                 ca_mutex_unlock(g_mutexStateList);
738
739                 (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
740                 (*env)->DeleteLocalRef(env, jbuf);
741                 (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
742                 (*env)->DeleteLocalRef(env, jni_str_address);
743                 goto exit;
744             }
745
746             if (g_edrPacketReceivedCallback)
747             {
748                 OIC_LOG_V(DEBUG, TAG,"data will be sent to callback routine: \
749                           %s, %d", deviceInfo->recvData, deviceInfo->recvDataLen);
750
751                 uint32_t sentLength = 0;
752                 g_edrPacketReceivedCallback(address, (void*) deviceInfo->recvData,
753                                             deviceInfo->recvDataLen, &sentLength);
754
755                 OICFree(deviceInfo->recvData);
756                 deviceInfo->recvData = NULL;
757                 deviceInfo->recvDataLen = 0;
758                 deviceInfo->totalDataLen = 0;
759             }
760         }
761         (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
762         (*env)->DeleteLocalRef(env, jbuf);
763         (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
764         (*env)->DeleteLocalRef(env, jni_str_address);
765     }
766     (*env)->DeleteLocalRef(env, jni_cid_InputStream);
767     (*env)->DeleteLocalRef(env, jni_obj_inputStream);
768
769     return CA_STATUS_OK;
770
771 exit:
772     (*env)->DeleteLocalRef(env, jni_cid_InputStream);
773     (*env)->DeleteLocalRef(env, jni_obj_inputStream);
774
775     return CA_STATUS_FAILED;
776 }
777
778 void CANativeStartListenTask(JNIEnv *env)
779 {
780     jobject jni_obj_BTServerSocket = CAEDRNativeListen(env);
781     if (!jni_obj_BTServerSocket)
782     {
783         OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
784         return;
785     }
786
787     ca_mutex_lock(g_mutexServerSocket);
788     g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
789     ca_mutex_unlock(g_mutexServerSocket);
790 }
791
792 jobject CAEDRNativeListen(JNIEnv *env)
793 {
794     OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - IN");
795
796     if (!CAEDRNativeIsEnableBTAdapter(env))
797     {
798         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
799         return NULL;
800     }
801
802     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
803     if (!jni_cid_BTAdapter)
804     {
805         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
806         return NULL;
807     }
808
809     // get BTadpater
810     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
811                                                                     "getDefaultAdapter",
812                                                                     METHODID_OBJECTNONPARAM);
813     if (!jni_mid_getDefaultAdapter)
814     {
815         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
816         return NULL;
817     }
818
819     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
820                                                                jni_mid_getDefaultAdapter);
821     if (!jni_obj_BTAdapter)
822     {
823         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
824         return NULL;
825     }
826
827     // get listen method ID
828     jmethodID jni_mid_listen = (*env)->GetMethodID(
829             env, jni_cid_BTAdapter, "listenUsingInsecureRfcommWithServiceRecord",
830             "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;");
831     if (!jni_mid_listen)
832     {
833         OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
834         return NULL;
835     }
836     // listenUsingInsecureRfcommWithServiceRecord  / listenUsingRfcommWithServiceRecord
837     // setting UUID
838     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
839     if (!jni_cid_uuid)
840     {
841         OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
842         return NULL;
843     }
844
845     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
846             env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
847     if (!jni_mid_fromString)
848     {
849         OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
850         return NULL;
851     }
852
853     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
854     if (!jni_uuid)
855     {
856         OIC_LOG(ERROR, TAG, "jni_uuid is null");
857         return NULL;
858     }
859     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
860                                                           jni_uuid);
861     if (!jni_obj_uuid)
862     {
863         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
864         return NULL;
865     }
866
867     // create socket
868     jstring jni_name = (*env)->NewStringUTF(env, "BluetoothTestSecure");
869     if (!jni_name)
870     {
871         OIC_LOG(ERROR, TAG, "jni_name is null");
872         return NULL;
873     }
874     jobject jni_obj_BTServerSocket = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_listen,
875                                                              jni_name, jni_obj_uuid);
876     if (!jni_obj_BTServerSocket)
877     {
878         OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
879         return NULL;
880     }
881
882     g_serverSocketObject = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
883
884     OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - OUT");
885
886     return jni_obj_BTServerSocket;
887 }
888
889 void CAEDRNativeAccept(JNIEnv *env, jobject serverSocketObject)
890 {
891     OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - IN");
892
893     if (NULL != serverSocketObject)
894     {
895         jmethodID jni_mid_accept = CAGetJNIMethodID(env, CLASSPATH_BT_SERVER_SOCKET,
896                                                     "accept",
897                                                     "()Landroid/bluetooth/BluetoothSocket;");
898         if (!jni_mid_accept)
899         {
900             OIC_LOG(ERROR, TAG, "jni_mid_accept is null");
901             return;
902         }
903
904         OIC_LOG(DEBUG, TAG, "waiting for the new connection request...");
905
906         jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, serverSocketObject,
907                                                             jni_mid_accept);
908         if (!jni_obj_BTSocket)
909         {
910             OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
911
912             if ((*env)->ExceptionCheck(env))
913             {
914                 OIC_LOG(ERROR, TAG, "socket might closed or timeout!!!");
915                 (*env)->ExceptionDescribe(env);
916                 (*env)->ExceptionClear(env);
917                 return;
918             }
919         }
920
921         // get remote address
922         jstring j_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_BTSocket);
923         if (!j_str_address)
924         {
925             OIC_LOG(ERROR, TAG, "j_str_address is null");
926             return;
927         }
928
929         const char* address = (*env)->GetStringUTFChars(env, j_str_address, NULL);
930         OIC_LOG_V(DEBUG, TAG, "received the connection request from [%s]", address);
931
932         // set socket to list
933         jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
934         ca_mutex_lock(g_mutexObjectList);
935         CAEDRNativeAddDeviceSocketToList(env, jni_socket);
936         ca_mutex_unlock(g_mutexObjectList);
937
938         // update state
939         ca_mutex_lock(g_mutexStateList);
940         CAEDRUpdateDeviceState(STATE_CONNECTED, address);
941         ca_mutex_unlock(g_mutexStateList);
942
943         (*env)->ReleaseStringUTFChars(env, j_str_address, address);
944         (*env)->DeleteLocalRef(env, j_str_address);
945
946         OIC_LOG_V(DEBUG, TAG, "connected with [%s]", address);
947     }
948     else
949     {
950         OIC_LOG(DEBUG, TAG, "serverSocket is close previously");
951     }
952
953     OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - OUT");
954 }
955
956 /**
957  * InputStream & BluetoothServerSocket will be close for Terminating.
958  */
959 void CAEDRNatvieCloseServerTask(JNIEnv* env)
960 {
961     if (g_serverSocket)
962     {
963         OIC_LOG(DEBUG, TAG, "Accept Resource will be close");
964
965         jmethodID jni_mid_close = CAGetJNIMethodID(env, CLASSPATH_BT_SERVER_SOCKET,
966                                                    "close", "()V");
967         if (!jni_mid_close)
968         {
969             OIC_LOG(ERROR, TAG, "jni_mid_close is null");
970             return;
971         }
972
973         (*env)->CallVoidMethod(env, g_serverSocket, jni_mid_close);
974         (*env)->DeleteGlobalRef(env, g_serverSocket);
975         g_serverSocket = NULL;
976
977         OIC_LOG(DEBUG, TAG, "close accept obj");
978     }
979 }