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 USER_REMOVED_BOND = 68;
45 static JavaVM *g_jvm = NULL;
46 static jobject g_context = NULL;
47 static jobject g_connectedDeviceSet = NULL;
49 void CASetLENetworkMonitorCallbacks(CAAdapterStateChangedCB adapterStateCB,
50 CAConnectionStateChangedCB connStateCB)
52 OIC_LOG(DEBUG, TAG, "CASetLENetworkMonitorCallbacks");
54 g_adapterStateCB = adapterStateCB;
55 g_connStateCB = connStateCB;
58 CAResult_t CASetLEClientAutoConnectionDeviceInfo(const char* address)
60 OIC_LOG(DEBUG, TAG, "CASetClientAutoConnectionDeviceInfo");
61 VERIFY_NON_NULL(address, TAG, "address");
63 bool isAttached = false;
65 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
68 OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
69 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
73 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
74 return CA_STATUS_FAILED;
78 OIC_LOG_V(DEBUG, TAG, "set [%s] for Auto Connection", address);
80 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
83 OIC_LOG(ERROR, TAG, "jni_leAddress is null");
87 if (!CAManagerCheckBTAddress(env, jni_leAddress))
89 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
93 // if there is target address in SharedPreference, it will be reset.
94 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
96 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
97 g_connectedDeviceSet))
99 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
103 OIC_LOG(INFO, TAG, "Preference - remove success");
107 // it will be added new target address.
108 if (!CAManagerAddConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
110 OIC_LOG(ERROR, TAG, "Preference - putting has failed");
114 OIC_LOG(INFO, TAG, "Preference - putting success");
119 (*g_jvm)->DetachCurrentThread(g_jvm);
128 (*g_jvm)->DetachCurrentThread(g_jvm);
131 return CA_STATUS_FAILED;
134 CAResult_t CAUnsetLEClientAutoConnectionDeviceInfo(const char* address)
136 OIC_LOG(DEBUG, TAG, "CAUnsetClientAutoConnectionDeviceInfo");
137 VERIFY_NON_NULL(address, TAG, "address");
139 bool isAttached = false;
141 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
144 OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
145 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
149 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
150 return CA_STATUS_FAILED;
154 OIC_LOG_V(DEBUG, TAG, "unset [%s] for Auto Connection", address);
156 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
159 OIC_LOG(ERROR, TAG, "jni_leAddress is null");
163 if (!CAManagerCheckBTAddress(env, jni_leAddress))
165 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
169 // if there is target address in SharedPreference, it will be removed
170 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
172 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
173 g_connectedDeviceSet))
175 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
179 OIC_LOG(INFO, TAG, "Preference - remove success");
183 // remove target device for auto connection
184 CAResult_t ret = CAManagerRemoveACData(env, jni_leAddress);
185 if (CA_STATUS_OK != ret)
187 OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
192 (*g_jvm)->DetachCurrentThread(g_jvm);
201 (*g_jvm)->DetachCurrentThread(g_jvm);
204 return CA_STATUS_FAILED;
207 CAResult_t CAManagerLEClientInitialize(JNIEnv *env, JavaVM *jvm, jobject context)
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");
214 jint jni_int_sdk = CALEGetBuildVersion(env);
215 if (jni_int_sdk < SUPPORT_ADNROID_API_LEVEL)
217 OIC_LOG_V(ERROR, TAG, "it is not supported (%d)", jni_int_sdk);
218 return CA_STATUS_FAILED;
222 g_context = (*env)->NewGlobalRef(env, context);;
224 CAManagerInitMutexVaraibles();
225 CAManagerInitLEAutoConnection();
226 CAManagerCreateACDataList();
228 // get last connected device list
230 set = CAManagerGetConnectedDeviceAddress(env, g_context);
233 // create new set<String> object
234 set = CAManagerCreateSetString(env);
237 OIC_LOG(ERROR, TAG, "CAManagerCreateSetString has failed");
238 return CA_STATUS_FAILED;
240 OIC_LOG(DEBUG, TAG, "created new SetString");
244 OIC_LOG(DEBUG, TAG, "get previous Set<String> object");
247 g_connectedDeviceSet = (jobject)(*env)->NewGlobalRef(env, set);
248 if (!g_connectedDeviceSet)
250 OIC_LOG(ERROR, TAG, "g_connectedDeviceSet is null");
251 return CA_STATUS_FAILED;
257 CAResult_t CAManagerLEClientTerminate(JNIEnv *env)
259 OIC_LOG(DEBUG, TAG, "CAManagerClientTerminate");
260 VERIFY_NON_NULL(env, TAG, "env");
262 // stop gatt connection
263 CAResult_t res = CALEClientDisconnectAll(env);
264 if (CA_STATUS_OK != res)
266 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
269 res = CAManagerRemoveAllACData(env);
270 if (CA_STATUS_OK != res)
272 OIC_LOG(ERROR, TAG, "CAManagerRemoveAllACData has failed");
275 CAManagerDestroyACDataList();
276 CAManagerTerminateLEAutoConnection();
277 CAManagerTerminateMutexVariables();
281 (*env)->DeleteGlobalRef(env, g_context);
285 if (g_connectedDeviceSet)
287 (*env)->DeleteGlobalRef(env, g_connectedDeviceSet);
288 g_connectedDeviceSet = NULL;
294 JNIEXPORT void JNICALL
295 Java_org_iotivity_ca_CaLeClientInterface_caManagerAdapterStateChangedCallback(
296 JNIEnv *env, jobject obj, jint state)
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");
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");
306 if (state_on == state)
308 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
309 if (g_adapterStateCB)
311 g_adapterStateCB(CA_ADAPTER_GATT_BTLE, true);
314 // when BT state is on. recovery flag has to be reset.
315 CAManagerSetBTRecovery(false);
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++)
322 jstring leAddress = CAManagerGetLEAddressFromACData(env, idx);
325 CAResult_t res = CAManagerStartAutoConnection(env, leAddress);
326 if (CA_STATUS_OK != res)
328 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
334 else if (state_off == state)
336 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
337 if (g_adapterStateCB)
339 g_adapterStateCB(CA_ADAPTER_GATT_BTLE, false);
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++)
347 jstring address = CAManagerGetLEAddressFromACData(env, idx);
350 CAManagerSetAutoConnectingFlag(env, address, false);
354 // check whether BT recovery is needed or not
355 if (CAManagerIsRecoveryFlagSet())
357 CAManagerProcessRecovery(env, STATE_OFF);
360 else if (state_turning_off == state)
362 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_turning_off");
366 OIC_LOG(INFO, TAG, "AdapterStateChangedCallback state is not available");
370 JNIEXPORT void JNICALL
371 Java_org_iotivity_ca_CaLeClientInterface_caManagerBondStateChangedCallback(
372 JNIEnv *env, jobject obj, jobject device)
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");
382 // get ble address from Bluetooth Device object
383 jstring jni_leAddress = CALEClientGetLEAddressFromBTDevice(env, device);
386 OIC_LOG(INFO, TAG, "unbonded : it isn't same device type");
390 char* leAddress = (char*)(*env)->GetStringUTFChars(env, jni_leAddress, NULL);
393 OIC_LOG(ERROR, TAG, "leAddress is null");
397 // if there is no data, CAData will be created.
398 OIC_LOG_V(DEBUG, TAG, "bond none device : %s", leAddress);
400 CAResult_t res = CAManagerRemoveACData(env, jni_leAddress);
401 if (CA_STATUS_OK != res)
403 OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
406 (*env)->ReleaseStringUTFChars(env, jni_leAddress, leAddress);
408 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
409 g_connectedDeviceSet))
411 OIC_LOG(ERROR, TAG, "CAManagerRemoveConnectedDeviceAddress has failed");
415 JNIEXPORT void JNICALL
416 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeGattConnectionStateChangeCB(
417 JNIEnv *env, jobject obj, jobject gatt, jint status, jint newState)
419 OIC_LOG_V(INFO, TAG, "caManagerLeGattConnectionStateChangeCB - status %d, newState %d",
422 VERIFY_NON_NULL_VOID(env, TAG, "env");
423 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
424 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
426 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
427 jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
429 jstring jni_address = CALEGetAddressFromGatt(env, gatt);
432 OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
436 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
439 OIC_LOG(ERROR, TAG, "address is null");
440 (*env)->DeleteLocalRef(env, jni_address);
444 OIC_LOG_V(DEBUG, TAG, "caManagerLeGattConnectionStateChangeCB - address [%s]", address);
446 if (GATT_SUCCESS == status && state_connected == newState) // le connected
448 OIC_LOG(DEBUG, TAG, "LE is connected");
450 CAResult_t res = CAManagerReadRemoteRssi(env, gatt);
451 if (CA_STATUS_OK != res)
453 OIC_LOG(ERROR, TAG, "CAManagerReadRemoteRssi has failed");
457 else if (state_disconnected == newState)// le disconnected
459 OIC_LOG(DEBUG, TAG, "LE is disconnected");
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");
468 if (LINK_LOSS == status || REMOTE_DISCONNECT == status)
470 if (!CAManagerIsInACDataList(env, jni_address))
472 OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
477 CAManagerSetAutoConnectingFlag(env, jni_address, false);
479 CAResult_t res = CAManagerStartAutoConnection(env, jni_address);
480 if (CA_STATUS_OK != res)
482 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
486 else if (ACCEPT_TIMEOUT_EXCEPTION == status)
488 CAManagerProcessRecovery(env, START_RECOVERY);
493 (*env)->ReleaseStringUTFChars(env, jni_address, address);
494 (*env)->DeleteLocalRef(env, jni_address);
498 * Class: org_iotivity_ca_jar_caleinterface
499 * Method: caManagerLeServicesDiscoveredCallback
500 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
502 JNIEXPORT void JNICALL
503 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeServicesDiscoveredCallback(JNIEnv *env,
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");
513 if (GATT_SUCCESS == status)
515 if (!g_connectedDeviceSet)
517 OIC_LOG(ERROR, TAG, "g_connectedDeviceSet is null");
521 jstring jni_address = CALEGetAddressFromGatt(env, gatt);
524 OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
528 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
531 OIC_LOG(ERROR, TAG, "address is null");
532 (*env)->DeleteLocalRef(env, jni_address);
536 OIC_LOG_V(DEBUG, TAG, "ServicesDiscovered device : %s", address);
538 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_address, g_connectedDeviceSet))
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);
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);
550 OIC_LOG(DEBUG, TAG, "AC list - the address is not set to AutoConnect");
555 g_connStateCB(CA_ADAPTER_GATT_BTLE, address, true);
556 OIC_LOG(DEBUG, TAG, "LE Connected callback is called");
559 (*env)->ReleaseStringUTFChars(env, jni_address, address);
560 (*env)->DeleteLocalRef(env, jni_address);
562 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
566 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
571 * Class: org_iotivity_ca_jar_caleinterface
572 * Method: caManagerLeRemoteRssiCallback
573 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
575 JNIEXPORT void JNICALL
576 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeRemoteRssiCallback(JNIEnv *env,
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");