Fix for memory leak in AdapterSertvice.cpp : The native jobjectArray and jintArray instances are being declared and de-referenced in adapter_properties_callback() and remote_device_properties_callback() methods but is being initialized in get_properties() method. Becasuse of this, when the get_properties() method returns, VM looses reference to the native instances and hence leading to memory leak.
Change-Id: I48944887903a492a40cb95f5f79a56b9d58f85fa
diff --git a/jni/com_android_bluetooth_btservice_AdapterService.cpp b/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 89d4823..2af399b 100755
--- a/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -77,19 +77,7 @@
static int get_properties(int num_properties, bt_property_t *properties, jintArray *types,
jobjectArray *props) {
- jbyteArray propVal, val;
- val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
- if (val == NULL) goto Fail;
-
- //TODO(BT) Is this the best way to do it ?
- *props = callbackEnv->NewObjectArray(num_properties, callbackEnv->GetObjectClass(val),
- NULL);
- if (*props == NULL) goto Fail;
-
- *types = callbackEnv->NewIntArray(num_properties);
- if (*types == NULL) goto Fail;
- // Delete the reference to val
- callbackEnv->DeleteLocalRef(val);
+ jbyteArray propVal;
for (int i = 0; i < num_properties; i++) {
/* The higher layers expect rssi as a short int value, while the value is sent as a byte
@@ -114,7 +102,6 @@
}
return 0;
Fail:
- if (val) callbackEnv->DeleteLocalRef(val);
if (propVal) callbackEnv->DeleteLocalRef(propVal);
LOGE("Error while allocation of array in %s", __FUNCTION__);
return -1;
@@ -124,6 +111,9 @@
bt_property_t *properties) {
jobjectArray props;
jintArray types;
+ jbyteArray val;
+ jclass mclass;
+
if (!checkCallbackThread()) {
LOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
return;
@@ -136,6 +126,34 @@
return;
}
+ val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
+ if (val == NULL) {
+ LOGE("%s: Error allocating byteArray", __FUNCTION__);
+ return;
+ }
+
+ mclass = callbackEnv->GetObjectClass(val);
+
+ /* (BT) Initialize the jobjectArray and jintArray here itself and send the
+ initialized array pointers alone to get_properties */
+
+ props = callbackEnv->NewObjectArray(num_properties, mclass,
+ NULL);
+ if (props == NULL) {
+ LOGE("%s: Error allocating object Array for properties", __FUNCTION__);
+ return;
+ }
+
+ types = (jintArray)callbackEnv->NewIntArray(num_properties);
+
+ if (types == NULL) {
+ LOGE("%s: Error allocating int Array for values", __FUNCTION__);
+ return;
+ }
+ // Delete the reference to val and mclass
+ callbackEnv->DeleteLocalRef(mclass);
+ callbackEnv->DeleteLocalRef(val);
+
if (get_properties(num_properties, properties, &types, &props) < 0) {
if (props) callbackEnv->DeleteLocalRef(props);
if (types) callbackEnv->DeleteLocalRef(types);
@@ -170,6 +188,36 @@
jobjectArray props;
jbyteArray addr;
jintArray types;
+ jbyteArray val;
+ jclass mclass;
+
+ val = (jbyteArray) callbackEnv->NewByteArray(num_properties);
+ if (val == NULL) {
+ LOGE("%s: Error allocating byteArray", __FUNCTION__);
+ return;
+ }
+
+ mclass = callbackEnv->GetObjectClass(val);
+
+ /* Initialize the jobjectArray and jintArray here itself and send the
+ initialized array pointers alone to get_properties */
+
+ props = callbackEnv->NewObjectArray(num_properties, mclass,
+ NULL);
+ if (props == NULL) {
+ LOGE("%s: Error allocating object Array for properties", __FUNCTION__);
+ return;
+ }
+
+ types = (jintArray)callbackEnv->NewIntArray(num_properties);
+
+ if (types == NULL) {
+ LOGE("%s: Error allocating int Array for values", __FUNCTION__);
+ return;
+ }
+ // Delete the reference to val and mclass
+ callbackEnv->DeleteLocalRef(mclass);
+ callbackEnv->DeleteLocalRef(val);
addr = callbackEnv->NewByteArray(sizeof(bt_bdaddr_t));
if (addr == NULL) goto Fail;
@@ -187,6 +235,7 @@
checkAndClearExceptionFromCallback(callbackEnv, __FUNCTION__);
callbackEnv->DeleteLocalRef(props);
callbackEnv->DeleteLocalRef(types);
+ callbackEnv->DeleteLocalRef(addr);
callbackEnv->PopLocalFrame(NULL);
return;