removed buffer size defined previously in android edr server
[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     jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket);
658     if (!jni_str_address)
659     {
660         OIC_LOG(ERROR, TAG, "jni_str_address is null");
661         return CA_STATUS_FAILED;
662     }
663     const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL);
664
665     // check it whether is still connected or not through google api
666     jboolean ret = CAEDRIsConnectedForSocket(env, jni_obj_socket);
667     if (!ret)
668     {
669         OIC_LOG(ERROR, TAG, "it is not connected yet.");
670
671         // remove socket to list
672         CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
673         (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
674         (*env)->DeleteLocalRef(env, jni_str_address);
675
676         return CA_STATUS_FAILED;
677     }
678
679     // start to read through InputStream
680     jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
681     if (!jni_cid_BTsocket)
682     {
683         OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
684         (*env)->DeleteLocalRef(env, jni_str_address);
685         return CA_STATUS_FAILED;
686     }
687     jmethodID jni_mid_getInputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
688                                                            "getInputStream",
689                                                            "()Ljava/io/InputStream;");
690
691     jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
692                                                            jni_mid_getInputStream);
693     if (!jni_obj_inputStream)
694     {
695         OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null");
696         (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
697         (*env)->DeleteLocalRef(env, jni_str_address);
698         return CA_STATUS_FAILED;
699     }
700
701     jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
702     if (!jni_cid_InputStream)
703     {
704         OIC_LOG(ERROR, TAG, "jni_cid_InputStream is null");
705         goto exit;
706     }
707
708     jmethodID jni_mid_available = (*env)->GetMethodID(env, jni_cid_InputStream,
709                                                       "available", "()I");
710     if (!jni_mid_available)
711     {
712         OIC_LOG(ERROR, TAG, "jni_mid_available is null");
713         goto exit;
714     }
715
716     jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available);
717
718     CAConnectedDeviceInfo_t *deviceInfo = NULL;
719     if (0 < available)
720     {
721         OIC_LOG_V(DEBUG, TAG, "get InputStream..%d, %s", id, address);
722         jmethodID jni_mid_read = (*env)->GetMethodID(env, jni_cid_InputStream,
723                                                      "read", "([BII)I");
724         if (!jni_mid_read)
725         {
726             OIC_LOG(ERROR, TAG, "jni_mid_read is null");
727             goto exit;
728         }
729
730         deviceInfo = (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address);
731         if (!deviceInfo)
732         {
733             OIC_LOG(ERROR, TAG, "failed to get device info from list");
734             goto exit;
735         }
736
737         jint bufSize = (deviceInfo->totalDataLen == 0) ?
738                 EDR_MAX_HEADER_LEN : deviceInfo->totalDataLen;
739         if (!deviceInfo->recvData)
740         {
741             deviceInfo->recvData = OICCalloc(1, bufSize);
742             if (!deviceInfo->recvData)
743             {
744                 OIC_LOG(ERROR, TAG, "out of memory");
745                 goto exit;
746             }
747         }
748
749         jbyteArray jbuf = (*env)->NewByteArray(env, (jint) bufSize - deviceInfo->recvDataLen);
750         jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read,
751                                              jbuf, (jint) 0,
752                                              (jint) bufSize - deviceInfo->recvDataLen);
753         if (-1 == recvLen)
754         {
755             (*env)->DeleteLocalRef(env, jbuf);
756             goto exit;
757         }
758
759         jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
760         if (!buf)
761         {
762             (*env)->DeleteLocalRef(env, jbuf);
763             goto exit;
764         }
765         memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen);
766         deviceInfo->recvDataLen += recvLen;
767
768         OIC_LOG(DEBUG, TAG, "read something from InputStream");
769
770         if (!deviceInfo->totalDataLen)
771         {
772             coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
773                     ((unsigned char *) deviceInfo->recvData)[0] >> 4);
774             size_t headerLen = coap_get_tcp_header_length_for_transport(transport);
775             if (deviceInfo->recvData && deviceInfo->recvDataLen >= headerLen)
776             {
777                 deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData,
778                                                                          deviceInfo->recvDataLen);
779                 OIC_LOG_V(DEBUG, TAG, "total data length [%d] bytes", deviceInfo->totalDataLen);
780
781                 uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen);
782                 if (!newBuf)
783                 {
784                     OIC_LOG(ERROR, TAG, "out of memory");
785                     (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
786                     (*env)->DeleteLocalRef(env, jbuf);
787                     goto exit;
788                 }
789                 deviceInfo->recvData = newBuf;
790             }
791         }
792
793         if (deviceInfo->totalDataLen == deviceInfo->recvDataLen)
794         {
795             if ((*env)->ExceptionCheck(env))
796             {
797                 OIC_LOG(ERROR, TAG, "read Error!!!");
798                 (*env)->ExceptionDescribe(env);
799                 (*env)->ExceptionClear(env);
800
801                 // update state to disconnect
802                 // the socket will be close next read thread routine
803                 ca_mutex_lock(g_mutexStateList);
804                 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
805                 ca_mutex_unlock(g_mutexStateList);
806
807                 (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
808                 (*env)->DeleteLocalRef(env, jbuf);
809                 goto exit;
810             }
811
812             if (g_edrPacketReceivedCallback)
813             {
814                 OIC_LOG_V(DEBUG, TAG,"data will be sent to callback routine: \
815                           %s, %d", deviceInfo->recvData, deviceInfo->recvDataLen);
816
817                 uint32_t sentLength = 0;
818                 g_edrPacketReceivedCallback(address, (void*) deviceInfo->recvData,
819                                             deviceInfo->recvDataLen, &sentLength);
820
821                 OICFree(deviceInfo->recvData);
822                 deviceInfo->recvData = NULL;
823                 deviceInfo->recvDataLen = 0;
824                 deviceInfo->totalDataLen = 0;
825             }
826         }
827         (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
828         (*env)->DeleteLocalRef(env, jbuf);
829     }
830     (*env)->DeleteLocalRef(env, jni_obj_inputStream);
831     (*env)->DeleteLocalRef(env, jni_cid_InputStream);
832     (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
833     (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
834     (*env)->DeleteLocalRef(env, jni_str_address);
835
836     return CA_STATUS_OK;
837
838 exit:
839     (*env)->DeleteLocalRef(env, jni_obj_inputStream);
840     (*env)->DeleteLocalRef(env, jni_cid_InputStream);
841     (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
842     (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
843     (*env)->DeleteLocalRef(env, jni_str_address);
844
845     return CA_STATUS_FAILED;
846 }
847
848 jboolean CAEDRIsConnectedForSocket(JNIEnv *env, jobject socket)
849 {
850     if (!socket)
851     {
852         OIC_LOG(ERROR, TAG, "socket is null");
853         return JNI_FALSE;
854     }
855
856     jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
857     if (!jni_cid_BTsocket)
858     {
859         OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
860         return JNI_FALSE;
861     }
862
863     jmethodID jni_mid_isConnected = (*env)->GetMethodID(env, jni_cid_BTsocket, "isConnected",
864                                                         "()Z");
865     if (!jni_mid_isConnected)
866     {
867         OIC_LOG(ERROR, TAG, "jni_mid_isConnected is null.");
868         (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
869         return JNI_FALSE;
870     }
871
872     jboolean jni_isConnected = (*env)->CallBooleanMethod(env, socket, jni_mid_isConnected);
873
874     (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
875
876     return jni_isConnected;
877 }
878
879 void CANativeStartListenTask(JNIEnv *env)
880 {
881     jobject jni_obj_BTServerSocket = CAEDRNativeListen(env);
882     if (!jni_obj_BTServerSocket)
883     {
884         OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
885         return;
886     }
887
888     ca_mutex_lock(g_mutexServerSocket);
889     g_serverSocket = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
890     ca_mutex_unlock(g_mutexServerSocket);
891 }
892
893 jobject CAEDRNativeListen(JNIEnv *env)
894 {
895     OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - IN");
896
897     if (!CAEDRNativeIsEnableBTAdapter(env))
898     {
899         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
900         return NULL;
901     }
902
903     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
904     if (!jni_cid_BTAdapter)
905     {
906         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
907         return NULL;
908     }
909
910     // get BTadpater
911     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
912                                                                     "getDefaultAdapter",
913                                                                     METHODID_OBJECTNONPARAM);
914     if (!jni_mid_getDefaultAdapter)
915     {
916         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
917         return NULL;
918     }
919
920     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
921                                                                jni_mid_getDefaultAdapter);
922     if (!jni_obj_BTAdapter)
923     {
924         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
925         return NULL;
926     }
927
928     // get listen method ID
929     jmethodID jni_mid_listen = (*env)->GetMethodID(
930             env, jni_cid_BTAdapter, "listenUsingInsecureRfcommWithServiceRecord",
931             "(Ljava/lang/String;Ljava/util/UUID;)Landroid/bluetooth/BluetoothServerSocket;");
932     if (!jni_mid_listen)
933     {
934         OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
935         return NULL;
936     }
937     // listenUsingInsecureRfcommWithServiceRecord  / listenUsingRfcommWithServiceRecord
938     // setting UUID
939     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
940     if (!jni_cid_uuid)
941     {
942         OIC_LOG(ERROR, TAG, "jni_mid_listen is null");
943         return NULL;
944     }
945
946     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
947             env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
948     if (!jni_mid_fromString)
949     {
950         OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
951         return NULL;
952     }
953
954     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
955     if (!jni_uuid)
956     {
957         OIC_LOG(ERROR, TAG, "jni_uuid is null");
958         return NULL;
959     }
960     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
961                                                           jni_uuid);
962     if (!jni_obj_uuid)
963     {
964         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
965         return NULL;
966     }
967
968     // create socket
969     jstring jni_name = (*env)->NewStringUTF(env, "BluetoothTestSecure");
970     if (!jni_name)
971     {
972         OIC_LOG(ERROR, TAG, "jni_name is null");
973         return NULL;
974     }
975     jobject jni_obj_BTServerSocket = (*env)->CallObjectMethod(env, jni_obj_BTAdapter, jni_mid_listen,
976                                                              jni_name, jni_obj_uuid);
977     if (!jni_obj_BTServerSocket)
978     {
979         OIC_LOG(ERROR, TAG, "jni_obj_BTServerSocket is null");
980         return NULL;
981     }
982
983     g_serverSocketObject = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
984
985     OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - OUT");
986
987     return jni_obj_BTServerSocket;
988 }
989
990 void CAEDRNativeAccept(JNIEnv *env, jobject serverSocketObject)
991 {
992     OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - IN");
993
994     if (NULL != serverSocketObject)
995     {
996         jclass jni_cid_BTServerSocket = (*env)->FindClass(
997                 env, "android/bluetooth/BluetoothServerSocket");
998         if (!jni_cid_BTServerSocket)
999         {
1000             OIC_LOG(ERROR, TAG, "jni_cid_BTServerSocket is null");
1001             return;
1002         }
1003
1004         jmethodID jni_mid_accept = (*env)->GetMethodID(env, jni_cid_BTServerSocket, "accept",
1005                                                        "()Landroid/bluetooth/BluetoothSocket;");
1006         if (!jni_mid_accept)
1007         {
1008             OIC_LOG(ERROR, TAG, "jni_mid_accept is null");
1009             return;
1010         }
1011
1012         OIC_LOG(DEBUG, TAG, "initiating accept...");
1013
1014         jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, serverSocketObject,
1015                                                             jni_mid_accept);
1016         if (!jni_obj_BTSocket)
1017         {
1018             OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1019
1020             if ((*env)->ExceptionCheck(env))
1021             {
1022                 OIC_LOG(ERROR, TAG, "socket might closed or timeout!!!");
1023                 (*env)->ExceptionDescribe(env);
1024                 (*env)->ExceptionClear(env);
1025                 return;
1026             }
1027         }
1028
1029         // get remote address
1030         jstring j_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_BTSocket);
1031         if (!j_str_address)
1032         {
1033             OIC_LOG(ERROR, TAG, "j_str_address is null");
1034             return;
1035         }
1036
1037         const char* address = (*env)->GetStringUTFChars(env, j_str_address, NULL);
1038         OIC_LOG_V(DEBUG, TAG, "address is %s", address);
1039
1040         // set socket to list
1041         jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1042         ca_mutex_lock(g_mutexObjectList);
1043         CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1044         ca_mutex_unlock(g_mutexObjectList);
1045
1046         OIC_LOG(DEBUG, TAG, "Accepted!!");
1047
1048         // update state
1049         ca_mutex_lock(g_mutexStateList);
1050         CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1051         ca_mutex_unlock(g_mutexStateList);
1052
1053         (*env)->ReleaseStringUTFChars(env, j_str_address, address);
1054         (*env)->DeleteLocalRef(env, j_str_address);
1055     }
1056     else
1057     {
1058         OIC_LOG(DEBUG, TAG, "serverSocket is close previously");
1059     }
1060
1061     OIC_LOG(DEBUG, TAG, "CAEDRNativeAccept - OUT");
1062 }
1063
1064 /**
1065  * InputStream & BluetoothServerSocket will be close for Terminating.
1066  */
1067 void CAEDRNatvieCloseServerTask(JNIEnv* env)
1068 {
1069     if (g_serverSocket)
1070     {
1071         OIC_LOG(DEBUG, TAG, "Accept Resource will be close");
1072
1073         jclass jni_cid_BTServerSocket = (*env)->FindClass(
1074                 env, "android/bluetooth/BluetoothServerSocket");
1075         if (!jni_cid_BTServerSocket)
1076         {
1077             OIC_LOG(ERROR, TAG, "jni_cid_BTServerSocket is null");
1078             return;
1079         }
1080
1081         jmethodID jni_mid_accept = (*env)->GetMethodID(env, jni_cid_BTServerSocket, "close", "()V");
1082         if (!jni_mid_accept)
1083         {
1084             OIC_LOG(ERROR, TAG, "jni_mid_accept is null");
1085             return;
1086         }
1087         (*env)->CallVoidMethod(env, g_serverSocket, jni_mid_accept);
1088         (*env)->DeleteGlobalRef(env, g_serverSocket);
1089         g_serverSocket = NULL;
1090
1091         OIC_LOG(DEBUG, TAG, "close accept obj");
1092     }
1093 }