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