Changed to be used only once to create input stream.
authorJaehong Jo <jaehong.jo@samsung.com>
Tue, 12 Apr 2016 07:50:03 +0000 (16:50 +0900)
committerJon A. Cruz <jon@joncruz.org>
Fri, 15 Apr 2016 07:18:32 +0000 (07:18 +0000)
Fixed a problem that generates whenever read data.

Change-Id: Ib07dac59dce69f8305926d3b7ad5597a582d0a4d
Signed-off-by: Jaehong Jo <jaehong.jo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/7755
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jon@joncruz.org>
resource/csdk/connectivity/src/bt_edr_adapter/android/caedrserver.c
resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.c
resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.h

index 0a54f98..1979eee 100644 (file)
@@ -40,7 +40,6 @@ static const char METHODID_OBJECTNONPARAM[] = "()Landroid/bluetooth/BluetoothAda
 static const char CLASSPATH_BT_ADPATER[] = "android/bluetooth/BluetoothAdapter";
 static const char CLASSPATH_BT_UUID[] = "java/util/UUID";
 static const char CLASSPATH_BT_SERVER_SOCKET[] = "android/bluetooth/BluetoothServerSocket";
-static const char CLASSPATH_BT_SOCKET[] = "android/bluetooth/BluetoothSocket";
 
 static ca_thread_pool_t g_threadPoolHandle = NULL;
 
@@ -53,11 +52,6 @@ static JavaVM *g_jvm;
 #define EDR_MAX_HEADER_LEN  6
 
 /**
- * server socket instance.
- */
-static jobject g_serverSocketObject = NULL;
-
-/**
  * Mutex to synchronize receive server.
  */
 static ca_mutex g_mutexReceiveServer = NULL;
@@ -571,53 +565,35 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
         return CA_STATUS_FAILED;
     }
 
-    // check whether this socket object is connected or not.
-    jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(id);
-    if (!jni_obj_socket)
-    {
-        return CA_STATUS_INVALID_PARAM;
-    }
-
-    // start to read through InputStream
-    jmethodID jni_mid_getInputStream = CAGetJNIMethodID(env,
-                                                        CLASSPATH_BT_SOCKET,
-                                                        "getInputStream",
-                                                        "()Ljava/io/InputStream;");
-
-    jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, jni_obj_socket,
-                                                           jni_mid_getInputStream);
+    jobject jni_obj_inputStream = CAEDRNativeGetInputStream(id);
     if (!jni_obj_inputStream)
     {
         OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null");
         return CA_STATUS_FAILED;
     }
 
-    jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
-    if (!jni_cid_InputStream)
-    {
-        OIC_LOG(ERROR, TAG, "jni_cid_InputStream is null");
-        (*env)->DeleteLocalRef(env, jni_obj_inputStream);
-        return CA_STATUS_FAILED;
-    }
-
-    jmethodID jni_mid_available = (*env)->GetMethodID(env, jni_cid_InputStream,
-                                                      "available", "()I");
+    jmethodID jni_mid_available = CAGetJNIMethodID(env, "java/io/InputStream", "available", "()I");
     if (!jni_mid_available)
     {
         OIC_LOG(ERROR, TAG, "jni_mid_available is null");
-        goto exit;
+        return CA_STATUS_FAILED;
     }
 
     jint available = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_available);
 
