Merge "Skeleton for IVmTethering service" into main
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
index ef6a2fc..1e0f6c6 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachineConfig.java
@@ -102,6 +102,7 @@
     private static final String KEY_OS = "os";
     private static final String KEY_EXTRA_APKS = "extraApks";
     private static final String KEY_NETWORK_SUPPORTED = "networkSupported";
+    private static final String KEY_SHOULD_BOOST_UCLAMP = "shouldBoostUclamp";
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
@@ -212,6 +213,8 @@
     /** Whether to run the VM with supporting network feature or not. */
     private final boolean mNetworkSupported;
 
+    private final boolean mShouldBoostUclamp;
+
     @Retention(RetentionPolicy.SOURCE)
     @StringDef(
             prefix = "MICRODROID",
@@ -247,7 +250,8 @@
             boolean connectVmConsole,
             @Nullable File vendorDiskImage,
             @NonNull @OsName String os,
-            boolean networkSupported) {
+            boolean networkSupported,
+            boolean shouldBoostUclamp) {
         // This is only called from Builder.build(); the builder handles parameter validation.
         mPackageName = packageName;
         mApkPath = apkPath;
@@ -271,6 +275,7 @@
         mVendorDiskImage = vendorDiskImage;
         mOs = os;
         mNetworkSupported = networkSupported;
+        mShouldBoostUclamp = shouldBoostUclamp;
     }
 
     /** Loads a config from a file. */
@@ -373,6 +378,7 @@
 
         builder.setNetworkSupported(b.getBoolean(KEY_NETWORK_SUPPORTED));
 
+        builder.setShouldBoostUclamp(b.getBoolean(KEY_SHOULD_BOOST_UCLAMP));
         return builder.build();
     }
 
@@ -424,6 +430,7 @@
             b.putStringArray(KEY_EXTRA_APKS, extraApks);
         }
         b.putBoolean(KEY_NETWORK_SUPPORTED, mNetworkSupported);
+        b.putBoolean(KEY_SHOULD_BOOST_UCLAMP, mShouldBoostUclamp);
         b.writeToStream(output);
     }
 
@@ -780,6 +787,8 @@
             customConfig.networkSupported = mNetworkSupported;
             vsConfig.customConfig = customConfig;
         }
+
+        vsConfig.boostUclamp = mShouldBoostUclamp;
         return vsConfig;
     }
 
@@ -860,6 +869,7 @@
         @Nullable private File mVendorDiskImage;
         @NonNull @OsName private String mOs = DEFAULT_OS;
         private boolean mNetworkSupported;
+        private boolean mShouldBoostUclamp = false;
 
         /**
          * Creates a builder for the given context.
@@ -958,7 +968,8 @@
                     mConnectVmConsole,
                     mVendorDiskImage,
                     mOs,
-                    mNetworkSupported);
+                    mNetworkSupported,
+                    mShouldBoostUclamp);
         }
 
         /**
@@ -1280,5 +1291,11 @@
             mNetworkSupported = networkSupported;
             return this;
         }
+
+        /** @hide */
+        public Builder setShouldBoostUclamp(boolean shouldBoostUclamp) {
+            mShouldBoostUclamp = shouldBoostUclamp;
+            return this;
+        }
     }
 }
diff --git a/tests/benchmark/Android.bp b/tests/benchmark/Android.bp
index 413ffe4..5ede699 100644
--- a/tests/benchmark/Android.bp
+++ b/tests/benchmark/Android.bp
@@ -22,8 +22,10 @@
         "MicrodroidTestNativeLib",
         "libiovsock_host_jni",
     ],
-    jni_uses_platform_apis: true,
-    sdk_version: "test_current",
+    libs: [
+        "framework-virtualization.impl",
+    ],
+    platform_apis: true,
     use_embedded_native_libs: true,
     compile_multilib: "64",
     required: ["perf-setup"],
