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