Allow setting APK path explicitly
Allow the absolute path of the APK containing the payload to be
specified. If it isn't, the existing default behavior is retained.
Add some minimal tests to exercise this.
Bug: 243129654
Bug: 245727626
Test: atest MicrodroidTests
Change-Id: I4feb5a733995518eeb2373b6d9606f934c4549a0
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
index d8ff8c6..9555d1e 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -18,6 +18,8 @@
import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -57,7 +59,7 @@
private static final String KEY_MEMORY_MIB = "memoryMib";
private static final String KEY_NUM_CPUS = "numCpus";
- // Paths to the APK file of this application.
+ // Absolute path to the APK file containing the VM payload.
@NonNull private final String mApkPath;
/** @hide */
@@ -128,7 +130,11 @@
boolean protectedVm,
int memoryMib,
int numCpus) {
- mApkPath = Objects.requireNonNull(apkPath);
+ requireNonNull(apkPath);
+ if (!apkPath.startsWith("/")) {
+ throw new IllegalArgumentException("APK path must be an absolute path");
+ }
+ mApkPath = apkPath;
mPayloadConfigPath = payloadConfigPath;
mPayloadBinaryPath = payloadBinaryPath;
mDebugLevel = debugLevel;
@@ -188,6 +194,17 @@
}
/**
+ * Returns the absolute path of the APK which should contain the binary payload that will
+ * execute within the VM.
+ *
+ * @hide
+ */
+ @NonNull
+ public String getApkPath() {
+ return mApkPath;
+ }
+
+ /**
* Returns the path to the payload config within the owning application.
*
* @hide
@@ -307,6 +324,7 @@
*/
public static final class Builder {
private final Context mContext;
+ @Nullable private String mApkPath;
@Nullable private String mPayloadConfigPath;
@Nullable private String mPayloadBinaryPath;
@DebugLevel private int mDebugLevel;
@@ -321,7 +339,7 @@
* @hide
*/
public Builder(@NonNull Context context) {
- mContext = Objects.requireNonNull(context);
+ mContext = requireNonNull(context);
mDebugLevel = DEBUG_LEVEL_NONE;
mNumCpus = 1;
}
@@ -333,9 +351,9 @@
*/
@NonNull
public VirtualMachineConfig build() {
- final String apkPath = mContext.getPackageCodePath();
+ String apkPath = (mApkPath == null) ? mContext.getPackageCodePath() : mApkPath;
- final int availableCpus = Runtime.getRuntime().availableProcessors();
+ int availableCpus = Runtime.getRuntime().availableProcessors();
if (mNumCpus < 1 || mNumCpus > availableCpus) {
throw new IllegalArgumentException("Number of vCPUs (" + mNumCpus + ") is out of "
+ "range [1, " + availableCpus + "]");
@@ -372,6 +390,18 @@
}
/**
+ * Sets the absolute path of the APK containing the binary payload that will execute within
+ * the VM. If not set explicitly, defaults to the primary APK of the context.
+ *
+ * @hide
+ */
+ @NonNull
+ public Builder setApkPath(@NonNull String apkPath) {
+ mApkPath = requireNonNull(apkPath);
+ return this;
+ }
+
+ /**
* Sets the path within the APK to the payload config file that defines software aspects
* of the VM.
*
@@ -380,7 +410,7 @@
@RequiresPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION)
@NonNull
public Builder setPayloadConfigPath(@NonNull String payloadConfigPath) {
- mPayloadConfigPath = Objects.requireNonNull(payloadConfigPath);
+ mPayloadConfigPath = requireNonNull(payloadConfigPath);
return this;
}
@@ -392,7 +422,7 @@
*/
@NonNull
public Builder setPayloadBinaryPath(@NonNull String payloadBinaryPath) {
- mPayloadBinaryPath = Objects.requireNonNull(payloadBinaryPath);
+ mPayloadBinaryPath = requireNonNull(payloadBinaryPath);
return this;
}
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 5c9cf42..ef8e0e6 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -157,6 +157,39 @@
.contains("android.permission.USE_CUSTOM_VIRTUAL_MACHINE permission");
}
+ @Test
+ @CddTest(requirements = {
+ "9.17/C-1-1",
+ })
+ public void validApkPathIsAccepted() throws Exception {
+ assumeSupportedKernel();
+
+ VirtualMachineConfig config = mInner.newVmConfigBuilder()
+ .setPayloadBinaryPath("MicrodroidTestNativeLib.so")
+ .setApkPath(getContext().getPackageCodePath())
+ .setMemoryMib(minMemoryRequired())
+ .build();
+
+ VirtualMachine vm = mInner.forceCreateNewVirtualMachine(
+ "test_vm_explicit_apk_path", config);
+
+ TestResults testResults = runVmTestService(vm);
+ assertThat(testResults.mException).isNull();
+ }
+
+ @Test
+ @CddTest(requirements = {
+ "9.17/C-1-1",
+ })
+ public void invalidApkPathIsRejected() {
+ assumeSupportedKernel();
+
+ VirtualMachineConfig.Builder builder = mInner.newVmConfigBuilder()
+ .setPayloadBinaryPath("MicrodroidTestNativeLib.so")
+ .setApkPath("relative/path/to.apk")
+ .setMemoryMib(minMemoryRequired());
+ assertThrows(IllegalArgumentException.class, () -> builder.build());
+ }
@Test
@CddTest(requirements = {