Merge changes I81b41460,I81561c19

* changes:
  DSU service: Show which partition is being installed in notification
  DSU service: Weighted progress bar
This commit is contained in:
Yi-yo Chiang
2022-03-28 03:31:10 +00:00
committed by Gerrit Code Review
3 changed files with 163 additions and 62 deletions

View File

@@ -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);
@@ -483,23 +486,46 @@ public class DynamicSystemInstallationService extends Service
switch (status) {
case STATUS_IN_PROGRESS:
builder.setContentText(getString(R.string.notification_install_inprogress));
String msgInProgress = getString(R.string.notification_install_inprogress);
if (mInstallTaskProgress != null) {
int max = 1024;
int progress = 0;
if (mInstallTaskProgress == null) {
builder.setContentText(msgInProgress);
} else {
if (mInstallTaskProgress.totalPartitionNumber > 0) {
builder.setContentText(
String.format(
"%s: %s partition [%d/%d]",
msgInProgress,
mInstallTaskProgress.partitionName,
mInstallTaskProgress.partitionNumber,
mInstallTaskProgress.totalPartitionNumber));
int currentMax = max >> mInstallTaskProgress.partitionNumber;
progress = max - currentMax * 2;
// totalProgressPercentage is defined iff totalPartitionNumber is defined
builder.setProgress(
100,
mInstallTaskProgress.totalProgressPercentage,
/* indeterminate = */ false);
} else {
builder.setContentText(
String.format(
"%s: %s partition",
msgInProgress, mInstallTaskProgress.partitionName));
long currentProgress =
(mInstallTaskProgress.installedSize >> 20)
* currentMax
/ Math.max(mInstallTaskProgress.partitionSize >> 20, 1);
int max = 1024;
int progress = 0;
progress += (int) currentProgress;
int currentMax = max >> mInstallTaskProgress.partitionNumber;
progress = max - currentMax * 2;
builder.setProgress(max, progress, false);
long currentProgress =
(mInstallTaskProgress.installedBytes >> 20)
* currentMax
/ Math.max(mInstallTaskProgress.totalBytes >> 20, 1);
progress += (int) currentProgress;
builder.setProgress(max, progress, false);
}
}
builder.addAction(new Notification.Action.Builder(
null, getString(R.string.notification_action_cancel),
@@ -609,10 +635,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 +666,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) {

View File

@@ -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)

View File

@@ -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"));