Merge "dynsystem: Fix memory leak" am: a227192105

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2033046

Change-Id: I1bde367ff181ed1c3cca018006fa3e6847a7f464
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Yi-yo Chiang
2022-04-14 04:33:17 +00:00
committed by Automerger Merge Worker

View File

@@ -16,17 +16,18 @@
package com.android.dynsystem; package com.android.dynsystem;
import android.annotation.NonNull;
import android.content.Context; import android.content.Context;
import android.gsi.AvbPublicKey; import android.gsi.AvbPublicKey;
import android.gsi.IGsiService; import android.gsi.IGsiService;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.MemoryFile; import android.os.SharedMemory;
import android.os.ParcelFileDescriptor;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.image.DynamicSystemManager; import android.os.image.DynamicSystemManager;
import android.service.persistentdata.PersistentDataBlockManager; import android.service.persistentdata.PersistentDataBlockManager;
import android.system.ErrnoException;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.util.Range; import android.util.Range;
@@ -39,6 +40,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
@@ -154,6 +156,22 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
void onResult(int resultCode, Throwable detail); void onResult(int resultCode, Throwable detail);
} }
private static class MappedMemoryBuffer implements AutoCloseable {
public ByteBuffer mBuffer;
MappedMemoryBuffer(@NonNull ByteBuffer buffer) {
mBuffer = buffer;
}
@Override
public void close() {
if (mBuffer != null) {
SharedMemory.unmap(mBuffer);
mBuffer = null;
}
}
}
private final int mSharedMemorySize; private final int mSharedMemorySize;
private final String mUrl; private final String mUrl;
private final String mDsuSlot; private final String mDsuSlot;
@@ -674,22 +692,24 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
Log.d(TAG, "Start installing: " + partitionName); Log.d(TAG, "Start installing: " + partitionName);
MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, mSharedMemorySize); long prevInstalledSize = 0;
ParcelFileDescriptor pfd = new ParcelFileDescriptor(memoryFile.getFileDescriptor()); try (SharedMemory sharedMemory =
SharedMemory.create("dsu_buffer_" + partitionName, mSharedMemorySize);
mInstallationSession.setAshmem(pfd, memoryFile.length()); MappedMemoryBuffer mappedBuffer =
new MappedMemoryBuffer(sharedMemory.mapReadWrite())) {
mInstallationSession.setAshmem(sharedMemory.getFdDup(), sharedMemory.getSize());
initPartitionProgress(partitionName, partitionSize, /* readonly = */ true); initPartitionProgress(partitionName, partitionSize, /* readonly = */ true);
publishProgress(/* installedSize = */ 0L); publishProgress(/* installedSize = */ 0L);
long prevInstalledSize = 0;
long installedSize = 0; long installedSize = 0;
byte[] bytes = new byte[memoryFile.length()]; byte[] readBuffer = new byte[sharedMemory.getSize()];
ByteBuffer buffer = mappedBuffer.mBuffer;
ExecutorService executor = Executors.newSingleThreadExecutor(); ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Boolean> submitPromise = null; Future<Boolean> submitPromise = null;
while (true) { while (true) {
final int numBytesRead = sis.read(bytes, 0, bytes.length); final int numBytesRead = sis.read(readBuffer, 0, readBuffer.length);
if (submitPromise != null) { if (submitPromise != null) {
// Wait until the previous submit task is complete. // Wait until the previous submit task is complete.
@@ -711,7 +731,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
} }
} }
// Ensure the previous submit task (submitPromise) is complete before exiting the loop. // Ensure the previous submit task (submitPromise) is complete before exiting the
// loop.
if (numBytesRead < 0) { if (numBytesRead < 0) {
break; break;
} }
@@ -720,7 +741,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
return; return;
} }
memoryFile.writeBytes(bytes, 0, 0, numBytesRead); buffer.position(0);
buffer.put(readBuffer, 0, numBytesRead);
submitPromise = submitPromise =
executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead)); executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead));
@@ -728,6 +750,9 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
// after the submit task (submitPromise) is complete. // after the submit task (submitPromise) is complete.
installedSize += numBytesRead; installedSize += numBytesRead;
} }
} catch (ErrnoException e) {
e.rethrowAsIOException();
}
AvbPublicKey avbPublicKey = new AvbPublicKey(); AvbPublicKey avbPublicKey = new AvbPublicKey();
if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) { if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) {