diff options
3 files changed, 146 insertions, 60 deletions
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java index 02128d480678..98d4cf0d1182 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java @@ -112,18 +112,20 @@ public class DynamicSystemInstallationService extends Service private static final int EVENT_DSU_INSTALL_FAILED = 120002; protected static void logEventProgressUpdate( - String partition, - long installedSize, - long partitionSize, + String partitionName, + long installedBytes, + long totalBytes, int partitionNumber, - int totalPartitionNumber) { + int totalPartitionNumber, + int totalProgressPercentage) { EventLog.writeEvent( EVENT_DSU_PROGRESS_UPDATE, - partition, - installedSize, - partitionSize, + partitionName, + installedBytes, + totalBytes, partitionNumber, - totalPartitionNumber); + totalPartitionNumber, + totalProgressPercentage); } protected static void logEventComplete() { @@ -231,10 +233,11 @@ public class DynamicSystemInstallationService extends Service public void onProgressUpdate(InstallationAsyncTask.Progress progress) { logEventProgressUpdate( progress.partitionName, - progress.installedSize, - progress.partitionSize, + progress.installedBytes, + progress.totalBytes, progress.partitionNumber, - progress.totalPartitionNumber); + progress.totalPartitionNumber, + progress.totalProgressPercentage); mInstallTaskProgress = progress; postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null); @@ -486,20 +489,28 @@ public class DynamicSystemInstallationService extends Service builder.setContentText(getString(R.string.notification_install_inprogress)); if (mInstallTaskProgress != null) { - int max = 1024; - int progress = 0; + if (mInstallTaskProgress.totalPartitionNumber > 0) { + // totalProgressPercentage is defined iff totalPartitionNumber is defined + builder.setProgress( + 100, + mInstallTaskProgress.totalProgressPercentage, + /* indeterminate = */ false); + } else { + int max = 1024; + int progress = 0; - int currentMax = max >> mInstallTaskProgress.partitionNumber; - progress = max - currentMax * 2; + int currentMax = max >> mInstallTaskProgress.partitionNumber; + progress = max - currentMax * 2; - long currentProgress = - (mInstallTaskProgress.installedSize >> 20) - * currentMax - / Math.max(mInstallTaskProgress.partitionSize >> 20, 1); + long currentProgress = + (mInstallTaskProgress.installedBytes >> 20) + * currentMax + / Math.max(mInstallTaskProgress.totalBytes >> 20, 1); - progress += (int) currentProgress; + progress += (int) currentProgress; - builder.setProgress(max, progress, false); + builder.setProgress(max, progress, false); + } } builder.addAction(new Notification.Action.Builder( null, getString(R.string.notification_action_cancel), @@ -609,10 +620,11 @@ public class DynamicSystemInstallationService extends Service if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) { msg.append( String.format( - ", partition name: %s, progress: %d/%d", + ", partition name: %s, progress: %d/%d, total_progress: %d%%", mInstallTaskProgress.partitionName, - mInstallTaskProgress.installedSize, - mInstallTaskProgress.partitionSize)); + mInstallTaskProgress.installedBytes, + mInstallTaskProgress.totalBytes, + mInstallTaskProgress.totalProgressPercentage)); } if (detail != null) { msg.append(", detail: " + detail); @@ -639,7 +651,7 @@ public class DynamicSystemInstallationService extends Service // TODO: send more info to the clients if (mInstallTaskProgress != null) { bundle.putLong( - DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize); + DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedBytes); } if (detail != null) { diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags index eae9de937700..407314384be8 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags @@ -2,6 +2,6 @@ option java_package com.android.dynsystem -120000 dsu_progress_update (partition|3),(installed_size|2|5),(partition_size|2|5),(partition_number|1|5),(total_partition_number|1|5) +120000 dsu_progress_update (partition_name|3),(installed_bytes|2|5),(total_bytes|2|5),(partition_number|1|5),(total_partition_number|1|5),(total_progress_percentage|1|5) 120001 dsu_install_complete 120002 dsu_install_failed (cause|3) diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java index 998aeeab4b47..2af7e00f9128 100644 --- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java +++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java @@ -113,22 +113,25 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { static class Progress { public final String partitionName; - public final long installedSize; - public final long partitionSize; + public final long installedBytes; + public final long totalBytes; public final int partitionNumber; public final int totalPartitionNumber; + public final int totalProgressPercentage; Progress( String partitionName, - long installedSize, - long partitionSize, + long installedBytes, + long totalBytes, int partitionNumber, - int totalPartitionNumber) { + int totalPartitionNumber, + int totalProgressPercentage) { this.partitionName = partitionName; - this.installedSize = installedSize; - this.partitionSize = partitionSize; + this.installedBytes = installedBytes; + this.totalBytes = totalBytes; this.partitionNumber = partitionNumber; this.totalPartitionNumber = totalPartitionNumber; + this.totalProgressPercentage = totalProgressPercentage; } } @@ -149,20 +152,28 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { private final ProgressListener mListener; private final boolean mIsNetworkUrl; private final boolean mIsDeviceBootloaderUnlocked; + private final boolean mWantScratchPartition; private DynamicSystemManager.Session mInstallationSession; private KeyRevocationList mKeyRevocationList; private boolean mIsZip; private boolean mIsCompleted; - - private String mPartitionName; - private long mPartitionSize; - private int mPartitionNumber; - private int mTotalPartitionNumber; - private InputStream mStream; private ZipFile mZipFile; + private static final double PROGRESS_READONLY_PARTITION_WEIGHT = 0.8; + private static final double PROGRESS_WRITABLE_PARTITION_WEIGHT = 0.2; + + private String mProgressPartitionName; + private long mProgressTotalBytes; + private int mProgressPartitionNumber; + private boolean mProgressPartitionIsReadonly; + private int mProgressCompletedReadonlyPartitions; + private int mProgressCompletedWritablePartitions; + private int mTotalReadonlyPartitions; + private int mTotalWritablePartitions; + private int mTotalPartitionNumber; + InstallationAsyncTask( String url, String dsuSlot, @@ -193,21 +204,18 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { (pdbManager != null) && (pdbManager.getFlashLockState() == PersistentDataBlockManager.FLASH_LOCK_UNLOCKED); + mWantScratchPartition = Build.IS_DEBUGGABLE; } @Override protected Throwable doInBackground(String... voids) { Log.d(TAG, "Start doInBackground(), URL: " + mUrl); - final boolean wantScratchPartition = Build.IS_DEBUGGABLE; try { // call DynamicSystemManager to cleanup stuff mDynSystem.remove(); verifyAndPrepare(); - if (wantScratchPartition) { - ++mTotalPartitionNumber; - } mDynSystem.startInstallation(mDsuSlot); @@ -226,7 +234,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { return null; } - if (wantScratchPartition) { + if (mWantScratchPartition) { // If host is debuggable, then install a scratch partition so that we can do // adb remount in the guest system. try { @@ -290,14 +298,54 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } @Override - protected void onProgressUpdate(Long... installedSize) { + protected void onProgressUpdate(Long... progress) { + final long installedBytes = progress[0]; + int totalProgressPercentage = 0; + if (mTotalPartitionNumber > 0) { + final double readonlyPartitionWeight = + mTotalReadonlyPartitions > 0 + ? PROGRESS_READONLY_PARTITION_WEIGHT / mTotalReadonlyPartitions + : 0; + final double writablePartitionWeight = + mTotalWritablePartitions > 0 + ? PROGRESS_WRITABLE_PARTITION_WEIGHT / mTotalWritablePartitions + : 0; + double totalProgress = 0.0; + if (mProgressTotalBytes > 0) { + totalProgress += + (mProgressPartitionIsReadonly + ? readonlyPartitionWeight + : writablePartitionWeight) + * installedBytes + / mProgressTotalBytes; + } + totalProgress += readonlyPartitionWeight * mProgressCompletedReadonlyPartitions; + totalProgress += writablePartitionWeight * mProgressCompletedWritablePartitions; + totalProgressPercentage = (int) (totalProgress * 100); + } mListener.onProgressUpdate( new Progress( - mPartitionName, - installedSize[0], - mPartitionSize, - mPartitionNumber, - mTotalPartitionNumber)); + mProgressPartitionName, + installedBytes, + mProgressTotalBytes, + mProgressPartitionNumber, + mTotalPartitionNumber, + totalProgressPercentage)); + } + + private void initPartitionProgress(String partitionName, long totalBytes, boolean readonly) { + if (mProgressPartitionNumber > 0) { + // Assume previous partition completed successfully. + if (mProgressPartitionIsReadonly) { + ++mProgressCompletedReadonlyPartitions; + } else { + ++mProgressCompletedWritablePartitions; + } + } + mProgressPartitionName = partitionName; + mProgressTotalBytes = totalBytes; + mProgressPartitionIsReadonly = readonly; + ++mProgressPartitionNumber; } private void verifyAndPrepare() throws Exception { @@ -314,16 +362,12 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { throw new UnsupportedFormatException( String.format(Locale.US, "Unsupported file format: %s", mUrl)); } - // At least two partitions, {system, userdata} - mTotalPartitionNumber = 2; if (mIsNetworkUrl) { mStream = new URL(mUrl).openStream(); } else if (URLUtil.isFileUrl(mUrl)) { if (mIsZip) { mZipFile = new ZipFile(new File(new URL(mUrl).toURI())); - // {*.img in zip} + {userdata} - mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1; } else { mStream = new URL(mUrl).openStream(); } @@ -334,6 +378,32 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { String.format(Locale.US, "Unsupported URL: %s", mUrl)); } + boolean hasTotalPartitionNumber = false; + if (mIsZip) { + if (mZipFile != null) { + // {*.img in zip} + {userdata} + hasTotalPartitionNumber = true; + mTotalReadonlyPartitions = calculateNumberOfImagesInLocalZip(mZipFile); + mTotalWritablePartitions = 1; + } else { + // TODO: Come up with a way to retrieve the number of total partitions from + // network URL. + } + } else { + // gzip has exactly two partitions, {system, userdata} + hasTotalPartitionNumber = true; + mTotalReadonlyPartitions = 1; + mTotalWritablePartitions = 1; + } + + if (hasTotalPartitionNumber) { + if (mWantScratchPartition) { + // {scratch} + ++mTotalWritablePartitions; + } + mTotalPartitionNumber = mTotalReadonlyPartitions + mTotalWritablePartitions; + } + try { String listUrl = mContext.getString(R.string.key_revocation_list_url); mKeyRevocationList = KeyRevocationList.fromUrl(new URL(listUrl)); @@ -370,9 +440,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } }; - mPartitionName = partitionName; - mPartitionSize = partitionSize; - ++mPartitionNumber; + initPartitionProgress(partitionName, partitionSize, /* readonly = */ false); publishProgress(/* installedSize = */ 0L); long prevInstalledSize = 0; @@ -396,6 +464,10 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } + if (prevInstalledSize != partitionSize) { + publishProgress(partitionSize); + } + if (mInstallationSession == null) { throw new IOException( "Failed to start installation with requested size: " + partitionSize); @@ -559,9 +631,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { mInstallationSession.setAshmem(pfd, memoryFile.length()); - mPartitionName = partitionName; - mPartitionSize = partitionSize; - ++mPartitionNumber; + initPartitionProgress(partitionName, partitionSize, /* readonly = */ true); publishProgress(/* installedSize = */ 0L); long prevInstalledSize = 0; @@ -588,6 +658,10 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> { } } + if (prevInstalledSize != partitionSize) { + publishProgress(partitionSize); + } + AvbPublicKey avbPublicKey = new AvbPublicKey(); if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) { imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed")); |