Merge "DSU service: Pipeline the installation task to improve performance" am: 309fad06f6 am: 1991fbc73b

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

Change-Id: I79b28d7273f81e741a32d2b77fd7901d7d4e8ef4
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Yi-yo Chiang
2022-03-30 03:19:57 +00:00
committed by Automerger Merge Worker

View File

@@ -41,6 +41,10 @@ import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
@@ -51,8 +55,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private static final String TAG = "InstallationAsyncTask"; private static final String TAG = "InstallationAsyncTask";
private static final int MIN_SHARED_MEMORY_SIZE = 8 << 10; // 8KiB private static final int MIN_SHARED_MEMORY_SIZE = 8 << 10; // 8KiB
private static final int MAX_SHARED_MEMORY_SIZE = 1024 << 10; // 1MiB private static final int MAX_SHARED_MEMORY_SIZE = 8 << 20; // 8MiB
private static final int DEFAULT_SHARED_MEMORY_SIZE = 64 << 10; // 64KiB private static final int DEFAULT_SHARED_MEMORY_SIZE = 512 << 10; // 512KiB
private static final String SHARED_MEMORY_SIZE_PROP = private static final String SHARED_MEMORY_SIZE_PROP =
"dynamic_system.data_transfer.shared_memory.size"; "dynamic_system.data_transfer.shared_memory.size";
@@ -488,7 +492,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
installWritablePartition("userdata", mUserdataSize); installWritablePartition("userdata", mUserdataSize);
} }
private void installImages() throws IOException, ImageValidationException { private void installImages() throws ExecutionException, IOException, ImageValidationException {
if (mStream != null) { if (mStream != null) {
if (mIsZip) { if (mIsZip) {
installStreamingZipUpdate(); installStreamingZipUpdate();
@@ -500,7 +504,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
} }
} }
private void installStreamingGzUpdate() throws IOException, ImageValidationException { private void installStreamingGzUpdate()
throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a streaming GZ update"); Log.d(TAG, "To install a streaming GZ update");
installImage("system", mSystemSize, new GZIPInputStream(mStream)); installImage("system", mSystemSize, new GZIPInputStream(mStream));
} }
@@ -528,7 +533,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
return total; return total;
} }
private void installStreamingZipUpdate() throws IOException, ImageValidationException { private void installStreamingZipUpdate()
throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a streaming ZIP update"); Log.d(TAG, "To install a streaming ZIP update");
ZipInputStream zis = new ZipInputStream(mStream); ZipInputStream zis = new ZipInputStream(mStream);
@@ -548,7 +554,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
} }
} }
private void installLocalZipUpdate() throws IOException, ImageValidationException { private void installLocalZipUpdate()
throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a local ZIP update"); Log.d(TAG, "To install a local ZIP update");
Enumeration<? extends ZipEntry> entries = mZipFile.entries(); Enumeration<? extends ZipEntry> entries = mZipFile.entries();
@@ -569,7 +576,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
} }
private void installImageFromAnEntry(ZipEntry entry, InputStream is) private void installImageFromAnEntry(ZipEntry entry, InputStream is)
throws IOException, ImageValidationException { throws ExecutionException, IOException, ImageValidationException {
String name = entry.getName(); String name = entry.getName();
Log.d(TAG, "ZipEntry: " + name); Log.d(TAG, "ZipEntry: " + name);
@@ -581,7 +588,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
} }
private void installImage(String partitionName, long uncompressedSize, InputStream is) private void installImage(String partitionName, long uncompressedSize, InputStream is)
throws IOException, ImageValidationException { throws ExecutionException, IOException, ImageValidationException {
SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is)); SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is));
@@ -637,27 +644,51 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
long prevInstalledSize = 0; long prevInstalledSize = 0;
long installedSize = 0; long installedSize = 0;
byte[] bytes = new byte[memoryFile.length()]; byte[] bytes = new byte[memoryFile.length()];
int numBytesRead; ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Boolean> submitPromise = null;
while (true) {
final int numBytesRead = sis.read(bytes, 0, bytes.length);
if (submitPromise != null) {
// Wait until the previous submit task is complete.
while (true) {
try {
if (!submitPromise.get()) {
throw new IOException("Failed submitFromAshmem() to DynamicSystem");
}
break;
} catch (InterruptedException e) {
// Ignore.
}
}
// Publish the progress of the previous submit task.
if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
publishProgress(installedSize);
prevInstalledSize = installedSize;
}
}
// Ensure the previous submit task (submitPromise) is complete before exiting the loop.
if (numBytesRead < 0) {
break;
}
while ((numBytesRead = sis.read(bytes, 0, bytes.length)) != -1) {
if (isCancelled()) { if (isCancelled()) {
return; return;
} }
memoryFile.writeBytes(bytes, 0, 0, numBytesRead); memoryFile.writeBytes(bytes, 0, 0, numBytesRead);
submitPromise =
executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead));
if (!mInstallationSession.submitFromAshmem(numBytesRead)) { // Even though we update the bytes counter here, the actual progress is updated only
throw new IOException("Failed write() to DynamicSystem"); // after the submit task (submitPromise) is complete.
}
installedSize += numBytesRead; installedSize += numBytesRead;
if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
publishProgress(installedSize);
prevInstalledSize = installedSize;
}
} }
// Ensure a 100% mark is published.
if (prevInstalledSize != partitionSize) { if (prevInstalledSize != partitionSize) {
publishProgress(partitionSize); publishProgress(partitionSize);
} }