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;
47 CAResult_t CASetLEClientAutoConnectionDeviceInfo(const char* address)
49 OIC_LOG(DEBUG, TAG, "CASetClientAutoConnectionDeviceInfo");
50 VERIFY_NON_NULL(address, TAG, "address");
52 bool isAttached = false;
54 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
57 OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
58 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
62 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
63 return CA_STATUS_FAILED;
67 OIC_LOG_V(DEBUG, TAG, "set [%s] for Auto Connection", address);
69 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
72 OIC_LOG(ERROR, TAG, "jni_leAddress is null");
76 if (!CAManagerCheckBTAddress(env, jni_leAddress))
78 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
82 // if there is target address in SharedPreference, it will be reset.
83 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
85 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
86 g_connectedDeviceSet))
88 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
92 OIC_LOG(INFO, TAG, "Preference - remove success");
96 // it will be added new target address.
97 if (!CAManagerAddConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
99 OIC_LOG(ERROR, TAG, "Preference - putting has failed");
103 OIC_LOG(INFO, TAG, "Preference - putting success");
108 (*g_jvm)->DetachCurrentThread(g_jvm);
117 (*g_jvm)->DetachCurrentThread(g_jvm);
120 return CA_STATUS_FAILED;
123 CAResult_t CAUnsetLEClientAutoConnectionDeviceInfo(const char* address)
125 OIC_LOG(DEBUG, TAG, "CAUnsetClientAutoConnectionDeviceInfo");
126 VERIFY_NON_NULL(address, TAG, "address");
128 bool isAttached = false;
130 jint res = (*g_jvm)->GetEnv(g_jvm, (void**) &env, JNI_VERSION_1_6);
133 OIC_LOG(DEBUG, TAG, "AttachCurrentThread will be called for JNIEnv pointer");
134 res = (*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL);
138 OIC_LOG(ERROR, TAG, "AttachCurrentThread has failed");
139 return CA_STATUS_FAILED;
143 OIC_LOG_V(DEBUG, TAG, "unset [%s] for Auto Connection", address);
145 jstring jni_leAddress = (*env)->NewStringUTF(env, address);
148 OIC_LOG(ERROR, TAG, "jni_leAddress is null");
152 if (!CAManagerCheckBTAddress(env, jni_leAddress))
154 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
158 // if there is target address in SharedPreference, it will be removed
159 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_leAddress, g_connectedDeviceSet))
161 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
162 g_connectedDeviceSet))
164 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
168 OIC_LOG(INFO, TAG, "Preference - remove success");
172 // remove target device for auto connection
173 CAResult_t ret = CAManagerRemoveACData(env, jni_leAddress);
174 if (CA_STATUS_OK != ret)
176 OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
181 (*g_jvm)->DetachCurrentThread(g_jvm);
190 (*g_jvm)->DetachCurrentThread(g_jvm);
193 return CA_STATUS_FAILED;
196 CAResult_t CAManagerLEClientInitialize(JNIEnv *env, JavaVM *jvm, jobject context)
198 OIC_LOG(DEBUG, TAG, "CAManagerClientInitialize");
199 VERIFY_NON_NULL(env, TAG, "env");
200 VERIFY_NON_NULL(jvm, TAG, "jvm");
201 VERIFY_NON_NULL(context, TAG, "context");
203 jint jni_int_sdk = CALEGetBuildVersion(env);
204 if (jni_int_sdk < SUPPORT_ADNROID_API_LEVEL)
206 OIC_LOG_V(ERROR, TAG, "it is not supported (%d)", jni_int_sdk);
207 return CA_STATUS_FAILED;
211 g_context = (*env)->NewGlobalRef(env, context);;
213 CAManagerInitMutexVaraibles();
214 CAManagerInitLEAutoConnection();
215 CAManagerCreateACDataList();
217 // get last connected device list
219 set = CAManagerGetConnectedDeviceAddress(env, g_context);
222 // create new set<String> object
223 set = CAManagerCreateSetString(env);
226 OIC_LOG(ERROR, TAG, "CAManagerCreateSetString has failed");
227 return CA_STATUS_FAILED;
229 OIC_LOG(DEBUG, TAG, "created new SetString");
233 OIC_LOG(DEBUG, TAG, "get previous Set<String> object");
236 g_connectedDeviceSet = (jobject)(*env)->NewGlobalRef(env, set);
237 if (!g_connectedDeviceSet)
239 OIC_LOG(ERROR, TAG, "g_connectedDeviceSet is null");
240 return CA_STATUS_FAILED;
246 CAResult_t CAManagerLEClientTerminate(JNIEnv *env)
248 OIC_LOG(DEBUG, TAG, "CAManagerClientTerminate");
249 VERIFY_NON_NULL(env, TAG, "env");
251 // stop gatt connection
252 CAResult_t res = CALEClientDisconnectAll(env);
253 if (CA_STATUS_OK != res)
255 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
258 res = CAManagerRemoveAllACData(env);
259 if (CA_STATUS_OK != res)
261 OIC_LOG(ERROR, TAG, "CAManagerRemoveAllACData has failed");
264 CAManagerDestroyACDataList();
265 CAManagerTerminateLEAutoConnection();
266 CAManagerTerminateMutexVariables();
270 (*env)->DeleteGlobalRef(env, g_context);
274 if (g_connectedDeviceSet)
276 (*env)->DeleteGlobalRef(env, g_connectedDeviceSet);
277 g_connectedDeviceSet = NULL;
283 void CAManagerLESetScanInterval(jint interval, jint count)
285 OIC_LOG(DEBUG, TAG, "CAManagerLESetScanInterval");
286 CALERestartScanWithInterval(interval, count, BLE_SCAN_ENABLE);
289 void CAManagerLEStopScan()
291 OIC_LOG(DEBUG, TAG, "CAManagerLEStopScan");
292 CALERestartScanWithInterval(0, 0, BLE_SCAN_DISABLE);
295 void CAManagerSetConfigure(CAUtilConfig_t config)
297 OIC_LOG_V(INFO, TAG, "set configure for bleFlags : %d", config.bleFlags);
298 caglobals.bleFlags = config.bleFlags;
301 CAResult_t CAManagerLEStartAdvertising()
303 CAResult_t ret = CALEServerStartAdvertise();
304 if (CA_STATUS_OK != ret)
306 OIC_LOG(ERROR, TAG, "CALEServerStartAdvertise has failed");
311 CAResult_t CAManagerLEStopAdvertising()
313 CAResult_t ret = CALEServerStopAdvertise();
314 if (CA_STATUS_OK != ret)
316 OIC_LOG(ERROR, TAG, "CALEServerStopAdvertise has failed");
321 JNIEXPORT void JNICALL
322 Java_org_iotivity_ca_CaLeClientInterface_caManagerAdapterStateChangedCallback(
323 JNIEnv *env, jobject obj, jint state)
325 OIC_LOG_V(INFO, TAG, "caManagerAdapterStateChangedCallback - state %d", state);
326 VERIFY_NON_NULL_VOID(env, TAG, "env");
327 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
329 jint state_on = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_ON");
330 jint state_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_OFF");
331 jint state_turning_off = CALEGetConstantsValue(env, CLASSPATH_BT_ADAPTER, "STATE_TURNING_OFF");
333 if (state_on == state)
335 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
337 // when BT state is on. recovery flag has to be reset.
338 CAManagerSetBTRecovery(false);
340 // find target device for autoconnect
341 size_t length = CAManagerGetACDataLength();
342 OIC_LOG_V(DEBUG, TAG, "length of ACDataList : %d", length);
343 for (size_t idx = 0; idx < length; idx++)
345 jstring leAddress = CAManagerGetLEAddressFromACData(env, idx);
348 CAResult_t res = CAManagerStartAutoConnection(env, leAddress);
349 if (CA_STATUS_OK != res)
351 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
357 else if (state_off == state)
359 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
361 // reset isAutoConnecting flag for all target devices
362 size_t length = CAManagerGetACDataLength();
363 OIC_LOG_V(DEBUG, TAG, "length of ACDataList : %d", length);
364 for (size_t idx = 0; idx < length; idx++)
366 jstring address = CAManagerGetLEAddressFromACData(env, idx);
369 CAManagerSetAutoConnectingFlag(env, address, false);
373 // check whether BT recovery is needed or not
374 if (CAManagerIsRecoveryFlagSet())
376 CAManagerProcessRecovery(env, STATE_OFF);
379 else if (state_turning_off == state)
381 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_turning_off");
385 OIC_LOG(INFO, TAG, "AdapterStateChangedCallback state is not available");
389 JNIEXPORT void JNICALL
390 Java_org_iotivity_ca_CaLeClientInterface_caManagerBondStateChangedCallback(
391 JNIEnv *env, jobject obj, jobject device)
393 OIC_LOG(INFO, TAG, "caManagerBondStateChangedCallback");
394 // this callback is called by CaLeClientInterface
395 // only when bond state is changed from BOND_BONDED to BOND_NONE
396 OIC_LOG(DEBUG, TAG, "bond state is changed from BOND_BONDED to BOND_NONE");
397 VERIFY_NON_NULL_VOID(env, TAG, "env");
398 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
399 VERIFY_NON_NULL_VOID(device, TAG, "device");
401 // get ble address from Bluetooth Device object
402 jstring jni_leAddress = CALEClientGetLEAddressFromBTDevice(env, device);
405 OIC_LOG(INFO, TAG, "unbonded : it isn't same device type");
409 char* leAddress = (char*)(*env)->GetStringUTFChars(env, jni_leAddress, NULL);
412 OIC_LOG(ERROR, TAG, "leAddress is null");
416 // if there is no data, CAData will be created.
417 OIC_LOG_V(DEBUG, TAG, "bond none device : %s", leAddress);
419 CAResult_t res = CAManagerRemoveACData(env, jni_leAddress);
420 if (CA_STATUS_OK != res)
422 OIC_LOG(ERROR, TAG, "CAManagerRemoveACData has failed");
425 (*env)->ReleaseStringUTFChars(env, jni_leAddress, leAddress);
427 if (!CAManagerRemoveConnectedDeviceAddress(env, g_context, jni_leAddress,
428 g_connectedDeviceSet))
430 OIC_LOG(ERROR, TAG, "CAManagerRemoveConnectedDeviceAddress has failed");
434 JNIEXPORT void JNICALL
435 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeGattConnectionStateChangeCB(
436 JNIEnv *env, jobject obj, jobject gatt, jint status, jint newState)
438 VERIFY_NON_NULL_VOID(env, TAG, "env");
439 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
440 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
442 jint state_connected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_CONNECTED");
443 jint state_disconnected = CALEGetConstantsValue(env, CLASSPATH_BT_PROFILE, "STATE_DISCONNECTED");
445 jstring jni_address = CALEGetAddressFromGatt(env, gatt);
448 OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
452 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
455 OIC_LOG(ERROR, TAG, "address is null");
456 (*env)->DeleteLocalRef(env, jni_address);
460 if (GATT_SUCCESS == status && state_connected == newState) // le connected
462 CAResult_t res = CAManagerReadRemoteRssi(env, gatt);
463 if (CA_STATUS_OK != res)
465 OIC_LOG(ERROR, TAG, "CAManagerReadRemoteRssi has failed");
469 else if (state_disconnected == newState)// le disconnected
471 if (LINK_LOSS == status || REMOTE_DISCONNECT == status)
473 if (!CAManagerIsInACDataList(env, jni_address))
475 OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
480 CAManagerSetAutoConnectingFlag(env, jni_address, false);
482 CAResult_t res = CAManagerStartAutoConnection(env, jni_address);
483 if (CA_STATUS_OK != res)
485 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
489 else if (ACCEPT_TIMEOUT_EXCEPTION == status)
491 CAManagerProcessRecovery(env, START_RECOVERY);
496 (*env)->ReleaseStringUTFChars(env, jni_address, address);
497 (*env)->DeleteLocalRef(env, jni_address);
501 * Class: org_iotivity_ca_jar_caleinterface
502 * Method: caManagerLeServicesDiscoveredCallback
503 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
505 JNIEXPORT void JNICALL
506 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeServicesDiscoveredCallback(JNIEnv *env,
511 VERIFY_NON_NULL_VOID(env, TAG, "env");
512 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
513 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");
515 if (GATT_SUCCESS == status)
517 if (!g_connectedDeviceSet)
519 OIC_LOG(INFO, TAG, "g_connectedDeviceSet is needed for CM. "
520 "please call CAManagerLEClientInitialize");
524 jstring jni_address = CALEGetAddressFromGatt(env, gatt);
527 OIC_LOG(ERROR, TAG, "CALEGetAddressFromGatt is null");
531 char* address = (char*)(*env)->GetStringUTFChars(env, jni_address, NULL);
534 OIC_LOG(ERROR, TAG, "address is null");
535 (*env)->DeleteLocalRef(env, jni_address);
539 if (CAManagerIsConnectedDeviceAddress(env, g_context, jni_address, g_connectedDeviceSet))
541 OIC_LOG(INFO, TAG, "AC list - the address will be added to ACData list");
542 CAManagerAddACData(env, jni_address);
543 CAManagerSetAutoConnectingFlag(env, jni_address, false);
545 // next connection will be requested with JNI_TRUE on autoConnect flag
546 // after first connection
547 CALEClientSetFlagToState(env, jni_address, CA_LE_AUTO_CONNECT_FLAG, JNI_TRUE);
551 OIC_LOG(DEBUG, TAG, "AC list - the address is not set to AutoConnect");
554 (*env)->ReleaseStringUTFChars(env, jni_address, address);
555 (*env)->DeleteLocalRef(env, jni_address);
559 OIC_LOG(ERROR, TAG, "ServicesDiscovery has failed");
564 * Class: org_iotivity_ca_jar_caleinterface
565 * Method: caManagerLeRemoteRssiCallback
566 * Signature: (Landroid/bluetooth/BluetoothGatt;I)V
568 JNIEXPORT void JNICALL
569 Java_org_iotivity_ca_CaLeClientInterface_caManagerLeRemoteRssiCallback(JNIEnv *env,
579 OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - rssi : %d: ", rssi);
580 OIC_LOG_V(DEBUG, TAG, "caManagerLeRemoteRssiCallback - status : %d: ", status);
581 VERIFY_NON_NULL_VOID(env, TAG, "env");
582 VERIFY_NON_NULL_VOID(obj, TAG, "obj");
583 VERIFY_NON_NULL_VOID(gatt, TAG, "gatt");