modified timing issue associated with data transmission.
authorjihwan.seo <jihwan.seo@samsung.com>
Fri, 4 Mar 2016 12:20:52 +0000 (21:20 +0900)
committerJon A. Cruz <jon@joncruz.org>
Mon, 7 Mar 2016 02:52:43 +0000 (02:52 +0000)
when gatt is disconnected during data transmittion.
there is some crash since some global variable was available.

Change-Id: I65cbedea1f1646c4636b507171a98c35dea76d4e
Signed-off-by: jihwan.seo <jihwan.seo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5433
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jon@joncruz.org>
android/android_api/base/jni/JniCaInterface.c
resource/csdk/connectivity/src/bt_le_adapter/android/caleclient.h
resource/csdk/connectivity/src/bt_le_adapter/android/caleserver.c
resource/csdk/connectivity/src/bt_le_adapter/android/caleutils.h

index 219ea7c..13b7042 100644 (file)
@@ -239,6 +239,7 @@ Java_org_iotivity_ca_CaInterface_caManagerTerminate(JNIEnv *env, jclass clazz)
     if (g_listenerObject)
     {
         (*env)->DeleteGlobalRef(env, g_listenerObject);
+        g_listenerObject = NULL;
     }
 }
 
index ad2f8da..10066e1 100644 (file)
@@ -45,9 +45,6 @@ static const uint16_t STATE_SEND_NONE = 0;
 static const uint16_t STATE_SEND_SUCCESS = 1;
 static const uint16_t STATE_SEND_FAILED = 2;
 
-static const jint STATE_CONNECTED = 2;
-static const jint STATE_DISCONNECTED = 0;
-
 typedef struct le_state_info
 {
     char address[CA_MACADDR_SIZE];
index 756f552..a28d662 100644 (file)
@@ -44,6 +44,7 @@ static jobject g_context = NULL;
 static jobject g_bluetoothGattServer = NULL;
 static jobject g_bluetoothGattServerCallback = NULL;
 static jobject g_leAdvertiseCallback = NULL;
+static jobject g_bluetoothManager = NULL;
 
 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
 static CABLEErrorHandleCallback g_serverErrorCallback;
@@ -54,6 +55,7 @@ static bool g_isStartServer = false;
 static bool g_isInitializedServer = false;
 
 static jbyteArray g_sendBuffer = NULL;
+static jobject g_obj_bluetoothDevice = NULL;
 
 static CABLEDataReceivedCallback g_CABLEServerDataReceivedCallback = NULL;
 static ca_mutex g_bleReqRespCbMutex = NULL;
@@ -144,6 +146,49 @@ CAResult_t CALEServerCreateJniInterfaceObject()
     return CA_STATUS_FAILED;
 }
 
+/**
+ * get the current connection state of the gatt profile to the remote device.
+ * @param[in]   env              JNI interface pointer.
+ * @param[in]   device           bluetooth device object
+ * @return  state of the profile connection.
+ */
+static jint CALEServerGetConnectionState(JNIEnv *env, jobject device)
+{
+    OIC_LOG(DEBUG, TAG, "CALEServerGetConnectionState");
+
+    VERIFY_NON_NULL_RET(env, TAG, "env", -1);
+    VERIFY_NON_NULL_RET(device, TAG, "device", -1);
+
+    jclass jni_cid_bluetoothManager = (*env)->FindClass(env, "android/bluetooth/BluetoothManager");
+    if (!jni_cid_bluetoothManager)
+    {
+        OIC_LOG(ERROR, TAG, "jni_cid_bluetoothManager is null");
+        return -1;
+    }
+
+    jmethodID jni_mid_getConnectionState = (*env)->GetMethodID(env, jni_cid_bluetoothManager,
+                                                               "getConnectionState",
+                                                               "(Landroid/bluetooth/BluetoothDevice"
+                                                               ";I)I");
+    if (!jni_mid_getConnectionState)
+    {
+        OIC_LOG(ERROR, TAG, "jni_mid_getConnectionState is null");
+        return -1;
+    }
+
+    if (!g_bluetoothManager)
+    {
+        OIC_LOG(ERROR, TAG, "g_bluetoothManager is null");
+        return -1;
+    }
+
+    jint jni_state = (jint)(*env)->CallIntMethod(env, g_bluetoothManager,
+                                                 jni_mid_getConnectionState,
+                                                 device, GATT_PROFILE);
+    OIC_LOG_V(INFO, TAG, "connection state is %d", jni_state);
+    return jni_state;
+}
+
 jobject CALEServerSetResponseData(JNIEnv *env, jbyteArray responseData)
 {
     OIC_LOG(DEBUG, TAG, "IN - CALEServerSetResponseData");
@@ -274,6 +319,12 @@ CAResult_t CALEServerSendResponseData(JNIEnv *env, jobject device, jobject respo
         return CA_ADAPTER_NOT_ENABLED;
     }
 
+    if (STATE_CONNECTED != CALEServerGetConnectionState(env, device))
+    {
+        OIC_LOG(ERROR, TAG, "it is not connected state");
+        return CA_STATUS_FAILED;
+    }
+
     jclass jni_cid_bluetoothGattServer = (*env)->FindClass(env,
                                                            "android/bluetooth/BluetoothGattServer");
     if (!jni_cid_bluetoothGattServer)
@@ -888,6 +939,12 @@ jobject CALEServerOpenGattServer(JNIEnv *env)
         return NULL;
     }
 
