Merge "Call apexd's API to allocate space before install non-AB package" am: 3736d7ac1b am: 259c28e935
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1673927 Change-Id: Ic618bb85e0f8be9468fa1158b9f9e62682b9932d
This commit is contained in:
@@ -211,6 +211,7 @@ java_library {
|
|||||||
"apex_aidl_interface-java",
|
"apex_aidl_interface-java",
|
||||||
"framework-protos",
|
"framework-protos",
|
||||||
"updatable-driver-protos",
|
"updatable-driver-protos",
|
||||||
|
"ota_metadata_proto_java",
|
||||||
"android.hidl.base-V1.0-java",
|
"android.hidl.base-V1.0-java",
|
||||||
"android.hardware.cas-V1.0-java",
|
"android.hardware.cas-V1.0-java",
|
||||||
"android.hardware.cas-V1.1-java",
|
"android.hardware.cas-V1.1-java",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.os.IRecoverySystemProgressListener;
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
|
|
||||||
interface IRecoverySystem {
|
interface IRecoverySystem {
|
||||||
|
boolean allocateSpaceForUpdate(in String packageFilePath);
|
||||||
boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
|
boolean uncrypt(in String packageFile, IRecoverySystemProgressListener listener);
|
||||||
boolean setupBcb(in String command);
|
boolean setupBcb(in String command);
|
||||||
boolean clearBcb();
|
boolean clearBcb();
|
||||||
|
|||||||
@@ -672,6 +672,14 @@ public class RecoverySystem {
|
|||||||
if (!rs.setupBcb(command)) {
|
if (!rs.setupBcb(command)) {
|
||||||
throw new IOException("Setup BCB failed");
|
throw new IOException("Setup BCB failed");
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
if (!rs.allocateSpaceForUpdate(packageFile)) {
|
||||||
|
throw new IOException("Failed to allocate space for update "
|
||||||
|
+ packageFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowAsRuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
// Having set up the BCB (bootloader control block), go ahead and reboot
|
// Having set up the BCB (bootloader control block), go ahead and reboot
|
||||||
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
|
||||||
@@ -1391,6 +1399,13 @@ public class RecoverySystem {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Talks to RecoverySystemService via Binder to allocate space
|
||||||
|
*/
|
||||||
|
private boolean allocateSpaceForUpdate(File packageFile) throws RemoteException {
|
||||||
|
return mService.allocateSpaceForUpdate(packageFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Talks to RecoverySystemService via Binder to clear up the BCB.
|
* Talks to RecoverySystemService via Binder to clear up the BCB.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,10 +24,13 @@ import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_SLOT_MISMA
|
|||||||
import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED;
|
import static android.os.RecoverySystem.RESUME_ON_REBOOT_REBOOT_ERROR_UNSPECIFIED;
|
||||||
import static android.os.RecoverySystem.ResumeOnRebootRebootErrorCode;
|
import static android.os.RecoverySystem.ResumeOnRebootRebootErrorCode;
|
||||||
import static android.os.UserHandle.USER_SYSTEM;
|
import static android.os.UserHandle.USER_SYSTEM;
|
||||||
|
import static android.ota.nano.OtaPackageMetadata.ApexMetadata;
|
||||||
|
|
||||||
import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE;
|
import static com.android.internal.widget.LockSettingsInternal.ARM_REBOOT_ERROR_NONE;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
import android.apex.CompressedApexInfo;
|
||||||
|
import android.apex.CompressedApexInfoList;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.IntentSender;
|
import android.content.IntentSender;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
@@ -47,9 +50,11 @@ import android.os.ResultReceiver;
|
|||||||
import android.os.ShellCallback;
|
import android.os.ShellCallback;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
|
import android.sysprop.ApexProperties;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.FastImmutableArraySet;
|
import android.util.FastImmutableArraySet;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
@@ -59,6 +64,7 @@ import com.android.internal.widget.LockSettingsInternal;
|
|||||||
import com.android.internal.widget.RebootEscrowListener;
|
import com.android.internal.widget.RebootEscrowListener;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.SystemService;
|
import com.android.server.SystemService;
|
||||||
|
import com.android.server.pm.ApexManager;
|
||||||
|
|
||||||
import libcore.io.IoUtils;
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
@@ -68,9 +74,13 @@ import java.io.File;
|
|||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The recovery system service is responsible for coordinating recovery related
|
* The recovery system service is responsible for coordinating recovery related
|
||||||
@@ -871,6 +881,76 @@ public class RecoverySystemService extends IRecoverySystem.Stub implements Reboo
|
|||||||
return rebootWithLskfImpl(packageName, reason, slotSwitch);
|
return rebootWithLskfImpl(packageName, reason, slotSwitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isUpdatableApexSupported() {
|
||||||
|
return ApexProperties.updatable().orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Metadata should be no more than few MB, if it's larger than 100MB something is wrong.
|
||||||
|
private static final long APEX_INFO_SIZE_LIMIT = 24 * 1024 * 100;
|
||||||
|
|
||||||
|
private static CompressedApexInfoList getCompressedApexInfoList(String packageFile)
|
||||||
|
throws IOException {
|
||||||
|
try (ZipFile zipFile = new ZipFile(packageFile)) {
|
||||||
|
final ZipEntry entry = zipFile.getEntry("apex_info.pb");
|
||||||
|
if (entry == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (entry.getSize() >= APEX_INFO_SIZE_LIMIT) {
|
||||||
|
throw new IllegalArgumentException("apex_info.pb has size "
|
||||||
|
+ entry.getSize()
|
||||||
|
+ " which is larger than the permitted limit" + APEX_INFO_SIZE_LIMIT);
|
||||||
|
}
|
||||||
|
if (entry.getSize() == 0) {
|
||||||
|
CompressedApexInfoList infoList = new CompressedApexInfoList();
|
||||||
|
infoList.apexInfos = new CompressedApexInfo[0];
|
||||||
|
return infoList;
|
||||||
|
}
|
||||||
|
Log.i(TAG, "Allocating " + entry.getSize()
|
||||||
|
+ " bytes of memory to store OTA Metadata");
|
||||||
|
byte[] data = new byte[(int) entry.getSize()];
|
||||||
|
|
||||||
|
try (InputStream is = zipFile.getInputStream(entry)) {
|
||||||
|
int bytesRead = is.read(data);
|
||||||
|
String msg = "Read " + bytesRead + " when expecting " + data.length;
|
||||||
|
Log.e(TAG, msg);
|
||||||
|
if (bytesRead != data.length) {
|
||||||
|
throw new IOException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ApexMetadata metadata = ApexMetadata.parseFrom(data);
|
||||||
|
CompressedApexInfoList apexInfoList = new CompressedApexInfoList();
|
||||||
|
apexInfoList.apexInfos =
|
||||||
|
Arrays.stream(metadata.apexInfo).filter(apex -> apex.isCompressed).map(apex -> {
|
||||||
|
CompressedApexInfo info = new CompressedApexInfo();
|
||||||
|
info.moduleName = apex.packageName;
|
||||||
|
info.decompressedSize = apex.decompressedSize;
|
||||||
|
info.versionCode = apex.version;
|
||||||
|
return info;
|
||||||
|
}).toArray(CompressedApexInfo[]::new);
|
||||||
|
return apexInfoList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allocateSpaceForUpdate(String packageFile) {
|
||||||
|
if (!isUpdatableApexSupported()) {
|
||||||
|
Log.i(TAG, "Updatable Apex not supported, "
|
||||||
|
+ "allocateSpaceForUpdate does nothing.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
CompressedApexInfoList apexInfoList = getCompressedApexInfoList(packageFile);
|
||||||
|
ApexManager apexManager = ApexManager.getInstance();
|
||||||
|
apexManager.reserveSpaceForCompressedApex(apexInfoList);
|
||||||
|
return true;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.rethrowAsRuntimeException();
|
||||||
|
} catch (IOException | UnsupportedOperationException e) {
|
||||||
|
Slog.e(TAG, "Failed to reserve space for compressed apex: ", e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override // Binder call
|
@Override // Binder call
|
||||||
public boolean isLskfCaptured(String packageName) {
|
public boolean isLskfCaptured(String packageName) {
|
||||||
enforcePermissionForResumeOnReboot();
|
enforcePermissionForResumeOnReboot();
|
||||||
|
|||||||
Reference in New Issue
Block a user