Merge "DSU service: Pipeline the installation task to improve performance"
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user