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 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;
46 void CASetScanUuid(char* uuid, int uuid_type)
48 OIC_LOG(DEBUG, TAG, "CASetScanUuid");
50 CALEClientAddUuid(uuid, uuid_type);
53 CAResult_t CASetLEClientAutoConnectionDeviceInfo(const char* address)
55 OIC_LOG(DEBUG, TAG, "CASetClientAutoConnectionDeviceInfo");
56 VERIFY_NON_NULL(address, TAG, "address");
58 bool isAttached = false;
60 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
63 OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
64 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
68 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
69 return CA_STATUS_FAILED;
73 OIC_LOG_V(DEBUG, TAG, "set [%s] for Auto Connection", address);
75 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
78 OIC_LOG(ERROR, TAG, "jni_leAddress is null");
82 if (!CAManagerCheckBTAddress(env, jni_leAddress))
84 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
88 // if there is target address in SharedPreference, it will be reset.
89 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
91 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
92 g_connectedDeviceSet))
94 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
98 OIC_LOG(INFO, TAG, "Preference - remove success");
102 // it will be added new target address.
103 if (!CAManagerAddConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
105 OIC_LOG(ERROR, TAG, "Preference - putting has failed");
109 OIC_LOG(INFO, TAG, "Preference - putting success");
114 (*g_jvm)->DetachCurrentThread(g_jvm);
123 (*g_jvm)->DetachCurrentThread(g_jvm);
126 return CA_STATUS_FAILED;
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;
149 OIC_LOG_V(DEBUG, TAG, "unset [%s] for Auto Connection", address);
151 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
154 OIC_LOG(ERROR, TAG, "jni_leAddress is null");
158 if (!CAManagerCheckBTAddress(env, jni_leAddress))
160 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
164 // if there is target address in SharedPreference, it will be removed
165 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
167 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
168 g_connectedDeviceSet))
170 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
174 OIC_LOG(INFO, TAG, "Preference - remove success");
178 // remove target device for auto connection
179 CAResult_t ret = CAManagerRemoveACData(env, jni_leAddress);
180 if (CA_STATUS_OK != ret)
182 OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
187 (*g_jvm)->DetachCurrentThread(g_jvm);
196 (*g_jvm)->DetachCurrentThread(g_jvm);
199 return CA_STATUS_FAILED;
202 CAResult_t CAManagerLEClientInitialize(JNIEnv *env, JavaVM *jvm, jobject context)
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");
209 jint jni_int_sdk = CALEGetBuildVersion(env);
210 if (jni_int_sdk < SUPPORT_ADNROID_API_LEVEL)
212 OIC_LOG_V(ERROR, TAG, "it is not supported (%d)", jni_int_sdk);
213 return CA_STATUS_FAILED;
217 g_context = (*env)->NewGlobalRef(env, context);;
219 CAManagerInitMutexVaraibles();
220 CAManagerInitLEAutoConnection();
221 CAManagerCreateACDataList();
223 // get last connected device list
225 set = CAManagerGetConnectedDeviceAddress(env, g_context);
228 // create new set<String> object
229 set = CAManagerCreateSetString(env);
232 OIC_LOG(ERROR, TAG, "CAManagerCreateSetString has failed");
233 return CA_STATUS_FAILED;
235 OIC_LOG(DEBUG, TAG, "created new SetString");
239 OIC_LOG(DEBUG, TAG, "get previous Set<String> object");
242 g_connectedDeviceSet = (jobject)(*env)->NewGlobalRef(env, set);
243 if (!g_connectedDeviceSet)
245 OIC_LOG(ERROR, TAG, "g_connectedDeviceSet is null");
246 return CA_STATUS_FAILED;
252 CAResult_t CAManagerLEClientTerminate(JNIEnv *env)
254 OIC_LOG(DEBUG, TAG, "CAManagerClientTerminate");
255 VERIFY_NON_NULL(env, TAG, "env");
257 // stop gatt connection
258 CAResult_t res = CALEClientDisconnectAll(env);
259 if (CA_STATUS_OK != res)
261 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
264 res = CAManagerRemoveAllACData(env);
265 if (CA_STATUS_OK != res)
267 OIC_LOG(ERROR, TAG, "CAManagerRemoveAllACData has failed");
270 CAManagerDestroyACDataList();
271 CAManagerTerminateLEAutoConnection();
272 CAManagerTerminateMutexVariables();
276 (*env)->DeleteGlobalRef(env, g_context);
280 if (g_connectedDeviceSet)
282 (*env)->DeleteGlobalRef(env, g_connectedDeviceSet);
283 g_connectedDeviceSet = NULL;
289 void CAManagerLESetScanInterval(jint interval, jint count)
291 OIC_LOG(DEBUG, TAG, "CAManagerLESetScanInterval");
292 CALERestartScanWithInterval(interval, count, BLE_SCAN_ENABLE);
295 void CAManagerLEStopScan()
297 OIC_LOG(DEBUG, TAG, "CAManagerLEStopScan");
298 CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE);
301 void CAManagerSetConfigure(CAUtilConfig_t config)
303 OIC_LOG_V(INFO, TAG, "set configure for bleFlags : %d", config.bleFlags);
304 caglobals.bleFlags = config.bleFlags;
307 CAResult_t CAManagerLEStartAdvertising()
309 CAResult_t ret = CALEServerStartAdvertise();
310 if (CA_STATUS_OK != ret)
312 OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
317 CAResult_t CAManagerLEStopAdvertising()
319 CAResult_t ret = CALEServerStopAdvertise();
320 if (CA_STATUS_OK != ret)
322 OIC_LOG(ERROR, TAG, "CAManagerLEStopAdvertising has failed");
327 JNIEXPORT void JNICALL
328 Java_org_iotivity_ca_CaLeClientInterface_caManagerAdapterStateChangedCallback(
329 JNIEnv *env, jobject obj, jint state)
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");
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");
339 if (state_on == state)
341 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
343 // when BT state is on. recovery flag has to be reset.
344 CAManagerSetBTRecovery(false);
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++)
351 jstring leAddress = CAManagerGetLEAddressFromACData(env, idx);
354 CAResult_t res = CAManagerStartAutoConnection(env, leAddress);
355 if (CA_STATUS_OK != res)
357 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
363 else if (state_off == state)
365 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
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++)
372 jstring address = CAManagerGetLEAddressFromACData(env, idx);
375 CAManagerSetAutoConnectingFlag(env, address, false);
379 // check whether BT recovery is needed or not
380 if (CAManagerIsRecoveryFlagSet())
382 CAManagerProcessRecovery(env, STATE_OFF);
385 else if (state_turning_off == state)
387 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_turning_off");
391 OIC_LOG(INFO, TAG, "AdapterStateChangedCallback state is not available");
395 JNIEXPORT void JNICALL
396 Java_org_iotivity_ca_CaLeClientInterface_caManagerBondStateChangedCallback(
397 JNIEnv *env, jobject obj, jobject device)
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");
407 // get ble address from Bluetooth Device object
408 jstring jni_leAddress = CALEClientGetLEAddressFromBTDevice(env, device);
411 OIC_LOG(INFO, TAG, "unbonded : it isn't same device type");
415 char* leAddress = (char*)(*env)->GetStringUTFChars(env, jni_leAddress, NULL);
418 OIC_LOG(ERROR, TAG, "leAddress is null");
422 // if there is no data, CAData will be created.
423 OIC_LOG_V(DEBUG, TAG, "bond none device : %s", leAddress);
425 CAResult_t res = CAManagerRemoveACData(env, jni_leAddress);
426 if (CA_STATUS_OK != res)
428 OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
431 (*env)->ReleaseStringUTFChars(env, jni_leAddress, leAddress);
433 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
434 g_connectedDeviceSet))
436 OIC_LOG(ERROR, TAG, "CAManagerRemoveConnectedDeviceAddress has failed");
440 JNIEXPORT void JNICALL
441 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeGattConnectionStateChangeCB(
442 JNIEnv *env, jobject obj, jobject gatt, jint status, jint newState)
444 VERIFY_NON_NULL_VOID(env, TAG, "env");
445 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
446 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
448 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
449 jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
451 jstring jni_address = CALEGetAddressFromGatt(env, gatt);
454 OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
458 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
461 OIC_LOG(ERROR, TAG, "address is null");
462 (*env)->DeleteLocalRef(env, jni_address);
466 if (GATT_SUCCESS == status && state_connected == newState) // le connected
468 CAResult_t res = CAManagerReadRemoteRssi(env, gatt);
469 if (CA_STATUS_OK != res)
471 OIC_LOG(ERROR, TAG, "CAManagerReadRemoteRssi has failed");
475 else if (state_disconnected == newState)// le disconnected
477 if (LINK_LOSS == status || REMOTE_DISCONNECT == status)
479 if (!CAManagerIsInACDataList(env, jni_address))
481 OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
486 CAManagerSetAutoConnectingFlag(env, jni_address, false);
488 CAResult_t res = CAManagerStartAutoConnection(env, jni_address);
489 if (CA_STATUS_OK != res)
491 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
495 else if (ACCEPT_TIMEOUT_EXCEPTION == status)
497 CAManagerProcessRecovery(env, START_RECOVERY);
502 (*env)->ReleaseStringUTFChars(env, jni_address, address);
503 (*env)->DeleteLocalRef(env, jni_address);
507 * Class: org_iotivity_ca_jar_caleinterface
508 * Method: caManagerLeServicesDiscoveredCallback
509 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
511 JNIEXPORT void JNICALL
512 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeServicesDiscoveredCallback(JNIEnv *env,
517 VERIFY_NON_NULL_VOID(env, TAG, "env");
518 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
519 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
521 if (GATT_SUCCESS == status)
523 if (!g_connectedDeviceSet)
525 OIC_LOG(INFO, TAG, "g_connectedDeviceSet is needed for CM. "
526 "please call CAManagerLEClientInitialize");
530 jstring jni_address = CALEGetAddressFromGatt(env, gatt);
533 OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
537 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
540 OIC_LOG(ERROR, TAG, "address is null");
541 (*env)->DeleteLocalRef(env, jni_address);
545 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_address, g_connectedDeviceSet))
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);
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);
557 OIC_LOG(DEBUG, TAG, "AC list - the address is not set to AutoConnect");
560 (*env)->ReleaseStringUTFChars(env, jni_address, address);
561 (*env)->DeleteLocalRef(env, jni_address);
565 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
570 * Class: org_iotivity_ca_jar_caleinterface
571 * Method: caManagerLeRemoteRssiCallback
572 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
574 JNIEXPORT void JNICALL
575 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeRemoteRssiCallback(JNIEnv *env,
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");