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);
274 if (g_connectedDeviceSet)
276 (*env)->DeleteGlobalRef(env, g_connectedDeviceSet);
282 JNIEXPORT void JNICALL
283 Java_org_iotivity_ca_CaLeClientInterface_caManagerAdapterStateChangedCallback(
284 JNIEnv *env, jobject obj, jint state)
286 OIC_LOG(DEBUG, TAG, "caManagerAdapterStateChangedCallback");
287 VERIFY_NON_NULL_VOID(env, TAG, "env");
288 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
290 jint state_on = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_ON");
291 jint state_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_OFF");
292 jint state_turning_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_TURNING_OFF");
294 if (state_on == state)
296 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
297 if (g_adapterStateCB)
299 g_adapterStateCB(CA_ADAPTER_GATT_BTLE, true);
302 // when BT state is on. recovery flag has to be reset.
303 CAManagerSetBTRecovery(false);
305 // find target device for autoconnect
306 size_t length = CAManagerGetACDataLength();
307 OIC_LOG_V(DEBUG, TAG, "target device : %d", length);
308 for (size_t idx = 0; idx < length; idx++)
310 jstring leAddress = CAManagerGetLEAddressFromACData(env, idx);
313 CAResult_t res = CAManagerStartAutoConnection(env, leAddress);
314 if (CA_STATUS_OK != res)
316 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
322 else if (state_off == state)
324 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
325 if (g_adapterStateCB)
327 g_adapterStateCB(CA_ADAPTER_GATT_BTLE, false);
330 // reset autoconnect flag for all target devices
331 size_t length = CAManagerGetACDataLength();
332 for (size_t idx = 0; idx < length; idx++)
334 jstring address = CAManagerGetLEAddressFromACData(env, idx);
337 CAManagerSetAutoConnectionFlag(env, address, false);
341 // check whether BT recovery is needed or not
342 if (CAManagerIsRecoveryFlagSet())
344 CAManagerProcessRecovery(env, STATE_OFF);
347 else if (state_turning_off == state)
349 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_turning_off");
354 OIC_LOG(INFO, TAG, "AdapterStateChangedCallback state is not available");
359 JNIEXPORT void JNICALL
360 Java_org_iotivity_ca_CaLeClientInterface_caManagerBondStateChangedCallback(
361 JNIEnv *env, jobject obj, jobject device)
363 OIC_LOG(DEBUG, TAG, "caManagerBondStateChangedCallback");
364 VERIFY_NON_NULL_VOID(env, TAG, "env");
365 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
366 VERIFY_NON_NULL_VOID(device, TAG, "device");
368 // get ble address from Bluetooth Device object
369 jstring jni_leAddress = CALEClientGetLEAddressFromBTDevice(env, device);
372 OIC_LOG(INFO, TAG, "unbonded : it isn't same device type");
376 char* leAddress = (char*)(*env)->GetStringUTFChars(env, jni_leAddress, NULL);
379 OIC_LOG(ERROR, TAG, "leAddress is null");
383 // if there is no data, CAData will be created.
384 OIC_LOG_V(DEBUG, TAG, "bond none device : %s", leAddress);
386 CAResult_t res = CAManagerRemoveData(env, jni_leAddress);
387 if (CA_STATUS_OK != res)
389 OIC_LOG(ERROR, TAG, "CAManagerRemoveData has failed");
392 (*env)->ReleaseStringUTFChars(env, jni_leAddress, leAddress);
394 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context,
396 g_connectedDeviceSet))
398 OIC_LOG(ERROR, TAG, "CAManagerRemoveConnectedDeviceAddress has failed");
401 OIC_LOG(INFO, TAG, "bonded state changed bone_none");
404 JNIEXPORT void JNICALL
405 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeGattConnectionStateChangeCB(
406 JNIEnv *env, jobject obj, jobject gatt, jint status, jint newState)
408 OIC_LOG_V(DEBUG, TAG, "caManagerLeGattConnectionStateChangeCB-status(%d), newState(%d)",
411 VERIFY_NON_NULL_VOID(env, TAG, "env");
412 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
413 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
415 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
416 jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
417 jint gatt_success = CALEGetConstantsValue(env, CLASSPATH_BT_GATT, "GATT_SUCCESS");
419 jstring jni_address = CAManagerGetAddressFromGatt(env, gatt);
422 OIC_LOG(ERROR, TAG, "CAManagerGetAddressFromGatt is null");
426 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
429 OIC_LOG(ERROR, TAG, "address is null");
433 OIC_LOG_V(INFO, TAG, "connection state : status(%d), addr:(%s), newState(%d)",
434 status, address, newState);
436 if (gatt_success == status && state_connected == newState) // le connected
438 OIC_LOG(DEBUG, TAG, "LE is connected");
439 CAResult_t res = CAManagerReadRemoteRssi(env, gatt);
440 if (CA_STATUS_OK != res)
442 OIC_LOG(ERROR, TAG, "CAManagerReadRemoteRssi has failed");
443 (*env)->ReleaseStringUTFChars(env, jni_address, address);
447 else if (state_disconnected == newState)// le disconnected
449 if (LINK_LOSS == status || REMOTE_DISCONNECT == status)
451 OIC_LOG(DEBUG, TAG, "LE is disconnected");
455 OIC_LOG_V(DEBUG, TAG, "LE Disconnected state is %d, %s", newState, address);
456 g_connStateCB(CA_ADAPTER_GATT_BTLE, address, false);
457 OIC_LOG(DEBUG, TAG, "LE Disconnected state callback is called");
460 if (!CAManagerIsMatchedACData(env, jni_address))
462 OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
464 (*env)->ReleaseStringUTFChars(env, jni_address, address);
468 CAManagerSetAutoConnectionFlag(env, jni_address, false);
470 CAResult_t res = CAManagerStartAutoConnection(env, jni_address);
471 if (CA_STATUS_OK != res)
473 (*env)->ReleaseStringUTFChars(env, jni_address, address);
474 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
478 else if (ACCEPT_TIMEOUT_EXCEPTION == status)
480 CAManagerProcessRecovery(env, START_RECOVERY);
483 (*env)->ReleaseStringUTFChars(env, jni_address, address);
484 (*env)->DeleteLocalRef(env, jni_address);
488 * Class: org_iotivity_ca_jar_caleinterface
489 * Method: caManagerLeServicesDiscoveredCallback
490 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
492 JNIEXPORT void JNICALL
493 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeServicesDiscoveredCallback(JNIEnv *env,
498 OIC_LOG_V(DEBUG, TAG, "caManagerLeServicesDiscoveredCallback - status %d: ", status);
499 VERIFY_NON_NULL_VOID(env, TAG, "env");
500 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
501 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
503 if (GATT_SUCCESS == status)
505 jstring jni_address = CAManagerGetAddressFromGatt(env, gatt);
508 OIC_LOG(ERROR, TAG, "CAManagerGetAddressFromGatt is null");
512 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
515 OIC_LOG(ERROR, TAG, "address is null");
518 OIC_LOG_V(DEBUG, TAG, "ServicesDiscovered device : %s", address);
520 // target address for auto connection will be set in device list.
521 // check set connected address information by user
522 jclass jni_cls_set = (*env)->FindClass(env, "java/util/HashSet");
525 OIC_LOG(ERROR, TAG, "jni_cls_set is null");
529 jmethodID jni_mid_iterator = (*env)->GetMethodID(env, jni_cls_set, "iterator", "()Ljava/util/Iterator;");
530 if (!jni_mid_iterator)
532 OIC_LOG(ERROR, TAG, "jni_mid_iterator is null");
536 jobject jni_obj_iter = (*env)->CallObjectMethod(env, g_connectedDeviceSet, jni_mid_iterator);
539 OIC_LOG(ERROR, TAG, "jni_obj_iter is null");
543 // Get the Iterator method IDs
544 jclass jni_cls_iterator = (*env)->FindClass(env, "java/util/Iterator");
545 if (!jni_cls_iterator)
547 OIC_LOG(ERROR, TAG, "jni_cls_iterator is null");
551 jmethodID jni_mid_hasNext = (*env)->GetMethodID(env, jni_cls_iterator, "hasNext", "()Z");
552 if (!jni_mid_hasNext)
554 OIC_LOG(ERROR, TAG, "jni_mid_hasNext is null");
558 jmethodID jni_mid_next = (*env)->GetMethodID(env, jni_cls_iterator, "next", "()Ljava/lang/Object;");
561 OIC_LOG(ERROR, TAG, "jni_mid_next is null");
565 // Iterate over the entry Set
566 while ((*env)->CallBooleanMethod(env, jni_obj_iter, jni_mid_hasNext))
568 jstring jni_str_entry = (jstring)(*env)->CallObjectMethod(env, jni_obj_iter, jni_mid_next);
569 const char* foundAddress = (*env)->GetStringUTFChars(env, jni_str_entry, NULL);
572 OIC_LOG(ERROR, TAG, "addr is null");
575 OIC_LOG_V(INFO, TAG, "found last connected address [%s] from SharedPreferences",
578 if (!strcmp(foundAddress, address))
580 // if BLE address is matched each other
581 // this address will be added into auto connection list.
582 OIC_LOG(INFO, TAG, "AC list - address will be added into ACData list");
583 CAManagerAddACData(env, jni_address);
584 CAManagerSetAutoConnectionFlag(env, jni_address, false);
586 // next connection will be requested as JNI_TRUE flag
587 // after first connection
591 OIC_LOG(INFO, TAG, "AC list - device is not matched");
594 (*env)->ReleaseStringUTFChars(env, jni_str_entry, foundAddress);
595 (*env)->DeleteLocalRef(env, jni_str_entry);
600 g_connStateCB(CA_ADAPTER_GATT_BTLE, address, true);
601 OIC_LOG(DEBUG, TAG, "LE Connected callback is called");
603 (*env)->ReleaseStringUTFChars(env, jni_address, address);
604 (*env)->DeleteLocalRef(env, jni_address);
605 (*env)->DeleteLocalRef(env, jni_cls_set);
606 (*env)->DeleteLocalRef(env, jni_obj_iter);
607 (*env)->DeleteLocalRef(env, jni_cls_iterator);
609 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
613 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
618 * Class: org_iotivity_ca_jar_caleinterface
619 * Method: caManagerLeRemoteRssiCallback
620 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
622 JNIEXPORT void JNICALL
623 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeRemoteRssiCallback(JNIEnv *env,
629 OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - rssi : %d: ", rssi);
630 OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - status : %d: ", status);
631 VERIFY_NON_NULL_VOID(env, TAG, "env");
632 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
633 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");