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