Merge changes from topic "prefer-staged"
* changes:
Pass sorted list of apexes to VM
prefer_staged keeps factory version
diff --git a/demo/java/com/android/microdroid/demo/MainActivity.java b/demo/java/com/android/microdroid/demo/MainActivity.java
index b52ef40..df6f44e 100644
--- a/demo/java/com/android/microdroid/demo/MainActivity.java
+++ b/demo/java/com/android/microdroid/demo/MainActivity.java
@@ -145,6 +145,7 @@
/** Models a virtual machine and outputs from it. */
public static class VirtualMachineModel extends AndroidViewModel {
+ private static final String VM_NAME = "demo_vm";
private VirtualMachine mVirtualMachine;
private final MutableLiveData<String> mConsoleOutput = new MutableLiveData<>();
private final MutableLiveData<String> mLogOutput = new MutableLiveData<>();
@@ -266,12 +267,12 @@
}
VirtualMachineConfig config = builder.build();
VirtualMachineManager vmm = VirtualMachineManager.getInstance(getApplication());
- mVirtualMachine = vmm.getOrCreate("demo_vm", config);
+ mVirtualMachine = vmm.getOrCreate(VM_NAME, config);
try {
mVirtualMachine.setConfig(config);
} catch (VirtualMachineException e) {
- mVirtualMachine.delete();
- mVirtualMachine = vmm.create("demo_vm", config);
+ vmm.delete(VM_NAME);
+ mVirtualMachine = vmm.create(VM_NAME, config);
}
mVirtualMachine.run();
mVirtualMachine.setCallback(Executors.newSingleThreadExecutor(), callback);
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachine.java b/javalib/src/android/system/virtualmachine/VirtualMachine.java
index e2fc33e..f3e4fe9 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachine.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachine.java
@@ -77,7 +77,11 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.FileVisitResult;
import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -90,8 +94,13 @@
import java.util.zip.ZipFile;
/**
- * A handle to the virtual machine. The virtual machine is local to the app which created the
- * virtual machine.
+ * Represents an VM instance, with its own configuration and state. Instances are persistent and are
+ * created or retrieved via {@link VirtualMachineManager}.
+ * <p>
+ * The {@link #run} method actually starts up the VM and allows the payload code to execute. It
+ * will continue until it exits or {@link #stop} is called. Updates on the state of the VM can
+ * be received using {@link #setCallback}. The app can communicate with the VM using
+ * {@link #connectToVsockServer} or {@link #connectVsock}.
*
* @hide
*/
@@ -230,10 +239,9 @@
mPackageName = context.getPackageName();
mName = requireNonNull(name, "Name must not be null");
mConfig = requireNonNull(config, "Config must not be null");
- mConfigFilePath = getConfigFilePath(context, name);
- final File vmRoot = new File(context.getFilesDir(), VM_DIR);
- final File thisVmDir = new File(vmRoot, mName);
+ File thisVmDir = getVmDir(context, mName);
+ mConfigFilePath = new File(thisVmDir, CONFIG_FILE);
mInstanceFilePath = new File(thisVmDir, INSTANCE_IMAGE_FILE);
mIdsigFilePath = new File(thisVmDir, IDSIG_FILE);
mExtraApks = setupExtraApks(context, config, thisVmDir);
@@ -310,15 +318,17 @@
@Nullable
static VirtualMachine load(
@NonNull Context context, @NonNull String name) throws VirtualMachineException {
- File configFilePath = getConfigFilePath(context, name);
+ File thisVmDir = getVmDir(context, name);
+ if (!thisVmDir.exists()) {
+ // The VM doesn't exist.
+ return null;
+ }
+ File configFilePath = new File(thisVmDir, CONFIG_FILE);
VirtualMachineConfig config;
try (FileInputStream input = new FileInputStream(configFilePath)) {
config = VirtualMachineConfig.from(input);
- } catch (FileNotFoundException e) {
- // The VM doesn't exist.
- return null;
} catch (IOException e) {
- throw new VirtualMachineException(e);
+ throw new VirtualMachineException("Failed to read config file", e);
}
VirtualMachine vm = null;
@@ -340,9 +350,6 @@
}
}
- // If config file exists, but the instance image file doesn't, it means that the VM is
- // corrupted. That's different from the case that the VM doesn't exist. Throw an exception
- // instead of returning null.
if (!vm.mInstanceFilePath.exists()) {
throw new VirtualMachineException("instance image missing");
}
@@ -483,7 +490,7 @@
try {
createVmPipes();
- VirtualMachineAppConfig appConfig = getConfig().toParcel();
+ VirtualMachineAppConfig appConfig = getConfig().toVsConfig();
appConfig.name = mName;
// Fill the idsig file by hashing the apk
@@ -587,7 +594,7 @@
mLogWriter = pipe[1];
}
} catch (IOException e) {
- throw new VirtualMachineException(e);
+ throw new VirtualMachineException("Failed to create stream for VM", e);
}
}
@@ -701,41 +708,60 @@
stop();
}
- /**
- * Deletes this virtual machine. Deleting a virtual machine means deleting any persisted data
- * associated with it including the per-VM secret. This is an irreversible action. A virtual
- * machine once deleted can never be restored. A new virtual machine created with the same name
- * and the same config is different from an already deleted virtual machine.
- *
- * @throws VirtualMachineException if the virtual machine is not stopped.
- * @hide
- */
- public void delete() throws VirtualMachineException {
- if (getStatus() != STATUS_STOPPED) {
+ static void delete(Context context, String name) throws VirtualMachineException {
+ VirtualMachine vm;
+ synchronized (sInstancesLock) {
+ Map<String, WeakReference<VirtualMachine>> instancesMap = sInstances.get(context);
+ if (instancesMap != null && instancesMap.containsKey(name)) {
+ vm = instancesMap.get(name).get();
+ } else {
+ vm = null;
+ }
+ }
+
+ if (vm != null && vm.getStatus() != STATUS_STOPPED) {
throw new VirtualMachineException("Virtual machine is not stopped");
}
- final File vmRootDir = mConfigFilePath.getParentFile();
- for (ExtraApkSpec extraApks : mExtraApks) {
- extraApks.idsig.delete();
+
+ try {
+ deleteRecursively(getVmDir(context, name));
+ } catch (IOException e) {
+ throw new VirtualMachineException(e);
}
- mConfigFilePath.delete();
- mInstanceFilePath.delete();
- mIdsigFilePath.delete();
- vmRootDir.delete();
synchronized (sInstancesLock) {
- Map<String, WeakReference<VirtualMachine>> instancesMap = sInstances.get(mContext);
- if (instancesMap != null) instancesMap.remove(mName);
+ Map<String, WeakReference<VirtualMachine>> instancesMap = sInstances.get(context);
+ if (instancesMap != null) instancesMap.remove(name);
}
}
+ private static void deleteRecursively(File dir) throws IOException {
+ // Note: This doesn't follow symlinks, which is important. Instead they are just deleted
+ // (and Files.delete deletes the link not the target).
+ Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
+ // Directory is deleted after we've visited (deleted) all its contents, so it
+ // should be empty by now.
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+
/**
* Returns the CID of this virtual machine, if it is running.
*
* @throws VirtualMachineException if the virtual machine is not running.
* @hide
*/
- @NonNull
public int getCid() throws VirtualMachineException {
if (getStatus() != STATUS_RUNNING) {
throw new VirtualMachineException("VM is not running");
@@ -777,7 +803,7 @@
newConfig.serialize(output);
output.close();
} catch (IOException e) {
- throw new VirtualMachineException(e);
+ throw new VirtualMachineException("Failed to persist config", e);
}
mConfig = newConfig;
@@ -922,9 +948,9 @@
}
}
- private static File getConfigFilePath(@NonNull Context context, @NonNull String name) {
- final File vmRoot = new File(context.getFilesDir(), VM_DIR);
- final File thisVmDir = new File(vmRoot, name);
- return new File(thisVmDir, CONFIG_FILE);
+ @NonNull
+ private static File getVmDir(Context context, String name) {
+ File vmRoot = new File(context.getDataDir(), VM_DIR);
+ return new File(vmRoot, name);
}
}
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
index 2dff9bb..90b09c8 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -21,6 +21,7 @@
import static java.util.Objects.requireNonNull;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -39,15 +40,16 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
+
/**
* Represents a configuration of a virtual machine. A configuration consists of hardware
* configurations like the number of CPUs and the size of RAM, and software configurations like the
- * OS and application to run on the virtual machine.
+ * payload to run on the virtual machine.
*
* @hide
*/
public final class VirtualMachineConfig {
- // These defines the schema of the config file persisted on disk.
+ // These define the schema of the config file persisted on disk.
private static final int VERSION = 2;
private static final String KEY_VERSION = "version";
private static final String KEY_APKPATH = "apkPath";
@@ -133,6 +135,43 @@
if (!apkPath.startsWith("/")) {
throw new IllegalArgumentException("APK path must be an absolute path");
}
+
+ if (memoryMib < 0) {
+ throw new IllegalArgumentException("Memory size cannot be negative");
+ }
+
+ int availableCpus = Runtime.getRuntime().availableProcessors();
+ if (numCpus < 1 || numCpus > availableCpus) {
+ throw new IllegalArgumentException("Number of vCPUs (" + numCpus + ") is out of "
+ + "range [1, " + availableCpus + "]");
+ }
+
+ if (debugLevel != DEBUG_LEVEL_NONE && debugLevel != DEBUG_LEVEL_APP_ONLY
+ && debugLevel != DEBUG_LEVEL_FULL) {
+ throw new IllegalArgumentException("Invalid debugLevel: " + debugLevel);
+ }
+
+ if (payloadBinaryPath == null) {
+ if (payloadConfigPath == null) {
+ throw new IllegalStateException("setPayloadBinaryPath must be called");
+ }
+ } else {
+ if (payloadConfigPath != null) {
+ throw new IllegalStateException(
+ "setPayloadBinaryPath and setPayloadConfigPath may not both be called");
+ }
+ }
+
+ if (protectedVm
+ && !HypervisorProperties.hypervisor_protected_vm_supported().orElse(false)) {
+ throw new UnsupportedOperationException(
+ "Protected VMs are not supported on this device.");
+ }
+ if (!protectedVm && !HypervisorProperties.hypervisor_vm_supported().orElse(false)) {
+ throw new UnsupportedOperationException(
+ "Unprotected VMs are not supported on this device.");
+ }
+
mApkPath = apkPath;
mPayloadConfigPath = payloadConfigPath;
mPayloadBinaryPath = payloadBinaryPath;
@@ -177,7 +216,7 @@
}
/** Persists this config to a stream, for example a file. */
- /* package */ void serialize(@NonNull OutputStream output) throws IOException {
+ void serialize(@NonNull OutputStream output) throws IOException {
PersistableBundle b = new PersistableBundle();
b.putInt(KEY_VERSION, VERSION);
b.putString(KEY_APKPATH, mApkPath);
@@ -204,7 +243,8 @@
}
/**
- * Returns the path to the payload config within the owning application.
+ * Returns the path within the APK to the payload config file that defines software aspects
+ * of the VM.
*
* @hide
*/
@@ -214,8 +254,8 @@
}
/**
- * Returns the path within the APK to the payload binary file that will be executed within the
- * VM.
+ * Returns the path within the {@code lib/<ABI>} directory of the APK to the payload binary
+ * file that will be executed within the VM.
*
* @hide
*/
@@ -249,6 +289,7 @@
*
* @hide
*/
+ @IntRange(from = 0)
public int getMemoryMib() {
return mMemoryMib;
}
@@ -258,6 +299,7 @@
*
* @hide
*/
+ @IntRange(from = 1)
public int getNumCpus() {
return mNumCpus;
}
@@ -279,41 +321,42 @@
}
/**
- * Converts this config object into a parcel. Used when creating a VM via the virtualization
- * service. Notice that the files are not passed as paths, but as file descriptors because the
- * service doesn't accept paths as it might not have permission to open app-owned files and that
- * could be abused to run a VM with software that the calling application doesn't own.
+ * Converts this config object into the parcelable type used when creating a VM via the
+ * virtualization service. Notice that the files are not passed as paths, but as file
+ * descriptors because the service doesn't accept paths as it might not have permission to open
+ * app-owned files and that could be abused to run a VM with software that the calling
+ * application doesn't own.
*/
- VirtualMachineAppConfig toParcel() throws FileNotFoundException {
- VirtualMachineAppConfig parcel = new VirtualMachineAppConfig();
- parcel.apk = ParcelFileDescriptor.open(new File(mApkPath), MODE_READ_ONLY);
+ VirtualMachineAppConfig toVsConfig() throws FileNotFoundException {
+ VirtualMachineAppConfig vsConfig = new VirtualMachineAppConfig();
+ vsConfig.apk = ParcelFileDescriptor.open(new File(mApkPath), MODE_READ_ONLY);
if (mPayloadBinaryPath != null) {
VirtualMachinePayloadConfig payloadConfig = new VirtualMachinePayloadConfig();
payloadConfig.payloadPath = mPayloadBinaryPath;
- parcel.payload =
+ vsConfig.payload =
VirtualMachineAppConfig.Payload.payloadConfig(payloadConfig);
} else {
- parcel.payload =
+ vsConfig.payload =
VirtualMachineAppConfig.Payload.configPath(mPayloadConfigPath);
}
switch (mDebugLevel) {
case DEBUG_LEVEL_APP_ONLY:
- parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.APP_ONLY;
+ vsConfig.debugLevel = VirtualMachineAppConfig.DebugLevel.APP_ONLY;
break;
case DEBUG_LEVEL_FULL:
- parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.FULL;
+ vsConfig.debugLevel = VirtualMachineAppConfig.DebugLevel.FULL;
break;
default:
- parcel.debugLevel = VirtualMachineAppConfig.DebugLevel.NONE;
+ vsConfig.debugLevel = VirtualMachineAppConfig.DebugLevel.NONE;
break;
}
- parcel.protectedVm = mProtectedVm;
- parcel.memoryMib = mMemoryMib;
- parcel.numCpus = mNumCpus;
+ vsConfig.protectedVm = mProtectedVm;
+ vsConfig.memoryMib = mMemoryMib;
+ vsConfig.numCpus = mNumCpus;
// Don't allow apps to set task profiles ... at last for now. Also, don't forget to
// validate the string because these are appended to the cmdline argument.
- parcel.taskProfiles = new String[0];
- return parcel;
+ vsConfig.taskProfiles = new String[0];
+ return vsConfig;
}
/**
@@ -333,7 +376,7 @@
private int mNumCpus;
/**
- * Creates a builder for the given context (APK).
+ * Creates a builder for the given context.
*
* @hide
*/
@@ -352,37 +395,10 @@
public VirtualMachineConfig build() {
String apkPath = (mApkPath == null) ? mContext.getPackageCodePath() : mApkPath;
- int availableCpus = Runtime.getRuntime().availableProcessors();
- if (mNumCpus < 1 || mNumCpus > availableCpus) {
- throw new IllegalArgumentException("Number of vCPUs (" + mNumCpus + ") is out of "
- + "range [1, " + availableCpus + "]");
- }
-
- if (mPayloadBinaryPath == null) {
- if (mPayloadConfigPath == null) {
- throw new IllegalStateException("payloadBinaryPath must be set");
- }
- } else {
- if (mPayloadConfigPath != null) {
- throw new IllegalStateException(
- "payloadBinaryPath and payloadConfigPath may not both be set");
- }
- }
-
if (!mProtectedVmSet) {
throw new IllegalStateException("setProtectedVm must be called explicitly");
}
- if (mProtectedVm
- && !HypervisorProperties.hypervisor_protected_vm_supported().orElse(false)) {
- throw new UnsupportedOperationException(
- "Protected VMs are not supported on this device.");
- }
- if (!mProtectedVm && !HypervisorProperties.hypervisor_vm_supported().orElse(false)) {
- throw new UnsupportedOperationException(
- "Unprotected VMs are not supported on this device.");
- }
-
return new VirtualMachineConfig(
apkPath, mPayloadConfigPath, mPayloadBinaryPath, mDebugLevel, mProtectedVm,
mMemoryMib, mNumCpus);
@@ -402,7 +418,8 @@
/**
* Sets the path within the APK to the payload config file that defines software aspects
- * of the VM.
+ * of the VM. The file is a JSON file; see
+ * packages/modules/Virtualization/microdroid/payload/config/src/lib.rs for the format.
*
* @hide
*/
@@ -426,7 +443,7 @@
}
/**
- * Sets the debug level
+ * Sets the debug level. Defaults to {@link #DEBUG_LEVEL_NONE}.
*
* @hide
*/
@@ -451,24 +468,25 @@
}
/**
- * Sets the amount of RAM to give the VM. If this is zero or negative then the default will
- * be used.
+ * Sets the amount of RAM to give the VM, in mebibytes. If zero or not explicitly set
+ * than a default size will be used.
*
* @hide
*/
@NonNull
- public Builder setMemoryMib(int memoryMib) {
+ public Builder setMemoryMib(@IntRange(from = 0) int memoryMib) {
mMemoryMib = memoryMib;
return this;
}
/**
- * Sets the number of vCPUs in the VM. Defaults to 1.
+ * Sets the number of vCPUs in the VM. Defaults to 1. Cannot be more than the number of
+ * real CPUs (as returned by {@link Runtime#availableProcessors()}).
*
* @hide
*/
@NonNull
- public Builder setNumCpus(int num) {
+ public Builder setNumCpus(@IntRange(from = 1) int num) {
mNumCpus = num;
return this;
}
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineException.java b/javalib/src/android/system/virtualmachine/VirtualMachineException.java
index 88b5ea3..828775a 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineException.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineException.java
@@ -24,10 +24,6 @@
* @hide
*/
public class VirtualMachineException extends Exception {
- public VirtualMachineException() {
- super();
- }
-
public VirtualMachineException(@Nullable String message) {
super(message);
}
diff --git a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
index 3f904be..f2b7802 100644
--- a/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
+++ b/javalib/src/android/system/virtualmachine/VirtualMachineManager.java
@@ -33,7 +33,14 @@
import java.util.WeakHashMap;
/**
- * Manages {@link VirtualMachine} objects created for an application.
+ * Manages {@link VirtualMachine virtual machine} instances created by an app. Each instance is
+ * created from a {@link VirtualMachineConfig configuration} that defines the shape of the VM
+ * (RAM, CPUs), the code to execute within it, etc.
+ * <p>
+ * Each virtual machine instance is named; the configuration and related state of each is
+ * persisted in the app's private data directory and an instance can be retrieved given the name.
+ * <p>
+ * The app can then start, stop and otherwise interact with the VM.
*
* @hide
*/
@@ -138,7 +145,8 @@
* Returns an existing {@link VirtualMachine} with the given name. Returns null if there is no
* such virtual machine.
*
- * @throws VirtualMachineException if the virtual machine could not be successfully retrieved.
+ * @throws VirtualMachineException if the virtual machine exists but could not be successfully
+ * retrieved.
* @hide
*/
@Nullable
@@ -166,4 +174,20 @@
}
return vm;
}
+
+ /**
+ * Deletes an existing {@link VirtualMachine}. Deleting a virtual machine means deleting any
+ * persisted data associated with it including the per-VM secret. This is an irreversible
+ * action. A virtual machine once deleted can never be restored. A new virtual machine created
+ * with the same name is different from an already deleted virtual machine even if it has the
+ * same config.
+ *
+ * @throws VirtualMachineException if the virtual machine does not exist, is not stopped,
+ * or cannot be deleted.
+ * @hide
+ */
+ public void delete(@NonNull String name) throws VirtualMachineException {
+ requireNonNull(name);
+ VirtualMachine.delete(mContext, name);
+ }
}
diff --git a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
index 66cd211..ede838b 100644
--- a/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
+++ b/tests/helper/src/java/com/android/microdroid/test/device/MicrodroidDeviceTestBase.java
@@ -106,7 +106,7 @@
throws VirtualMachineException {
VirtualMachine existingVm = mVmm.get(name);
if (existingVm != null) {
- existingVm.delete();
+ mVmm.delete(name);
}
return mVmm.create(name, config);
}
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 e5052bf..42c0e64 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -31,6 +31,8 @@
import android.system.virtualmachine.VirtualMachine;
import android.system.virtualmachine.VirtualMachineCallback;
import android.system.virtualmachine.VirtualMachineConfig;
+import android.system.virtualmachine.VirtualMachineException;
+import android.system.virtualmachine.VirtualMachineManager;
import android.util.Log;
import com.android.compatibility.common.util.CddTest;
@@ -104,7 +106,7 @@
.setPayloadBinaryPath("MicrodroidTestNativeLib.so")
.setMemoryMib(minMemoryRequired())
.build();
- VirtualMachine vm = mInner.forceCreateNewVirtualMachine("test_vm_extra_apk", config);
+ VirtualMachine vm = mInner.forceCreateNewVirtualMachine("test_vm", config);
TestResults testResults = runVmTestService(vm);
assertThat(testResults.mException).isNull();
@@ -162,6 +164,33 @@
@CddTest(requirements = {
"9.17/C-1-1",
})
+ public void deleteVm() throws Exception {
+ assumeSupportedKernel();
+
+ VirtualMachineConfig config = mInner.newVmConfigBuilder()
+ .setPayloadBinaryPath("MicrodroidTestNativeLib.so")
+ .setMemoryMib(minMemoryRequired())
+ .build();
+
+ VirtualMachine vm = mInner.forceCreateNewVirtualMachine("test_vm_delete",
+ config);
+ VirtualMachineManager vmm = mInner.getVirtualMachineManager();
+ vmm.delete("test_vm_delete");
+
+ // VM should no longer exist
+ assertThat(vmm.get("test_vm_delete")).isNull();
+
+ // Can't start the VM even with an existing reference
+ assertThrows(VirtualMachineException.class, vm::run);
+
+ // Can't delete the VM since it no longer exists
+ assertThrows(VirtualMachineException.class, () -> vmm.delete("test_vm_delete"));
+ }
+
+ @Test
+ @CddTest(requirements = {
+ "9.17/C-1-1",
+ })
public void validApkPathIsAccepted() throws Exception {
assumeSupportedKernel();
@@ -260,7 +289,7 @@
// Try to run the VM again with the previous instance.img
// We need to make sure that no changes on config don't invalidate the identity, to compare
// the result with the below "different debug level" test.
- File vmRoot = new File(getContext().getFilesDir(), "vm");
+ File vmRoot = new File(getContext().getDataDir(), "vm");
File vmInstance = new File(new File(vmRoot, "test_vm"), "instance.img");
File vmInstanceBackup = File.createTempFile("instance", ".img");
Files.copy(vmInstance.toPath(), vmInstanceBackup.toPath(), REPLACE_EXISTING);
@@ -448,7 +477,7 @@
mInner.forceCreateNewVirtualMachine(vmName, config);
assertThat(tryBootVm(TAG, vmName).payloadStarted).isTrue();
- File vmRoot = new File(getContext().getFilesDir(), "vm");
+ File vmRoot = new File(getContext().getDataDir(), "vm");
File vmDir = new File(vmRoot, vmName);
File instanceImgPath = new File(vmDir, "instance.img");
return new RandomAccessFile(instanceImgPath, "rw");