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