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