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