1 /* ****************************************************************
3 * Copyright 2016 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
23 #include "cautilinterface.h"
24 #include "camanagerleinterface.h"
25 #include "camanagerleutil.h"
26 #include "caleautoconnector.h"
28 #include "cacommonutil.h"
29 #include "camanagerdevice.h"
30 #include "caleclient.h"
31 #include "caleutils.h"
33 #define TAG "OIC_CA_MANAGER_LE"
35 static CAAdapterStateChangedCB g_adapterStateCB = NULL;
36 static CAConnectionStateChangedCB g_connStateCB = NULL;
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 CONNECTION_FAILED_TO_BE_EASTABLISHED = 62;
45 static const jint USER_REMOVED_BOND = 68;
46 static JavaVM *g_jvm = NULL;
47 static jobject g_context = NULL;
48 static jobject g_connectedDeviceSet = NULL;
50 void CASetLENetworkMonitorCallbacks(CAAdapterStateChangedCB adapterStateCB,
51 CAConnectionStateChangedCB connStateCB)
53 OIC_LOG(DEBUG, TAG, "CASetLENetworkMonitorCallbacks");
55 g_adapterStateCB = adapterStateCB;
56 g_connStateCB = connStateCB;
59 CAResult_t CASetLEClientAutoConnectionDeviceInfo(const char* address)
61 OIC_LOG(DEBUG, TAG, "CASetClientAutoConnectionDeviceInfo");
62 VERIFY_NON_NULL(address, TAG, "address");
64 bool isAttached = false;
66 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
69 OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
70 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
74 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
75 return CA_STATUS_FAILED;
80 OIC_LOG_V(DEBUG, TAG, "set [%s] for Auto Connection", address);
81 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
83 if (!CAManagerCheckBTAddress(env, jni_leAddress))
85 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
88 (*g_jvm)->DetachCurrentThread(g_jvm);
90 return CA_STATUS_FAILED;
93 // if there is target address in SharedPreference. it will be reseted.
94 if (CAManagerIsConnectedDeviceAddress(env, g_context,
96 g_connectedDeviceSet))
98 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context,
100 g_connectedDeviceSet))
102 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
106 OIC_LOG(INFO, TAG, "Preference - remove success");
110 // it will be added new target address.
111 if (!CAManagerAddConnectedDeviceAddress(env, g_context,
112 jni_leAddress, g_connectedDeviceSet))
114 OIC_LOG(ERROR, TAG, "Preference - putting has failed");
118 OIC_LOG(INFO, TAG, "Preference - putting success");
123 (*g_jvm)->DetachCurrentThread(g_jvm);
129 CAResult_t CAUnsetLEClientAutoConnectionDeviceInfo(const char* address)
131 OIC_LOG(DEBUG, TAG, "CAUnsetClientAutoConnectionDeviceInfo");
132 VERIFY_NON_NULL(address, TAG, "address");
134 bool isAttached = false;
136 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
139 OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
140 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
144 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
145 return CA_STATUS_FAILED;
150 OIC_LOG_V(DEBUG, TAG, "unset [%s] for Auto Connection", address);
151 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
153 if (!CAManagerCheckBTAddress(env, jni_leAddress))
155 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
158 (*g_jvm)->DetachCurrentThread(g_jvm);
160 return CA_STATUS_FAILED;
163 // if there is target address in SharedPreference. it would be removed
164 if (CAManagerIsConnectedDeviceAddress(env, g_context,
166 g_connectedDeviceSet))
168 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context,
170 g_connectedDeviceSet))
172 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
176 OIC_LOG(INFO, TAG, "Preference - remove success");
180 // remove target device for auto connection
181 CAResult_t ret = CAManagerRemoveData(env, jni_leAddress);
182 if (CA_STATUS_OK != ret)
184 OIC_LOG(ERROR, TAG, "CAManagerRemoveData has failed");
189 (*g_jvm)->DetachCurrentThread(g_jvm);
195 CAResult_t CAManagerLEClientInitialize(JNIEnv *env, JavaVM *jvm, jobject context)
197 OIC_LOG(DEBUG, TAG, "CAManagerClientInitialize");
198 VERIFY_NON_NULL(env, TAG, "env");
199 VERIFY_NON_NULL(jvm, TAG, "jvm");
200 VERIFY_NON_NULL(context, TAG, "context");
202 jint jni_int_sdk = CALEGetBuildVersion(env);
203 if (jni_int_sdk < SUPPORT_ADNROID_API_LEVEL)
205 OIC_LOG_V(ERROR, TAG, "it is not supported (%d)", jni_int_sdk);
206 return CA_STATUS_FAILED;
210 g_context = (*env)->NewGlobalRef(env, context);;
211 CAManagerInitMutexVaraibles();
212 CAManagerInitLEAutoConnection();
214 CAManagerCreateACDataList(env);
216 // get last connected device list
218 set = CAManagerGetConnectedDeviceAddress(env, g_context);
221 // create new set<String> object
222 set = CAManagerCreateSetString(env);
225 OIC_LOG(DEBUG, TAG, "created new SetString");
229 OIC_LOG(ERROR, TAG, "CAManagerCreateSetString has failed");
230 return CA_STATUS_FAILED;
235 OIC_LOG(DEBUG, TAG, "get previous Set<String> object");
238 g_connectedDeviceSet = (jobject)(*env)->NewGlobalRef(env, set);
239 if (!g_connectedDeviceSet)
241 OIC_LOG(ERROR, TAG, "g_connectedDeviceSet is null");
242 return CA_STATUS_FAILED;
248 CAResult_t CAManagerLEClientTerminate(JNIEnv *env)
250 OIC_LOG(DEBUG, TAG, "CAManagerClientTerminate");
251 VERIFY_NON_NULL(env, TAG, "env");
253 // stop gatt connection
254 CAResult_t res = CALEClientDisconnectAll(env);
255 if (CA_STATUS_OK != res)
257 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
260 res = CAManagerRemoveAllData(env);
261 if (CA_STATUS_OK != res)
263 OIC_LOG(ERROR, TAG, "CAManagerRemoveAllData has failed");
266 CAManagerTerminateLEAutoConnection();
267 CAManagerTerminateMutexVariables();
271 (*env)->DeleteGlobalRef(env, g_context);
275 if (g_connectedDeviceSet)
277 (*env)->DeleteGlobalRef(env, g_connectedDeviceSet);
278 g_connectedDeviceSet = NULL;
284 JNIEXPORT void JNICALL
285 Java_org_iotivity_ca_CaLeClientInterface_caManagerAdapterStateChangedCallback(
286 JNIEnv *env, jobject obj, jint state)
288 OIC_LOG(DEBUG, TAG, "caManagerAdapterStateChangedCallback");
289 VERIFY_NON_NULL_VOID(env, TAG, "env");
290 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
292 jint state_on = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_ON");
293 jint state_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_OFF");
294 jint state_turning_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_TURNING_OFF");
296 if (state_on == state)
298 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
299 if (g_adapterStateCB)
301 g_adapterStateCB(CA_ADAPTER_GATT_BTLE, true);
304 // when BT state is on. recovery flag has to be reset.
305 CAManagerSetBTRecovery(false);
307 // find target device for autoconnect
308 size_t length = CAManagerGetACDataLength();
309 OIC_LOG_V(DEBUG, TAG, "target device : %d", length);
310 for (size_t idx = 0; idx < length; idx++)
312 jstring leAddress = CAManagerGetLEAddressFromACData(env, idx);
315 CAResult_t res = CAManagerStartAutoConnection(env, leAddress);
316 if (CA_STATUS_OK != res)
318 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
324 else if (state_off == state)
326 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
327 if (g_adapterStateCB)
329 g_adapterStateCB(CA_ADAPTER_GATT_BTLE, false);
332 // reset autoconnect flag for all target devices
333 size_t length = CAManagerGetACDataLength();
334 for (size_t idx = 0; idx < length; idx++)
336 jstring address = CAManagerGetLEAddressFromACData(env, idx);
339 CAManagerSetAutoConnectionFlag(env, address, false);
343 // check whether BT recovery is needed or not
344 if (CAManagerIsRecoveryFlagSet())
346 CAManagerProcessRecovery(env, STATE_OFF);
349 else if (state_turning_off == state)
351 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_turning_off");
356 OIC_LOG(INFO, TAG, "AdapterStateChangedCallback state is not available");
361 JNIEXPORT void JNICALL
362 Java_org_iotivity_ca_CaLeClientInterface_caManagerBondStateChangedCallback(
363 JNIEnv *env, jobject obj, jobject device)
365 OIC_LOG(DEBUG, TAG, "caManagerBondStateChangedCallback");
366 VERIFY_NON_NULL_VOID(env, TAG, "env");
367 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
368 VERIFY_NON_NULL_VOID(device, TAG, "device");
370 // get ble address from Bluetooth Device object
371 jstring jni_leAddress = CALEClientGetLEAddressFromBTDevice(env, device);
374 OIC_LOG(INFO, TAG, "unbonded : it isn't same device type");
378 char* leAddress = (char*)(*env)->GetStringUTFChars(env, jni_leAddress, NULL);
381 OIC_LOG(ERROR, TAG, "leAddress is null");
385 // if there is no data, CAData will be created.
386 OIC_LOG_V(DEBUG, TAG, "bond none device : %s", leAddress);
388 CAResult_t res = CAManagerRemoveData(env, jni_leAddress);
389 if (CA_STATUS_OK != res)
391 OIC_LOG(ERROR, TAG, "CAManagerRemoveData has failed");
394 (*env)->ReleaseStringUTFChars(env, jni_leAddress, leAddress);
396 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context,
398 g_connectedDeviceSet))
400 OIC_LOG(ERROR, TAG, "CAManagerRemoveConnectedDeviceAddress has failed");
403 OIC_LOG(INFO, TAG, "bonded state changed bone_none");
406 JNIEXPORT void JNICALL
407 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeGattConnectionStateChangeCB(
408 JNIEnv *env, jobject obj, jobject gatt, jint status, jint newState)
410 OIC_LOG_V(DEBUG, TAG, "caManagerLeGattConnectionStateChangeCB-status(%d), newState(%d)",
413 VERIFY_NON_NULL_VOID(env, TAG, "env");
414 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
415 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
417 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
418 jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
419 jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
421 jstring jni_address = CAManagerGetAddressFromGatt(env, gatt);
424 OIC_LOG(ERROR, TAG, "CAManagerGetAddressFromGatt is null");
428 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
431 OIC_LOG(ERROR, TAG, "address is null");
435 OIC_LOG_V(INFO, TAG, "connection state : status(%d), addr:(%s), newState(%d)",
436 status, address, newState);
438 if (gatt_success == status && state_connected == newState) // le connected
440 OIC_LOG(DEBUG, TAG, "LE is connected");
441 CAResult_t res = CAManagerReadRemoteRssi(env, gatt);
442 if (CA_STATUS_OK != res)
444 OIC_LOG(ERROR, TAG, "CAManagerReadRemoteRssi has failed");
445 (*env)->ReleaseStringUTFChars(env, jni_address, address);
449 else if (state_disconnected == newState)// le disconnected
451 if (LINK_LOSS == status || REMOTE_DISCONNECT == status)
453 OIC_LOG(DEBUG, TAG, "LE is disconnected");
457 OIC_LOG_V(DEBUG, TAG, "LE Disconnected state is %d, %s", newState, address);
458 g_connStateCB(CA_ADAPTER_GATT_BTLE, address, false);
459 OIC_LOG(DEBUG, TAG, "LE Disconnected state callback is called");
462 if (!CAManagerIsMatchedACData(env, jni_address))
464 OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
466 (*env)->ReleaseStringUTFChars(env, jni_address, address);
470 CAManagerSetAutoConnectionFlag(env, jni_address, false);
472 CAResult_t res = CAManagerStartAutoConnection(env, jni_address);
473 if (CA_STATUS_OK != res)
475 (*env)->ReleaseStringUTFChars(env, jni_address, address);
476 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
480 else if (ACCEPT_TIMEOUT_EXCEPTION == status)
482 CAManagerProcessRecovery(env, START_RECOVERY);
485 (*env)->ReleaseStringUTFChars(env, jni_address, address);
486 (*env)->DeleteLocalRef(env, jni_address);
490 * Class: org_iotivity_ca_jar_caleinterface
491 * Method: caManagerLeServicesDiscoveredCallback
492 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
494 JNIEXPORT void JNICALL
495 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeServicesDiscoveredCallback(JNIEnv *env,
500 OIC_LOG_V(DEBUG, TAG, "caManagerLeServicesDiscoveredCallback - status %d: ", status);
501 VERIFY_NON_NULL_VOID(env, TAG, "env");
502 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
503 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
505 if (GATT_SUCCESS == status)
507 if (!g_connectedDeviceSet)
509 OIC_LOG(ERROR, TAG, "g_connectedDeviceSet is null");
513 jstring jni_address = CAManagerGetAddressFromGatt(env, gatt);
516 OIC_LOG(ERROR, TAG, "CAManagerGetAddressFromGatt is null");
520 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
523 OIC_LOG(ERROR, TAG, "address is null");
524 (*env)->DeleteLocalRef(env, jni_address);
527 OIC_LOG_V(DEBUG, TAG, "ServicesDiscovered device : %s", address);
529 // target address for auto connection will be set in device list.
530 // check set connected address information by user
531 jclass jni_cls_set = (*env)->FindClass(env, "java/util/HashSet");
534 OIC_LOG(ERROR, TAG, "jni_cls_set is null");
535 (*env)->ReleaseStringUTFChars(env, jni_address, address);
536 (*env)->DeleteLocalRef(env, jni_address);
540 jmethodID jni_mid_iterator = (*env)->GetMethodID(env, jni_cls_set, "iterator",
541 "()Ljava/util/Iterator;");
542 if (!jni_mid_iterator)
544 OIC_LOG(ERROR, TAG, "jni_mid_iterator is null");
545 (*env)->DeleteLocalRef(env, jni_cls_set);
546 (*env)->ReleaseStringUTFChars(env, jni_address, address);
547 (*env)->DeleteLocalRef(env, jni_address);
551 jobject jni_obj_iter = (*env)->CallObjectMethod(env, g_connectedDeviceSet, jni_mid_iterator);
554 OIC_LOG(ERROR, TAG, "jni_obj_iter is null");
555 (*env)->DeleteLocalRef(env, jni_cls_set);
556 (*env)->ReleaseStringUTFChars(env, jni_address, address);
557 (*env)->DeleteLocalRef(env, jni_address);
561 // Get the Iterator method IDs
562 jclass jni_cls_iterator = (*env)->FindClass(env, "java/util/Iterator");
563 if (!jni_cls_iterator)
565 OIC_LOG(ERROR, TAG, "jni_cls_iterator is null");
566 (*env)->DeleteLocalRef(env, jni_obj_iter);
567 (*env)->DeleteLocalRef(env, jni_cls_set);
568 (*env)->ReleaseStringUTFChars(env, jni_address, address);
569 (*env)->DeleteLocalRef(env, jni_address);
573 jmethodID jni_mid_hasNext = (*env)->GetMethodID(env, jni_cls_iterator, "hasNext", "()Z");
574 if (!jni_mid_hasNext)
576 OIC_LOG(ERROR, TAG, "jni_mid_hasNext is null");
577 (*env)->DeleteLocalRef(env, jni_cls_iterator);
578 (*env)->DeleteLocalRef(env, jni_obj_iter);
579 (*env)->DeleteLocalRef(env, jni_cls_set);
580 (*env)->ReleaseStringUTFChars(env, jni_address, address);
581 (*env)->DeleteLocalRef(env, jni_address);
585 jmethodID jni_mid_next = (*env)->GetMethodID(env, jni_cls_iterator, "next",
586 "()Ljava/lang/Object;");
589 OIC_LOG(ERROR, TAG, "jni_mid_next is null");
590 (*env)->DeleteLocalRef(env, jni_cls_iterator);
591 (*env)->DeleteLocalRef(env, jni_obj_iter);
592 (*env)->DeleteLocalRef(env, jni_cls_set);
593 (*env)->ReleaseStringUTFChars(env, jni_address, address);
594 (*env)->DeleteLocalRef(env, jni_address);
598 // Iterate over the entry Set
599 while ((*env)->CallBooleanMethod(env, jni_obj_iter, jni_mid_hasNext))
601 jstring jni_str_entry = (jstring)(*env)->CallObjectMethod(env, jni_obj_iter,
605 OIC_LOG(ERROR, TAG, "jni_str_entry is null");
606 (*env)->DeleteLocalRef(env, jni_cls_iterator);
607 (*env)->DeleteLocalRef(env, jni_obj_iter);
608 (*env)->DeleteLocalRef(env, jni_cls_set);
609 (*env)->ReleaseStringUTFChars(env, jni_address, address);
610 (*env)->DeleteLocalRef(env, jni_address);
613 const char* foundAddress = (*env)->GetStringUTFChars(env, jni_str_entry, NULL);
616 OIC_LOG(ERROR, TAG, "addr is null");
617 (*env)->DeleteLocalRef(env, jni_str_entry);
618 (*env)->DeleteLocalRef(env, jni_cls_iterator);
619 (*env)->DeleteLocalRef(env, jni_obj_iter);
620 (*env)->DeleteLocalRef(env, jni_cls_set);
621 (*env)->ReleaseStringUTFChars(env, jni_address, address);
622 (*env)->DeleteLocalRef(env, jni_address);
625 OIC_LOG_V(INFO, TAG, "found last connected address [%s] from SharedPreferences",
628 if (!strcmp(foundAddress, address))
630 // if BLE address is matched each other
631 // this address will be added into auto connection list.
632 OIC_LOG(INFO, TAG, "AC list - address will be added into ACData list");
633 CAManagerAddACData(env, jni_address);
634 CAManagerSetAutoConnectionFlag(env, jni_address, false);
636 // next connection will be requested as JNI_TRUE flag
637 // after first connection
638 CALEClientSetAutoConnectFlag(env, jni_str_entry, JNI_TRUE);
642 OIC_LOG(INFO, TAG, "AC list - device is not matched");
645 (*env)->ReleaseStringUTFChars(env, jni_str_entry, foundAddress);
646 (*env)->DeleteLocalRef(env, jni_str_entry);
651 g_connStateCB(CA_ADAPTER_GATT_BTLE, address, true);
652 OIC_LOG(DEBUG, TAG, "LE Connected callback is called");
655 (*env)->DeleteLocalRef(env, jni_cls_iterator);
656 (*env)->DeleteLocalRef(env, jni_obj_iter);
657 (*env)->DeleteLocalRef(env, jni_cls_set);
658 (*env)->ReleaseStringUTFChars(env, jni_address, address);
659 (*env)->DeleteLocalRef(env, jni_address);
660 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
664 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
669 * Class: org_iotivity_ca_jar_caleinterface
670 * Method: caManagerLeRemoteRssiCallback
671 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
673 JNIEXPORT void JNICALL
674 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeRemoteRssiCallback(JNIEnv *env,
680 OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - rssi : %d: ", rssi);
681 OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - status : %d: ", status);
682 VERIFY_NON_NULL_VOID(env, TAG, "env");
683 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
684 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");