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