Replace/examine usages of mem* and strcat/strcpy
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_edr_adapter / android / caedrclient.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 "caedrclient.h"
28 #include "logger.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "cathreadpool.h" /* for thread pool */
32 #include "camutex.h"
33 #include "uarraylist.h"
34 #include "caadapterutils.h"
35
36 //#define DEBUG_MODE
37 #define TAG PCF("CA_EDR_CLIENT")
38
39 static const char METHODID_CONTEXTNONPARAM[] = "()Landroid/content/Context;";
40 static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAdapter;";
41 static const char METHODID_OUTPUTNONPARAM[] = "()Ljava/io/OutputStream;";
42 static const char METHODID_STRINGNONPARAM[] = "()Ljava/lang/String;";
43 static const char METHODID_BT_DEVICEPARAM[] =
44         "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;";
45 static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter";
46 static const char CLASSPATH_BT_DEVICE[] = "android/bluetooth/BluetoothDevice";
47 static const char CLASSPATH_BT_INTERFACE[] = "org/iotivity/ca/CaEdrInterface";
48 static const char CLASSPATH_BT_SOCKET[] = "android/bluetooth/BluetoothSocket";
49 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
50 static const char CLASSPATH_CONTEXT[] = "android/content/Context";
51 static const char CLASSPATH_OUTPUT[] = "java/io/OutputStream";
52
53 static ca_thread_pool_t g_threadPoolHandle = NULL;
54
55 static JavaVM *g_jvm;
56 static jobject g_context;
57
58 /**
59  * @var g_mutexUnicastServer
60  * @brief Mutex to synchronize unicast server
61  */
62 static ca_mutex g_mutexUnicastServer = NULL;
63
64 /**
65  * @var g_stopUnicast
66  * @brief Flag to control the Receive Unicast Data Thread
67  */
68 static bool g_stopUnicast = false;
69
70 /**
71  * @var g_mutexMulticastServer
72  * @brief Mutex to synchronize secure multicast server
73  */
74 static ca_mutex g_mutexMulticastServer = NULL;
75
76 /**
77  * @var g_stopMulticast
78  * @brief Flag to control the Receive Multicast Data Thread
79  */
80 static bool g_stopMulticast = false;
81
82 /**
83  * @var g_stopAccept
84  * @brief Flag to control the Accept Thread
85  */
86 static bool g_stopAccept = false;
87
88 /**
89  * @var g_mutexStateList
90  * @brief Mutex to synchronize device state list
91  */
92 static ca_mutex g_mutexStateList = NULL;
93
94 /**
95  * @var g_mutexObjectList
96  * @brief Mutex to synchronize device object list
97  */
98 static ca_mutex g_mutexObjectList = NULL;
99
100 typedef struct send_data
101 {
102     char* address;
103     char* data;
104     uint32_t id;
105 } data_t;
106
107 /**
108  @brief 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  * implement for BT-EDR adapter common method
123  */
124 CAResult_t CAEDRGetInterfaceInformation(CALocalConnectivity_t **info)
125 {
126     OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
127
128     if (!info)
129     {
130         OIC_LOG(ERROR, TAG, "LocalConnectivity info is null");
131         return CA_STATUS_FAILED;
132     }
133
134     int32_t netInfoSize = 1;
135
136     char *macAddress = NULL;
137     CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
138     OIC_LOG_V(ERROR, TAG, "address : %s", macAddress);
139     if (NULL == macAddress)
140     {
141         OIC_LOG(ERROR, TAG, "mac address is null");
142
143         return CA_STATUS_FAILED;
144     }
145     if (CA_STATUS_OK != ret)
146     {
147         OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
148
149         OICFree(macAddress);
150         return ret;
151     }
152
153     // Create local endpoint using util function
154     CALocalConnectivity_t *endpoint = CAAdapterCreateLocalEndpoint(CA_EDR, macAddress);
155     if (NULL == endpoint)
156     {
157         OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
158         OICFree(macAddress);
159         return CA_STATUS_FAILED;
160     }
161
162     // copy unicast server information
163     endpoint->isSecured = false;
164     CALocalConnectivity_t *netInfo = (CALocalConnectivity_t *) OICMalloc(
165             sizeof(CALocalConnectivity_t) * netInfoSize);
166     if (NULL == netInfo)
167     {
168         OIC_LOG(ERROR, TAG, "Invalid input..");
169         OICFree(macAddress);
170         CAAdapterFreeLocalEndpoint(endpoint);
171         return CA_MEMORY_ALLOC_FAILED;
172     }
173     memcpy(netInfo, endpoint, sizeof(CALocalConnectivity_t));
174     *info = netInfo;
175
176     OICFree(macAddress);
177     CAAdapterFreeLocalEndpoint(endpoint);
178
179     OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
180     return CA_STATUS_OK;
181 }
182
183 void CAEDRClientTerminate()
184 {
185     OIC_LOG(DEBUG, TAG, "IN");
186     CAEDRTerminate();
187     OIC_LOG(DEBUG, TAG, "OUT");
188 }
189
190 CAResult_t CAEDRManagerReadData(void)
191 {
192     OIC_LOG(DEBUG, TAG, "IN");
193
194     OIC_LOG(DEBUG, TAG, "OUT");
195     return CA_NOT_SUPPORTED;
196 }
197
198 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const char *serviceUUID,
199                                       const void *data, uint32_t dataLength, uint32_t *sentLength)
200 {
201     OIC_LOG(DEBUG, TAG, "IN");
202     CAEDRSendUnicastMessage(remoteAddress, (const char*) data, dataLength);
203     OIC_LOG(DEBUG, TAG, "OUT");
204     return CA_STATUS_OK;
205 }
206
207 CAResult_t CAEDRClientSendMulticastData(const char *serviceUUID, const void *data,
208                                         uint32_t dataLength, uint32_t *sentLength)
209 {
210     OIC_LOG(DEBUG, TAG, "IN");
211     CAEDRSendMulticastMessage((const char*) data, dataLength);
212     OIC_LOG(DEBUG, TAG, "OUT");
213     return CA_STATUS_OK;
214 }
215
216 // It will be updated when android EDR support is added
217 void CAEDRClientUnsetCallbacks(void)
218 {
219     OIC_LOG(DEBUG, TAG, "IN");
220
221     OIC_LOG(DEBUG, TAG, "OUT");
222 }
223
224 // It will be updated when android EDR support is added
225 void CAEDRClientDisconnectAll(void)
226 {
227     OIC_LOG(DEBUG, TAG, "IN");
228
229     OIC_LOG(DEBUG, TAG, "OUT");
230 }
231
232 CAResult_t CAEDRGetAdapterEnableState(bool *state)
233 {
234     OIC_LOG(DEBUG, TAG, "IN");
235     if (!g_jvm)
236     {
237         OIC_LOG(ERROR, TAG, "g_jvm is null");
238         return CA_STATUS_INVALID_PARAM;
239     }
240     bool isAttached = false;
241     JNIEnv* env;
242     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
243     if (JNI_OK != res)
244     {
245         OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
246         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
247
248         if (JNI_OK != res)
249         {
250             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
251             return CA_STATUS_INVALID_PARAM;
252         }
253         isAttached = true;
254     }
255     jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
256     if (ret)
257     {
258         *state = true;
259     }
260     else
261     {
262         *state = false;
263     }
264
265     if (isAttached)
266     {
267         (*g_jvm)->DetachCurrentThread(g_jvm);
268     }
269
270     OIC_LOG(DEBUG, TAG, "OUT");
271     return CA_STATUS_OK;
272 }
273
274 void CAEDRJniInitContext()
275 {
276     OIC_LOG(DEBUG, TAG, "CAEDRJniInitContext");
277
278     g_context = (jobject) CANativeJNIGetContext();
279 }
280
281 CAResult_t CAEDRCreateJNIInterfaceObject(jobject context)
282 {
283     JNIEnv* env;
284     OIC_LOG(DEBUG, TAG, "[EDRCore] CAEDRCreateJNIInterfaceObject");
285
286     if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
287     {
288         OIC_LOG(ERROR, TAG, "[EDRCore] Could not get JNIEnv pointer");
289         return CA_STATUS_FAILED;
290     }
291
292     //getApplicationContext
293     jclass contextClass = (*env)->FindClass(env, CLASSPATH_CONTEXT);
294     if (!contextClass)
295     {
296         OIC_LOG(ERROR, TAG, "[EDRCore] Could not get context object class");
297         return CA_STATUS_FAILED;
298     }
299
300     jmethodID getApplicationContextMethod = (*env)->GetMethodID(env, contextClass,
301                                                                 "getApplicationContext",
302                                                                 METHODID_CONTEXTNONPARAM);
303     if (!getApplicationContextMethod)
304     {
305         OIC_LOG(ERROR, TAG, "[EDRCore] Could not get getApplicationContext method");
306         return CA_STATUS_FAILED;
307     }
308
309     //Create EDRJniInterface instance
310     jclass EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
311     if (!EDRJniInterface)
312     {
313         OIC_LOG(ERROR, TAG, "[EDRCore] Could not get CaEdrInterface class");
314         return CA_STATUS_FAILED;
315     }
316
317     jmethodID EDRInterfaceConstructorMethod = (*env)->GetMethodID(env, EDRJniInterface, "<init>",
318                                                                   "(Landroid/content/Context;)V");
319     if (!EDRInterfaceConstructorMethod)
320     {
321         OIC_LOG(ERROR, TAG, "[EDRCore] Could not get CaEdrInterface constructor method");
322         return CA_STATUS_FAILED;
323     }
324
325     (*env)->NewObject(env, EDRJniInterface, EDRInterfaceConstructorMethod, context);
326     OIC_LOG(DEBUG, TAG, "[EDRCore] NewObject Success");
327
328     return CA_STATUS_OK;
329
330 }
331
332 static void CAEDRDestroyMutex()
333 {
334     OIC_LOG(DEBUG, TAG, "IN");
335
336     if (g_mutexUnicastServer)
337     {
338         ca_mutex_free(g_mutexUnicastServer);
339         g_mutexUnicastServer = NULL;
340     }
341
342     if (g_mutexMulticastServer)
343     {
344         ca_mutex_free(g_mutexMulticastServer);
345         g_mutexMulticastServer = NULL;
346     }
347
348     if (g_mutexStateList)
349     {
350         ca_mutex_free(g_mutexStateList);
351         g_mutexStateList = NULL;
352     }
353
354     if (g_mutexObjectList)
355     {
356         ca_mutex_free(g_mutexObjectList);
357         g_mutexObjectList = NULL;
358     }
359     OIC_LOG(DEBUG, TAG, "OUT");
360 }
361
362 static CAResult_t CAEDRCreateMutex()
363 {
364     OIC_LOG(DEBUG, TAG, "IN");
365
366     g_mutexUnicastServer = ca_mutex_new();
367     if (!g_mutexUnicastServer)
368     {
369         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
370         return CA_STATUS_FAILED;
371     }
372
373     g_mutexMulticastServer = ca_mutex_new();
374     if (!g_mutexMulticastServer)
375     {
376         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
377
378         CAEDRDestroyMutex();
379         return CA_STATUS_FAILED;
380     }
381
382     g_mutexStateList = ca_mutex_new();
383     if (!g_mutexStateList)
384     {
385         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
386
387         CAEDRDestroyMutex();
388         return CA_STATUS_FAILED;
389     }
390
391     g_mutexObjectList = ca_mutex_new();
392     if (!g_mutexObjectList)
393     {
394         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
395
396         CAEDRDestroyMutex();
397         return CA_STATUS_FAILED;
398     }
399
400     OIC_LOG(DEBUG, TAG, "OUT");
401     return CA_STATUS_OK;
402 }
403
404 void CAEDRInitialize(ca_thread_pool_t handle)
405 {
406     OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
407
408     g_threadPoolHandle = handle;
409
410     CAEDRCoreJniInit();
411
412     CAEDRJniInitContext();
413
414     // init mutex
415     CAEDRCreateMutex();
416
417     bool isAttached = false;
418     JNIEnv* env;
419     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
420     if (JNI_OK != res)
421     {
422         OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
423         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
424
425         if (JNI_OK != res)
426         {
427             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
428             return;
429         }
430         isAttached = true;
431     }
432     jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
433     if (jni_address)
434     {
435         const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
436         OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
437         (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
438     }
439
440     ca_mutex_lock(g_mutexStateList);
441     CAEDRNativeCreateDeviceStateList();
442     ca_mutex_unlock(g_mutexStateList);
443
444     ca_mutex_lock(g_mutexObjectList);
445     CAEDRNativeCreateDeviceSocketList();
446     ca_mutex_unlock(g_mutexObjectList);
447
448     if (isAttached)
449     {
450         (*g_jvm)->DetachCurrentThread(g_jvm);
451     }
452
453     if (g_context)
454     {
455         CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
456     }
457
458     OIC_LOG(DEBUG, TAG, "OUT");
459 }
460
461 void CAEDRTerminate()
462 {
463     OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
464
465     bool isAttached = false;
466     JNIEnv* env;
467     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
468     if (JNI_OK != res)
469     {
470         OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
471         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
472
473         if (JNI_OK != res)
474         {
475             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
476             return;
477         }
478         isAttached = true;
479     }
480
481     g_stopAccept = true;
482     g_stopMulticast = true;
483     g_stopUnicast = true;
484
485     if (isAttached)
486     {
487         (*g_jvm)->DetachCurrentThread(g_jvm);
488     }
489
490     if (g_context)
491     {
492         (*env)->DeleteGlobalRef(env, g_context);
493     }
494
495     CAEDRNativeSocketCloseToAll(env);
496
497     // delete mutex
498     CAEDRDestroyMutex();
499
500     CAEDRNativeRemoveAllDeviceState();
501     CAEDRNativeRemoveAllDeviceSocket(env);
502 }
503
504 void CAEDRCoreJniInit()
505 {
506     OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
507     g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
508 }
509
510 CAResult_t CAEDRSendUnicastMessage(const char* address, const char* data, uint32_t dataLen)
511 {
512     OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessage(%s, %s)", address, data);
513
514     CAEDRSendUnicastMessageImpl(address, data, dataLen);
515     return CA_STATUS_OK;
516 }
517
518 CAResult_t CAEDRSendMulticastMessage(const char* data, uint32_t dataLen)
519 {
520     OIC_LOG_V(DEBUG, TAG, "CAEDRSendMulticastMessage(%s)", data);
521
522     bool isAttached = false;
523     JNIEnv* env;
524     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
525     if (JNI_OK != res)
526     {
527         OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
528         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
529
530         if (JNI_OK != res)
531         {
532             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
533             return CA_STATUS_INVALID_PARAM;
534         }
535         isAttached = true;
536     }
537
538     CAEDRSendMulticastMessageImpl(env, data, dataLen);
539
540     OIC_LOG(DEBUG, TAG, "sent data");
541
542     if (isAttached)
543     {
544         OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
545         (*g_jvm)->DetachCurrentThread(g_jvm);
546     }
547
548     OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
549     return CA_STATUS_OK;
550 }
551
552 CAResult_t CAEDRGetInterfaceInfo(char **address)
553 {
554     CAEDRGetLocalAddress(address);
555     return CA_STATUS_OK;
556 }
557
558 void CAEDRGetLocalAddress(char **address)
559 {
560     bool isAttached = false;
561     JNIEnv* env;
562     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
563     if (JNI_OK != res)
564     {
565         OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
566         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
567         if (JNI_OK != res)
568         {
569             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
570             return;
571         }
572         isAttached = true;
573     }
574
575     jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
576     if (jni_address)
577     {
578         const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
579         *address = OICStrdup(localAddress);
580         if (*address == NULL)
581         {
582             if (isAttached)
583             {
584                 (*g_jvm)->DetachCurrentThread(g_jvm);
585             }
586             return;
587         }
588
589         (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
590     }
591
592     OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
593     if (isAttached)
594     {
595         (*g_jvm)->DetachCurrentThread(g_jvm);
596     }
597 }
598
599 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const char* data, uint32_t dataLen)
600 {
601     OIC_LOG_V(DEBUG, TAG, "CAEDRSendUnicastMessageImpl, address: %s, data: %s", address, data);
602
603     bool isAttached = false;
604     JNIEnv* env;
605     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
606     if (JNI_OK != res)
607     {
608         OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
609         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
610         if (JNI_OK != res)
611         {
612             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
613             return CA_STATUS_INVALID_PARAM;
614         }
615         isAttached = true;
616     }
617
618     OIC_LOG(DEBUG, TAG, "[EDR][Native] set byteArray for data");
619
620     // get bonded device list
621     jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
622     if (!jni_arrayPairedDevices)
623     {
624         OIC_LOG(ERROR, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
625         if (isAttached)
626         {
627             (*g_jvm)->DetachCurrentThread(g_jvm);
628         }
629         return CA_STATUS_INVALID_PARAM;
630     }
631     // Get information from array of devices
632     jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
633     jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
634                                                   METHODID_STRINGNONPARAM);
635     jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
636                                                      METHODID_STRINGNONPARAM);
637
638     jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
639     jsize i;
640     for (i = 0; i < length; i++)
641     {
642         OIC_LOG(DEBUG, TAG, "[EDR][Native] start to check device");
643         // get name, address from BT device
644         jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
645         jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
646
647         if (j_str_name)
648         {
649             const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
650             OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name);
651             (*env)->ReleaseStringUTFChars(env, j_str_name, name);
652         }
653
654         jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
655         const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
656         OIC_LOG_V(DEBUG, TAG,
657                   "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
658
659         if (!remoteAddress)
660         {
661             OIC_LOG(ERROR, TAG, "[EDR][Native] remoteAddress is null");
662             if (isAttached)
663             {
664                 (*g_jvm)->DetachCurrentThread(g_jvm);
665             }
666             return CA_STATUS_INVALID_PARAM;
667         }
668         if (!address)
669         {
670             OIC_LOG(ERROR, TAG, "[EDR][Native] address is null");
671             if (isAttached)
672             {
673                 (*g_jvm)->DetachCurrentThread(g_jvm);
674             }
675             (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
676             return CA_STATUS_INVALID_PARAM;
677         }
678         // find address
679         if (!strcmp(remoteAddress, address))
680         {
681             CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen, i);
682             if (CA_STATUS_OK != res)
683             {
684                 (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
685                 return res;
686             }
687         }
688         (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
689     }
690
691     if (isAttached)
692     {
693         (*g_jvm)->DetachCurrentThread(g_jvm);
694     }
695
696     return CA_STATUS_OK;
697 }
698
699 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const char* data, uint32_t dataLen)
700 {
701     OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %s, %d", data, dataLen);
702
703     // get bonded device list
704     jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
705     if (!jni_arrayPairedDevices)
706     {
707         OIC_LOG(ERROR, TAG, "[EDR][Native] jni_arrayPairedDevices is empty");
708         return CA_STATUS_INVALID_PARAM;
709     }
710     // Get information from array of devices
711     jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
712     jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
713                                                   METHODID_STRINGNONPARAM);
714     jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
715                                                      METHODID_STRINGNONPARAM);
716
717     jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
718     jsize i;
719     for (i = 0; i < length; i++)
720     {
721         // get name, address from BT device
722         jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
723         jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
724
725         if (j_str_name)
726         {
727             const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
728             OIC_LOG_V(DEBUG, TAG, "[EDR][Native] getBondedDevices: ~~device name is %s", name);
729             (*env)->ReleaseStringUTFChars(env, j_str_name, name);
730         }
731
732         jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
733         const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
734         OIC_LOG_V(DEBUG, TAG,
735                   "[EDR][Native] getBondedDevices: ~~device address is %s", remoteAddress);
736
737         // find address
738         CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen, i);
739         (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
740         if (CA_STATUS_OK != res)
741         {
742             OIC_LOG_V(DEBUG, TAG, "[EDR][Native] Send data has failed : %s", remoteAddress);
743             continue;
744         }
745     }
746
747     return CA_STATUS_OK;
748 }
749
750 /**
751  * EDR Method
752  */
753 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const char *data,
754                                uint32_t dataLength, uint32_t id)
755 {
756     OIC_LOG_V(DEBUG, TAG, "[EDR][Native] btSendData logic start : %s, %d", data, dataLength);
757
758     if (!CAEDRNativeIsEnableBTAdapter(env))
759     {
760         OIC_LOG(ERROR, TAG, "BT adpater is not enable");
761         return CA_STATUS_INVALID_PARAM;
762     }
763
764     if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
765     {
766         // connect before send data
767         OIC_LOG(DEBUG, TAG, "[EDR][Native] connect before send data");
768
769         if (NULL == address)
770         {
771             OIC_LOG(ERROR, TAG, "[EDR][Native] remote address is empty");
772             return CA_STATUS_INVALID_PARAM;
773         }
774         else
775         {
776             CAResult_t res = CAEDRNativeConnect(env, address, id);
777             if (CA_STATUS_OK != res)
778             {
779                 return res;
780             }
781         }
782     }
783
784     if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
785     {
786         if (!((*env)->ExceptionCheck(env)))
787         {
788             jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
789             if (!jni_cid_BTsocket)
790             {
791                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_BTsocket is null");
792                 return CA_STATUS_FAILED;
793             }
794
795             jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
796                                                                     "getOutputStream",
797                                                                     METHODID_OUTPUTNONPARAM);
798             if (!jni_mid_getOutputStream)
799             {
800                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_getOutputStream is null");
801                 return CA_STATUS_FAILED;
802             }
803
804             OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Get MethodID for i/o stream");
805
806             jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
807             if (!jni_obj_socket)
808             {
809                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_socket is not available");
810                 return CA_STATUS_FAILED;
811             }
812
813             jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
814                                                                     jni_mid_getOutputStream);
815             if (!jni_obj_outputStream)
816             {
817                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_obj_outputStream is null");
818                 return CA_STATUS_FAILED;
819             }
820
821             OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: ready outputStream..");
822
823             jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
824             if (!jni_cid_OutputStream)
825             {
826                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_cid_OutputStream is null");
827                 return CA_STATUS_FAILED;
828             }
829
830             jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
831                                                           "([BII)V");
832             if (!jni_mid_write)
833             {
834                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: jni_mid_write is null");
835                 return CA_STATUS_FAILED;
836             }
837
838             jbyteArray jbuf;
839             jbuf = (*env)->NewByteArray(env, dataLength);
840             (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
841
842             (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
843                                    (jint) dataLength);
844
845             if ((*env)->ExceptionCheck(env))
846             {
847                 OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: Write Error!!!");
848                 (*env)->ExceptionDescribe(env);
849                 (*env)->ExceptionClear(env);
850                 return CA_STATUS_FAILED;
851             }
852
853             OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: Write Success");
854         }
855         else
856         {
857             (*env)->ExceptionDescribe(env);
858             (*env)->ExceptionClear(env);
859             OIC_LOG(ERROR, TAG, "[EDR][Native] btSendData: error!!");
860             return CA_STATUS_FAILED;
861         }
862     }
863     else
864     {
865         OIC_LOG(DEBUG, TAG, "[EDR][Native] btSendData: BT connection is not completed!!");
866     }
867
868     return CA_STATUS_OK;
869 }
870
871 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address, uint32_t id)
872 {
873     OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect..");
874
875     if (!CAEDRNativeIsEnableBTAdapter(env))
876     {
877         OIC_LOG(ERROR, TAG, "BT adpater is not enable");
878         return CA_STATUS_INVALID_PARAM;
879     }
880
881     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
882     if (!jni_cid_BTAdapter)
883     {
884         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BTAdapter is null");
885         return CA_STATUS_FAILED;
886     }
887
888     // get BTadpater
889     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
890                                                                     "getDefaultAdapter",
891                                                                     METHODID_OBJECTNONPARAM);
892     if (!jni_mid_getDefaultAdapter)
893     {
894         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getDefaultAdapter is null");
895         return CA_STATUS_FAILED;
896     }
897
898     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
899                                                                jni_mid_getDefaultAdapter);
900     if (!jni_obj_BTAdapter)
901     {
902         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTAdapter is null");
903         return CA_STATUS_FAILED;
904     }
905
906     // get remote bluetooth device
907     jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
908                                                             "getRemoteDevice",
909                                                             METHODID_BT_DEVICEPARAM);
910     if (!jni_mid_getRemoteDevice)
911     {
912         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_getRemoteDevice is null");
913         return CA_STATUS_FAILED;
914     }
915
916     jstring jni_address = (*env)->NewStringUTF(env, address);
917     jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
918                                                               jni_mid_getRemoteDevice, jni_address);
919     if (!jni_obj_remoteBTDevice)
920     {
921         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_remoteBTDevice is null");
922         return CA_STATUS_FAILED;
923     }
924
925     // get create Rfcomm Socket method ID
926     jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
927     if (!jni_cid_BluetoothDevice)
928     {
929         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BluetoothDevice is null");
930         return CA_STATUS_FAILED;
931     }
932
933     jmethodID jni_mid_createSocket = (*env)->GetMethodID(
934             env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
935             "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
936     if (!jni_mid_createSocket)
937     {
938         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_createSocket is null");
939         return CA_STATUS_FAILED;
940     }
941
942     // setting UUID
943     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
944     if (!jni_cid_uuid)
945     {
946         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_uuid is null");
947         return CA_STATUS_FAILED;
948     }
949
950     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
951             env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
952     if (!jni_mid_fromString)
953     {
954         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_fromString is null");
955         return CA_STATUS_FAILED;
956     }
957
958     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
959     if (!jni_uuid)
960     {
961         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_uuid is null");
962         return CA_STATUS_FAILED;
963     }
964     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
965                                                           jni_uuid);
966     if (!jni_obj_uuid)
967     {
968         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_uuid is null");
969         return CA_STATUS_FAILED;
970     }
971     // create socket
972     jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
973                                                         jni_mid_createSocket, jni_obj_uuid);
974     if (!jni_obj_BTSocket)
975     {
976         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_obj_BTSocket is null");
977         return CA_STATUS_FAILED;
978     }
979
980     // connect
981     jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
982     if (!jni_cid_BTSocket)
983     {
984         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_cid_BTSocket is null");
985         return CA_STATUS_FAILED;
986     }
987
988     jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
989     if (!jni_mid_connect)
990     {
991         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_mid_connect is null");
992         return CA_STATUS_FAILED;
993     }
994
995     OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: initiating connection...");
996     (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
997
998     if ((*env)->ExceptionCheck(env))
999     {
1000         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: Connect is Failed!!!");
1001         (*env)->ExceptionDescribe(env);
1002         (*env)->ExceptionClear(env);
1003         return CA_STATUS_FAILED;
1004     }
1005
1006     // set socket to list
1007     jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1008     if (!jni_socket)
1009     {
1010         OIC_LOG(ERROR, TAG, "[EDR][Native] btConnect: jni_socket is null");
1011         return CA_STATUS_FAILED;
1012     }
1013     ca_mutex_lock(g_mutexObjectList);
1014     CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1015     ca_mutex_unlock(g_mutexObjectList);
1016
1017     // update state
1018     ca_mutex_lock(g_mutexStateList);
1019     CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1020     ca_mutex_unlock(g_mutexStateList);
1021
1022     OIC_LOG(DEBUG, TAG, "[EDR][Native] btConnect: connected");
1023
1024     return CA_STATUS_OK;
1025 }
1026
1027 void CAEDRNativeSocketClose(JNIEnv *env, const char *address, uint32_t id)
1028 {
1029
1030     jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1031     if (!jni_cid_BTSocket)
1032     {
1033         OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_cid_BTSocket is null");
1034         return;
1035     }
1036
1037     jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1038     if (!jni_mid_close)
1039     {
1040         OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_mid_close is null");
1041         return;
1042     }
1043
1044     jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1045     if (!jni_obj_socket)
1046     {
1047         OIC_LOG(ERROR, TAG, "[EDR][Native] close: jni_obj_socket is not available");
1048         return;
1049     }
1050
1051     (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1052
1053     if ((*env)->ExceptionCheck(env))
1054     {
1055         OIC_LOG(ERROR, TAG, "[EDR][Native] close: close is Failed!!!");
1056         (*env)->ExceptionDescribe(env);
1057         (*env)->ExceptionClear(env);
1058         return;
1059     }
1060
1061     // remove socket to list
1062     CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1063
1064     // update state
1065     ca_mutex_lock(g_mutexStateList);
1066     CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1067     ca_mutex_unlock(g_mutexStateList);
1068
1069     OIC_LOG(DEBUG, TAG, "[EDR][Native] close: disconnected");
1070 }
1071
1072 void CAEDRInitializeClient(ca_thread_pool_t handle)
1073 {
1074     OIC_LOG(DEBUG, TAG, "IN");
1075     CAEDRInitialize(handle);
1076     OIC_LOG(DEBUG, TAG, "OUT");
1077 }