+    if (g_bluetoothManager)
+    {
+        (*env)->DeleteGlobalRef(env, g_bluetoothManager);
+    }
+    g_bluetoothManager = (*env)->NewGlobalRef(env, jni_obj_bluetoothManager);
+
     jobject jni_obj_bluetoothGattServer = (*env)->CallObjectMethod(env, jni_obj_bluetoothManager,
                                                                    jni_mid_openGattServer,
                                                                    g_context,
@@ -1523,6 +1580,12 @@ void CALEServerTerminate()
         g_sendBuffer = NULL;
     }
 
+    if (g_bluetoothManager)
+    {
+        (*env)->DeleteGlobalRef(env, g_bluetoothManager);
+        g_bluetoothManager = NULL;
+    }
+
     ca_cond_free(g_threadSendNotifyCond);
     g_threadSendNotifyCond = NULL;
 
@@ -1758,7 +1821,6 @@ CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, co
 
     ca_mutex_lock(g_threadSendMutex);
 
-    jobject jni_obj_bluetoothDevice = NULL;
     uint32_t length = u_arraylist_length(g_connectedDeviceList);
     for (uint32_t index = 0; index < length; index++)
     {
@@ -1789,23 +1851,33 @@ CAResult_t CALEServerSendUnicastMessageImpl(JNIEnv *env, const char* address, co
         if (!strcmp(setAddress, address))
         {
             OIC_LOG(DEBUG, TAG, "found the device");
-            jni_obj_bluetoothDevice = jarrayObj;
+
+            if (g_obj_bluetoothDevice)
+            {
+                (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
+            }
+            g_obj_bluetoothDevice = (*env)->NewGlobalRef(env, jarrayObj);
             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
             break;
         }
         (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
     }
 
-    if (jni_obj_bluetoothDevice)
+    if (g_obj_bluetoothDevice)
     {
         jbyteArray jni_arr = (*env)->NewByteArray(env, dataLen);
         (*env)->SetByteArrayRegion(env, jni_arr, 0, dataLen, (jbyte*) data);
         g_sendBuffer = (jbyteArray)(*env)->NewGlobalRef(env, jni_arr);
 
-        CAResult_t res = CALEServerSend(env, jni_obj_bluetoothDevice, g_sendBuffer);
+        CAResult_t res = CALEServerSend(env, g_obj_bluetoothDevice, g_sendBuffer);
         if (CA_STATUS_OK != res)
         {
             OIC_LOG(ERROR, TAG, "send has failed");
+            if (g_obj_bluetoothDevice)
+            {
+                (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
+                g_obj_bluetoothDevice = NULL;
+            }
             goto error_exit;
         }
     }
@@ -1888,11 +1960,22 @@ CAResult_t CALEServerSendMulticastMessageImpl(JNIEnv *env, const uint8_t *data,
             continue;
         }
 
-        CAResult_t res = CALEServerSend(env, jarrayObj, jni_bytearr_data);
+        if (g_obj_bluetoothDevice)
+        {
+            (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
+        }
+        g_obj_bluetoothDevice = (*env)->NewGlobalRef(env, jarrayObj);
+
+        CAResult_t res = CALEServerSend(env, g_obj_bluetoothDevice, jni_bytearr_data);
         if (CA_STATUS_OK != res)
         {
             OIC_LOG_V(ERROR, TAG, "send has failed for the device[%s]", address);
             (*env)->ReleaseStringUTFChars(env, jni_address, address);
+            if (g_obj_bluetoothDevice)
+            {
+                (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
+                g_obj_bluetoothDevice = NULL;
+            }
             continue;
         }
 
@@ -2315,6 +2398,13 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerNotificationSentCallback(
         if (CA_STATUS_OK != res)
         {
             OIC_LOG(ERROR, TAG, "send has failed");
+
+            if (g_obj_bluetoothDevice)
+            {
+                (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
+                g_obj_bluetoothDevice = NULL;
+            }
+
             ca_mutex_lock(g_threadSendNotifyMutex);
             g_isSignalSetFlag = true;
             ca_cond_signal(g_threadSendNotifyCond);
@@ -2326,6 +2416,12 @@ Java_org_iotivity_ca_CaLeServerInterface_caLeGattServerNotificationSentCallback(
     {
         OIC_LOG(DEBUG, TAG, "notify success");
 
+        if (g_obj_bluetoothDevice)
+        {
+            (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
+            g_obj_bluetoothDevice = NULL;
+        }
+
         // next data can be sent
         ca_mutex_lock(g_threadSendNotifyMutex);
         OIC_LOG(DEBUG, TAG, "g_isSignalSetFlag is set true and signal");
@@ -2440,6 +2536,12 @@ CAResult_t CAStopLEGattServer()
         (*env)->DeleteGlobalRef(env, g_bluetoothGattServerCallback);
     }
 
+    if (g_obj_bluetoothDevice)
+    {
+        (*env)->DeleteGlobalRef(env, g_obj_bluetoothDevice);
+        g_obj_bluetoothDevice = NULL;
+    }
+
     ca_mutex_lock(g_threadSendNotifyMutex);
     ca_cond_signal(g_threadSendNotifyCond);
     ca_mutex_unlock(g_threadSendNotifyMutex);
index 4d91676..c1fe2ce 100644 (file)
@@ -53,12 +53,15 @@ static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAda
 static const char METHODID_BT_DEVICE[] = "()Landroid/bluetooth/BluetoothDevice;";
 static const char METHODID_BT_REMOTE_DEVICE[] = "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;";
 
+static const jint GATT_PROFILE = 7;
 static const jint GATT_SUCCESS = 0;
 
 static const jint BOND_BONDED = 12;
 static const jint BOND_BONDING = 11;
 static const jint BOND_NONE = 10;
 
+static const jint STATE_CONNECTED = 2;
+static const jint STATE_DISCONNECTED = 0;
 /**
  * get uuid(jni object) from uuid(character).
  * @param[in]   env              JNI interface pointer.