Merge branch 'tizen' into tizen_5.5
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / android / caleutils.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 <jni.h>
22 #include <stdio.h>
23 #include <android/log.h>
24
25 #include "caleutils.h"
26 #include "logger.h"
27 #include "cathreadpool.h"
28 #include "uarraylist.h"
29 #include "caadapterutils.h"
30
31 #define TAG PCF("OIC_CA_LE_UTILS")
32
33 jobject CALEGetUuidFromString(JNIEnv *env, const char* uuid)
34 {
35     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
36     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
37
38     jclass jni_cid_UUID = (*env)->FindClass(env, "java/util/UUID");
39     if (!jni_cid_UUID)
40     {
41         OIC_LOG(ERROR, TAG, "jni_cid_UUID is not available");
42         goto error_exit;
43     }
44
45     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_UUID, "fromString",
46                                                              "(Ljava/lang/String;)"
47                                                              "Ljava/util/UUID;");
48     if (!jni_mid_fromString)
49     {
50         OIC_LOG(ERROR, TAG, "jni_mid_fromString is not available");
51         goto error_exit;
52     }
53
54     jstring str_uuid = (*env)->NewStringUTF(env, uuid);
55     if (!str_uuid)
56     {
57         OIC_LOG(ERROR, TAG, "str_uuid is not available");
58         goto error_exit;
59     }
60
61     jobject jni_obj_uuid = (*env)->CallStaticObjectMethod(env, jni_cid_UUID, jni_mid_fromString,
62                                                           str_uuid);
63     if (!jni_obj_uuid)
64     {
65         OIC_LOG(ERROR, TAG, "Fail to get jni uuid object");
66         goto error_exit;
67     }
68
69     return jni_obj_uuid;
70
71 error_exit:
72     CACheckJNIException(env);
73     return NULL;
74 }
75
76 jobject CALEGetParcelUuid(JNIEnv *env, jobject uuid)
77 {
78     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
79     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
80
81     jclass jni_cid_ParcelUuid = (*env)->FindClass(env, "android/os/ParcelUuid");
82     if (!jni_cid_ParcelUuid)
83     {
84         OIC_LOG(ERROR, TAG, "jni_cid_ParcelUuid is not available");
85         goto error_exit;
86     }
87
88     jmethodID jni_mid_ParcelUuid = (*env)->GetMethodID(env, jni_cid_ParcelUuid, "<init>",
89                                                        "(Ljava/util/UUID;)V");
90     if (!jni_mid_ParcelUuid)
91     {
92         OIC_LOG(ERROR, TAG, "jni_mid_ParcelUuid is not available");
93         goto error_exit;
94     }
95
96     jobject jni_ParcelUuid = (*env)->NewObject(env, jni_cid_ParcelUuid, jni_mid_ParcelUuid, uuid);
97     if (!jni_ParcelUuid)
98     {
99         OIC_LOG(ERROR, TAG, "Fail to get jni ParcelUuid");
100         goto error_exit;
101     }
102
103     return jni_ParcelUuid;
104 error_exit:
105     CACheckJNIException(env);
106     return NULL;
107 }
108
109 jobject CALEGetParcelUuidFromString(JNIEnv *env, const char* uuid)
110 {
111     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
112     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
113
114     jclass jni_cid_ParcelUuid = (*env)->FindClass(env, "android/os/ParcelUuid");
115     if (!jni_cid_ParcelUuid)
116     {
117         OIC_LOG(ERROR, TAG, "jni_cid_ParcelUuid is not available");
118         goto error_exit;
119     }
120
121     jmethodID jni_mid_fromString = (*env)->GetStaticMethodID(env, jni_cid_ParcelUuid,
122                                                              "fromString",
123                                                              "(Ljava/lang/String;)"
124                                                              "Landroid/os/ParcelUuid;");
125     if (!jni_mid_fromString)
126     {
127         OIC_LOG(ERROR, TAG, "jni_mid_fromString is not available");
128         goto error_exit;
129     }
130
131     jstring str_uuid = (*env)->NewStringUTF(env, uuid);
132     if (!str_uuid)
133     {
134         OIC_LOG(ERROR, TAG, "str_uuid is not available");
135         goto error_exit;
136     }
137
138     jobject jni_obj_parcelUuid = (*env)->CallStaticObjectMethod(env, jni_cid_ParcelUuid,
139                                                                 jni_mid_fromString,
140                                                                 str_uuid);
141     if (!jni_obj_parcelUuid)
142     {
143         OIC_LOG(ERROR, TAG, "Fail to get jni uuid object");
144         goto error_exit;
145     }
146
147     return jni_obj_parcelUuid;
148 error_exit:
149     CACheckJNIException(env);
150     return NULL;
151 }
152
153 static int CALEGetIntFromHex(char c)
154 {
155     if(c >= '0' && c <= '9')
156         return c - '0';
157     switch (c)
158     {
159         case 'A':
160             return 10;
161         case 'B':
162             return 11;
163         case 'C':
164             return 12;
165         case 'D':
166             return 13;
167         case 'E':
168             return 14;
169         case 'F':
170             return 15;
171         default:
172             return -1;
173     }
174 }
175
176 jbyteArray CALEGetManufacturerData(JNIEnv *env, const char* uuid)
177 {
178     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
179     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
180
181     jbyteArray jni_byte_Data = (*env)->NewByteArray(env, 2);
182     uint8_t data_array[2];
183     int c1,c2,c3,c4;
184     c1 = CALEGetIntFromHex(uuid[4]);
185     c2 = CALEGetIntFromHex(uuid[5]);
186     c3 = CALEGetIntFromHex(uuid[6]);
187     c4 = CALEGetIntFromHex(uuid[7]);
188     data_array[0] = c1 * 16 + c2;
189     data_array[1] = c3 * 16 + c4;
190     OIC_LOG_V(DEBUG, TAG, "data_array[0]: %d, data_array[1]: %d", data_array[0], data_array[1]);
191     (*env)->SetByteArrayRegion(env, jni_byte_Data, 0, 2, data_array);
192     return jni_byte_Data;
193
194 }
195
196 bool CALEIsBondedDevice(JNIEnv *env, jobject bluetoothDevice)
197 {
198     VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
199     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", false);
200
201     jmethodID jni_mid_getBondState = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
202                                                       "getBondState",
203                                                       "()I");
204     if (!jni_mid_getBondState)
205     {
206         OIC_LOG(ERROR, TAG, "jni_mid_getBondState is null");
207         return false;
208     }
209
210     jint jni_bondState = (jint)(*env)->CallIntMethod(env, bluetoothDevice, jni_mid_getBondState);
211     CACheckJNIException(env);
212     OIC_LOG_V(DEBUG, TAG, "bond state is %d", jni_bondState);
213
214     if (BOND_BONDED == jni_bondState)
215     {
216         OIC_LOG(DEBUG, TAG, "remote device is bonded");
217         return true;
218     }
219     else
220     {
221         OIC_LOG(DEBUG, TAG, "remote device is not bonded");
222         return false;
223     }
224
225     return false;
226 }
227
228 jobjectArray CALEGetBondedDevices(JNIEnv *env)
229 {
230     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
231
232     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
233     if (!jni_cid_BTAdapter)
234     {
235         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_cid_BTAdapter is null");
236         goto error_exit;
237     }
238
239     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
240                                                                     "getDefaultAdapter",
241                                                                     METHODID_OBJECTNONPARAM);
242     CACheckJNIException(env);
243     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
244                                                                jni_mid_getDefaultAdapter);
245     if (!jni_obj_BTAdapter)
246     {
247         OIC_LOG(ERROR, TAG, "getBondedDevices: bluetooth adapter is null");
248         goto error_exit;
249     }
250
251     // Get a list of currently paired devices
252     jmethodID jni_mid_getBondedDevices = (*env)->GetMethodID(env, jni_cid_BTAdapter,
253                                                              "getBondedDevices",
254                                                              "()Ljava/util/Set;");
255     if (!jni_mid_getBondedDevices)
256     {
257         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_mid_getBondedDevicesr is null");
258         goto error_exit;
259     }
260
261     jobject jni_obj_setPairedDevices = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
262                                                                 jni_mid_getBondedDevices);
263     if (!jni_obj_setPairedDevices)
264     {
265         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_obj_setPairedDevices is null");
266         goto error_exit;
267     }
268
269     jmethodID jni_mid_toArray = CAGetJNIMethodID(env, "java/util/Set", "toArray",
270                                                  "()[Ljava/lang/Object;");
271     if (!jni_mid_toArray)
272     {
273         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_mid_toArray is null");
274         return NULL;
275     }
276
277     jobjectArray jni_arrayPairedDevices = (jobjectArray)(
278             (*env)->CallObjectMethod(env, jni_obj_setPairedDevices, jni_mid_toArray));
279     if (!jni_arrayPairedDevices)
280     {
281         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_arrayPairedDevices is null");
282         goto error_exit;
283     }
284
285     return jni_arrayPairedDevices;
286
287 error_exit:
288     CACheckJNIException(env);
289     return NULL;
290 }
291
292 jint CALEGetBTStateOnInfo(JNIEnv *env)
293 {
294     VERIFY_NON_NULL_RET(env, TAG, "env is null", -1);
295
296     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
297     if (!jni_cid_BTAdapter)
298     {
299         OIC_LOG(ERROR, TAG, "getBTStateOnInfo: jni_cid_BTAdapter is null");
300         CACheckJNIException(env);
301         return -1;
302     }
303
304     jfieldID jni_fid_stateon = (*env)->GetStaticFieldID(env, jni_cid_BTAdapter, "STATE_ON", "I");
305     if (!jni_fid_stateon)
306     {
307         OIC_LOG(ERROR, TAG, "get_field_state is not available");
308         CACheckJNIException(env);
309         return -1;
310     }
311
312     jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTAdapter, jni_fid_stateon);
313     CACheckJNIException(env);
314     OIC_LOG_V(DEBUG, TAG, "bluetooth.STATE_ON state integer value : %d", jni_int_val);
315
316     return jni_int_val;
317 }
318
319 CAResult_t CALECheckPlatformVersion(JNIEnv *env, uint16_t level)
320 {
321     jint jni_int_sdk = CALEGetBuildVersion(env);
322     if (jni_int_sdk < level)
323     {
324         OIC_LOG(ERROR, TAG, "it is not supported");
325         return CA_NOT_SUPPORTED;
326     }
327
328     return CA_STATUS_OK;
329 }
330
331 jint CALEGetBuildVersion(JNIEnv *env)
332 {
333     VERIFY_NON_NULL_RET(env, TAG, "env is null", -1);
334
335     // VERSION is a nested class within android.os.Build (hence "$" rather than "/")
336     jclass jni_cls_version = (*env)->FindClass(env, "android/os/Build$VERSION");
337     if (!jni_cls_version)
338     {
339         OIC_LOG(ERROR, TAG, "jni_cls_version is null");
340         CACheckJNIException(env);
341         return -1;
342     }
343
344     jfieldID jni_fid_sdk = (*env)->GetStaticFieldID(env, jni_cls_version, "SDK_INT", "I");
345     if (!jni_fid_sdk)
346     {
347         OIC_LOG(ERROR, TAG, "jni_fid_sdk is null");
348         CACheckJNIException(env);
349         return -1;
350     }
351
352     jint jni_int_sdk = (*env)->GetStaticIntField(env, jni_cls_version, jni_fid_sdk);
353     CACheckJNIException(env);
354     OIC_LOG_V(DEBUG, TAG, "sdk version is %d", jni_int_sdk);
355
356     return jni_int_sdk;
357 }
358
359 jint CALEGetBuildVersionCodeForName(JNIEnv *env, const char* versionName)
360 {
361     VERIFY_NON_NULL_RET(env, TAG, "env is null", -1);
362     VERIFY_NON_NULL_RET(versionName, TAG, "versionName is null", -1);
363
364     // VERSION is a nested class within android.os.Build (hence "$" rather than "/")
365     jclass jni_cls_version = (*env)->FindClass(env, "android/os/Build$VERSION_CODES");
366     if (!jni_cls_version)
367     {
368         OIC_LOG(ERROR, TAG, "jni_cls_version is null");
369         CACheckJNIException(env);
370         return -1;
371     }
372
373     jfieldID jni_fid_version = (*env)->GetStaticFieldID(env, jni_cls_version, versionName, "I");
374     if (!jni_fid_version)
375     {
376         OIC_LOG(ERROR, TAG, "jni_fid_version is null");
377         CACheckJNIException(env);
378         return -1;
379     }
380
381     jint jni_int_version = (*env)->GetStaticIntField(env, jni_cls_version, jni_fid_version);
382     CACheckJNIException(env);
383     OIC_LOG_V(DEBUG, TAG, "version [%s] is %d",versionName, jni_int_version);
384
385     return jni_int_version;
386 }
387
388 jboolean CALEIsEnableBTAdapter(JNIEnv *env)
389 {
390     VERIFY_NON_NULL_RET(env, TAG, "env is null", JNI_FALSE);
391
392     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
393     if (!jni_cid_BTAdapter)
394     {
395         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter: jni_cid_BTAdapter is null");
396         CACheckJNIException(env);
397         return JNI_FALSE;
398     }
399
400     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
401                                                                     "getDefaultAdapter",
402                                                                     METHODID_OBJECTNONPARAM);
403     if (!jni_mid_getDefaultAdapter)
404     {
405         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
406         CACheckJNIException(env);
407         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
408         return JNI_FALSE;
409     }
410
411     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
412                                                                jni_mid_getDefaultAdapter);
413     if (!jni_obj_BTAdapter)
414     {
415         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
416         CACheckJNIException(env);
417         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
418         return JNI_FALSE;
419     }
420
421     // isEnable()
422     jmethodID jni_mid_isEnable = (*env)->GetMethodID(env, jni_cid_BTAdapter, "isEnabled", "()Z");
423     if (!jni_mid_isEnable)
424     {
425         OIC_LOG(ERROR, TAG, "jni_mid_isEnable is null");
426         CACheckJNIException(env);
427         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
428         (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
429         return JNI_FALSE;
430     }
431
432     jboolean jni_isEnable = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter, jni_mid_isEnable);
433     CACheckJNIException(env);
434     OIC_LOG_V(DEBUG, TAG, "adapter state is %d", jni_isEnable);
435
436     (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
437     (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
438     return jni_isEnable;
439 }
440
441 jstring CALEGetAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
442 {
443     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
444     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
445
446     jmethodID jni_mid_getAddress = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
447                                                     "getAddress",
448                                                     "()Ljava/lang/String;");
449     if (!jni_mid_getAddress)
450     {
451         OIC_LOG(ERROR, TAG, "jni_mid_getAddress is null");
452         return NULL;
453     }
454
455     jstring jni_address = (jstring)(*env)->CallObjectMethod(env, bluetoothDevice,
456                                                             jni_mid_getAddress);
457     if (!jni_address)
458     {
459         OIC_LOG(ERROR, TAG, "jni_address is null");
460         CACheckJNIException(env);
461         return NULL;
462     }
463
464     return jni_address;
465 }
466
467 jint CALEGetConstantsValue(JNIEnv *env, const char* classType, const char* name)
468 {
469     VERIFY_NON_NULL_RET(env, TAG, "env", -1);
470     VERIFY_NON_NULL_RET(classType, TAG, "classType", -1);
471     VERIFY_NON_NULL_RET(name, TAG, "name", -1);
472
473     jclass jni_cid = (*env)->FindClass(env, classType);
474     if (!jni_cid)
475     {
476         OIC_LOG(ERROR, TAG, "jni_cid is null");
477         CACheckJNIException(env);
478         return -1;
479     }
480
481     jfieldID jni_fieldID = (*env)->GetStaticFieldID(env, jni_cid,
482                                                     name, "I");
483     if (!jni_fieldID)
484     {
485         OIC_LOG(ERROR, TAG, "jni_fieldID is null");
486         CACheckJNIException(env);
487         return -1;
488     }
489
490     jint jni_id = (*env)->GetStaticIntField(env, jni_cid, jni_fieldID);
491     CACheckJNIException(env);
492     return jni_id;
493 }
494
495 jobject CALEGetRemoteDevice(JNIEnv *env, jstring address)
496 {
497     OIC_LOG(DEBUG, TAG, "CALEGetRemoteDevice");
498
499     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
500     VERIFY_NON_NULL_RET(address, TAG, "address is null", NULL);
501
502     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
503     if (!jni_cid_BTAdapter)
504     {
505         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
506         goto error_exit;
507     }
508
509     // get remote bt adapter method
510     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
511                                                                     "getDefaultAdapter",
512                                                                     METHODID_OBJECTNONPARAM);
513     if (!jni_mid_getDefaultAdapter)
514     {
515         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
516         goto error_exit;
517     }
518
519     // gat bt adapter object
520     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
521                                                                jni_mid_getDefaultAdapter);
522     if (!jni_obj_BTAdapter)
523     {
524         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
525         goto error_exit;
526     }
527
528     jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
529                                                             "getRemoteDevice",
530                                                             METHODID_BT_REMOTE_DEVICE);
531     if (!jni_mid_getRemoteDevice)
532     {
533         OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
534         goto error_exit;
535     }
536
537     jobject jni_obj_device = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
538                                                       jni_mid_getRemoteDevice,
539                                                       address);
540     if (!jni_obj_device)
541     {
542         OIC_LOG(ERROR, TAG, "jni_obj_device is null");
543         goto error_exit;
544     }
545     return jni_obj_device;
546
547 error_exit:
548     CACheckJNIException(env);
549     return NULL;
550 }
551
552 jstring CALEGetAddressFromGatt(JNIEnv *env, jobject gatt)
553 {
554     OIC_LOG(DEBUG, TAG, "CALEGetAddressFromGatt");
555
556     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
557     VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
558
559     jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
560                                                    METHODID_BT_DEVICE);
561     if (!jni_mid_getDevice)
562     {
563         OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
564         return NULL;
565     }
566
567     jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
568     if (!jni_obj_device)
569     {
570         OIC_LOG(ERROR, TAG, "jni_obj_device is null");
571         CACheckJNIException(env);
572         return NULL;
573     }
574
575     jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
576     if (!jni_address)
577     {
578         OIC_LOG(ERROR, TAG, "jni_address is null");
579         return NULL;
580     }
581
582     return jni_address;
583 }
584
585 bool CALEAttachCurrentThread(JNIEnv **env, JavaVM *g_jvm, bool *attach_status)
586 {
587     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) env, JNI_VERSION_1_6);
588     if (JNI_OK != res)
589     {
590         res = (*g_jvm)->AttachCurrentThread(g_jvm, env, NULL);
591
592         if (JNI_OK != res)
593         {
594             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
595             return false;
596         }
597         *attach_status = true;
598     }
599
600     return true;
601 }