removed buffer size defined previously in android edr server
[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 #include "caremotehandler.h"
36
37 #define TAG PCF("OIC_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 JavaVM *g_jvm;
54 static jobject g_context;
55
56 /**
57  * @var g_mutexUnicastServer
58  * @brief Mutex to synchronize unicast server
59  */
60 static ca_mutex g_mutexUnicastServer = NULL;
61
62 /**
63  * @var g_stopUnicast
64  * @brief Flag to control the Receive Unicast Data Thread
65  */
66 static bool g_stopUnicast = false;
67
68 /**
69  * @var g_mutexMulticastServer
70  * @brief Mutex to synchronize secure multicast server
71  */
72 static ca_mutex g_mutexMulticastServer = NULL;
73
74 /**
75  * @var g_stopMulticast
76  * @brief Flag to control the Receive Multicast Data Thread
77  */
78 static bool g_stopMulticast = false;
79
80 /**
81  * @var g_stopAccept
82  * @brief Flag to control the Accept Thread
83  */
84 static bool g_stopAccept = false;
85
86 /**
87  * @var g_mutexStateList
88  * @brief Mutex to synchronize device state list
89  */
90 static ca_mutex g_mutexStateList = NULL;
91
92 /**
93  * @var g_mutexObjectList
94  * @brief Mutex to synchronize device object list
95  */
96 static ca_mutex g_mutexObjectList = NULL;
97
98 /**
99  * @var g_edrErrorHandler
100  * @brief Error callback to update error in EDR
101  */
102 static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
103
104 typedef struct send_data
105 {
106     char* address;
107     char* data;
108     uint32_t id;
109 } data_t;
110
111 /**
112  @brief Thread context information for unicast, multicast and secured unicast server
113  */
114 typedef struct
115 {
116     bool *stopFlag;
117     CAAdapterServerType_t type;
118 } CAAdapterReceiveThreadContext_t;
119
120 typedef struct
121 {
122     bool *stopFlag;
123 } CAAdapterAcceptThreadContext_t;
124
125 /**
126  * implement for BT-EDR adapter common method
127  */
128 CAResult_t CAEDRGetInterfaceInformation(CAEndpoint_t **info)
129 {
130     OIC_LOG(DEBUG, TAG, "IN - CAEDRGetInterfaceInformation");
131
132     if (!info)
133     {
134         OIC_LOG(ERROR, TAG, "endpoint info is null");
135         return CA_STATUS_INVALID_PARAM;
136     }
137
138     char *macAddress = NULL;
139     CAResult_t ret = CAEDRGetInterfaceInfo(&macAddress);
140     if (CA_STATUS_OK != ret)
141     {
142         OIC_LOG_V(ERROR, TAG, "Failed to get interface info [%d]", ret);
143         OICFree(macAddress);
144         return ret;
145     }
146
147     if (!macAddress)
148     {
149         OIC_LOG(ERROR, TAG, "mac address is null");
150         return CA_STATUS_FAILED;
151     }
152     OIC_LOG_V(DEBUG, TAG, "address : %s", macAddress);
153
154     // Create local endpoint using util function
155     CAEndpoint_t *endpoint = CACreateEndpointObject(CA_DEFAULT_FLAGS, CA_ADAPTER_RFCOMM_BTEDR,
156                                                     macAddress, 0);
157     if (NULL == endpoint)
158     {
159         OIC_LOG(ERROR, TAG, "Failed to create Local Endpoint!");
160         OICFree(macAddress);
161         return CA_STATUS_FAILED;
162     }
163
164     // copy unicast server information
165     int32_t netInfoSize = 1;
166     CAEndpoint_t *netInfo = (CAEndpoint_t *)OICMalloc(sizeof(CAEndpoint_t) * netInfoSize);
167     if (NULL == netInfo)
168     {
169         OIC_LOG(ERROR, TAG, "Invalid input..");
170         OICFree(macAddress);
171         CAFreeEndpoint(endpoint);
172         return CA_MEMORY_ALLOC_FAILED;
173     }
174     *netInfo = *endpoint;
175     *info = netInfo;
176
177     OICFree(macAddress);
178     CAFreeEndpoint(endpoint);
179
180     OIC_LOG(DEBUG, TAG, "OUT - CAEDRGetInterfaceInformation");
181     return CA_STATUS_OK;
182 }
183
184 void CAEDRClientTerminate()
185 {
186     OIC_LOG(DEBUG, TAG, "IN");
187     CAEDRTerminate();
188     OIC_LOG(DEBUG, TAG, "OUT");
189 }
190
191 CAResult_t CAEDRManagerReadData()
192 {
193     OIC_LOG(DEBUG, TAG, "IN");
194
195     OIC_LOG(DEBUG, TAG, "OUT");
196     return CA_NOT_SUPPORTED;
197 }
198
199 CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const uint8_t *data,
200                                       uint32_t dataLength)
201 {
202     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
203     VERIFY_NON_NULL(data, TAG, "data is null");
204
205     CAResult_t result = CAEDRSendUnicastMessage(remoteAddress, data, dataLength);
206     return result;
207 }
208
209 CAResult_t CAEDRClientSendMulticastData(const uint8_t *data, uint32_t dataLength)
210 {
211     VERIFY_NON_NULL(data, TAG, "data is null");
212
213     CAResult_t result = CAEDRSendMulticastMessage(data, dataLength);
214     return result;
215 }
216
217 // It will be updated when android EDR support is added
218 void CAEDRClientUnsetCallbacks()
219 {
220     OIC_LOG(DEBUG, TAG, "IN");
221
222     OIC_LOG(DEBUG, TAG, "OUT");
223 }
224
225 // It will be updated when android EDR support is added
226 void CAEDRClientDisconnectAll()
227 {
228     OIC_LOG(DEBUG, TAG, "IN");
229
230     OIC_LOG(DEBUG, TAG, "OUT");
231 }
232
233 CAResult_t CAEDRGetAdapterEnableState(bool *state)
234 {
235     VERIFY_NON_NULL(state, TAG, "state is null");
236
237     if (!g_jvm)
238     {
239         OIC_LOG(ERROR, TAG, "g_jvm is null");
240         return CA_STATUS_INVALID_PARAM;
241     }
242     bool isAttached = false;
243     JNIEnv* env;
244     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
245     if (JNI_OK != res)
246     {
247         OIC_LOG(DEBUG, TAG, "CAEDRGetAdapterEnableState - Could not get JNIEnv pointer");
248         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
249
250         if (JNI_OK != res)
251         {
252             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
253             return CA_STATUS_INVALID_PARAM;
254         }
255         isAttached = true;
256     }
257
258     *state = false;
259     jboolean ret = CAEDRNativeIsEnableBTAdapter(env);
260     if (ret)
261     {
262         *state = true;
263     }
264
265     if (isAttached)
266     {
267         (*g_jvm)->DetachCurrentThread(g_jvm);
268     }
269
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, "CAEDRCreateJNIInterfaceObject");
284
285     if ((*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
286     {
287         OIC_LOG(ERROR, TAG, "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, "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, "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, "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, "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, "NewObject Success");
326
327     return CA_STATUS_OK;
328 }
329
330 static void CAEDRDestroyMutex()
331 {
332     if (g_mutexUnicastServer)
333     {
334         ca_mutex_free(g_mutexUnicastServer);
335         g_mutexUnicastServer = NULL;
336     }
337
338     if (g_mutexMulticastServer)
339     {
340         ca_mutex_free(g_mutexMulticastServer);
341         g_mutexMulticastServer = NULL;
342     }
343
344     if (g_mutexStateList)
345     {
346         ca_mutex_free(g_mutexStateList);
347         g_mutexStateList = NULL;
348     }
349
350     if (g_mutexObjectList)
351     {
352         ca_mutex_free(g_mutexObjectList);
353         g_mutexObjectList = NULL;
354     }
355 }
356
357 static CAResult_t CAEDRCreateMutex()
358 {
359     g_mutexUnicastServer = ca_mutex_new();
360     if (!g_mutexUnicastServer)
361     {
362         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
363         return CA_STATUS_FAILED;
364     }
365
366     g_mutexMulticastServer = ca_mutex_new();
367     if (!g_mutexMulticastServer)
368     {
369         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
370
371         CAEDRDestroyMutex();
372         return CA_STATUS_FAILED;
373     }
374
375     g_mutexStateList = ca_mutex_new();
376     if (!g_mutexStateList)
377     {
378         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
379
380         CAEDRDestroyMutex();
381         return CA_STATUS_FAILED;
382     }
383
384     g_mutexObjectList = ca_mutex_new();
385     if (!g_mutexObjectList)
386     {
387         OIC_LOG(ERROR, TAG, "Failed to created mutex!");
388
389         CAEDRDestroyMutex();
390         return CA_STATUS_FAILED;
391     }
392
393     return CA_STATUS_OK;
394 }
395
396 CAResult_t CAEDRInitialize()
397 {
398     OIC_LOG(DEBUG, TAG, "CAEDRInitialize");
399
400     CAEDRCoreJniInit();
401
402     CAEDRJniInitContext();
403
404     // init mutex
405     CAResult_t result = CAEDRCreateMutex();
406     if(CA_STATUS_OK != result)
407     {
408         OIC_LOG(ERROR, TAG, "CAEDRInitialize - Could not create mutex");
409         return result;
410     }
411
412     bool isAttached = false;
413     JNIEnv* env;
414     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
415     if (JNI_OK != res)
416     {
417         OIC_LOG(DEBUG, TAG, "CAEDRInitialize - Could not get JNIEnv pointer");
418         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
419
420         if (JNI_OK != res)
421         {
422             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
423             return CA_STATUS_NOT_INITIALIZED;
424         }
425         isAttached = true;
426     }
427     jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
428     if (jni_address)
429     {
430         const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
431         OIC_LOG_V(DEBUG, TAG, "My BT Address is %s", localAddress);
432         (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
433     }
434     (*env)->DeleteLocalRef(env, jni_address);
435
436     ca_mutex_lock(g_mutexStateList);
437     CAEDRNativeCreateDeviceStateList();
438     ca_mutex_unlock(g_mutexStateList);
439
440     ca_mutex_lock(g_mutexObjectList);
441     CAEDRNativeCreateDeviceSocketList();
442     ca_mutex_unlock(g_mutexObjectList);
443
444     if (isAttached)
445     {
446         (*g_jvm)->DetachCurrentThread(g_jvm);
447     }
448
449     if (g_context)
450     {
451         CAEDRCreateJNIInterfaceObject(g_context); /* create java CaEdrInterface instance*/
452     }
453
454     OIC_LOG(DEBUG, TAG, "OUT");
455
456     return result;
457 }
458
459 void CAEDRTerminate()
460 {
461     OIC_LOG(DEBUG, TAG, "CAEDRTerminate");
462
463     bool isAttached = false;
464     JNIEnv* env;
465     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
466     if (JNI_OK != res)
467     {
468         OIC_LOG(DEBUG, TAG, "CAEDRTerminate - Could not get JNIEnv pointer");
469         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
470
471         if (JNI_OK != res)
472         {
473             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
474             return;
475         }
476         isAttached = true;
477     }
478
479     g_stopAccept = true;
480     g_stopMulticast = true;
481     g_stopUnicast = true;
482
483     if (isAttached)
484     {
485         (*g_jvm)->DetachCurrentThread(g_jvm);
486     }
487
488     if (g_context)
489     {
490         (*env)->DeleteGlobalRef(env, g_context);
491     }
492
493     CAEDRNativeSocketCloseToAll(env);
494
495     // delete mutex
496     CAEDRDestroyMutex();
497
498     CAEDRNativeRemoveAllDeviceState();
499     CAEDRNativeRemoveAllDeviceSocket(env);
500     CAEDRDestroyJniInterface();
501 }
502
503 CAResult_t CAEDRDestroyJniInterface()
504 {
505     OIC_LOG(DEBUG, TAG, "CAEDRDestroyJniInterface");
506
507     if (!g_jvm)
508     {
509         OIC_LOG(ERROR, TAG, "g_jvm is null");
510         return CA_STATUS_FAILED;
511     }
512
513     bool isAttached = false;
514     JNIEnv* env;
515     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
516     if (JNI_OK != res)
517     {
518         OIC_LOG(INFO, TAG, "Could not get JNIEnv pointer");
519         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
520
521         if (JNI_OK != res)
522         {
523             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
524             return CA_STATUS_FAILED;
525         }
526         isAttached = true;
527     }
528
529     jclass jni_EDRJniInterface = (*env)->FindClass(env, CLASSPATH_BT_INTERFACE);
530     if (!jni_EDRJniInterface)
531     {
532         OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface class");
533         goto error_exit;
534     }
535
536     jmethodID jni_EDRInterfaceDestroyMethod = (*env)->GetStaticMethodID(env, jni_EDRJniInterface,
537                                                                         "destroyEdrInterface",
538                                                                         "()V");
539     if (!jni_EDRInterfaceDestroyMethod)
540     {
541         OIC_LOG(ERROR, TAG, "Could not get CaEdrInterface destroy method");
542         goto error_exit;
543     }
544
545     (*env)->CallStaticVoidMethod(env, jni_EDRJniInterface, jni_EDRInterfaceDestroyMethod);
546
547     if ((*env)->ExceptionCheck(env))
548     {
549         OIC_LOG(ERROR, TAG, "destroyEdrInterface has failed");
550         (*env)->ExceptionDescribe(env);
551         (*env)->ExceptionClear(env);
552         goto error_exit;
553     }
554
555     OIC_LOG(DEBUG, TAG, "Destroy instance for CaEdrInterface");
556
557     if (isAttached)
558     {
559         (*g_jvm)->DetachCurrentThread(g_jvm);
560     }
561
562     return CA_STATUS_OK;
563
564 error_exit:
565
566     if (isAttached)
567     {
568         (*g_jvm)->DetachCurrentThread(g_jvm);
569     }
570
571     return CA_STATUS_FAILED;
572 }
573
574 void CAEDRCoreJniInit()
575 {
576     OIC_LOG(DEBUG, TAG, "CAEdrClientJniInit");
577     g_jvm = (JavaVM*) CANativeJNIGetJavaVM();
578 }
579
580 CAResult_t CAEDRSendUnicastMessage(const char* address, const uint8_t* data, uint32_t dataLen)
581 {
582     VERIFY_NON_NULL(address, TAG, "address is null");
583     VERIFY_NON_NULL(data, TAG, "data is null");
584
585     CAResult_t result = CAEDRSendUnicastMessageImpl(address, data, dataLen);
586     return result;
587 }
588
589 CAResult_t CAEDRSendMulticastMessage(const uint8_t* data, uint32_t dataLen)
590 {
591     VERIFY_NON_NULL(data, TAG, "data is null");
592
593     bool isAttached = false;
594     JNIEnv* env;
595     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
596     if (JNI_OK != res)
597     {
598         OIC_LOG(DEBUG, TAG, "CAEDRSendMulticastMessage - Could not get JNIEnv pointer");
599         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
600
601         if (JNI_OK != res)
602         {
603             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
604             return CA_STATUS_INVALID_PARAM;
605         }
606         isAttached = true;
607     }
608
609     CAResult_t result = CAEDRSendMulticastMessageImpl(env, data, dataLen);
610     if(CA_STATUS_OK != result)
611     {
612         OIC_LOG(ERROR, TAG, "CAEDRSendMulticastMessage - could not send multicast message");
613         return result;
614     }
615
616     OIC_LOG(DEBUG, TAG, "sent data");
617
618     if (isAttached)
619     {
620         OIC_LOG(DEBUG, TAG, "DetachCurrentThread");
621         (*g_jvm)->DetachCurrentThread(g_jvm);
622     }
623
624     OIC_LOG(DEBUG, TAG, "OUT - CAEDRSendMulticastMessage");
625     return CA_STATUS_OK;
626 }
627
628 CAResult_t CAEDRGetInterfaceInfo(char **address)
629 {
630     CAEDRGetLocalAddress(address);
631     return CA_STATUS_OK;
632 }
633
634 void CAEDRGetLocalAddress(char **address)
635 {
636     bool isAttached = false;
637     JNIEnv* env;
638     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
639     if (JNI_OK != res)
640     {
641         OIC_LOG(DEBUG, TAG, "CAEDRGetLocalAddress - Could not get JNIEnv pointer");
642         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
643         if (JNI_OK != res)
644         {
645             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
646             return;
647         }
648         isAttached = true;
649     }
650
651     jstring jni_address = CAEDRNativeGetLocalDeviceAddress(env);
652     if (jni_address)
653     {
654         const char* localAddress = (*env)->GetStringUTFChars(env, jni_address, NULL);
655         *address = OICStrdup(localAddress);
656         if (*address == NULL)
657         {
658             if (isAttached)
659             {
660                 (*g_jvm)->DetachCurrentThread(g_jvm);
661             }
662             (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
663             (*env)->DeleteLocalRef(env, jni_address);
664             return;
665         }
666
667         (*env)->ReleaseStringUTFChars(env, jni_address, localAddress);
668         (*env)->DeleteLocalRef(env, jni_address);
669     }
670
671     OIC_LOG_V(DEBUG, TAG, "Local Address : %s", *address);
672     if (isAttached)
673     {
674         (*g_jvm)->DetachCurrentThread(g_jvm);
675     }
676 }
677
678 CAResult_t CAEDRSendUnicastMessageImpl(const char* address, const uint8_t* data, uint32_t dataLen)
679 {
680     VERIFY_NON_NULL(address, TAG, "address is null");
681     VERIFY_NON_NULL(data, TAG, "data is null");
682
683     bool isAttached = false;
684     JNIEnv* env;
685     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
686     if (JNI_OK != res)
687     {
688         OIC_LOG(DEBUG, TAG, "CAEDRSendUnicastMessageImpl - Could not get JNIEnv pointer");
689         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
690         if (JNI_OK != res)
691         {
692             OIC_LOG(ERROR, TAG, "AttachCurrentThread failed");
693             return CA_STATUS_INVALID_PARAM;
694         }
695         isAttached = true;
696     }
697
698     OIC_LOG(DEBUG, TAG, "set byteArray for data");
699
700     // get bonded device list
701     jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
702     if (!jni_arrayPairedDevices)
703     {
704         OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
705         if (isAttached)
706         {
707             (*g_jvm)->DetachCurrentThread(g_jvm);
708         }
709         return CA_STATUS_INVALID_PARAM;
710     }
711     // Get information from array of devices
712     jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
713     jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
714                                                   METHODID_STRINGNONPARAM);
715     jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
716                                                      METHODID_STRINGNONPARAM);
717
718     jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
719     for (jsize i = 0; i < length; i++)
720     {
721         OIC_LOG(DEBUG, TAG, "start to check device");
722         // get name, address from BT device
723         jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
724         jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
725
726         if (j_str_name)
727         {
728             const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
729             OIC_LOG_V(DEBUG, TAG, "device name is %s", name);
730             (*env)->ReleaseStringUTFChars(env, j_str_name, name);
731             (*env)->DeleteLocalRef(env, j_str_name);
732         }
733
734         jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
735         const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
736         (*env)->DeleteLocalRef(env, j_obj_device);
737         if (!remoteAddress)
738         {
739             OIC_LOG(ERROR, TAG, "remoteAddress is null");
740             if (isAttached)
741             {
742                 (*g_jvm)->DetachCurrentThread(g_jvm);
743             }
744
745             (*env)->DeleteLocalRef(env, j_str_address);
746             (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
747             (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
748             return CA_STATUS_INVALID_PARAM;
749         }
750         OIC_LOG_V(DEBUG, TAG, "device address is %s", remoteAddress);
751
752         // find address
753         if (!strcmp(remoteAddress, address))
754         {
755             CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
756             (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
757             (*env)->DeleteLocalRef(env, j_str_address);
758             if (CA_STATUS_OK != res)
759             {
760                 (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
761                 (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
762                 return res;
763             }
764             break;
765         }
766         (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
767         (*env)->DeleteLocalRef(env, j_str_address);
768     }
769
770     (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
771     (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
772
773     if (isAttached)
774     {
775         (*g_jvm)->DetachCurrentThread(g_jvm);
776     }
777
778     return CA_STATUS_OK;
779 }
780
781 CAResult_t CAEDRSendMulticastMessageImpl(JNIEnv *env, const uint8_t* data, uint32_t dataLen)
782 {
783     VERIFY_NON_NULL(env, TAG, "env is null");
784     VERIFY_NON_NULL(data, TAG, "data is null");
785
786     // get bonded device list
787     jobjectArray jni_arrayPairedDevices = CAEDRNativeGetBondedDevices(env);
788     if (!jni_arrayPairedDevices)
789     {
790         OIC_LOG(ERROR, TAG, "jni_arrayPairedDevices is empty");
791         return CA_STATUS_INVALID_PARAM;
792     }
793     // Get information from array of devices
794     jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
795     jmethodID j_mid_getName = (*env)->GetMethodID(env, jni_cid_BTDevice, "getName",
796                                                   METHODID_STRINGNONPARAM);
797     jmethodID j_mid_getAddress = (*env)->GetMethodID(env, jni_cid_BTDevice, "getAddress",
798                                                      METHODID_STRINGNONPARAM);
799
800     jsize length = (*env)->GetArrayLength(env, jni_arrayPairedDevices);
801     for (jsize i = 0; i < length; i++)
802     {
803         // get name, address from BT device
804         jobject j_obj_device = (*env)->GetObjectArrayElement(env, jni_arrayPairedDevices, i);
805         jstring j_str_name = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getName);
806         jstring j_str_address = (*env)->CallObjectMethod(env, j_obj_device, j_mid_getAddress);
807
808         if (j_str_name && j_str_address)
809         {
810             const char * name = (*env)->GetStringUTFChars(env, j_str_name, NULL);
811             const char * remoteAddress = (*env)->GetStringUTFChars(env, j_str_address, NULL);
812             if (name && remoteAddress)
813             {
814                 OIC_LOG_V(DEBUG, TAG, "device name is %s, address is %s", name, remoteAddress);
815
816                 CAResult_t res = CAEDRNativeSendData(env, remoteAddress, data, dataLen);
817                 if (CA_STATUS_OK != res)
818                 {
819                     OIC_LOG_V(ERROR, TAG, "Failed to send multicast message to : %s",
820                               remoteAddress);
821                     g_edrErrorHandler(remoteAddress, data, dataLen, res);
822                 }
823             }
824             (*env)->ReleaseStringUTFChars(env, j_str_name, name);
825             (*env)->ReleaseStringUTFChars(env, j_str_address, remoteAddress);
826         }
827
828         (*env)->DeleteLocalRef(env, j_obj_device);
829         (*env)->DeleteLocalRef(env, j_str_name);
830         (*env)->DeleteLocalRef(env, j_str_address);
831     }
832
833     (*env)->DeleteLocalRef(env, jni_arrayPairedDevices);
834     (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
835
836     return CA_STATUS_OK;
837 }
838
839 CAResult_t CAEDRNativeSendData(JNIEnv *env, const char *address, const uint8_t *data,
840                                uint32_t dataLength)
841 {
842     VERIFY_NON_NULL(env, TAG, "env is null");
843     VERIFY_NON_NULL(address, TAG, "address is null");
844     VERIFY_NON_NULL(data, TAG, "data is null");
845
846     if (!CAEDRNativeIsEnableBTAdapter(env))
847     {
848         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
849         return CA_ADAPTER_NOT_ENABLED;
850     }
851
852     if (STATE_DISCONNECTED == CAEDRIsConnectedDevice(address))
853     {
854         // connect before send data
855         OIC_LOG(DEBUG, TAG, "connect before send data");
856
857         CAResult_t res = CAEDRNativeConnect(env, address);
858         if (CA_STATUS_OK != res)
859         {
860             return res;
861         }
862     }
863
864     if (STATE_CONNECTED == CAEDRIsConnectedDevice(address))
865     {
866         if (!((*env)->ExceptionCheck(env)))
867         {
868             jclass jni_cid_BTsocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
869             if (!jni_cid_BTsocket)
870             {
871                 OIC_LOG(ERROR, TAG, "jni_cid_BTsocket is null");
872                 return CA_STATUS_FAILED;
873             }
874
875             jmethodID jni_mid_getOutputStream = (*env)->GetMethodID(env, jni_cid_BTsocket,
876                                                                     "getOutputStream",
877                                                                     METHODID_OUTPUTNONPARAM);
878             if (!jni_mid_getOutputStream)
879             {
880                 OIC_LOG(ERROR, TAG, "jni_mid_getOutputStream is null");
881                 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
882                 return CA_STATUS_FAILED;
883             }
884
885             OIC_LOG(DEBUG, TAG, "Get MethodID for i/o stream");
886
887             jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
888             if (!jni_obj_socket)
889             {
890                 OIC_LOG(ERROR, TAG, "jni_socket is not available");
891                 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
892                 return CA_STATUS_FAILED;
893             }
894
895             jobject jni_obj_outputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
896                                                                     jni_mid_getOutputStream);
897             if (!jni_obj_outputStream)
898             {
899                 OIC_LOG(ERROR, TAG, "jni_obj_outputStream is null");
900                 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
901                 return CA_STATUS_FAILED;
902             }
903
904             OIC_LOG(DEBUG, TAG, "ready outputStream..");
905
906             jclass jni_cid_OutputStream = (*env)->FindClass(env, CLASSPATH_OUTPUT);
907             if (!jni_cid_OutputStream)
908             {
909                 OIC_LOG(ERROR, TAG, "jni_cid_OutputStream is null");
910                 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
911                 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
912                 return CA_STATUS_FAILED;
913             }
914
915             jmethodID jni_mid_write = (*env)->GetMethodID(env, jni_cid_OutputStream, "write",
916                                                           "([BII)V");
917             if (!jni_mid_write)
918             {
919                 OIC_LOG(ERROR, TAG, "jni_mid_write is null");
920                 (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
921                 (*env)->DeleteLocalRef(env, jni_obj_outputStream);
922                 (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
923                 return CA_STATUS_FAILED;
924             }
925
926             jbyteArray jbuf = (*env)->NewByteArray(env, dataLength);
927             (*env)->SetByteArrayRegion(env, jbuf, 0, dataLength, (jbyte*) data);
928
929             (*env)->CallVoidMethod(env, jni_obj_outputStream, jni_mid_write, jbuf, (jint) 0,
930                                    (jint) dataLength);
931
932             (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
933             (*env)->DeleteLocalRef(env, jni_obj_outputStream);
934             (*env)->DeleteLocalRef(env, jni_cid_OutputStream);
935             (*env)->DeleteLocalRef(env, jbuf);
936
937             if ((*env)->ExceptionCheck(env))
938             {
939                 OIC_LOG(ERROR, TAG, "Failed to write data in outputStram");
940                 (*env)->ExceptionDescribe(env);
941                 (*env)->ExceptionClear(env);
942                 return CA_STATUS_FAILED;
943             }
944
945             OIC_LOG_V(INFO, TAG, "EDR sendTo is successful: %u bytes, to %s",
946                       dataLength, address);
947         }
948         else
949         {
950             (*env)->ExceptionDescribe(env);
951             (*env)->ExceptionClear(env);
952             OIC_LOG(ERROR, TAG, "error!!");
953             return CA_STATUS_FAILED;
954         }
955     }
956     else
957     {
958         OIC_LOG(DEBUG, TAG, "BT connection is not completed!!");
959     }
960
961     return CA_STATUS_OK;
962 }
963
964 CAResult_t CAEDRNativeConnect(JNIEnv *env, const char *address)
965 {
966     VERIFY_NON_NULL(address, TAG, "address is null");
967     OIC_LOG(DEBUG, TAG, "btConnect..");
968
969     if (!CAEDRNativeIsEnableBTAdapter(env))
970     {
971         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
972         return CA_ADAPTER_NOT_ENABLED;
973     }
974
975     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADPATER);
976     if (!jni_cid_BTAdapter)
977     {
978         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
979         return CA_STATUS_FAILED;
980     }
981
982     // get BTadpater
983     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
984                                                                     "getDefaultAdapter",
985                                                                     METHODID_OBJECTNONPARAM);
986     if (!jni_mid_getDefaultAdapter)
987     {
988         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
989         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
990         return CA_STATUS_FAILED;
991     }
992
993     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
994                                                                jni_mid_getDefaultAdapter);
995     if (!jni_obj_BTAdapter)
996     {
997         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
998         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
999         return CA_STATUS_FAILED;
1000     }
1001
1002     // get remote bluetooth device
1003     jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
1004                                                             "getRemoteDevice",
1005                                                             METHODID_BT_DEVICEPARAM);
1006     (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
1007     if (!jni_mid_getRemoteDevice)
1008     {
1009         OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
1010         (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1011         return CA_STATUS_FAILED;
1012     }
1013
1014     jstring jni_address = (*env)->NewStringUTF(env, address);
1015     jobject jni_obj_remoteBTDevice = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
1016                                                               jni_mid_getRemoteDevice, jni_address);
1017     (*env)->DeleteLocalRef(env, jni_address);
1018     (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
1019     if (!jni_obj_remoteBTDevice)
1020     {
1021         OIC_LOG(ERROR, TAG, "jni_obj_remoteBTDevice is null");
1022         return CA_STATUS_FAILED;
1023     }
1024
1025     // get create Rfcomm Socket method ID
1026     jclass jni_cid_BluetoothDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
1027     if (!jni_cid_BluetoothDevice)
1028     {
1029         OIC_LOG(ERROR, TAG, "jni_cid_BluetoothDevice is null");
1030         (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1031         return CA_STATUS_FAILED;
1032     }
1033
1034     jmethodID jni_mid_createSocket = (*env)->GetMethodID(
1035             env, jni_cid_BluetoothDevice, "createInsecureRfcommSocketToServiceRecord",
1036             "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;");
1037     (*env)->DeleteLocalRef(env, jni_cid_BluetoothDevice);
1038     if (!jni_mid_createSocket)
1039     {
1040         OIC_LOG(ERROR, TAG, "jni_mid_createSocket is null");
1041         (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1042         return CA_STATUS_FAILED;
1043     }
1044
1045     // setting UUID
1046     jclass jni_cid_uuid = (*env)->FindClass(env, CLASSPATH_BT_UUID);
1047     if (!jni_cid_uuid)
1048     {
1049         OIC_LOG(ERROR, TAG, "jni_cid_uuid is null");
1050         (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1051         return CA_STATUS_FAILED;
1052     }
1053
1054     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(
1055             env, jni_cid_uuid, "fromString", "(Ljava/lang/String;)Ljava/util/UUID;");
1056     if (!jni_mid_fromString)
1057     {
1058         OIC_LOG(ERROR, TAG, "jni_mid_fromString is null");
1059         (*env)->DeleteLocalRef(env, jni_cid_uuid);
1060         (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1061         return CA_STATUS_FAILED;
1062     }
1063
1064     jstring jni_uuid = (*env)->NewStringUTF(env, OIC_EDR_SERVICE_ID);
1065     if (!jni_uuid)
1066     {
1067         OIC_LOG(ERROR, TAG, "jni_uuid is null");
1068         (*env)->DeleteLocalRef(env, jni_cid_uuid);
1069         (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1070         return CA_STATUS_FAILED;
1071     }
1072     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_uuid, jni_mid_fromString,
1073                                                           jni_uuid);
1074     (*env)->DeleteLocalRef(env, jni_cid_uuid);
1075     (*env)->DeleteLocalRef(env, jni_uuid);
1076     if (!jni_obj_uuid)
1077     {
1078         OIC_LOG(ERROR, TAG, "jni_obj_uuid is null");
1079         (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1080         return CA_STATUS_FAILED;
1081     }
1082     // create socket
1083     jobject jni_obj_BTSocket = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice,
1084                                                         jni_mid_createSocket, jni_obj_uuid);
1085     (*env)->DeleteLocalRef(env, jni_obj_uuid);
1086     (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
1087     if (!jni_obj_BTSocket)
1088     {
1089         OIC_LOG(ERROR, TAG, "jni_obj_BTSocket is null");
1090         return CA_STATUS_FAILED;
1091     }
1092
1093     // connect
1094     jclass jni_cid_BTSocket = (*env)->FindClass(env, CLASSPATH_BT_SOCKET);
1095     if (!jni_cid_BTSocket)
1096     {
1097         OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1098         (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1099         return CA_STATUS_FAILED;
1100     }
1101
1102     jmethodID jni_mid_connect = (*env)->GetMethodID(env, jni_cid_BTSocket, "connect", "()V");
1103     (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
1104     if (!jni_mid_connect)
1105     {
1106         OIC_LOG(ERROR, TAG, "jni_mid_connect is null");
1107         (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1108         return CA_STATUS_FAILED;
1109     }
1110
1111     OIC_LOG(DEBUG, TAG, "initiating connection...");
1112     (*env)->CallVoidMethod(env, jni_obj_BTSocket, jni_mid_connect);
1113
1114     if ((*env)->ExceptionCheck(env))
1115     {
1116         OIC_LOG(ERROR, TAG, "Connect is Failed!!!");
1117         (*env)->ExceptionDescribe(env);
1118         (*env)->ExceptionClear(env);
1119         return CA_STATUS_FAILED;
1120     }
1121
1122     // set socket to list
1123     jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
1124     if (!jni_socket)
1125     {
1126         OIC_LOG(ERROR, TAG, "jni_socket is null");
1127         (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1128         return CA_STATUS_FAILED;
1129     }
1130     ca_mutex_lock(g_mutexObjectList);
1131     CAEDRNativeAddDeviceSocketToList(env, jni_socket);
1132     (*env)->DeleteGlobalRef(env, jni_socket);
1133     (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
1134     ca_mutex_unlock(g_mutexObjectList);
1135
1136     // update state
1137     ca_mutex_lock(g_mutexStateList);
1138     CAEDRUpdateDeviceState(STATE_CONNECTED, address);
1139     ca_mutex_unlock(g_mutexStateList);
1140
1141     OIC_LOG(DEBUG, TAG, "connected");
1142
1143     return CA_STATUS_OK;
1144 }
1145
1146 void CAEDRNativeSocketClose(JNIEnv *env, const char *address)
1147 {
1148     VERIFY_NON_NULL_VOID(address, TAG, "address is null");
1149
1150     jclass jni_cid_BTSocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
1151     if (!jni_cid_BTSocket)
1152     {
1153         OIC_LOG(ERROR, TAG, "jni_cid_BTSocket is null");
1154         return;
1155     }
1156
1157     jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_BTSocket, "close", "()V");
1158     if (!jni_mid_close)
1159     {
1160         OIC_LOG(ERROR, TAG, "jni_mid_close is null");
1161         return;
1162     }
1163
1164     jobject jni_obj_socket = CAEDRNativeGetDeviceSocketBaseAddr(env, address);
1165     if (!jni_obj_socket)
1166     {
1167         OIC_LOG(ERROR, TAG, "jni_obj_socket is not available");
1168         return;
1169     }
1170
1171     (*env)->CallVoidMethod(env, jni_obj_socket, jni_mid_close);
1172
1173     if ((*env)->ExceptionCheck(env))
1174     {
1175         OIC_LOG(ERROR, TAG, "close is Failed!!!");
1176         (*env)->ExceptionDescribe(env);
1177         (*env)->ExceptionClear(env);
1178         return;
1179     }
1180
1181     // remove socket to list
1182     CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
1183
1184     // update state
1185     ca_mutex_lock(g_mutexStateList);
1186     CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
1187     ca_mutex_unlock(g_mutexStateList);
1188
1189     OIC_LOG(DEBUG, TAG, "disconnected");
1190 }
1191
1192 CAResult_t CAEDRClientInitialize()
1193 {
1194     CAResult_t result = CAEDRInitialize();
1195     return result;
1196 }
1197
1198 void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
1199 {
1200     g_edrErrorHandler = errorHandleCallback;
1201 }