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