Implementation of Filtered Scan for BLE android client
[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 jbyteArray CALEGetManufacturerData(JNIEnv *env, const char* uuid)
154 {
155     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
156     VERIFY_NON_NULL_RET(uuid, TAG, "uuid is null", NULL);
157
158     jbyteArray jni_byte_Data = (*env)->NewByteArray(env, 2);
159     uint8_t data_array[2];
160     if(uuid[7] == '9')
161     {
162         // OIC_GATT_CUSTOM_UUID
163         data_array[0] = 66, data_array[1] = 9;
164     }
165     else if(uuid[7] == '4')
166     {
167         // OIC_GATT_CUSTOM_UUID2
168         data_array[0] = 66, data_array[1] = 4;
169     }
170     else
171     {
172         // OIC_GATT_CUSTOM_UUID3
173         data_array[0] = 66, data_array[1] = 12;
174     }
175     (*env)->SetByteArrayRegion(env, jni_byte_Data, 0, 2, data_array);
176     return jni_byte_Data;
177
178 }
179
180 bool CALEIsBondedDevice(JNIEnv *env, jobject bluetoothDevice)
181 {
182     VERIFY_NON_NULL_RET(env, TAG, "env is null", false);
183     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", false);
184
185     jmethodID jni_mid_getBondState = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
186                                                       "getBondState",
187                                                       "()I");
188     if (!jni_mid_getBondState)
189     {
190         OIC_LOG(ERROR, TAG, "jni_mid_getBondState is null");
191         return false;
192     }
193
194     jint jni_bondState = (jint)(*env)->CallIntMethod(env, bluetoothDevice, jni_mid_getBondState);
195     CACheckJNIException(env);
196     OIC_LOG_V(DEBUG, TAG, "bond state is %d", jni_bondState);
197
198     if (BOND_BONDED == jni_bondState)
199     {
200         OIC_LOG(DEBUG, TAG, "remote device is bonded");
201         return true;
202     }
203     else
204     {
205         OIC_LOG(DEBUG, TAG, "remote device is not bonded");
206         return false;
207     }
208
209     return false;
210 }
211
212 jobjectArray CALEGetBondedDevices(JNIEnv *env)
213 {
214     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
215
216     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
217     if (!jni_cid_BTAdapter)
218     {
219         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_cid_BTAdapter is null");
220         goto error_exit;
221     }
222
223     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
224                                                                     "getDefaultAdapter",
225                                                                     METHODID_OBJECTNONPARAM);
226     CACheckJNIException(env);
227     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
228                                                                jni_mid_getDefaultAdapter);
229     if (!jni_obj_BTAdapter)
230     {
231         OIC_LOG(ERROR, TAG, "getBondedDevices: bluetooth adapter is null");
232         goto error_exit;
233     }
234
235     // Get a list of currently paired devices
236     jmethodID jni_mid_getBondedDevices = (*env)->GetMethodID(env, jni_cid_BTAdapter,
237                                                              "getBondedDevices",
238                                                              "()Ljava/util/Set;");
239     if (!jni_mid_getBondedDevices)
240     {
241         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_mid_getBondedDevicesr is null");
242         goto error_exit;
243     }
244
245     jobject jni_obj_setPairedDevices = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
246                                                                 jni_mid_getBondedDevices);
247     if (!jni_obj_setPairedDevices)
248     {
249         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_obj_setPairedDevices is null");
250         goto error_exit;
251     }
252
253     jmethodID jni_mid_toArray = CAGetJNIMethodID(env, "java/util/Set", "toArray",
254                                                  "()[Ljava/lang/Object;");
255     if (!jni_mid_toArray)
256     {
257         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_mid_toArray is null");
258         return NULL;
259     }
260
261     jobjectArray jni_arrayPairedDevices = (jobjectArray)(
262             (*env)->CallObjectMethod(env, jni_obj_setPairedDevices, jni_mid_toArray));
263     if (!jni_arrayPairedDevices)
264     {
265         OIC_LOG(ERROR, TAG, "getBondedDevices: jni_arrayPairedDevices is null");
266         goto error_exit;
267     }
268
269     return jni_arrayPairedDevices;
270
271 error_exit:
272     CACheckJNIException(env);
273     return NULL;
274 }
275
276 jint CALEGetBTStateOnInfo(JNIEnv *env)
277 {
278     VERIFY_NON_NULL_RET(env, TAG, "env is null", -1);
279
280     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
281     if (!jni_cid_BTAdapter)
282     {
283         OIC_LOG(ERROR, TAG, "getBTStateOnInfo: jni_cid_BTAdapter is null");
284         CACheckJNIException(env);
285         return -1;
286     }
287
288     jfieldID jni_fid_stateon = (*env)->GetStaticFieldID(env, jni_cid_BTAdapter, "STATE_ON", "I");
289     if (!jni_fid_stateon)
290     {
291         OIC_LOG(ERROR, TAG, "get_field_state is not available");
292         CACheckJNIException(env);
293         return -1;
294     }
295
296     jint jni_int_val = (*env)->GetStaticIntField(env, jni_cid_BTAdapter, jni_fid_stateon);
297     CACheckJNIException(env);
298     OIC_LOG_V(DEBUG, TAG, "bluetooth.STATE_ON state integer value : %d", jni_int_val);
299
300     return jni_int_val;
301 }
302
303 CAResult_t CALECheckPlatformVersion(JNIEnv *env, uint16_t level)
304 {
305     jint jni_int_sdk = CALEGetBuildVersion(env);
306     if (jni_int_sdk < level)
307     {
308         OIC_LOG(ERROR, TAG, "it is not supported");
309         return CA_NOT_SUPPORTED;
310     }
311
312     return CA_STATUS_OK;
313 }
314
315 jint CALEGetBuildVersion(JNIEnv *env)
316 {
317     VERIFY_NON_NULL_RET(env, TAG, "env is null", -1);
318
319     // VERSION is a nested class within android.os.Build (hence "$" rather than "/")
320     jclass jni_cls_version = (*env)->FindClass(env, "android/os/Build$VERSION");
321     if (!jni_cls_version)
322     {
323         OIC_LOG(ERROR, TAG, "jni_cls_version is null");
324         CACheckJNIException(env);
325         return -1;
326     }
327
328     jfieldID jni_fid_sdk = (*env)->GetStaticFieldID(env, jni_cls_version, "SDK_INT", "I");
329     if (!jni_fid_sdk)
330     {
331         OIC_LOG(ERROR, TAG, "jni_fid_sdk is null");
332         CACheckJNIException(env);
333         return -1;
334     }
335
336     jint jni_int_sdk = (*env)->GetStaticIntField(env, jni_cls_version, jni_fid_sdk);
337     CACheckJNIException(env);
338     OIC_LOG_V(DEBUG, TAG, "sdk version is %d", jni_int_sdk);
339
340     return jni_int_sdk;
341 }
342
343 jint CALEGetBuildVersionCodeForName(JNIEnv *env, const char* versionName)
344 {
345     VERIFY_NON_NULL_RET(env, TAG, "env is null", -1);
346     VERIFY_NON_NULL_RET(versionName, TAG, "versionName is null", -1);
347
348     // VERSION is a nested class within android.os.Build (hence "$" rather than "/")
349     jclass jni_cls_version = (*env)->FindClass(env, "android/os/Build$VERSION_CODES");
350     if (!jni_cls_version)
351     {
352         OIC_LOG(ERROR, TAG, "jni_cls_version is null");
353         CACheckJNIException(env);
354         return -1;
355     }
356
357     jfieldID jni_fid_version = (*env)->GetStaticFieldID(env, jni_cls_version, versionName, "I");
358     if (!jni_fid_version)
359     {
360         OIC_LOG(ERROR, TAG, "jni_fid_version is null");
361         CACheckJNIException(env);
362         return -1;
363     }
364
365     jint jni_int_version = (*env)->GetStaticIntField(env, jni_cls_version, jni_fid_version);
366     CACheckJNIException(env);
367     OIC_LOG_V(DEBUG, TAG, "version [%s] is %d",versionName, jni_int_version);
368
369     return jni_int_version;
370 }
371
372 jboolean CALEIsEnableBTAdapter(JNIEnv *env)
373 {
374     VERIFY_NON_NULL_RET(env, TAG, "env is null", JNI_FALSE);
375
376     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
377     if (!jni_cid_BTAdapter)
378     {
379         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter: jni_cid_BTAdapter is null");
380         CACheckJNIException(env);
381         return JNI_FALSE;
382     }
383
384     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
385                                                                     "getDefaultAdapter",
386                                                                     METHODID_OBJECTNONPARAM);
387     if (!jni_mid_getDefaultAdapter)
388     {
389         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
390         CACheckJNIException(env);
391         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
392         return JNI_FALSE;
393     }
394
395     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
396                                                                jni_mid_getDefaultAdapter);
397     if (!jni_obj_BTAdapter)
398     {
399         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
400         CACheckJNIException(env);
401         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
402         return JNI_FALSE;
403     }
404
405     // isEnable()
406     jmethodID jni_mid_isEnable = (*env)->GetMethodID(env, jni_cid_BTAdapter, "isEnabled", "()Z");
407     if (!jni_mid_isEnable)
408     {
409         OIC_LOG(ERROR, TAG, "jni_mid_isEnable is null");
410         CACheckJNIException(env);
411         (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
412         (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
413         return JNI_FALSE;
414     }
415
416     jboolean jni_isEnable = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter, jni_mid_isEnable);
417     CACheckJNIException(env);
418     OIC_LOG_V(DEBUG, TAG, "adapter state is %d", jni_isEnable);
419
420     (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
421     (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
422     return jni_isEnable;
423 }
424
425 jstring CALEGetAddressFromBTDevice(JNIEnv *env, jobject bluetoothDevice)
426 {
427     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
428     VERIFY_NON_NULL_RET(bluetoothDevice, TAG, "bluetoothDevice is null", NULL);
429
430     jmethodID jni_mid_getAddress = CAGetJNIMethodID(env, "android/bluetooth/BluetoothDevice",
431                                                     "getAddress",
432                                                     "()Ljava/lang/String;");
433     if (!jni_mid_getAddress)
434     {
435         OIC_LOG(ERROR, TAG, "jni_mid_getAddress is null");
436         return NULL;
437     }
438
439     jstring jni_address = (jstring)(*env)->CallObjectMethod(env, bluetoothDevice,
440                                                             jni_mid_getAddress);
441     if (!jni_address)
442     {
443         OIC_LOG(ERROR, TAG, "jni_address is null");
444         CACheckJNIException(env);
445         return NULL;
446     }
447
448     return jni_address;
449 }
450
451 jint CALEGetConstantsValue(JNIEnv *env, const char* classType, const char* name)
452 {
453     VERIFY_NON_NULL_RET(env, TAG, "env", -1);
454     VERIFY_NON_NULL_RET(classType, TAG, "classType", -1);
455     VERIFY_NON_NULL_RET(name, TAG, "name", -1);
456
457     jclass jni_cid = (*env)->FindClass(env, classType);
458     if (!jni_cid)
459     {
460         OIC_LOG(ERROR, TAG, "jni_cid is null");
461         CACheckJNIException(env);
462         return -1;
463     }
464
465     jfieldID jni_fieldID = (*env)->GetStaticFieldID(env, jni_cid,
466                                                     name, "I");
467     if (!jni_fieldID)
468     {
469         OIC_LOG(ERROR, TAG, "jni_fieldID is null");
470         CACheckJNIException(env);
471         return -1;
472     }
473
474     jint jni_id = (*env)->GetStaticIntField(env, jni_cid, jni_fieldID);
475     CACheckJNIException(env);
476     return jni_id;
477 }
478
479 jobject CALEGetRemoteDevice(JNIEnv *env, jstring address)
480 {
481     OIC_LOG(DEBUG, TAG, "CALEGetRemoteDevice");
482
483     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
484     VERIFY_NON_NULL_RET(address, TAG, "address is null", NULL);
485
486     jclass jni_cid_BTAdapter = (*env)->FindClass(env, CLASSPATH_BT_ADAPTER);
487     if (!jni_cid_BTAdapter)
488     {
489         OIC_LOG(ERROR, TAG, "jni_cid_BTAdapter is null");
490         goto error_exit;
491     }
492
493     // get remote bt adapter method
494     jmethodID jni_mid_getDefaultAdapter = (*env)->GetStaticMethodID(env, jni_cid_BTAdapter,
495                                                                     "getDefaultAdapter",
496                                                                     METHODID_OBJECTNONPARAM);
497     if (!jni_mid_getDefaultAdapter)
498     {
499         OIC_LOG(ERROR, TAG, "jni_mid_getDefaultAdapter is null");
500         goto error_exit;
501     }
502
503     // gat bt adapter object
504     jobject jni_obj_BTAdapter = (*env)->CallStaticObjectMethod(env, jni_cid_BTAdapter,
505                                                                jni_mid_getDefaultAdapter);
506     if (!jni_obj_BTAdapter)
507     {
508         OIC_LOG(ERROR, TAG, "jni_obj_BTAdapter is null");
509         goto error_exit;
510     }
511
512     jmethodID jni_mid_getRemoteDevice = (*env)->GetMethodID(env, jni_cid_BTAdapter,
513                                                             "getRemoteDevice",
514                                                             METHODID_BT_REMOTE_DEVICE);
515     if (!jni_mid_getRemoteDevice)
516     {
517         OIC_LOG(ERROR, TAG, "jni_mid_getRemoteDevice is null");
518         goto error_exit;
519     }
520
521     jobject jni_obj_device = (*env)->CallObjectMethod(env, jni_obj_BTAdapter,
522                                                       jni_mid_getRemoteDevice,
523                                                       address);
524     if (!jni_obj_device)
525     {
526         OIC_LOG(ERROR, TAG, "jni_obj_device is null");
527         goto error_exit;
528     }
529     return jni_obj_device;
530
531 error_exit:
532     CACheckJNIException(env);
533     return NULL;
534 }
535
536 jstring CALEGetAddressFromGatt(JNIEnv *env, jobject gatt)
537 {
538     OIC_LOG(DEBUG, TAG, "CALEGetAddressFromGatt");
539
540     VERIFY_NON_NULL_RET(env, TAG, "env is null", NULL);
541     VERIFY_NON_NULL_RET(gatt, TAG, "gatt is null", NULL);
542
543     jmethodID jni_mid_getDevice = CAGetJNIMethodID(env, CLASSPATH_BT_GATT, "getDevice",
544                                                    METHODID_BT_DEVICE);
545     if (!jni_mid_getDevice)
546     {
547         OIC_LOG(ERROR, TAG, "jni_mid_getDevice is null");
548         return NULL;
549     }
550
551     jobject jni_obj_device = (*env)->CallObjectMethod(env, gatt, jni_mid_getDevice);
552     if (!jni_obj_device)
553     {
554         OIC_LOG(ERROR, TAG, "jni_obj_device is null");
555         CACheckJNIException(env);
556         return NULL;
557     }
558
559     jstring jni_address = CALEGetAddressFromBTDevice(env, jni_obj_device);
560     if (!jni_address)
561     {
562         OIC_LOG(ERROR, TAG, "jni_address is null");
563         return NULL;
564     }
565
566     return jni_address;
567 }