Fix Android EDR memory leak
authorYu-Hsin Hung <hungys@hotmail.com>
Tue, 4 Aug 2015 02:50:59 +0000 (02:50 +0000)
committerErich Keane <erich.keane@intel.com>
Wed, 5 Aug 2015 16:50:51 +0000 (16:50 +0000)
Android applications with EDR adpater always get crashed after
running for few minutes. The exception says that the JNI local reference
table is overflow, due to some memory not released by GC.

Change-Id: Ie274d7b28ab9f187728f04aa0dceaa4ebcb61240
Signed-off-by: Yu-Hsin Hung <hungys@hotmail.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2099
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
Reviewed-by: Ashok Babu Channa <ashok.channa@samsung.com>
Reviewed-by: Jaehong Jo <jaehong.jo@samsung.com>
Reviewed-by: Erich Keane <erich.keane@intel.com>
resource/csdk/connectivity/src/bt_edr_adapter/android/caedrserver.c
resource/csdk/connectivity/src/bt_edr_adapter/android/caedrutils.c

index c335b75..3b7c3a1 100644 (file)
@@ -755,6 +755,8 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
             CAEDRNativeRemoveDeviceSocket(env, jni_obj_socket);
             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
 
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             return CA_STATUS_FAILED;
         }
 
@@ -762,6 +764,8 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
         jclass jni_cid_BTsocket = (*env)->FindClass(env, "android/bluetooth/BluetoothSocket");
         if (!jni_cid_BTsocket)
         {
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             OIC_LOG(ERROR, TAG, "[EDR][Native] btReadData: jni_cid_BTsocket is null");
             return CA_STATUS_FAILED;
         }