-    CAConnectedDeviceInfo_t *deviceInfo = NULL;
     if (0 < available)
     {
+        jobject jni_obj_socket = CAEDRNativeGetDeviceSocket(id);
+        if (!jni_obj_socket)
+        {
+            OIC_LOG(ERROR, TAG, "jni_obj_socket is null");
+            return CA_STATUS_FAILED;
+        }
         jstring jni_str_address = CAEDRNativeGetAddressFromDeviceSocket(env, jni_obj_socket);
         if (!jni_str_address)
         {
             OIC_LOG(ERROR, TAG, "jni_str_address is null");
-            goto exit;
+            return CA_STATUS_FAILED;
         }
 
         const char* address = (*env)->GetStringUTFChars(env, jni_str_address, NULL);
@@ -625,27 +601,28 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
         {
             OIC_LOG(ERROR, TAG, "address is null");
             (*env)->DeleteLocalRef(env, jni_str_address);
-            goto exit;
+            return CA_STATUS_FAILED;
         }
 
         OIC_LOG_V(DEBUG, TAG, "get InputStream..%d, %s", id, address);
-        jmethodID jni_mid_read = (*env)->GetMethodID(env, jni_cid_InputStream,
-                                                     "read", "([BII)I");
+        jmethodID jni_mid_read = CAGetJNIMethodID(env, "java/io/InputStream", "read", "([BII)I");
         if (!jni_mid_read)
         {
             OIC_LOG(ERROR, TAG, "jni_mid_read is null");
             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
             (*env)->DeleteLocalRef(env, jni_str_address);
-            goto exit;
+            return CA_STATUS_FAILED;
         }
 
-        deviceInfo = (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address);
+        CAConnectedDeviceInfo_t *deviceInfo =
+                (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(address);
+
+        (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+        (*env)->DeleteLocalRef(env, jni_str_address);
         if (!deviceInfo)
         {
             OIC_LOG(ERROR, TAG, "failed to get device info from list");
-            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-            (*env)->DeleteLocalRef(env, jni_str_address);
-            goto exit;
+            return CA_STATUS_FAILED;
         }
 
         jint bufSize = (deviceInfo->totalDataLen == 0) ?
@@ -656,31 +633,30 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
             if (!deviceInfo->recvData)
             {
                 OIC_LOG(ERROR, TAG, "out of memory");
-                (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-                (*env)->DeleteLocalRef(env, jni_str_address);
-                goto exit;
+                return CA_STATUS_FAILED;
             }
         }
 
-        jbyteArray jbuf = (*env)->NewByteArray(env, (jint) bufSize - deviceInfo->recvDataLen);
+        jint remainSize = (jint) bufSize - deviceInfo->recvDataLen;
+        if (0 >= remainSize)
+        {
+            OIC_LOG(ERROR, TAG, "remainSize value is invalid.");
+            return CA_STATUS_FAILED;
+        }
+        jbyteArray jbuf = (*env)->NewByteArray(env, remainSize);
         if (!jbuf)
         {
             OIC_LOG(ERROR, TAG, "jbuf is null");
-            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-            (*env)->DeleteLocalRef(env, jni_str_address);
-            goto exit;
+            return CA_STATUS_FAILED;
         }
 
         jint recvLen = (*env)->CallIntMethod(env, jni_obj_inputStream, jni_mid_read,
-                                             jbuf, (jint) 0,
-                                             (jint) bufSize - deviceInfo->recvDataLen);
+                                             jbuf, (jint) 0, remainSize);
         if (-1 == recvLen)
         {
             OIC_LOG(ERROR, TAG, "recvLen is -1");
             (*env)->DeleteLocalRef(env, jbuf);
-            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-            (*env)->DeleteLocalRef(env, jni_str_address);
-            goto exit;
+            return CA_STATUS_FAILED;
         }
 
         jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
@@ -688,13 +664,14 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
         {
             OIC_LOG(ERROR, TAG, "buf is null");
             (*env)->DeleteLocalRef(env, jbuf);
-            (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-            (*env)->DeleteLocalRef(env, jni_str_address);
-            goto exit;
+            return CA_STATUS_FAILED;
         }
         memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*) buf, recvLen);
         deviceInfo->recvDataLen += recvLen;
 
+        (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
+        (*env)->DeleteLocalRef(env, jbuf);
+
         OIC_LOG(DEBUG, TAG, "read something from InputStream");
 
         if (!deviceInfo->totalDataLen)
@@ -712,11 +689,7 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
                 if (!newBuf)
                 {
                     OIC_LOG(ERROR, TAG, "out of memory");
-                    (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
-                    (*env)->DeleteLocalRef(env, jbuf);
-                    (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-                    (*env)->DeleteLocalRef(env, jni_str_address);
-                    goto exit;
+                    return CA_STATUS_FAILED;
                 }
                 deviceInfo->recvData = newBuf;
             }
@@ -736,11 +709,7 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
                 CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
                 ca_mutex_unlock(g_mutexStateList);
 
-                (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
-                (*env)->DeleteLocalRef(env, jbuf);
-                (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-                (*env)->DeleteLocalRef(env, jni_str_address);
-                goto exit;
+                return CA_STATUS_FAILED;
             }
 
             if (g_edrPacketReceivedCallback)
@@ -758,21 +727,9 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id)
                 deviceInfo->totalDataLen = 0;
             }
         }
-        (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
-        (*env)->DeleteLocalRef(env, jbuf);
-        (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
-        (*env)->DeleteLocalRef(env, jni_str_address);
     }
-    (*env)->DeleteLocalRef(env, jni_cid_InputStream);
-    (*env)->DeleteLocalRef(env, jni_obj_inputStream);
 
     return CA_STATUS_OK;
-
-exit:
-    (*env)->DeleteLocalRef(env, jni_cid_InputStream);
-    (*env)->DeleteLocalRef(env, jni_obj_inputStream);
-
-    return CA_STATUS_FAILED;
 }
 
 void CANativeStartListenTask(JNIEnv *env)
@@ -879,8 +836,6 @@ jobject CAEDRNativeListen(JNIEnv *env)
         return NULL;
     }
 
