[CONPRO-1483] Implementation of API for setting scanfilter UUIDs
[platform/upstream/iotivity.git] / resource / csdk / connectivity / util / src / camanager / bt_le_manager / android / caleconnectionmanager.c
1 /* ****************************************************************
2  *
3  * Copyright 2016 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 "logger.h"
23 #include "cautilinterface.h"
24 #include "camanagerleinterface.h"
25 #include "camanagerleutil.h"
26 #include "caleautoconnector.h"
27 #include "cacommon.h"
28 #include "cacommonutil.h"
29 #include "camanagerdevice.h"
30 #include "caleclient.h"
31 #include "caleutils.h"
32
33 #define TAG "OIC_CA_MANAGER_LE"
34
35 static const jint SUPPORT_ADNROID_API_LEVEL = 18;
36 static const jint AUTH_FAIL = 5;
37 static const jint LINK_LOSS = 8;
38 static const jint ACCEPT_TIMEOUT_EXCEPTION = 16;
39 static const jint REMOTE_DISCONNECT = 19;
40 static const jint LOCAL_DISCONNECT = 22;
41 static const jint USER_REMOVED_BOND = 68;
42 static JavaVM *g_jvm = NULL;
43 static jobject g_context = NULL;
44 static jobject g_connectedDeviceSet = NULL;
45
46 void CASetScanUuid(char* uuid, int uuid_type)
47 {
48     OIC_LOG(DEBUG, TAG, "CASetScanUuid");
49
50     CALEClientAddUuid(uuid, uuid_type);
51 }
52
53 CAResult_t CASetLEClientAutoConnectionDeviceInfo(const char* address)
54 {
55     OIC_LOG(DEBUG, TAG, "CASetClientAutoConnectionDeviceInfo");
56     VERIFY_NON_NULL(address, TAG, "address");
57
58     bool isAttached = false;
59     JNIEnv* env = NULL;
60     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
61     if (JNI_OK != res)
62     {
63         OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
64         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
65
66         if (JNI_OK != res)
67         {
68             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
69             return CA_STATUS_FAILED;
70         }
71         isAttached = true;
72     }
73     OIC_LOG_V(DEBUG, TAG, "set [%s] for Auto Connection", address);
74
75     jstring jni_leAddress = (*env)->NewStringUTF(env, address);
76     if (!jni_leAddress)
77     {
78         OIC_LOG(ERROR, TAG, "jni_leAddress is null");
79         goto error_exit;
80     }
81
82     if (!CAManagerCheckBTAddress(env, jni_leAddress))
83     {
84         OIC_LOG(ERROR, TAG, "this address is not BT address string format");
85         goto error_exit;
86     }
87
88     // if there is target address in SharedPreference, it will be reset.
89     if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
90     {
91         if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
92                                                    g_connectedDeviceSet))
93         {
94             OIC_LOG(ERROR, TAG, "Preference - remove has failed");
95         }
96         else
97         {
98             OIC_LOG(INFO, TAG, "Preference - remove success");
99         }
100     }
101
102     // it will be added new target address.
103     if (!CAManagerAddConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
104     {
105         OIC_LOG(ERROR, TAG, "Preference - putting has failed");
106     }
107     else
108     {
109         OIC_LOG(INFO, TAG, "Preference - putting success");
110     }
111
112     if (isAttached)
113     {
114         (*g_jvm)->DetachCurrentThread(g_jvm);
115     }
116
117     return CA_STATUS_OK;
118
119 error_exit:
120
121     if (isAttached)
122     {
123         (*g_jvm)->DetachCurrentThread(g_jvm);
124     }
125
126     return CA_STATUS_FAILED;
127 }
128
129 CAResult_t CAUnsetLEClientAutoConnectionDeviceInfo(const char* address)
130 {
131     OIC_LOG(DEBUG, TAG, "CAUnsetClientAutoConnectionDeviceInfo");
132     VERIFY_NON_NULL(address, TAG, "address");
133
134     bool isAttached = false;
135     JNIEnv* env = NULL;
136     jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
137     if (JNI_OK != res)
138     {
139         OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
140         res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
141
142         if (JNI_OK != res)
143         {
144             OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
145             return CA_STATUS_FAILED;
146         }
147         isAttached = true;
148     }
149     OIC_LOG_V(DEBUG, TAG, "unset [%s] for Auto Connection", address);
150
151     jstring jni_leAddress = (*env)->NewStringUTF(env, address);
152     if (!jni_leAddress)
153     {
154         OIC_LOG(ERROR, TAG, "jni_leAddress is null");
155         goto error_exit;
156     }
157
158     if (!CAManagerCheckBTAddress(env, jni_leAddress))
159     {
160         OIC_LOG(ERROR, TAG, "this address is not BT address string format");
161         goto error_exit;
162     }
163
164     // if there is target address in SharedPreference, it will be removed
165     if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
166     {
167         if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
168                                                    g_connectedDeviceSet))
169         {
170             OIC_LOG(ERROR, TAG, "Preference - remove has failed");
171         }
172         else
173         {
174             OIC_LOG(INFO, TAG, "Preference - remove success");
175         }
176     }
177
178     // remove target device for auto connection
179     CAResult_t ret = CAManagerRemoveACData(env, jni_leAddress);
180     if (CA_STATUS_OK != ret)
181     {
182         OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
183     }
184
185     if (isAttached)
186     {
187         (*g_jvm)->DetachCurrentThread(g_jvm);
188     }
189
190     return ret;
191
192 error_exit:
193
194     if (isAttached)
195     {
196         (*g_jvm)->DetachCurrentThread(g_jvm);
197     }
198
199     return CA_STATUS_FAILED;
200 }
201
202 CAResult_t CAManagerLEClientInitialize(JNIEnv *env, JavaVM *jvm, jobject context)
203 {
204     OIC_LOG(DEBUG, TAG, "CAManagerClientInitialize");
205     VERIFY_NON_NULL(env, TAG, "env");
206     VERIFY_NON_NULL(jvm, TAG, "jvm");
207     VERIFY_NON_NULL(context, TAG, "context");
208
209     jint jni_int_sdk = CALEGetBuildVersion(env);
210     if (jni_int_sdk < SUPPORT_ADNROID_API_LEVEL)
211     {
212         OIC_LOG_V(ERROR, TAG, "it is not supported (%d)", jni_int_sdk);
213         return CA_STATUS_FAILED;
214     }
215
216     g_jvm = jvm;
217     g_context = (*env)->NewGlobalRef(env, context);;
218
219     CAManagerInitMutexVaraibles();
220     CAManagerInitLEAutoConnection();
221     CAManagerCreateACDataList();
222
223     // get last connected device list
224     jobject set = NULL;
225     set = CAManagerGetConnectedDeviceAddress(env, g_context);
226     if (!set)
227     {
228         // create new set<String> object
229         set = CAManagerCreateSetString(env);
230         if (!set)
231         {
232             OIC_LOG(ERROR, TAG, "CAManagerCreateSetString has failed");
233             return CA_STATUS_FAILED;
234         }
235         OIC_LOG(DEBUG, TAG, "created new SetString");
236     }
237     else
238     {
239         OIC_LOG(DEBUG, TAG, "get previous Set<String> object");
240     }
241
242     g_connectedDeviceSet = (jobject)(*env)->NewGlobalRef(env, set);
243     if (!g_connectedDeviceSet)
244     {
245         OIC_LOG(ERROR, TAG, "g_connectedDeviceSet is null");
246         return CA_STATUS_FAILED;
247     }
248
249     return CA_STATUS_OK;
250 }
251
252 CAResult_t CAManagerLEClientTerminate(JNIEnv *env)
253 {
254     OIC_LOG(DEBUG, TAG, "CAManagerClientTerminate");
255     VERIFY_NON_NULL(env, TAG, "env");
256
257     // stop gatt connection
258     CAResult_t res = CALEClientDisconnectAll(env);
259     if (CA_STATUS_OK != res)
260     {
261         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
262     }
263
264     res = CAManagerRemoveAllACData(env);
265     if (CA_STATUS_OK != res)
266     {
267         OIC_LOG(ERROR, TAG, "CAManagerRemoveAllACData has failed");
268     }
269
270     CAManagerDestroyACDataList();
271     CAManagerTerminateLEAutoConnection();
272     CAManagerTerminateMutexVariables();
273
274     if (g_context)
275     {
276         (*env)->DeleteGlobalRef(env, g_context);
277         g_context = NULL;
278     }
279
280     if (g_connectedDeviceSet)
281     {
282         (*env)->DeleteGlobalRef(env, g_connectedDeviceSet);
283         g_connectedDeviceSet = NULL;
284     }
285
286     return res;
287 }
288
289 void CAManagerLESetScanInterval(jint interval, jint count)
290 {
291     OIC_LOG(DEBUG, TAG, "CAManagerLESetScanInterval");
292     CALERestartScanWithInterval(interval, count, BLE_SCAN_ENABLE);
293 }
294
295 void CAManagerLEStopScan()
296 {
297     OIC_LOG(DEBUG, TAG, "CAManagerLEStopScan");
298     CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE);
299 }
300
301 void CAManagerSetConfigure(CAUtilConfig_t config)
302 {
303     OIC_LOG_V(INFO, TAG, "set configure for bleFlags : %d", config.bleFlags);
304     caglobals.bleFlags = config.bleFlags;
305 }
306
307 CAResult_t CAManagerLEStartAdvertising()
308 {
309     CAResult_t ret = CALEServerStartAdvertise();
310     if (CA_STATUS_OK != ret)
311     {
312         OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
313     }
314     return ret;
315 }
316
317 CAResult_t CAManagerLEStopAdvertising()
318 {
319     CAResult_t ret = CALEServerStopAdvertise();
320     if (CA_STATUS_OK != ret)
321     {
322         OIC_LOG(ERROR, TAG, "CAManagerLEStopAdvertising has failed");
323     }
324     return ret;
325 }
326
327 JNIEXPORT void JNICALL
328 Java_org_iotivity_ca_CaLeClientInterface_caManagerAdapterStateChangedCallback(
329         JNIEnv *env, jobject obj, jint state)
330 {
331     OIC_LOG_V(INFO, TAG, "caManagerAdapterStateChangedCallback - state %d", state);
332     VERIFY_NON_NULL_VOID(env, TAG, "env");
333     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
334
335     jint state_on = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_ON");
336     jint state_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_OFF");
337     jint state_turning_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_TURNING_OFF");
338
339     if (state_on == state)
340     {
341         OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
342
343         // when BT state is on. recovery flag has to be reset.
344         CAManagerSetBTRecovery(false);
345
346         // find target device for autoconnect
347         size_t length = CAManagerGetACDataLength();
348         OIC_LOG_V(DEBUG, TAG, "length of ACDataList : %d", length);
349         for (size_t idx = 0; idx < length; idx++)
350         {
351             jstring leAddress = CAManagerGetLEAddressFromACData(env, idx);
352             if (leAddress)
353             {
354                 CAResult_t res = CAManagerStartAutoConnection(env, leAddress);
355                 if (CA_STATUS_OK != res)
356                 {
357                     OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
358                     return;
359                 }
360             }
361         }
362     }
363     else if (state_off == state)
364     {
365         OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
366
367         // reset isAutoConnecting flag for all target devices
368         size_t length = CAManagerGetACDataLength();
369         OIC_LOG_V(DEBUG, TAG, "length of ACDataList : %d", length);
370         for (size_t idx = 0; idx < length; idx++)
371         {
372             jstring address = CAManagerGetLEAddressFromACData(env, idx);
373             if (address)
374             {
375                 CAManagerSetAutoConnectingFlag(env, address, false);
376             }
377         }
378
379         // check whether BT recovery is needed or not
380         if (CAManagerIsRecoveryFlagSet())
381         {
382             CAManagerProcessRecovery(env, STATE_OFF);
383         }
384     }
385     else if (state_turning_off == state)
386     {
387         OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_turning_off");
388     }
389     else
390     {
391         OIC_LOG(INFO, TAG, "AdapterStateChangedCallback state is not available");
392     }
393 }
394
395 JNIEXPORT void JNICALL
396 Java_org_iotivity_ca_CaLeClientInterface_caManagerBondStateChangedCallback(
397         JNIEnv *env, jobject obj, jobject device)
398 {
399     OIC_LOG(INFO, TAG, "caManagerBondStateChangedCallback");
400     // this callback is called by CaLeClientInterface
401     // only when bond state is changed from BOND_BONDED to BOND_NONE
402     OIC_LOG(DEBUG, TAG, "bond state is changed from BOND_BONDED to BOND_NONE");
403     VERIFY_NON_NULL_VOID(env, TAG, "env");
404     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
405     VERIFY_NON_NULL_VOID(device, TAG, "device");
406
407     // get ble address from Bluetooth Device object
408     jstring jni_leAddress = CALEClientGetLEAddressFromBTDevice(env, device);
409     if (!jni_leAddress)
410     {
411         OIC_LOG(INFO, TAG, "unbonded : it isn't same device type");
412         return;
413     }
414
415     char* leAddress = (char*)(*env)->GetStringUTFChars(env, jni_leAddress, NULL);
416     if (!leAddress)
417     {
418         OIC_LOG(ERROR, TAG, "leAddress is null");
419         return;
420     }
421
422     // if there is no data, CAData will be created.
423     OIC_LOG_V(DEBUG, TAG, "bond none device : %s", leAddress);
424
425     CAResult_t res = CAManagerRemoveACData(env, jni_leAddress);
426     if (CA_STATUS_OK != res)
427     {
428         OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
429     }
430
431     (*env)->ReleaseStringUTFChars(env, jni_leAddress, leAddress);
432
433     if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
434                                                g_connectedDeviceSet))
435     {
436         OIC_LOG(ERROR, TAG, "CAManagerRemoveConnectedDeviceAddress has failed");
437     }
438 }
439
440 JNIEXPORT void JNICALL
441 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeGattConnectionStateChangeCB(
442         JNIEnv *env, jobject obj, jobject gatt, jint status, jint newState)
443 {
444     VERIFY_NON_NULL_VOID(env, TAG, "env");
445     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
446     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
447
448     jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
449     jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
450
451     jstring jni_address = CALEGetAddressFromGatt(env, gatt);
452     if (!jni_address)
453     {
454         OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
455         return;
456     }
457
458     char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
459     if (!address)
460     {
461         OIC_LOG(ERROR, TAG, "address is null");
462         (*env)->DeleteLocalRef(env, jni_address);
463         return;
464     }
465
466     if (GATT_SUCCESS == status && state_connected == newState) // le connected
467     {
468         CAResult_t res = CAManagerReadRemoteRssi(env, gatt);
469         if (CA_STATUS_OK != res)
470         {
471             OIC_LOG(ERROR, TAG, "CAManagerReadRemoteRssi has failed");
472             goto exit;
473         }
474     }
475     else if (state_disconnected == newState)// le disconnected
476     {
477         if (LINK_LOSS == status || REMOTE_DISCONNECT == status)
478         {
479             if (!CAManagerIsInACDataList(env, jni_address))
480             {
481                 OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
482                           address);
483                 goto exit;
484             }
485
486             CAManagerSetAutoConnectingFlag(env, jni_address, false);
487
488             CAResult_t res = CAManagerStartAutoConnection(env, jni_address);
489             if (CA_STATUS_OK != res)
490             {
491                 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
492                 goto exit;
493             }
494         }
495         else if (ACCEPT_TIMEOUT_EXCEPTION == status)
496         {
497             CAManagerProcessRecovery(env, START_RECOVERY);
498         }
499     }
500
501 exit:
502     (*env)->ReleaseStringUTFChars(env, jni_address, address);
503     (*env)->DeleteLocalRef(env, jni_address);
504 }
505
506 /*
507  * Class:     org_iotivity_ca_jar_caleinterface
508  * Method:    caManagerLeServicesDiscoveredCallback
509  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
510  */
511 JNIEXPORT void JNICALL
512 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeServicesDiscoveredCallback(JNIEnv *env,
513                                                                                jobject obj,
514                                                                                jobject gatt,
515                                                                                jint status)
516 {
517     VERIFY_NON_NULL_VOID(env, TAG, "env");
518     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
519     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
520
521     if (GATT_SUCCESS == status)
522     {
523         if (!g_connectedDeviceSet)
524         {
525             OIC_LOG(INFO, TAG, "g_connectedDeviceSet is needed for CM. "
526                     "please call CAManagerLEClientInitialize");
527             return;
528         }
529
530         jstring jni_address = CALEGetAddressFromGatt(env, gatt);
531         if (!jni_address)
532         {
533             OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
534             return;
535         }
536
537         char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
538         if (!address)
539         {
540             OIC_LOG(ERROR, TAG, "address is null");
541             (*env)->DeleteLocalRef(env, jni_address);
542             return;
543         }
544
545         if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_address, g_connectedDeviceSet))
546         {
547             OIC_LOG(INFO, TAG, "AC list - the address will be added to ACData list");
548             CAManagerAddACData(env, jni_address);
549             CAManagerSetAutoConnectingFlag(env, jni_address, false);
550
551             // next connection will be requested with JNI_TRUE on autoConnect flag
552             // after first connection
553             CALEClientSetFlagToState(env, jni_address, CA_LE_AUTO_CONNECT_FLAG, JNI_TRUE);
554         }
555         else
556         {
557             OIC_LOG(DEBUG, TAG, "AC list - the address is not set to AutoConnect");
558         }
559
560         (*env)->ReleaseStringUTFChars(env, jni_address, address);
561         (*env)->DeleteLocalRef(env, jni_address);
562     }
563     else
564     {
565         OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
566     }
567 }
568
569 /*
570  * Class:     org_iotivity_ca_jar_caleinterface
571  * Method:    caManagerLeRemoteRssiCallback
572  * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
573  */
574 JNIEXPORT void JNICALL
575 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeRemoteRssiCallback(JNIEnv *env,
576                                                                        jobject obj,
577                                                                        jobject gatt,
578                                                                        jint rssi,
579                                                                        jint status)
580 {
581 #ifndef TB_LOG
582     (void)rssi;
583     (void)status;
584 #endif
585     OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - rssi : %d: ", rssi);
586     OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - status : %d: ", status);
587     VERIFY_NON_NULL_VOID(env, TAG, "env");
588     VERIFY_NON_NULL_VOID(obj, TAG, "obj");
589     VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
590 }