Merge "DSU service: Log insufficient storage space error" am: 9b420e664a
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2049806 Change-Id: I929141ce4840a879b62664c917904aa541b3f635 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -16,13 +16,16 @@
|
|||||||
|
|
||||||
package android.os.image;
|
package android.os.image;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.SystemService;
|
import android.annotation.SystemService;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.gsi.AvbPublicKey;
|
import android.gsi.AvbPublicKey;
|
||||||
import android.gsi.GsiProgress;
|
import android.gsi.GsiProgress;
|
||||||
|
import android.gsi.IGsiService;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DynamicSystemManager offers a mechanism to use a new system image temporarily. After the
|
* 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 name The DSU partition name
|
||||||
* @param size Size of the DSU image in bytes
|
* @param size Size of the DSU image in bytes
|
||||||
* @param readOnly True if the partition is read only, e.g. system.
|
* @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
|
* @return {@code Integer} an IGsiService.INSTALL_* status code. {@link Session} an installation
|
||||||
* enough space or a DynamicSystem is currently in use where the {@link #isInUse} would be
|
* session object if successful, otherwise {@code null}.
|
||||||
* true.
|
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
|
@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 {
|
try {
|
||||||
if (mService.createPartition(name, size, readOnly)) {
|
int status = mService.createPartition(name, size, readOnly);
|
||||||
return new Session();
|
if (status == IGsiService.INSTALL_OK) {
|
||||||
|
return new Pair<>(status, new Session());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return new Pair<>(status, null);
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw new RuntimeException(e.toString());
|
throw new RuntimeException(e.toString());
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ interface IDynamicSystemService
|
|||||||
* @param name The DSU partition name
|
* @param name The DSU partition name
|
||||||
* @param size Size of the DSU image in bytes
|
* @param size Size of the DSU image in bytes
|
||||||
* @param readOnly True if this partition is readOnly
|
* @param readOnly True if this partition is readOnly
|
||||||
* @return true if the call succeeds
|
* @return IGsiService.INSTALL_* status code
|
||||||
*/
|
*/
|
||||||
@EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
|
@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.
|
* 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_PROGRESS_UPDATE = 120000;
|
||||||
private static final int EVENT_DSU_INSTALL_COMPLETE = 120001;
|
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_FAILED = 120002;
|
||||||
|
private static final int EVENT_DSU_INSTALL_INSUFFICIENT_SPACE = 120003;
|
||||||
|
|
||||||
protected static void logEventProgressUpdate(
|
protected static void logEventProgressUpdate(
|
||||||
String partitionName,
|
String partitionName,
|
||||||
@@ -136,6 +137,10 @@ public class DynamicSystemInstallationService extends Service
|
|||||||
EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
|
EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static void logEventInsufficientSpace() {
|
||||||
|
EventLog.writeEvent(EVENT_DSU_INSTALL_INSUFFICIENT_SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IPC
|
* IPC
|
||||||
*/
|
*/
|
||||||
@@ -258,6 +263,8 @@ public class DynamicSystemInstallationService extends Service
|
|||||||
|
|
||||||
if (result == RESULT_CANCELLED) {
|
if (result == RESULT_CANCELLED) {
|
||||||
logEventFailed("Dynamic System installation task is canceled by the user.");
|
logEventFailed("Dynamic System installation task is canceled by the user.");
|
||||||
|
} else if (detail instanceof InstallationAsyncTask.InsufficientSpaceException) {
|
||||||
|
logEventInsufficientSpace();
|
||||||
} else {
|
} else {
|
||||||
logEventFailed("error: " + detail);
|
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)
|
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)
|
||||||
|
120003 dsu_install_insufficient_space
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.dynsystem;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.gsi.AvbPublicKey;
|
import android.gsi.AvbPublicKey;
|
||||||
|
import android.gsi.IGsiService;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -27,6 +28,7 @@ import android.os.SystemProperties;
|
|||||||
import android.os.image.DynamicSystemManager;
|
import android.os.image.DynamicSystemManager;
|
||||||
import android.service.persistentdata.PersistentDataBlockManager;
|
import android.service.persistentdata.PersistentDataBlockManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
import android.util.Range;
|
import android.util.Range;
|
||||||
import android.webkit.URLUtil;
|
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 */
|
/** UNSET means the installation is not completed */
|
||||||
static final int RESULT_UNSET = 0;
|
static final int RESULT_UNSET = 0;
|
||||||
|
|
||||||
static final int RESULT_OK = 1;
|
static final int RESULT_OK = 1;
|
||||||
static final int RESULT_CANCELLED = 2;
|
static final int RESULT_CANCELLED = 2;
|
||||||
static final int RESULT_ERROR_IO = 3;
|
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 mIsNetworkUrl;
|
||||||
private final boolean mIsDeviceBootloaderUnlocked;
|
private final boolean mIsDeviceBootloaderUnlocked;
|
||||||
private final boolean mWantScratchPartition;
|
private final boolean mWantScratchPartition;
|
||||||
|
private int mCreatePartitionStatus;
|
||||||
private DynamicSystemManager.Session mInstallationSession;
|
private DynamicSystemManager.Session mInstallationSession;
|
||||||
private KeyRevocationList mKeyRevocationList;
|
private KeyRevocationList mKeyRevocationList;
|
||||||
|
|
||||||
@@ -364,7 +374,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
mIsZip = true;
|
mIsZip = true;
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedFormatException(
|
throw new UnsupportedFormatException(
|
||||||
String.format(Locale.US, "Unsupported file format: %s", mUrl));
|
String.format(Locale.US, "Unsupported file format: %s", mUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsNetworkUrl) {
|
if (mIsNetworkUrl) {
|
||||||
@@ -435,14 +445,19 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
Log.d(TAG, "Creating writable partition: " + partitionName + ", size: " + partitionSize);
|
Log.d(TAG, "Creating writable partition: " + partitionName + ", size: " + partitionSize);
|
||||||
|
|
||||||
Thread thread = new Thread() {
|
mCreatePartitionStatus = 0;
|
||||||
@Override
|
mInstallationSession = null;
|
||||||
public void run() {
|
Thread thread =
|
||||||
mInstallationSession =
|
new Thread() {
|
||||||
mDynSystem.createPartition(
|
@Override
|
||||||
partitionName, partitionSize, /* readOnly= */ false);
|
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);
|
initPartitionProgress(partitionName, partitionSize, /* readonly = */ false);
|
||||||
publishProgress(/* installedSize = */ 0L);
|
publishProgress(/* installedSize = */ 0L);
|
||||||
@@ -468,13 +483,17 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prevInstalledSize != partitionSize) {
|
|
||||||
publishProgress(partitionSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mInstallationSession == null) {
|
if (mInstallationSession == null) {
|
||||||
throw new IOException(
|
if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE
|
||||||
"Failed to start installation with requested size: " + partitionSize);
|
|| 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.
|
// Reset installation session and verify that installation completes successfully.
|
||||||
@@ -482,6 +501,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
if (!mDynSystem.closePartition()) {
|
if (!mDynSystem.closePartition()) {
|
||||||
throw new IOException("Failed to complete partition installation: " + partitionName);
|
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 {
|
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);
|
throw new IOException("Cannot get raw size for " + partitionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread thread = new Thread(() -> {
|
mCreatePartitionStatus = 0;
|
||||||
mInstallationSession =
|
mInstallationSession = null;
|
||||||
mDynSystem.createPartition(partitionName, partitionSize, true);
|
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);
|
Log.d(TAG, "Start creating partition: " + partitionName);
|
||||||
thread.start();
|
thread.start();
|
||||||
@@ -627,8 +660,16 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mInstallationSession == null) {
|
if (mInstallationSession == null) {
|
||||||
throw new IOException(
|
if (mCreatePartitionStatus == IGsiService.INSTALL_ERROR_NO_SPACE
|
||||||
"Failed to start installation with requested size: " + partitionSize);
|
|| 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);
|
Log.d(TAG, "Start installing: " + partitionName);
|
||||||
@@ -688,11 +729,6 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
installedSize += numBytesRead;
|
installedSize += numBytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure a 100% mark is published.
|
|
||||||
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"));
|
||||||
@@ -708,6 +744,11 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
|
|||||||
if (!mDynSystem.closePartition()) {
|
if (!mDynSystem.closePartition()) {
|
||||||
throw new IOException("Failed to complete partition installation: " + partitionName);
|
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) {
|
private static String toHexString(byte[] bytes) {
|
||||||
|
|||||||
@@ -119,14 +119,13 @@ public class DynamicSystemService extends IDynamicSystemService.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
|
@EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
|
||||||
public boolean createPartition(String name, long size, boolean readOnly)
|
public int createPartition(String name, long size, boolean readOnly) throws RemoteException {
|
||||||
throws RemoteException {
|
|
||||||
IGsiService service = getGsiService();
|
IGsiService service = getGsiService();
|
||||||
if (service.createPartition(name, size, readOnly) != 0) {
|
int status = service.createPartition(name, size, readOnly);
|
||||||
Slog.i(TAG, "Failed to install " + name);
|
if (status != IGsiService.INSTALL_OK) {
|
||||||
return false;
|
Slog.i(TAG, "Failed to create partition: " + name);
|
||||||
}
|
}
|
||||||
return true;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user