-    g_serverSocketObject = (*env)->NewGlobalRef(env, jni_obj_BTServerSocket);
-
     OIC_LOG(DEBUG, TAG, "CAEDRNativeListen - OUT");
 
     return jni_obj_BTServerSocket;
@@ -931,8 +886,16 @@ void CAEDRNativeAccept(JNIEnv *env, jobject serverSocketObject)
 
         // set socket to list
         jobject jni_socket = (*env)->NewGlobalRef(env, jni_obj_BTSocket);
+        if (!jni_socket)
+        {
+            OIC_LOG(ERROR, TAG, "jni_socket is null");
+            (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
+            return;
+        }
         ca_mutex_lock(g_mutexObjectList);
         CAEDRNativeAddDeviceSocketToList(env, jni_socket);
+        (*env)->DeleteGlobalRef(env, jni_socket);
+        (*env)->DeleteLocalRef(env, jni_obj_BTSocket);
         ca_mutex_unlock(g_mutexObjectList);
 
         // update state
index 858b808..a70ddc0 100644 (file)
@@ -558,8 +558,43 @@ void CAEDRNativeAddDeviceSocketToList(JNIEnv *env, jobject deviceSocket)
 
     if (!CAEDRNativeIsDeviceSocketInList(env, remoteAddress))
     {
-        jobject gDeviceSocker = (*env)->NewGlobalRef(env, deviceSocket);
-        u_arraylist_add(g_deviceObjectList, gDeviceSocker);
+        CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) OICCalloc(1, sizeof(*socketInfo));
+        if (!socketInfo)
+        {
+            OIC_LOG(ERROR, TAG, "Out of memory");
+            return;
+        }
+
+        jmethodID jni_mid_getInputStream = CAGetJNIMethodID(env,
+                                                            "android/bluetooth/BluetoothSocket",
+                                                            "getInputStream",
+                                                            "()Ljava/io/InputStream;");
+        if (!jni_mid_getInputStream)
+        {
+            OIC_LOG(ERROR, TAG, "jni_mid_getInputStream is null");
+            return;
+        }
+
+        jobject jni_obj_inputStream = (*env)->CallObjectMethod(env, deviceSocket,
+                                                               jni_mid_getInputStream);
+        if (!jni_obj_inputStream)
+        {
+            OIC_LOG(ERROR, TAG, "jni_obj_inputStream is null");
+            return;
+        }
+
+        socketInfo->deviceSocket = (*env)->NewGlobalRef(env, deviceSocket);
+        socketInfo->inputStream = (*env)->NewGlobalRef(env, jni_obj_inputStream);
+        (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+
+        bool result = u_arraylist_add(g_deviceObjectList, (void *) socketInfo);
+        if (!result)
+        {
+            OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+            OICFree(socketInfo);
+            return;
+        }
+
         OIC_LOG(DEBUG, TAG, "add new device socket object to list");
     }
     (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
@@ -579,8 +614,15 @@ bool CAEDRNativeIsDeviceSocketInList(JNIEnv *env, const char* remoteAddress)
     jint length = u_arraylist_length(g_deviceStateList);
     for (jint index = 0; index < length; index++)
     {
+        CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) u_arraylist_get(g_deviceObjectList,
+                                                                              index);
+        if (!socketInfo)
+        {
+            OIC_LOG(DEBUG, TAG, "socketInfo is null");
+            return false;
+        }
 
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
+        jobject jarrayObj = socketInfo->deviceSocket;
         if (!jarrayObj)
         {
             OIC_LOG(DEBUG, TAG, "jarrayObj is null");
@@ -671,13 +713,26 @@ void CAEDRNativeRemoveAllDeviceSocket(JNIEnv *env)
     jint length = u_arraylist_length(g_deviceStateList);
     for (jint index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
-        if (!jarrayObj)
+
+        CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) u_arraylist_get(g_deviceObjectList,
+                                                                              index);
+        if (!socketInfo)
         {
-            OIC_LOG(ERROR, TAG, "jarrayObj is null");
-            return;
+            OIC_LOG(ERROR, TAG, "socketInfo is null");
+            continue;
+        }
+
+        jobject jdeviceSocket = socketInfo->deviceSocket;
+        if (jdeviceSocket)
+        {
+            (*env)->DeleteGlobalRef(env, jdeviceSocket);
+        }
+
+        jobject jinputStream = socketInfo->inputStream;
+        if (jinputStream)
+        {
+            (*env)->DeleteGlobalRef(env, jinputStream);
         }
-        (*env)->DeleteGlobalRef(env, jarrayObj);
     }
 
     OICFree(g_deviceObjectList);
@@ -698,7 +753,15 @@ void CAEDRNativeRemoveDeviceSocket(JNIEnv *env, jobject deviceSocket)
     jint length = u_arraylist_length(g_deviceStateList);
     for (jint index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
+        CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) u_arraylist_get(g_deviceObjectList,
+                                                                              index);
+        if (!socketInfo)
+        {
+            OIC_LOG(ERROR, TAG, "socketInfo is null");
+            continue;
+        }
+
+        jobject jarrayObj = socketInfo->deviceSocket;
         if (!jarrayObj)
         {
             OIC_LOG(DEBUG, TAG, "jarrayObj is null");
@@ -726,6 +789,11 @@ void CAEDRNativeRemoveDeviceSocket(JNIEnv *env, jobject deviceSocket)
         {
             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
             (*env)->DeleteGlobalRef(env, jarrayObj);
+            jobject jinputStream = socketInfo->inputStream;
+            if (jinputStream)
+            {
+                (*env)->DeleteGlobalRef(env, jinputStream);
+            }
             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
             (*env)->ReleaseStringUTFChars(env, jni_remoteAddress, remoteAddress);
 
@@ -753,7 +821,15 @@ void CAEDRNativeRemoveDeviceSocketBaseAddr(JNIEnv *env, jstring address)
     jint length = u_arraylist_length(g_deviceStateList);
     for (jint index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
+        CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) u_arraylist_get(g_deviceObjectList,
+                                                                              index);
+        if (!socketInfo)
+        {
+            OIC_LOG(ERROR, TAG, "socketInfo is null");
+            continue;
+        }
+
+        jobject jarrayObj = socketInfo->deviceSocket;
         if (!jarrayObj)
         {
             OIC_LOG(DEBUG, TAG, "jarrayObj is null");
@@ -771,8 +847,13 @@ void CAEDRNativeRemoveDeviceSocketBaseAddr(JNIEnv *env, jstring address)
 
         if (!strcmp(setAddress, remoteAddress))
         {
-            OIC_LOG_V(ERROR, TAG, "remove object : %s", remoteAddress);
+            OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddress);
             (*env)->DeleteGlobalRef(env, jarrayObj);
+            jobject jinputStream = socketInfo->inputStream;
+            if (jinputStream)
+            {
+                (*env)->DeleteGlobalRef(env, jinputStream);
+            }
             (*env)->ReleaseStringUTFChars(env, jni_setAddress, setAddress);
             (*env)->ReleaseStringUTFChars(env, address, remoteAddress);
 
@@ -787,7 +868,7 @@ void CAEDRNativeRemoveDeviceSocketBaseAddr(JNIEnv *env, jstring address)
     return;
 }
 
-jobject CAEDRNativeGetDeviceSocket(uint32_t idx)
+jobject CAEDRNativeGetDeviceSocket(uint32_t index)
 {
     if (!g_deviceObjectList)
     {
@@ -795,7 +876,15 @@ jobject CAEDRNativeGetDeviceSocket(uint32_t idx)
         return NULL;
     }
 
-    jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, idx);
+    CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) u_arraylist_get(g_deviceObjectList,
+                                                                          index);
+    if (!socketInfo)
+    {
+        OIC_LOG(ERROR, TAG, "socketInfo is null");
+        return NULL;
+    }
+
+    jobject jarrayObj = socketInfo->deviceSocket;
     if (!jarrayObj)
     {
         OIC_LOG(ERROR, TAG, "jarrayObj is not available");
@@ -817,7 +906,15 @@ jobject CAEDRNativeGetDeviceSocketBaseAddr(JNIEnv *env, const char* remoteAddres
     jint length = u_arraylist_length(g_deviceStateList);
     for (jint index = 0; index < length; index++)
     {
-        jobject jarrayObj = (jobject) u_arraylist_get(g_deviceObjectList, index);
+        CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) u_arraylist_get(g_deviceObjectList,
+                                                                              index);
+        if (!socketInfo)
+        {
+            OIC_LOG(ERROR, TAG, "socketInfo is null");
+            continue;
+        }
+
+        jobject jarrayObj = socketInfo->deviceSocket;
         if (!jarrayObj)
         {
             OIC_LOG(ERROR, TAG, "jarrayObj is null");
@@ -846,6 +943,31 @@ jobject CAEDRNativeGetDeviceSocketBaseAddr(JNIEnv *env, const char* remoteAddres
     return NULL;
 }
 
+jobject CAEDRNativeGetInputStream(uint32_t index)
+{
+    if (!g_deviceObjectList)
+    {
+        OIC_LOG(ERROR, TAG, "gdeviceObjectList is null");
+        return NULL;
+    }
+
+    CAEDRSocketInfo_t *socketInfo = (CAEDRSocketInfo_t *) u_arraylist_get(g_deviceObjectList,
+                                                                          index);
+    if (!socketInfo)
+    {
+        OIC_LOG(ERROR, TAG, "socketInfo is null");
+        return NULL;
+    }
+
+    jobject jarrayObj = socketInfo->inputStream;
+    if (!jarrayObj)
+    {
+        OIC_LOG(ERROR, TAG, "jarrayObj is not available");
+        return NULL;
+    }
+    return jarrayObj;
+}
+
 uint32_t CAEDRGetSocketListLength()
 {
     if (!g_deviceObjectList)
index 7d1601e..6b83897 100644 (file)
@@ -36,6 +36,15 @@ extern "C"
 #endif
 
 /**
+ * EDR Socket Information for EDR transport
+ */
+typedef struct
+{
+    jobject deviceSocket;   /**< Bluetooth device socket info */
+    jobject inputStream;    /**< InputStream for read data */
+} CAEDRSocketInfo_t;
+
+/**
  * Get address from device socket.
  * @param[in]   env                 JNI interface pointer.
  * @param[in]   bluetoothSocketObj  bluetooth socket object.
@@ -170,10 +179,10 @@ void CAEDRNativeRemoveDeviceSocketBaseAddr(JNIEnv *env, jstring address);
 
 /**
  * Get device socket object from the list.
- * @param[in]  idx              index of device list.
+ * @param[in]  index            index of device list.
  * @return Device socket object or NULL.
  */
-jobject CAEDRNativeGetDeviceSocket(uint32_t idx);
+jobject CAEDRNativeGetDeviceSocket(uint32_t index);
 
 /**
  * Get device socket address.
@@ -184,6 +193,13 @@ jobject CAEDRNativeGetDeviceSocket(uint32_t idx);
 jobject CAEDRNativeGetDeviceSocketBaseAddr(JNIEnv *env, const char* remoteAddress);
 
 /**
+ * Get input stream object from the list.
+ * @param[in]   index           index of device list.
+ * @return Input stream object or NULL.
+ */
+jobject CAEDRNativeGetInputStream(uint32_t index);
+
+/**
  * Get length of device socket list.
  * @return length of list.
  */