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