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