Merge "DSU service: Pipeline the installation task to improve performance" am: 309fad06f6 am: 1991fbc73b am: 31de7473e8
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2045078
Change-Id: If1a1cc1ddcccc2fda857204b6e59a888a7b2ce62
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index 2af7e00..38d851e 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -41,6 +41,10 @@
import java.util.Enumeration;
import java.util.List;
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.ZipEntry;
import java.util.zip.ZipFile;
@@ -51,8 +55,8 @@
private static final String TAG = "InstallationAsyncTask";
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 DEFAULT_SHARED_MEMORY_SIZE = 64 << 10; // 64KiB
+ private static final int MAX_SHARED_MEMORY_SIZE = 8 << 20; // 8MiB
+ private static final int DEFAULT_SHARED_MEMORY_SIZE = 512 << 10; // 512KiB
private static final String SHARED_MEMORY_SIZE_PROP =
"dynamic_system.data_transfer.shared_memory.size";
@@ -488,7 +492,7 @@
installWritablePartition("userdata", mUserdataSize);
}
- private void installImages() throws IOException, ImageValidationException {
+ private void installImages() throws ExecutionException, IOException, ImageValidationException {
if (mStream != null) {
if (mIsZip) {
installStreamingZipUpdate();
@@ -500,7 +504,8 @@
}
}
- private void installStreamingGzUpdate() throws IOException, ImageValidationException {
+ private void installStreamingGzUpdate()
+ throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a streaming GZ update");
installImage("system", mSystemSize, new GZIPInputStream(mStream));
}
@@ -528,7 +533,8 @@
return total;
}
- private void installStreamingZipUpdate() throws IOException, ImageValidationException {
+ private void installStreamingZipUpdate()
+ throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a streaming ZIP update");
ZipInputStream zis = new ZipInputStream(mStream);
@@ -548,7 +554,8 @@
}
}
- private void installLocalZipUpdate() throws IOException, ImageValidationException {
+ private void installLocalZipUpdate()
+ throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a local ZIP update");
Enumeration<? extends ZipEntry> entries = mZipFile.entries();
@@ -569,7 +576,7 @@
}
private void installImageFromAnEntry(ZipEntry entry, InputStream is)
- throws IOException, ImageValidationException {
+ throws ExecutionException, IOException, ImageValidationException {
String name = entry.getName();
Log.d(TAG, "ZipEntry: " + name);
@@ -581,7 +588,7 @@
}
private void installImage(String partitionName, long uncompressedSize, InputStream is)
- throws IOException, ImageValidationException {
+ throws ExecutionException, IOException, ImageValidationException {
SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is));
@@ -637,27 +644,51 @@
long prevInstalledSize = 0;
long installedSize = 0;
byte[] bytes = new byte[memoryFile.length()];
- int numBytesRead;
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Boolean> submitPromise = null;
- while ((numBytesRead = sis.read(bytes, 0, bytes.length)) != -1) {
+ 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;
+ }
+
if (isCancelled()) {
return;
}
memoryFile.writeBytes(bytes, 0, 0, numBytesRead);
+ submitPromise =
+ executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead));
- if (!mInstallationSession.submitFromAshmem(numBytesRead)) {
- throw new IOException("Failed write() to DynamicSystem");
- }
-
+ // Even though we update the bytes counter here, the actual progress is updated only
+ // after the submit task (submitPromise) is complete.
installedSize += numBytesRead;
-
- if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
- publishProgress(installedSize);
- prevInstalledSize = installedSize;
- }
}
+ // Ensure a 100% mark is published.
if (prevInstalledSize != partitionSize) {
publishProgress(partitionSize);
}