Merge "DSU installation service: Add event log tags"

This commit is contained in:
Yi-yo Chiang
2022-03-19 06:50:37 +00:00
committed by Gerrit Code Review
4 changed files with 174 additions and 60 deletions

View File

@@ -22,6 +22,9 @@ android_app {
defaults: ["platform_app_defaults"], defaults: ["platform_app_defaults"],
srcs: ["src/**/*.java"], srcs: ["src/**/*.java"],
static_libs: [
"DynamicSystemInstallationService-logtags",
],
resource_dirs: ["res"], resource_dirs: ["res"],
certificate: "platform", certificate: "platform",
@@ -32,3 +35,8 @@ android_app {
enabled: false, enabled: false,
}, },
} }
java_library {
name: "DynamicSystemInstallationService-logtags",
srcs: ["src/**/*.logtags"],
}

View File

@@ -58,6 +58,7 @@ import android.os.RemoteException;
import android.os.image.DynamicSystemClient; import android.os.image.DynamicSystemClient;
import android.os.image.DynamicSystemManager; import android.os.image.DynamicSystemManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@@ -103,6 +104,36 @@ public class DynamicSystemInstallationService extends Service
private static final String NOTIFICATION_CHANNEL_ID = "com.android.dynsystem"; private static final String NOTIFICATION_CHANNEL_ID = "com.android.dynsystem";
private static final int NOTIFICATION_ID = 1; private static final int NOTIFICATION_ID = 1;
/*
* Event log tags
*/
private static final int EVENT_DSU_PROGRESS_UPDATE = 120000;
private static final int EVENT_DSU_INSTALL_COMPLETE = 120001;
private static final int EVENT_DSU_INSTALL_FAILED = 120002;
protected static void logEventProgressUpdate(
String partition,
long installedSize,
long partitionSize,
int partitionNumber,
int totalPartitionNumber) {
EventLog.writeEvent(
EVENT_DSU_PROGRESS_UPDATE,
partition,
installedSize,
partitionSize,
partitionNumber,
totalPartitionNumber);
}
protected static void logEventComplete() {
EventLog.writeEvent(EVENT_DSU_INSTALL_COMPLETE);
}
protected static void logEventFailed(String cause) {
EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
}
/* /*
* IPC * IPC
*/ */
@@ -132,15 +163,10 @@ public class DynamicSystemInstallationService extends Service
private DynamicSystemManager mDynSystem; private DynamicSystemManager mDynSystem;
private NotificationManager mNM; private NotificationManager mNM;
private int mNumInstalledPartitions;
private String mCurrentPartitionName;
private long mCurrentPartitionSize;
private long mCurrentPartitionInstalledSize;
// This is for testing only now // This is for testing only now
private boolean mEnableWhenCompleted; private boolean mEnableWhenCompleted;
private InstallationAsyncTask.Progress mInstallTaskProgress;
private InstallationAsyncTask mInstallTask; private InstallationAsyncTask mInstallTask;
@@ -203,17 +229,21 @@ public class DynamicSystemInstallationService extends Service
@Override @Override
public void onProgressUpdate(InstallationAsyncTask.Progress progress) { public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
mCurrentPartitionName = progress.partitionName; logEventProgressUpdate(
mCurrentPartitionSize = progress.partitionSize; progress.partitionName,
mCurrentPartitionInstalledSize = progress.installedSize; progress.installedSize,
mNumInstalledPartitions = progress.numInstalledPartitions; progress.partitionSize,
progress.partitionNumber,
progress.totalPartitionNumber);
mInstallTaskProgress = progress;
postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null); postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
} }
@Override @Override
public void onResult(int result, Throwable detail) { public void onResult(int result, Throwable detail) {
if (result == RESULT_OK) { if (result == RESULT_OK) {
logEventComplete();
postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null); postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null);
// For testing: enable DSU and restart the device when install completed // For testing: enable DSU and restart the device when install completed
@@ -223,6 +253,12 @@ public class DynamicSystemInstallationService extends Service
return; return;
} }
if (result == RESULT_CANCELLED) {
logEventFailed("Dynamic System installation task is canceled by the user.");
} else {
logEventFailed("error: " + detail);
}
boolean removeNotification = false; boolean removeNotification = false;
switch (result) { switch (result) {
case RESULT_CANCELLED: case RESULT_CANCELLED:
@@ -251,16 +287,20 @@ public class DynamicSystemInstallationService extends Service
private void executeInstallCommand(Intent intent) { private void executeInstallCommand(Intent intent) {
if (!verifyRequest(intent)) { if (!verifyRequest(intent)) {
Log.e(TAG, "Verification failed. Did you use VerificationActivity?"); Log.e(TAG, "Verification failed. Did you use VerificationActivity?");
logEventFailed("VerificationActivity");
return; return;
} }
if (mInstallTask != null) { if (mInstallTask != null) {
Log.e(TAG, "There is already an installation task running"); Log.e(TAG, "There is already an installation task running");
logEventFailed("There is already an ongoing installation task.");
return; return;
} }
if (isInDynamicSystem()) { if (isInDynamicSystem()) {
Log.e(TAG, "We are already running in DynamicSystem"); Log.e(TAG, "We are already running in DynamicSystem");
logEventFailed(
"Cannot start a Dynamic System installation task within a Dynamic System.");
return; return;
} }
@@ -445,19 +485,22 @@ public class DynamicSystemInstallationService extends Service
case STATUS_IN_PROGRESS: case STATUS_IN_PROGRESS:
builder.setContentText(getString(R.string.notification_install_inprogress)); builder.setContentText(getString(R.string.notification_install_inprogress));
int max = 1024; if (mInstallTaskProgress != null) {
int progress = 0; int max = 1024;
int progress = 0;
int currentMax = max >> (mNumInstalledPartitions + 1); int currentMax = max >> mInstallTaskProgress.partitionNumber;
progress = max - currentMax * 2; progress = max - currentMax * 2;
long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax long currentProgress =
/ Math.max(mCurrentPartitionSize >> 20, 1); (mInstallTaskProgress.installedSize >> 20)
* currentMax
/ Math.max(mInstallTaskProgress.partitionSize >> 20, 1);
progress += (int) currentProgress; progress += (int) currentProgress;
builder.setProgress(max, progress, false);
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),
createPendingIntent(ACTION_CANCEL_INSTALL)).build()); createPendingIntent(ACTION_CANCEL_INSTALL)).build());
@@ -563,13 +606,13 @@ public class DynamicSystemInstallationService extends Service
StringBuilder msg = new StringBuilder(); StringBuilder msg = new StringBuilder();
msg.append("status: " + statusString + ", cause: " + causeString); msg.append("status: " + statusString + ", cause: " + causeString);
if (status == STATUS_IN_PROGRESS) { 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",
mCurrentPartitionName, mInstallTaskProgress.partitionName,
mCurrentPartitionInstalledSize, mInstallTaskProgress.installedSize,
mCurrentPartitionSize)); mInstallTaskProgress.partitionSize));
} }
if (detail != null) { if (detail != null) {
msg.append(", detail: " + detail); msg.append(", detail: " + detail);
@@ -594,7 +637,10 @@ public class DynamicSystemInstallationService extends Service
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
// TODO: send more info to the clients // TODO: send more info to the clients
bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mCurrentPartitionInstalledSize); if (mInstallTaskProgress != null) {
bundle.putLong(
DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize);
}
if (detail != null) { if (detail != null) {
bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL, bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL,

View File

@@ -0,0 +1,7 @@
# See system/logging/logcat/event.logtags for a description of the format of this file.
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)
120001 dsu_install_complete
120002 dsu_install_failed (cause|3)

View File

@@ -44,7 +44,7 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Progress, Throwable> { class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private static final String TAG = "InstallationAsyncTask"; private static final String TAG = "InstallationAsyncTask";
@@ -106,14 +106,22 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
static class Progress { static class Progress {
public final String partitionName; public final String partitionName;
public final long installedSize;
public final long partitionSize; public final long partitionSize;
public final int numInstalledPartitions; public final int partitionNumber;
public long installedSize; public final int totalPartitionNumber;
Progress(String partitionName, long partitionSize, int numInstalledPartitions) { Progress(
String partitionName,
long installedSize,
long partitionSize,
int partitionNumber,
int totalPartitionNumber) {
this.partitionName = partitionName; this.partitionName = partitionName;
this.installedSize = installedSize;
this.partitionSize = partitionSize; this.partitionSize = partitionSize;
this.numInstalledPartitions = numInstalledPartitions; this.partitionNumber = partitionNumber;
this.totalPartitionNumber = totalPartitionNumber;
} }
} }
@@ -139,7 +147,10 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
private boolean mIsZip; private boolean mIsZip;
private boolean mIsCompleted; private boolean mIsCompleted;
private int mNumInstalledPartitions; private String mPartitionName;
private long mPartitionSize;
private int mPartitionNumber;
private int mTotalPartitionNumber;
private InputStream mStream; private InputStream mStream;
private ZipFile mZipFile; private ZipFile mZipFile;
@@ -175,11 +186,15 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
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);
@@ -198,7 +213,7 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
return null; return null;
} }
if (Build.IS_DEBUGGABLE) { if (wantScratchPartition) {
// 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 {
@@ -262,9 +277,14 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
} }
@Override @Override
protected void onProgressUpdate(Progress... values) { protected void onProgressUpdate(Long... installedSize) {
Progress progress = values[0]; mListener.onProgressUpdate(
mListener.onProgressUpdate(progress); new Progress(
mPartitionName,
installedSize[0],
mPartitionSize,
mPartitionNumber,
mTotalPartitionNumber));
} }
private void verifyAndPrepare() throws Exception { private void verifyAndPrepare() throws Exception {
@@ -281,12 +301,16 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
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();
} }
@@ -333,9 +357,13 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
} }
}; };
thread.start(); mPartitionName = partitionName;
Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++); mPartitionSize = partitionSize;
++mPartitionNumber;
publishProgress(/* installedSize = */ 0L);
long prevInstalledSize = 0;
thread.start();
while (thread.isAlive()) { while (thread.isAlive()) {
if (isCancelled()) { if (isCancelled()) {
return; return;
@@ -343,9 +371,9 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
final long installedSize = mDynSystem.getInstallationProgress().bytes_processed; final long installedSize = mDynSystem.getInstallationProgress().bytes_processed;
if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) { if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
progress.installedSize = installedSize; publishProgress(installedSize);
publishProgress(progress); prevInstalledSize = installedSize;
} }
try { try {
@@ -392,14 +420,42 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
installImage("system", mSystemSize, new GZIPInputStream(mStream)); installImage("system", mSystemSize, new GZIPInputStream(mStream));
} }
private boolean shouldInstallEntry(String name) {
if (!name.endsWith(".img")) {
return false;
}
String partitionName = name.substring(0, name.length() - 4);
if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
return false;
}
return true;
}
private int calculateNumberOfImagesInLocalZip(ZipFile zipFile) {
int total = 0;
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (shouldInstallEntry(entry.getName())) {
++total;
}
}
return total;
}
private void installStreamingZipUpdate() throws IOException, ImageValidationException { private void installStreamingZipUpdate() throws 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);
ZipEntry zipEntry = null; ZipEntry entry = null;
while ((zipEntry = zis.getNextEntry()) != null) { while ((entry = zis.getNextEntry()) != null) {
installImageFromAnEntry(zipEntry, zis); String name = entry.getName();
if (shouldInstallEntry(name)) {
installImageFromAnEntry(entry, zis);
} else {
Log.d(TAG, name + " installation is not supported, skip it.");
}
if (isCancelled()) { if (isCancelled()) {
break; break;
@@ -414,7 +470,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement(); ZipEntry entry = entries.nextElement();
installImageFromAnEntry(entry, mZipFile.getInputStream(entry)); String name = entry.getName();
if (shouldInstallEntry(name)) {
installImageFromAnEntry(entry, mZipFile.getInputStream(entry));
} else {
Log.d(TAG, name + " installation is not supported, skip it.");
}
if (isCancelled()) { if (isCancelled()) {
break; break;
@@ -422,28 +483,16 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
} }
} }
private boolean installImageFromAnEntry(ZipEntry entry, InputStream is) private void installImageFromAnEntry(ZipEntry entry, InputStream is)
throws IOException, ImageValidationException { throws IOException, ImageValidationException {
String name = entry.getName(); String name = entry.getName();
Log.d(TAG, "ZipEntry: " + name); Log.d(TAG, "ZipEntry: " + name);
if (!name.endsWith(".img")) {
return false;
}
String partitionName = name.substring(0, name.length() - 4); String partitionName = name.substring(0, name.length() - 4);
if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
Log.d(TAG, name + " installation is not supported, skip it.");
return false;
}
long uncompressedSize = entry.getSize(); long uncompressedSize = entry.getSize();
installImage(partitionName, uncompressedSize, is); installImage(partitionName, uncompressedSize, is);
return true;
} }
private void installImage(String partitionName, long uncompressedSize, InputStream is) private void installImage(String partitionName, long uncompressedSize, InputStream is)
@@ -497,8 +546,12 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE); mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE);
Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++); mPartitionName = partitionName;
mPartitionSize = partitionSize;
++mPartitionNumber;
publishProgress(/* installedSize = */ 0L);
long prevInstalledSize = 0;
long installedSize = 0; long installedSize = 0;
byte[] bytes = new byte[READ_BUFFER_SIZE]; byte[] bytes = new byte[READ_BUFFER_SIZE];
int numBytesRead; int numBytesRead;
@@ -516,9 +569,9 @@ class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Prog
installedSize += numBytesRead; installedSize += numBytesRead;
if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) { if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
progress.installedSize = installedSize; publishProgress(installedSize);
publishProgress(progress); prevInstalledSize = installedSize;
} }
} }