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