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