Add basic test that starts a VM with payload from another app

An ability to start a payload from another app is important for the case
of VM sharing. An end-to-end for which will be added in the follow-up
cl.

Bug: 259384440
Test: atest MicrodroidTestApp
Change-Id: I3a9c532c6ba24768fe7df0b1beadec7243b29e00
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 5f9b915..76b4184 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -2,12 +2,22 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-android_test {
-    name: "MicrodroidTestApp",
+java_defaults {
+    name: "MicrodroidTestAppsDefaults",
     test_suites: [
         "cts",
         "general-tests",
     ],
+    sdk_version: "test_current",
+    jni_uses_platform_apis: true,
+    use_embedded_native_libs: true,
+    // We only support 64-bit ABI, but CTS demands all APKs to be multi-ABI.
+    compile_multilib: "both",
+}
+
+android_test {
+    name: "MicrodroidTestApp",
+    defaults: ["MicrodroidTestAppsDefaults"],
     srcs: ["src/java/**/*.java"],
     static_libs: [
         "MicrodroidDeviceTestHelper",
@@ -19,7 +29,6 @@
         "truth-prebuilt",
         "compatibility-common-util-devicesidelib",
     ],
-    sdk_version: "test_current",
     jni_libs: [
         "MicrodroidTestNativeLib",
         "MicrodroidIdleNativeLib",
@@ -27,15 +36,28 @@
         "MicrodroidExitNativeLib",
         "MicrodroidPrivateLinkingNativeLib",
     ],
-    jni_uses_platform_apis: true,
-    use_embedded_native_libs: true,
-    // We only support 64-bit ABI, but CTS demands all APKs to be multi-ABI.
-    compile_multilib: "both",
     min_sdk_version: "33",
+    data: [":MicrodroidVmShareApp"],
 }
 
-cc_library_shared {
-    name: "MicrodroidTestNativeLib",
+// Helper app to verify that we can create a VM using others app payload.
+android_test_helper_app {
+    name: "MicrodroidVmShareApp",
+    defaults: ["MicrodroidTestAppsDefaults"],
+    jni_libs: [
+        "MicrodroidPayloadInOtherAppNativeLib",
+    ],
+    min_sdk_version: "UpsideDownCake",
+    manifest: "AndroidManifest_VmShareApp.xml",
+    // The MicrodroidVmShareApp doesn't need assets.
+    asset_dirs: [],
+}
+
+// Defaults shared between MicrodroidTestNativeLib and MicrodroidPayloadInOtherAppNativeLib shared
+// libs. They are expected to share everything apart from the name, so that one app
+// (MicrodroidTestApp) can start a payload defined in the another app (MicrodroidVmShareApp).
+cc_defaults {
+    name: "MicrodroidTestNativeLibDefaults",
     srcs: ["src/native/testbinary.cpp"],
     stl: "libc++_static",
     header_libs: ["vm_payload_restricted_headers"],
@@ -55,6 +77,16 @@
 }
 
 cc_library_shared {
+    name: "MicrodroidPayloadInOtherAppNativeLib",
+    defaults: ["MicrodroidTestNativeLibDefaults"],
+}
+
+cc_library_shared {
+    name: "MicrodroidTestNativeLib",
+    defaults: ["MicrodroidTestNativeLibDefaults"],
+}
+
+cc_library_shared {
     name: "MicrodroidTestNativeLibSub",
     srcs: ["src/native/testlib.cpp"],
     stl: "libc++_static",
diff --git a/tests/testapk/AndroidManifest.xml b/tests/testapk/AndroidManifest.xml
index fefd20a..2ea3f6c 100644
--- a/tests/testapk/AndroidManifest.xml
+++ b/tests/testapk/AndroidManifest.xml
@@ -19,6 +19,9 @@
     <uses-permission android:name="android.permission.USE_CUSTOM_VIRTUAL_MACHINE" />
     <uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33" />
     <uses-feature android:name="android.software.virtualization_framework" android:required="false" />
+    <queries>
+        <package android:name="com.android.microdroid.vmshare_app" />
+    </queries>
     <application>
     </application>
     <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/tests/testapk/AndroidManifest_VmShareApp.xml b/tests/testapk/AndroidManifest_VmShareApp.xml
new file mode 100644
index 0000000..eed3364
--- /dev/null
+++ b/tests/testapk/AndroidManifest_VmShareApp.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.android.microdroid.vmshare_app">
+    <uses-permission android:name="android.permission.MANAGE_VIRTUAL_MACHINE" />
+
+    <uses-feature android:name="android.software.virtualization_framework"
+                  android:required="false" />
+
+    <application />
+</manifest>
diff --git a/tests/testapk/AndroidTest.xml b/tests/testapk/AndroidTest.xml
index 787ebd4..929dd31 100644
--- a/tests/testapk/AndroidTest.xml
+++ b/tests/testapk/AndroidTest.xml
@@ -21,6 +21,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="test-file-name" value="MicrodroidTestApp.apk" />
+        <option name="test-file-name" value="MicrodroidVmShareApp.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.microdroid.test" />
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 9cafd68..8163a0e 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -125,6 +125,8 @@
     private static final long MIN_MEM_X86_64 = 196 * ONE_MEBI;
     private static final String EXAMPLE_STRING = "Literally any string!! :)";
 
+    private static final String VM_SHARE_APP_PACKAGE_NAME = "com.android.microdroid.vmshare_app";
+
     @Test
     @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
     public void createAndConnectToVm() throws Exception {
@@ -1458,6 +1460,33 @@
         assertThat(checkVmOutputIsRedirectedToLogcat(false)).isFalse();
     }
 
+    @Test
+    public void testStartVmWithPayloadOfAnotherApp() throws Exception {
+        assumeSupportedKernel();
+
+        Context ctx = getContext();
+        Context otherAppCtx = ctx.createPackageContext(VM_SHARE_APP_PACKAGE_NAME, 0);
+
+        VirtualMachineConfig config =
+                new VirtualMachineConfig.Builder(otherAppCtx)
+                        .setDebugLevel(DEBUG_LEVEL_FULL)
+                        .setProtectedVm(isProtectedVm())
+                        .setPayloadBinaryName("MicrodroidPayloadInOtherAppNativeLib.so")
+                        .build();
+
+        try (VirtualMachine vm = forceCreateNewVirtualMachine("vm_from_another_app", config)) {
+            TestResults results =
+                    runVmTestService(
+                            vm,
+                            (ts, tr) -> {
+                                tr.mAddInteger = ts.addInteger(101, 303);
+                            });
+            assertThat(results.mAddInteger).isEqualTo(404);
+        }
+
+        getVirtualMachineManager().delete("vm_from_another_app");
+    }
+
     private void assertFileContentsAreEqualInTwoVms(String fileName, String vmName1, String vmName2)
             throws IOException {
         File file1 = getVmFile(vmName1, fileName);