@@ -772,6 +776,9 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
 
         if (!jni_obj_socket)
         {
+            (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore..");
             return CA_STATUS_FAILED;
         }
@@ -783,6 +790,10 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
         jclass jni_cid_InputStream = (*env)->FindClass(env, "java/io/InputStream");
         if (!jni_cid_InputStream)
         {
+            (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+            (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             OIC_LOG(ERROR, TAG, "[EDR][Native] btReadData: jni_cid_InputStream is null");
             return CA_STATUS_FAILED;
         }
@@ -792,6 +803,11 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
 
         if (!jni_obj_socket)
         {
+            (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+            (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+            (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_socket is not available anymore...");
             return CA_STATUS_FAILED;
         }
@@ -810,6 +826,12 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
 
         if (-1 == length)
         {
+            (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+            (*env)->DeleteLocalRef(env, jbuf);
+            (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+            (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             OIC_LOG(ERROR, TAG, "[EDR][Native] read buffer is empty...");
             return CA_STATUS_FAILED;
         }
@@ -826,6 +848,13 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
             CAEDRUpdateDeviceState(STATE_DISCONNECTED, address);
             ca_mutex_unlock(g_mutexStateList);
             (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+
+            (*env)->DeleteLocalRef(env, jbuf);
+            (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+            (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+            (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             return CA_STATUS_FAILED;
         }
 
@@ -833,6 +862,12 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
         jbyte* buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
         if (NULL == buf)
         {
+            (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+            (*env)->DeleteLocalRef(env, jbuf);
+            (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+            (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+            (*env)->DeleteLocalRef(env, jni_str_address);
+
             OIC_LOG(ERROR, TAG, "[EDR][Native] btReadData: buf is null");
             return CA_STATUS_FAILED;
         }
@@ -863,6 +898,12 @@ CAResult_t CAEDRNativeReadData(JNIEnv *env, uint32_t id, CAAdapterServerType_t t
         }
         (*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
         (*env)->ReleaseStringUTFChars(env, jni_str_address, address);
+
+        (*env)->DeleteLocalRef(env, jni_cid_InputStream);
+        (*env)->DeleteLocalRef(env, jbuf);
+        (*env)->DeleteLocalRef(env, jni_obj_inputStream);
+        (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+        (*env)->DeleteLocalRef(env, jni_str_address);
     }
     else
     {
@@ -902,6 +943,8 @@ jboolean CAEDRIsConnectedForSocket(JNIEnv *env, jobject socket)
                                                         "()Z");
     if (!jni_mid_isConnected)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] CAEDRIsConnectedForSocket \
                 - jni_mid_isConnected is null.");
         return JNI_FALSE;
@@ -909,6 +952,8 @@ jboolean CAEDRIsConnectedForSocket(JNIEnv *env, jobject socket)
 
     jboolean jni_isConnected = (*env)->CallBooleanMethod(env, socket, jni_mid_isConnected);
 
+    (*env)->DeleteLocalRef(env, jni_cid_BTsocket);
+
     return jni_isConnected;
 }
 
index 22dc24f..cbd1fb8 100644 (file)
@@ -60,6 +60,8 @@ jstring CAEDRNativeGetAddressFromDeviceSocket(JNIEnv *env, jobject bluetoothSock
             env, jni_cid_BTSocket, "getRemoteDevice", "()Landroid/bluetooth/BluetoothDevice;");
     if (!jni_mid_getRemoteDevice)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
         OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: jni_mid_getRemoteDevice is null");
         return NULL;
     }
@@ -68,6 +70,8 @@ jstring CAEDRNativeGetAddressFromDeviceSocket(JNIEnv *env, jobject bluetoothSock
                                                               jni_mid_getRemoteDevice);
     if (!jni_obj_remoteBTDevice)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
         OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: jni_obj_remoteBTDevice is null");
         return NULL;
     }
@@ -75,6 +79,9 @@ jstring CAEDRNativeGetAddressFromDeviceSocket(JNIEnv *env, jobject bluetoothSock
     jclass jni_cid_BTDevice = (*env)->FindClass(env, CLASSPATH_BT_DEVICE);
     if (!jni_cid_BTDevice)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+        (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
         OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: jni_cid_BTDevice is null");
         return NULL;
     }
@@ -82,6 +89,10 @@ jstring CAEDRNativeGetAddressFromDeviceSocket(JNIEnv *env, jobject bluetoothSock
                                                      METHODID_STRINGNONPARAM);
     if (!j_mid_getAddress)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+        (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+        (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
         OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: j_mid_getAddress is null");
         return NULL;
     }
@@ -89,10 +100,18 @@ jstring CAEDRNativeGetAddressFromDeviceSocket(JNIEnv *env, jobject bluetoothSock
     jstring j_str_address = (*env)->CallObjectMethod(env, jni_obj_remoteBTDevice, j_mid_getAddress);
     if (!j_str_address)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+        (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+        (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
         OIC_LOG(ERROR, TAG, "[EDR] getRemoteAddress: j_str_address is null");
         return NULL;
     }
 
+    (*env)->DeleteLocalRef(env, jni_obj_remoteBTDevice);
+    (*env)->DeleteLocalRef(env, jni_cid_BTDevice);
+    (*env)->DeleteLocalRef(env, jni_cid_BTSocket);
+
     return j_str_address;
 }
 
@@ -110,6 +129,8 @@ jstring CAEDRNativeGetLocalDeviceAddress(JNIEnv* env)
                                                                     METHODID_OBJECTNONPARAM);
     if (!jni_mid_getDefaultAdapter)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_mid_getDefaultAdapter is null");
         return NULL;
     }
@@ -118,6 +139,8 @@ jstring CAEDRNativeGetLocalDeviceAddress(JNIEnv* env)
                                                        METHODID_STRINGNONPARAM);
     if (!jni_mid_getAddress)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_mid_getAddress is null");
         return NULL;
     }
@@ -126,6 +149,8 @@ jstring CAEDRNativeGetLocalDeviceAddress(JNIEnv* env)
                                                                jni_mid_getDefaultAdapter);
     if (!jni_obj_BTAdapter)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_obj_BTAdapter is null");
         return NULL;
     }
@@ -134,10 +159,16 @@ jstring CAEDRNativeGetLocalDeviceAddress(JNIEnv* env)
                                                                 jni_mid_getAddress);
     if (!jni_str_address)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getAddress: jni_str_address is null");
         return NULL;
     }
 
+    (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+    (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
     return jni_str_address;
 }
 
@@ -155,6 +186,8 @@ jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env)
                                                                     METHODID_OBJECTNONPARAM);
     if (!jni_mid_getDefaultAdapter)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: default adapter is null");
         return NULL;
     }
@@ -163,6 +196,8 @@ jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env)
                                                                jni_mid_getDefaultAdapter);
     if (!jni_obj_BTAdapter)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: bluetooth adapter is null");
         return NULL;
     }
@@ -173,6 +208,9 @@ jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env)
                                                              "()Ljava/util/Set;");
     if (!jni_mid_getBondedDevices)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_mid_getBondedDevicesr is null");
         return NULL;
     }
