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