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