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:
@@ -112,18 +112,20 @@ public class DynamicSystemInstallationService extends Service
|
|||||||
private static final int EVENT_DSU_INSTALL_FAILED = 120002;
|
private static final int EVENT_DSU_INSTALL_FAILED = 120002;
|
||||||
|
|
||||||
protected static void logEventProgressUpdate(
|
protected static void logEventProgressUpdate(
|
||||||
String partition,
|
String partitionName,
|
||||||
long installedSize,
|
long installedBytes,
|
||||||
long partitionSize,
|
long totalBytes,
|
||||||
int partitionNumber,
|
int partitionNumber,
|
||||||
int totalPartitionNumber) {
|
int totalPartitionNumber,
|
||||||
|
int totalProgressPercentage) {
|
||||||
EventLog.writeEvent(
|
EventLog.writeEvent(
|
||||||
EVENT_DSU_PROGRESS_UPDATE,
|
EVENT_DSU_PROGRESS_UPDATE,
|
||||||
partition,
|
partitionName,
|
||||||
installedSize,
|
installedBytes,
|
||||||
partitionSize,
|
totalBytes,
|
||||||
partitionNumber,
|
partitionNumber,
|
||||||
totalPartitionNumber);
|
totalPartitionNumber,
|
||||||
|
totalProgressPercentage);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void logEventComplete() {
|
protected static void logEventComplete() {
|
||||||
@@ -231,10 +233,11 @@ public class DynamicSystemInstallationService extends Service
|
|||||||
public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
|
public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
|
||||||
logEventProgressUpdate(
|
logEventProgressUpdate(
|
||||||
progress.partitionName,
|
progress.partitionName,
|
||||||
progress.installedSize,
|
progress.installedBytes,
|
||||||
progress.partitionSize,
|
progress.totalBytes,
|
||||||
progress.partitionNumber,
|
progress.partitionNumber,
|
||||||
progress.totalPartitionNumber);
|
progress.totalPartitionNumber,
|
||||||
|
progress.totalProgressPercentage);
|
||||||
|
|
||||||
mInstallTaskProgress = progress;
|
mInstallTaskProgress = progress;
|
||||||
postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
|
postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
|
||||||
@@ -483,23 +486,46 @@ public class DynamicSystemInstallationService extends Service
|
|||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case STATUS_IN_PROGRESS:
|
case STATUS_IN_PROGRESS:
|
||||||
builder.setContentText(getString(R.string.notification_install_inprogress));
|
String msgInProgress = getString(R.string.notification_install_inprogress);
|
||||||
|
|
||||||
if (mInstallTaskProgress != null) {
|
if (mInstallTaskProgress == null) {
|
||||||
int max = 1024;
|
builder.setContentText(msgInProgress);
|
||||||
int progress = 0;
|
} 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;
|
// totalProgressPercentage is defined iff totalPartitionNumber is defined
|
||||||
progress = max - currentMax * 2;
|
builder.setProgress(
|
||||||
|
100,
|
||||||
|
mInstallTaskProgress.totalProgressPercentage,
|
||||||
|
/* indeterminate = */ false);
|
||||||
|
} else {
|
||||||
|
builder.setContentText(
|
||||||
|
String.format(
|
||||||
|
"%s: %s partition",
|
||||||
|
msgInProgress, mInstallTaskProgress.partitionName));
|
||||||
|
|
||||||
long currentProgress =
|
int max = 1024;
|
||||||
(mInstallTaskProgress.installedSize >> 20)
|
int progress = 0;
|
||||||
* currentMax
|
|
||||||
/ Math.max(mInstallTaskProgress.partitionSize >> 20, 1);
|
|
||||||
|
|
||||||
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(
|
builder.addAction(new Notification.Action.Builder(
|
||||||
null, getString(R.string.notification_action_cancel),
|
null, getString(R.string.notification_action_cancel),
|
||||||
@@ -609,10 +635,11 @@ public class DynamicSystemInstallationService extends Service
|
|||||||
if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) {
|
if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) {
|
||||||
msg.append(
|
msg.append(
|
||||||
String.format(
|
String.format(
|
||||||
", partition name: %s, progress: %d/%d",
|
", partition name: %s, progress: %d/%d, total_progress: %d%%",
|
||||||
mInstallTaskProgress.partitionName,
|
mInstallTaskProgress.partitionName,
|
||||||
mInstallTaskProgress.installedSize,
|
mInstallTaskProgress.installedBytes,
|
||||||
mInstallTaskProgress.partitionSize));
|
mInstallTaskProgress.totalBytes,
|
||||||
|
mInstallTaskProgress.totalProgressPercentage));
|
||||||
}
|
}
|
||||||
if (detail != null) {
|
if (detail != null) {
|
||||||
msg.append(", detail: " + detail);
|
msg.append(", detail: " + detail);
|
||||||
@@ -639,7 +666,7 @@ public class DynamicSystemInstallationService extends Service
|
|||||||
// TODO: send more info to the clients
|
// TODO: send more info to the clients
|
||||||
if (mInstallTaskProgress != null) {
|
if (mInstallTaskProgress != null) {
|
||||||
bundle.putLong(
|
bundle.putLong(
|
||||||
DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize);
|
DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (detail != null) {
|
if (detail != null) {
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
option java_package com.android.dynsystem
|
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
|
120001 dsu_install_complete
|
||||||
120002 dsu_install_failed (cause|3)
|
120002 dsu_install_failed (cause|3)
|
||||||
|
|||||||
@@ -113,22 +113,25 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
|
|
||||||
static class Progress {
|
static class Progress {
|
||||||
public final String partitionName;
|
public final String partitionName;
|
||||||
public final long installedSize;
|
public final long installedBytes;
|
||||||
public final long partitionSize;
|
public final long totalBytes;
|
||||||
public final int partitionNumber;
|
public final int partitionNumber;
|
||||||
public final int totalPartitionNumber;
|
public final int totalPartitionNumber;
|
||||||
|
public final int totalProgressPercentage;
|
||||||
|
|
||||||
Progress(
|
Progress(
|
||||||
String partitionName,
|
String partitionName,
|
||||||
long installedSize,
|
long installedBytes,
|
||||||
long partitionSize,
|
long totalBytes,
|
||||||
int partitionNumber,
|
int partitionNumber,
|
||||||
int totalPartitionNumber) {
|
int totalPartitionNumber,
|
||||||
|
int totalProgressPercentage) {
|
||||||
this.partitionName = partitionName;
|
this.partitionName = partitionName;
|
||||||
this.installedSize = installedSize;
|
this.installedBytes = installedBytes;
|
||||||
this.partitionSize = partitionSize;
|
this.totalBytes = totalBytes;
|
||||||
this.partitionNumber = partitionNumber;
|
this.partitionNumber = partitionNumber;
|
||||||
this.totalPartitionNumber = totalPartitionNumber;
|
this.totalPartitionNumber = totalPartitionNumber;
|
||||||
|
this.totalProgressPercentage = totalProgressPercentage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,20 +152,28 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
private final ProgressListener mListener;
|
private final ProgressListener mListener;
|
||||||
private final boolean mIsNetworkUrl;
|
private final boolean mIsNetworkUrl;
|
||||||
private final boolean mIsDeviceBootloaderUnlocked;
|
private final boolean mIsDeviceBootloaderUnlocked;
|
||||||
|
private final boolean mWantScratchPartition;
|
||||||
private DynamicSystemManager.Session mInstallationSession;
|
private DynamicSystemManager.Session mInstallationSession;
|
||||||
private KeyRevocationList mKeyRevocationList;
|
private KeyRevocationList mKeyRevocationList;
|
||||||
|
|
||||||
private boolean mIsZip;
|
private boolean mIsZip;
|
||||||
private boolean mIsCompleted;
|
private boolean mIsCompleted;
|
||||||
|
|
||||||
private String mPartitionName;
|
|
||||||
private long mPartitionSize;
|
|
||||||
private int mPartitionNumber;
|
|
||||||
private int mTotalPartitionNumber;
|
|
||||||
|
|
||||||
private InputStream mStream;
|
private InputStream mStream;
|
||||||
private ZipFile mZipFile;
|
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(
|
InstallationAsyncTask(
|
||||||
String url,
|
String url,
|
||||||
String dsuSlot,
|
String dsuSlot,
|
||||||
@@ -193,21 +204,18 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
(pdbManager != null)
|
(pdbManager != null)
|
||||||
&& (pdbManager.getFlashLockState()
|
&& (pdbManager.getFlashLockState()
|
||||||
== PersistentDataBlockManager.FLASH_LOCK_UNLOCKED);
|
== PersistentDataBlockManager.FLASH_LOCK_UNLOCKED);
|
||||||
|
mWantScratchPartition = Build.IS_DEBUGGABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Throwable doInBackground(String... voids) {
|
protected Throwable doInBackground(String... voids) {
|
||||||
Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
|
Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
|
||||||
|
|
||||||
final boolean wantScratchPartition = Build.IS_DEBUGGABLE;
|
|
||||||
try {
|
try {
|
||||||
// call DynamicSystemManager to cleanup stuff
|
// call DynamicSystemManager to cleanup stuff
|
||||||
mDynSystem.remove();
|
mDynSystem.remove();
|
||||||
|
|
||||||
verifyAndPrepare();
|
verifyAndPrepare();
|
||||||
if (wantScratchPartition) {
|
|
||||||
++mTotalPartitionNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDynSystem.startInstallation(mDsuSlot);
|
mDynSystem.startInstallation(mDsuSlot);
|
||||||
|
|
||||||
@@ -226,7 +234,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wantScratchPartition) {
|
if (mWantScratchPartition) {
|
||||||
// If host is debuggable, then install a scratch partition so that we can do
|
// If host is debuggable, then install a scratch partition so that we can do
|
||||||
// adb remount in the guest system.
|
// adb remount in the guest system.
|
||||||
try {
|
try {
|
||||||
@@ -290,14 +298,54 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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(
|
mListener.onProgressUpdate(
|
||||||
new Progress(
|
new Progress(
|
||||||
mPartitionName,
|
mProgressPartitionName,
|
||||||
installedSize[0],
|
installedBytes,
|
||||||
mPartitionSize,
|
mProgressTotalBytes,
|
||||||
mPartitionNumber,
|
mProgressPartitionNumber,
|
||||||
mTotalPartitionNumber));
|
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 {
|
private void verifyAndPrepare() throws Exception {
|
||||||
@@ -314,16 +362,12 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
throw new UnsupportedFormatException(
|
throw new UnsupportedFormatException(
|
||||||
String.format(Locale.US, "Unsupported file format: %s", mUrl));
|
String.format(Locale.US, "Unsupported file format: %s", mUrl));
|
||||||
}
|
}
|
||||||
// At least two partitions, {system, userdata}
|
|
||||||
mTotalPartitionNumber = 2;
|
|
||||||
|
|
||||||
if (mIsNetworkUrl) {
|
if (mIsNetworkUrl) {
|
||||||
mStream = new URL(mUrl).openStream();
|
mStream = new URL(mUrl).openStream();
|
||||||
} else if (URLUtil.isFileUrl(mUrl)) {
|
} else if (URLUtil.isFileUrl(mUrl)) {
|
||||||
if (mIsZip) {
|
if (mIsZip) {
|
||||||
mZipFile = new ZipFile(new File(new URL(mUrl).toURI()));
|
mZipFile = new ZipFile(new File(new URL(mUrl).toURI()));
|
||||||
// {*.img in zip} + {userdata}
|
|
||||||
mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1;
|
|
||||||
} else {
|
} else {
|
||||||
mStream = new URL(mUrl).openStream();
|
mStream = new URL(mUrl).openStream();
|
||||||
}
|
}
|
||||||
@@ -334,6 +378,32 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
String.format(Locale.US, "Unsupported URL: %s", mUrl));
|
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 {
|
try {
|
||||||
String listUrl = mContext.getString(R.string.key_revocation_list_url);
|
String listUrl = mContext.getString(R.string.key_revocation_list_url);
|
||||||
mKeyRevocationList = KeyRevocationList.fromUrl(new URL(listUrl));
|
mKeyRevocationList = KeyRevocationList.fromUrl(new URL(listUrl));
|
||||||
@@ -370,9 +440,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mPartitionName = partitionName;
|
initPartitionProgress(partitionName, partitionSize, /* readonly = */ false);
|
||||||
mPartitionSize = partitionSize;
|
|
||||||
++mPartitionNumber;
|
|
||||||
publishProgress(/* installedSize = */ 0L);
|
publishProgress(/* installedSize = */ 0L);
|
||||||
|
|
||||||
long prevInstalledSize = 0;
|
long prevInstalledSize = 0;
|
||||||
@@ -396,6 +464,10 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prevInstalledSize != partitionSize) {
|
||||||
|
publishProgress(partitionSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (mInstallationSession == null) {
|
if (mInstallationSession == null) {
|
||||||
throw new IOException(
|
throw new IOException(
|
||||||
"Failed to start installation with requested size: " + partitionSize);
|
"Failed to start installation with requested size: " + partitionSize);
|
||||||
@@ -559,9 +631,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
|
|
||||||
mInstallationSession.setAshmem(pfd, memoryFile.length());
|
mInstallationSession.setAshmem(pfd, memoryFile.length());
|
||||||
|
|
||||||
mPartitionName = partitionName;
|
initPartitionProgress(partitionName, partitionSize, /* readonly = */ true);
|
||||||
mPartitionSize = partitionSize;
|
|
||||||
++mPartitionNumber;
|
|
||||||
publishProgress(/* installedSize = */ 0L);
|
publishProgress(/* installedSize = */ 0L);
|
||||||
|
|
||||||
long prevInstalledSize = 0;
|
long prevInstalledSize = 0;
|
||||||
@@ -588,6 +658,10 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prevInstalledSize != partitionSize) {
|
||||||
|
publishProgress(partitionSize);
|
||||||
|
}
|
||||||
|
|
||||||
AvbPublicKey avbPublicKey = new AvbPublicKey();
|
AvbPublicKey avbPublicKey = new AvbPublicKey();
|
||||||
if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) {
|
if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) {
|
||||||
imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed"));
|
imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed"));
|
||||||
|
|||||||
Reference in New Issue
Block a user