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