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