diff --git a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
index 9cc1b7b..d8b17f1 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -233,6 +233,7 @@
         for (int i = 0; i < trialCount; i++) {
             VirtualMachineConfig.Builder builder =
                     newVmConfigBuilderWithPayloadBinary("MicrodroidIdleNativeLib.so")
+                            .setShouldBoostUclamp(true)
                             .setMemoryBytes(256 * ONE_MEBI)
                             .setDebugLevel(DEBUG_LEVEL_NONE);
             if (fullDebug) {
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 0055b3b..8e1b6bb 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -401,68 +401,9 @@
             check_gdb_allowed(config)?;
         }
 
-        // Currently, VirtMgr adds the host copy of reference DT & untrusted properties
-        // (e.g. instance-id)
-        let host_ref_dt = Path::new(VM_REFERENCE_DT_ON_HOST_PATH);
-        let host_ref_dt = if host_ref_dt.exists()
-            && read_dir(host_ref_dt).or_service_specific_exception(-1)?.next().is_some()
-        {
-            Some(host_ref_dt)
-        } else {
-            warn!("VM reference DT doesn't exist in host DT");
-            None
-        };
-
-        let vendor_hashtree_digest = extract_vendor_hashtree_digest(config)
-            .context("Failed to extract vendor hashtree digest")
-            .or_service_specific_exception(-1)?;
-
-        let trusted_props = if let Some(ref vendor_hashtree_digest) = vendor_hashtree_digest {
-            info!(
-                "Passing vendor hashtree digest to pvmfw. This will be rejected if it doesn't \
-                match the trusted digest in the pvmfw config, causing the VM to fail to start."
-            );
-            vec![(
-                cstr!("vendor_hashtree_descriptor_root_digest"),
-                vendor_hashtree_digest.as_slice(),
-            )]
-        } else {
-            vec![]
-        };
-
-        let instance_id;
-        let mut untrusted_props = Vec::with_capacity(2);
-        if cfg!(llpvm_changes) {
-            instance_id = extract_instance_id(config);
-            untrusted_props.push((cstr!("instance-id"), &instance_id[..]));
-            let want_updatable = extract_want_updatable(config);
-            if want_updatable && is_secretkeeper_supported() {
-                // Let guest know that it can defer rollback protection to Secretkeeper by setting
-                // an empty property in untrusted node in DT. This enables Updatable VMs.
-                untrusted_props.push((cstr!("defer-rollback-protection"), &[]))
-            }
-        }
-
-        let device_tree_overlay =
-            if host_ref_dt.is_some() || !untrusted_props.is_empty() || !trusted_props.is_empty() {
-                let dt_output = temporary_directory.join(VM_DT_OVERLAY_PATH);
-                let mut data = [0_u8; VM_DT_OVERLAY_MAX_SIZE];
-                let fdt = create_device_tree_overlay(
-                    &mut data,
-                    host_ref_dt,
-                    &untrusted_props,
-                    &trusted_props,
-                )
-                .map_err(|e| anyhow!("Failed to create DT overlay, {e:?}"))
-                .or_service_specific_exception(-1)?;
-                fs::write(&dt_output, fdt.as_slice()).or_service_specific_exception(-1)?;
-                Some(File::open(dt_output).or_service_specific_exception(-1)?)
-            } else {
-                None
-            };
+        let device_tree_overlay = maybe_create_device_tree_overlay(config, &temporary_directory)?;
 
         let debug_config = DebugConfig::new(config);
-
         let ramdump = if !uses_gki_kernel(config) && debug_config.is_ramdump_needed() {
             Some(prepare_ramdump_file(&temporary_directory)?)
         } else {
@@ -658,6 +599,7 @@
             tap,
             virtio_snd_backend,
             console_input_device: config.consoleInputDevice.clone(),
+            boost_uclamp: config.boostUclamp,
         };
         let instance = Arc::new(
             VmInstance::new(
@@ -732,6 +674,67 @@
     Err(anyhow!("No hashtree digest is extracted from microdroid vendor image"))
 }
 
+fn maybe_create_device_tree_overlay(
+    config: &VirtualMachineConfig,
+    temporary_directory: &Path,
+) -> binder::Result<Option<File>> {
+    // Currently, VirtMgr adds the host copy of reference DT & untrusted properties
+    // (e.g. instance-id)
+    let host_ref_dt = Path::new(VM_REFERENCE_DT_ON_HOST_PATH);
+    let host_ref_dt = if host_ref_dt.exists()
+        && read_dir(host_ref_dt).or_service_specific_exception(-1)?.next().is_some()
+    {
+        Some(host_ref_dt)
+    } else {
+        warn!("VM reference DT doesn't exist in host DT");
+        None
+    };
+
+    let vendor_hashtree_digest = extract_vendor_hashtree_digest(config)
+        .context("Failed to extract vendor hashtree digest")
+        .or_service_specific_exception(-1)?;
+
+    let trusted_props = if let Some(ref vendor_hashtree_digest) = vendor_hashtree_digest {
+        info!(
+            "Passing vendor hashtree digest to pvmfw. This will be rejected if it doesn't \
+                match the trusted digest in the pvmfw config, causing the VM to fail to start."
+        );
+        vec![(cstr!("vendor_hashtree_descriptor_root_digest"), vendor_hashtree_digest.as_slice())]
+    } else {
+        vec![]
+    };
+
+    let instance_id;
+    let mut untrusted_props = Vec::with_capacity(2);
+    if cfg!(llpvm_changes) {
+        instance_id = extract_instance_id(config);
+        untrusted_props.push((cstr!("instance-id"), &instance_id[..]));
+        let want_updatable = extract_want_updatable(config);
+        if want_updatable && is_secretkeeper_supported() {
+            // Let guest know that it can defer rollback protection to Secretkeeper by setting
+            // an empty property in untrusted node in DT. This enables Updatable VMs.
+            untrusted_props.push((cstr!("defer-rollback-protection"), &[]))
+        }
+    }
+
+    let device_tree_overlay = if host_ref_dt.is_some()
+        || !untrusted_props.is_empty()
+        || !trusted_props.is_empty()
+    {
+        let dt_output = temporary_directory.join(VM_DT_OVERLAY_PATH);
+        let mut data = [0_u8; VM_DT_OVERLAY_MAX_SIZE];
+        let fdt =
+            create_device_tree_overlay(&mut data, host_ref_dt, &untrusted_props, &trusted_props)
+                .map_err(|e| anyhow!("Failed to create DT overlay, {e:?}"))
+                .or_service_specific_exception(-1)?;
+        fs::write(&dt_output, fdt.as_slice()).or_service_specific_exception(-1)?;
+        Some(File::open(dt_output).or_service_specific_exception(-1)?)
+    } else {
+        None
+    };
+    Ok(device_tree_overlay)
+}
+
 fn write_zero_filler(zero_filler_path: &Path) -> Result<()> {
     let file = OpenOptions::new()
         .create_new(true)
@@ -958,6 +961,7 @@
     vm_config.protectedVm = config.protectedVm;
     vm_config.cpuTopology = config.cpuTopology;
     vm_config.hugePages = config.hugePages || vm_payload_config.hugepages;
+    vm_config.boostUclamp = config.boostUclamp;
 
     // Microdroid takes additional init ramdisk & (optionally) storage image
     add_microdroid_system_images(config, instance_file, storage_image, os_name, &mut vm_config)?;
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index 4b03bac..79c7b7f 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -132,6 +132,7 @@
     pub tap: Option<File>,
     pub virtio_snd_backend: Option<String>,
     pub console_input_device: Option<String>,
+    pub boost_uclamp: bool,
 }
 
 #[derive(Debug)]
@@ -1054,6 +1055,10 @@
         command.arg("--hugepages");
     }
 
+    if config.boost_uclamp {
+        command.arg("--boost-uclamp");
+    }
+
     append_platform_devices(&mut command, &mut preserved_fds, &config)?;
 
     debug!("Preserving FDs {:?}", preserved_fds);
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
index a3f4b0f..ee39d75 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineAppConfig.aidl
@@ -139,4 +139,7 @@
      *  https://docs.kernel.org/admin-guide/mm/transhuge.html
      */
     boolean hugePages;
+
+    /** Enable boost UClamp for less variance during testing/benchmarking */
+    boolean boostUclamp;
 }
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
index c927c9b..0d175dd 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/VirtualMachineRawConfig.aidl
@@ -91,4 +91,7 @@
 
     /** The serial device for VM console input. */
     @nullable @utf8InCpp String consoleInputDevice;
+
+    /** Enable boost UClamp for less variance during testing/benchmarking */
+    boolean boostUclamp;
 }
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 390a60d..a250c35 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -65,6 +65,10 @@
     #[cfg(network)]
     #[arg(short, long)]
     network_supported: bool,
+
+    /// Boost uclamp to stablise results for benchmarks.
+    #[arg(short, long)]
+    boost_uclamp: bool,
 }
 
 impl CommonConfig {
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 0c9fbb6..cb15802 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -179,6 +179,7 @@
         customConfig: Some(custom_config),
         osName: os_name,
         hugePages: config.common.hugepages,
+        boostUclamp: config.common.boost_uclamp,
     });
     run(
         service.as_ref(),
@@ -260,6 +261,7 @@
     }
     vm_config.cpuTopology = config.common.cpu_topology;
     vm_config.hugePages = config.common.hugepages;
+    vm_config.boostUclamp = config.common.boost_uclamp;
     run(
         get_service()?.as_ref(),
         &VirtualMachineConfig::RawConfig(vm_config),