DSU service: Log insufficient storage space error
Log a specialized error message if installation task failed due to insufficient storage space. This helps the user to disgnose the source of error. Bug: 200002443 Test: start DSU task and check logcat Change-Id: Iabb3e0325ae99c343978ca6c35ab8378f20e0527
This commit is contained in:
parent
c32215ee94
commit
c88a3d9be4
@ -16,13 +16,16 @@
|
||||
|
||||
package android.os.image;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemService;
|
||||
import android.content.Context;
|
||||
import android.gsi.AvbPublicKey;
|
||||
import android.gsi.GsiProgress;
|
||||
import android.gsi.IGsiService;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Pair;
|
||||
|
||||
/**
|
||||
* The DynamicSystemManager offers a mechanism to use a new system image temporarily. After the
|
||||
@ -138,17 +141,18 @@ public class DynamicSystemManager {
|
||||
* @param name The DSU partition name
|
||||
* @param size Size of the DSU image in bytes
|
||||
* @param readOnly True if the partition is read only, e.g. system.
|
||||
* @return {@code true} if the call succeeds. {@code false} either the device does not contain
|
||||
* enough space or a DynamicSystem is currently in use where the {@link #isInUse} would be
|
||||
* true.
|
||||
* @return {@code Integer} an IGsiService.INSTALL_* status code. {@link Session} an installation
|
||||
* session object if successful, otherwise {@code null}.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
|
||||
public Session createPartition(String name, long size, boolean readOnly) {
|
||||
public @NonNull Pair<Integer, Session> createPartition(
|
||||
String name, long size, boolean readOnly) {
|
||||
try {
|
||||
if (mService.createPartition(name, size, readOnly)) {
|
||||
return new Session();
|
||||
int status = mService.createPartition(name, size, readOnly);
|
||||
if (status == IGsiService.INSTALL_OK) {
|
||||
return new Pair<>(status, new Session());
|
||||
} else {
|
||||
return null;
|
||||
return new Pair<>(status, null);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e.toString());
|
||||
|
@ -35,10 +35,10 @@ interface IDynamicSystemService
|
||||
* @param name The DSU partition name
|
||||
* @param size Size of the DSU image in bytes
|
||||
* @param readOnly True if this partition is readOnly
|
||||
* @return true if the call succeeds
|
||||
* @return IGsiService.INSTALL_* status code
|
||||
*/
|
||||
@EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
|
||||
boolean createPartition(@utf8InCpp String name, long size, boolean readOnly);
|
||||
int createPartition(@utf8InCpp String name, long size, boolean readOnly);
|
||||
|
||||
/**
|
||||
* Complete the current partition installation.
|
||||
|
@ -110,6 +110,7 @@ public class DynamicSystemInstallationService extends Service
|
||||
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;
|
||||
private static final int EVENT_DSU_INSTALL_INSUFFICIENT_SPACE = 120003;
|
||||
|
||||
protected static void logEventProgressUpdate(
|
||||
String partitionName,
|
||||
@ -136,6 +137,10 @@ public class DynamicSystemInstallationService extends Service
|
||||
EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
|
||||
}
|
||||
|
||||
protected static void logEventInsufficientSpace() {
|
||||
EventLog.writeEvent(EVENT_DSU_INSTALL_INSUFFICIENT_SPACE);
|
||||
}
|
||||
|
||||
/*
|
||||
* IPC
|
||||
*/
|
||||
@ -258,6 +263,8 @@ public class DynamicSystemInstallationService extends Service
|
||||
|
||||
if (result == RESULT_CANCELLED) {
|
||||
logEventFailed("Dynamic System installation task is canceled by the user.");
|
||||
} else if (detail instanceof InstallationAsyncTask.InsufficientSpaceException) {
|
||||
logEventInsufficientSpace();
|
||||
} else {
|
||||
logEventFailed("error: " + detail);
|
||||
}
|
||||
|
@ -5,3 +5,4 @@ option java_package com.android.dynsystem
|
||||
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)
|
||||
120003 dsu_install_insufficient_space
|
||||
|
@ -18,6 +18,7 @@ package com.android.dynsystem;
|
||||
|
||||
import android.content.Context;
|
||||
import android.gsi.AvbPublicKey;
|
||||
import android.gsi.IGsiService;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
@ -27,6 +28,7 @@ import android.os.SystemProperties;
|
||||
import android.os.image.DynamicSystemManager;
|
||||
import android.service.persistentdata.PersistentDataBlockManager;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Range;
|
||||
import android.webkit.URLUtil;
|
||||
|
||||
@ -106,8 +108,15 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
}
|
||||
}
|
||||
|
||||
static class InsufficientSpaceException extends IOException {
|
||||
InsufficientSpaceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
/** UNSET means the installation is not completed */
|
||||
static final int RESULT_UNSET = 0;
|
||||
|
||||
static final int RESULT_OK = 1;
|
||||
static final int RESULT_CANCELLED = 2;
|
||||
static final int RESULT_ERROR_IO = 3;
|
||||
@ -157,6 +166,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
private final boolean mIsNetworkUrl;
|
||||
private final boolean mIsDeviceBootloaderUnlocked;
|
||||
private final boolean mWantScratchPartition;
|
||||
private int mCreatePartitionStatus;
|
||||
private DynamicSystemManager.Session mInstallationSession;
|
||||
private KeyRevocationList mKeyRevocationList;
|
||||
|
||||
@ -364,7 +374,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
mIsZip = true;
|
||||
} else {
|
||||
throw new UnsupportedFormatException(
|
||||
String.format(Locale.US, "Unsupported file format: %s", mUrl));
|
||||
String.format(Locale.US, "Unsupported file format: %s", mUrl));
|
||||
}
|
||||
|
||||
if (mIsNetworkUrl) {
|
||||
@ -435,14 +445,19 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
throws IOException {
|
||||
Log.d(TAG, "Creating writable partition: " + partitionName + ", size: " + partitionSize);
|
||||
|
||||
Thread thread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
mInstallationSession =
|
||||
mDynSystem.createPartition(
|
||||
partitionName, partitionSize, /* readOnly= */ false);
|
||||
}
|
||||
};
|
||||
mCreatePartitionStatus = 0;
|
||||
mInstallationSession = null;
|
||||
Thread thread =
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pair<Integer, DynamicSystemManager.Session> result =
|
||||
mDynSystem.createPartition(
|
||||
partitionName, partitionSize, /* readOnly = */ false);
|
||||
mCreatePartitionStatus = result.first;
|
||||
mInstallationSession = result.second;
|
||||
}
|
||||
};
|
||||
|
||||
initPartitionProgress(partitionName, partitionSize, /* readonly = */ false);
|
||||
publishProgress(/* installedSize = */ 0L);
|
||||
@ -468,13 +483,17 @@ 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);
|
||||
if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE
|
||||
|| mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) {
|
||||
throw new InsufficientSpaceException(
|
||||
"Failed to create "
|
||||
+ partitionName
|
||||
+ " partition: storage media has insufficient free space");
|
||||
} else {
|
||||
throw new IOException(
|
||||
"Failed to start installation with requested size: " + partitionSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset installation session and verify that installation completes successfully.
|
||||
@ -482,6 +501,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
if (!mDynSystem.closePartition()) {
|
||||
throw new IOException("Failed to complete partition installation: " + partitionName);
|
||||
}
|
||||
|
||||
// Ensure a 100% mark is published.
|
||||
if (prevInstalledSize != partitionSize) {
|
||||
publishProgress(partitionSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void installScratch() throws IOException {
|
||||
@ -606,10 +630,19 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
throw new IOException("Cannot get raw size for " + partitionName);
|
||||
}
|
||||
|
||||
Thread thread = new Thread(() -> {
|
||||
mInstallationSession =
|
||||
mDynSystem.createPartition(partitionName, partitionSize, true);
|
||||
});
|
||||
mCreatePartitionStatus = 0;
|
||||
mInstallationSession = null;
|
||||
Thread thread =
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
Pair<Integer, DynamicSystemManager.Session> result =
|
||||
mDynSystem.createPartition(
|
||||
partitionName, partitionSize, /* readOnly = */ true);
|
||||
mCreatePartitionStatus = result.first;
|
||||
mInstallationSession = result.second;
|
||||
}
|
||||
};
|
||||
|
||||
Log.d(TAG, "Start creating partition: " + partitionName);
|
||||
thread.start();
|
||||
@ -627,8 +660,16 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
}
|
||||
|
||||
if (mInstallationSession == null) {
|
||||
throw new IOException(
|
||||
"Failed to start installation with requested size: " + partitionSize);
|
||||
if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE
|
||||
|| mCreatePartitionStatus == IGsiService.INSTALL_ERROR_FILE_SYSTEM_CLUTTERED) {
|
||||
throw new InsufficientSpaceException(
|
||||
"Failed to create "
|
||||
+ partitionName
|
||||
+ " partition: storage media has insufficient free space");
|
||||
} else {
|
||||
throw new IOException(
|
||||
"Failed to start installation with requested size: " + partitionSize);
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "Start installing: " + partitionName);
|
||||
@ -688,11 +729,6 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
installedSize += numBytesRead;
|
||||
}
|
||||
|
||||
// Ensure a 100% mark is published.
|
||||
if (prevInstalledSize != partitionSize) {
|
||||
publishProgress(partitionSize);
|
||||
}
|
||||
|
||||
AvbPublicKey avbPublicKey = new AvbPublicKey();
|
||||
if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) {
|
||||
imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed"));
|
||||
@ -708,6 +744,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
||||
if (!mDynSystem.closePartition()) {
|
||||
throw new IOException("Failed to complete partition installation: " + partitionName);
|
||||
}
|
||||
|
||||
// Ensure a 100% mark is published.
|
||||
if (prevInstalledSize != partitionSize) {
|
||||
publishProgress(partitionSize);
|
||||
}
|
||||
}
|
||||
|
||||
private static String toHexString(byte[] bytes) {
|
||||
|
@ -119,14 +119,13 @@ public class DynamicSystemService extends IDynamicSystemService.Stub {
|
||||
|
||||
@Override
|
||||
@EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
|
||||
public boolean createPartition(String name, long size, boolean readOnly)
|
||||
throws RemoteException {
|
||||
public int createPartition(String name, long size, boolean readOnly) throws RemoteException {
|
||||
IGsiService service = getGsiService();
|
||||
if (service.createPartition(name, size, readOnly) != 0) {
|
||||
Slog.i(TAG, "Failed to install " + name);
|
||||
return false;
|
||||
int status = service.createPartition(name, size, readOnly);
|
||||
if (status != IGsiService.INSTALL_OK) {
|
||||
Slog.i(TAG, "Failed to create partition: " + name);
|
||||
}
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
x
Reference in New Issue
Block a user