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