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