Add test to verify page size of Microdroid VM

Also fix the x86_64 microdroid_16k. Unfortunately passing the
`page_shift = 14` option in the bootconfig doesn't enable 16k emulation,
so we need to pass the option in the kernel cmdline until support for
bootconfig is implemented in the kernel.

Bug: 333730505
Test: atest MicrodroidTests
Change-Id: I35375ad272b4ff91c37a9a69658a17045a4a7ac8
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index f55471e..87d7a88 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -1154,6 +1154,13 @@
         }
     }
 
+    // Unfortunately specifying page_shift = 14 in bootconfig doesn't enable 16k pages emulation,
+    // so we need to provide it in the kernel cmdline.
+    // TODO(b/376901009): remove this after passing page_shift in bootconfig is supported.
+    if os_name.ends_with("_16k") && cfg!(target_arch = "x86_64") {
+        append_kernel_param("page_shift=14", &mut vm_config);
+    }
+
     if config.memoryMib > 0 {
         vm_config.memoryMib = config.memoryMib;
     }
diff --git a/build/microdroid/bootconfig.x86_64_16k b/build/microdroid/bootconfig.x86_64_16k
index 6a8423b..ee01de5 100644
--- a/build/microdroid/bootconfig.x86_64_16k
+++ b/build/microdroid/bootconfig.x86_64_16k
@@ -1 +1 @@
-page_shift=14
+page_shift = 14
diff --git a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
index e81f6d7..6a3bc1b 100644
--- a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
+++ b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
@@ -70,6 +70,9 @@
     /** Returns flags for the given mountPoint. */
     int getMountFlags(String mountPoint);
 
+    /** Returns page size of the VM. */
+    int getPageSize();
+
     /** Requests the VM to asynchronously call appCallback.setVmCallback() */
     void requestCallback(IAppCallback appCallback);
 
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 5309ceb..2986bdc 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
@@ -587,6 +587,7 @@
         public int mMountFlags;
         public String mConsoleInput;
         public byte[] mInstanceSecret;
+        public int mPageSize;
 
         public void assertNoException() {
             if (mException != null) {
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 53fc819..917a027 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -2511,6 +2511,30 @@
         assertThat(testResults.mMountFlags & expectedFlags).isEqualTo(expectedFlags);
     }
 
+    @Test
+    public void pageSize() throws Exception {
+        assumeSupportedDevice();
+
+        VirtualMachineConfig config =
+                newVmConfigBuilderWithPayloadBinary("MicrodroidTestNativeLib.so")
+                        .setDebugLevel(DEBUG_LEVEL_FULL)
+                        .build();
+
+        VirtualMachine vm = forceCreateNewVirtualMachine("test_page_size", config);
+
+        TestResults testResults =
+                runVmTestService(
+                        TAG,
+                        vm,
+                        (ts, tr) -> {
+                            tr.mPageSize = ts.getPageSize();
+                        });
+
+        assertThat(testResults.mException).isNull();
+        int expectedPageSize = mOs.endsWith("_16k") ? 16384 : 4096;
+        assertThat(testResults.mPageSize).isEqualTo(expectedPageSize);
+    }
+
     private static class VmShareServiceConnection implements ServiceConnection {
 
         private final CountDownLatch mLatch = new CountDownLatch(1);
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 1a75102..632f648 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -34,6 +34,7 @@
 #include <vm_main.h>
 #include <vm_payload_restricted.h>
 
+#include <cstdint>
 #include <string>
 #include <thread>
 
@@ -311,6 +312,11 @@
             return ScopedAStatus::ok();
         }
 
+        ScopedAStatus getPageSize(int32_t* out) override {
+            *out = getpagesize();
+            return ScopedAStatus::ok();
+        }
+
         ScopedAStatus requestCallback(const std::shared_ptr<IAppCallback>& appCallback) {
             auto vmCallback = ndk::SharedRefBase::make<VmCallbackImpl>(appCallback);
             std::thread callback_thread{[=] { appCallback->setVmCallback(vmCallback); }};
diff --git a/tests/testapk/src/native/testbinary.rs b/tests/testapk/src/native/testbinary.rs
index 85b411e..e479342 100644
--- a/tests/testapk/src/native/testbinary.rs
+++ b/tests/testapk/src/native/testbinary.rs
@@ -123,6 +123,9 @@
     fn getMountFlags(&self, _: &str) -> BinderResult<i32> {
         unimplemented()
     }
+    fn getPageSize(&self) -> BinderResult<i32> {
+        unimplemented()
+    }
     fn requestCallback(&self, _: &Strong<dyn IAppCallback + 'static>) -> BinderResult<()> {
         unimplemented()
     }
diff --git a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
index 9f606e5..13b0c51 100644
--- a/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
+++ b/tests/vmshareapp/src/java/com/android/microdroid/test/sharevm/VmShareServiceImpl.java
@@ -258,6 +258,11 @@
         }
 
         @Override
+        public int getPageSize() throws RemoteException {
+            throw new UnsupportedOperationException("Not supported");
+        }
+
+        @Override
         public void requestCallback(IAppCallback appCallback) {
             throw new UnsupportedOperationException("Not supported");
         }