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