@@ -181,6 +219,9 @@ jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env)
                                                                 jni_mid_getBondedDevices);
     if (!jni_obj_setPairedDevices)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_obj_setPairedDevices is null");
         return NULL;
     }
@@ -190,6 +231,9 @@ jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env)
     jclass jni_cid_Set = (*env)->FindClass(env, "java/util/Set");
     if (!jni_cid_Set)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_cid_Set is null");
         return NULL;
     }
@@ -198,6 +242,9 @@ jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env)
 
     if (!jni_mid_toArray)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_mid_toArray is null");
         return NULL;
     }
@@ -206,10 +253,16 @@ jobjectArray CAEDRNativeGetBondedDevices(JNIEnv *env)
             (*env)->CallObjectMethod(env, jni_obj_setPairedDevices, jni_mid_toArray));
     if (!jni_arrayPairedDevices)
     {
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] getBondedDevices: jni_arrayPairedDevices is null");
         return NULL;
     }
 
+    (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+    (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
     return jni_arrayPairedDevices;
 }
 
@@ -225,6 +278,8 @@ jint CAEDRNativeGetBTStateOnInfo(JNIEnv *env)
     jfieldID jni_fid_stateon = (*env)->GetStaticFieldID(env, jni_cid_BTAdapter, "STATE_ON", "I");
     if (jni_fid_stateon == 0)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] get_field_state is 0");
         return ERROR_CODE;
     }
@@ -232,6 +287,8 @@ jint CAEDRNativeGetBTStateOnInfo(JNIEnv *env)
 
     OIC_LOG_V(DEBUG, TAG, "[EDR][Native] bluetooth state integer value : %d", jni_int_val);
 
+    (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
     return jni_int_val;
 }
 
@@ -249,6 +306,8 @@ jboolean CAEDRNativeIsEnableBTAdapter(JNIEnv *env)
                                                                     METHODID_OBJECTNONPARAM);
     if (!jni_mid_getDefaultAdapter)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] jni_mid_getDefaultAdapter is null");
         return JNI_FALSE;
     }
@@ -257,6 +316,8 @@ jboolean CAEDRNativeIsEnableBTAdapter(JNIEnv *env)
                                                                jni_mid_getDefaultAdapter);
     if (!jni_obj_BTAdapter)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] jni_obj_BTAdapter is null");
         return JNI_FALSE;
     }
@@ -265,6 +326,9 @@ jboolean CAEDRNativeIsEnableBTAdapter(JNIEnv *env)
     jmethodID jni_mid_isEnable = (*env)->GetMethodID(env, jni_cid_BTAdapter, "isEnabled", "()Z");
     if (!jni_mid_isEnable)
     {
+        (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+        (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+
         OIC_LOG(ERROR, TAG, "[EDR][Native] jni_mid_isEnable is null");
         return JNI_FALSE;
     }
@@ -272,6 +336,9 @@ jboolean CAEDRNativeIsEnableBTAdapter(JNIEnv *env)
     jboolean jni_isEnable = (*env)->CallBooleanMethod(env, jni_obj_BTAdapter, jni_mid_isEnable);
     OIC_LOG_V(DEBUG, TAG, "[EDR][Native] adapter state is %d", jni_isEnable);
 
+    (*env)->DeleteLocalRef(env, jni_obj_BTAdapter);
+    (*env)->DeleteLocalRef(env, jni_cid_BTAdapter);
+
     return jni_isEnable;
 }