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