[vm tool] Introduce check-feature-enabled

Introduce this command to allow host to query feature (such as
com.android.kvm.LLPVM_CHANGES) is enabled on device. Implement this in
libavf_features, so that virtmrg can share code.

Bug: 325630143
Test: Inspect output of vm check-feature-enabled
com.android.kvm.LLPVM_CHANGES

Change-Id: I9f11f6d8a98e1df6926492edee2152908c770e73
diff --git a/libs/avf_features/Android.bp b/libs/avf_features/Android.bp
new file mode 100644
index 0000000..71f33db
--- /dev/null
+++ b/libs/avf_features/Android.bp
@@ -0,0 +1,26 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "libavf_features.defaults",
+    crate_name: "avf_features",
+    defaults: ["avf_build_flags_rust"],
+    srcs: ["src/lib.rs"],
+    edition: "2021",
+    prefer_rlib: true,
+    rustlibs: [
+        "android.system.virtualizationservice-rust",
+        "libanyhow",
+        "liblog_rust",
+    ],
+}
+
+rust_library {
+    name: "libavf_features",
+    defaults: ["libavf_features.defaults"],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
+}
diff --git a/libs/avf_features/src/lib.rs b/libs/avf_features/src/lib.rs
new file mode 100644
index 0000000..c0faab0
--- /dev/null
+++ b/libs/avf_features/src/lib.rs
@@ -0,0 +1,38 @@
+// Copyright 2024, 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.
+
+//! Provide functionality for handling AVF build-time feature flags.
+
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+    IVirtualizationService::FEATURE_DICE_CHANGES, IVirtualizationService::FEATURE_LLPVM_CHANGES,
+    IVirtualizationService::FEATURE_MULTI_TENANT,
+    IVirtualizationService::FEATURE_REMOTE_ATTESTATION,
+    IVirtualizationService::FEATURE_VENDOR_MODULES,
+};
+use log::warn;
+
+/// Check if an AVF feature is enabled.
+pub fn is_feature_enabled(feature: &str) -> bool {
+    match feature {
+        FEATURE_DICE_CHANGES => cfg!(dice_changes),
+        FEATURE_LLPVM_CHANGES => cfg!(llpvm_changes),
+        FEATURE_MULTI_TENANT => cfg!(multi_tenant),
+        FEATURE_REMOTE_ATTESTATION => cfg!(remote_attestation),
+        FEATURE_VENDOR_MODULES => cfg!(vendor_modules),
+        _ => {
+            warn!("unknown feature {feature}");
+            false
+        }
+    }
+}
diff --git a/virtualizationmanager/Android.bp b/virtualizationmanager/Android.bp
index 48b5cd1..3320c80 100644
--- a/virtualizationmanager/Android.bp
+++ b/virtualizationmanager/Android.bp
@@ -32,6 +32,7 @@
         "libandroid_logger",
         "libanyhow",
         "libapkverify",
+        "libavf_features",
         "libavflog",
         "libbase_rust",
         "libbinder_rs",
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 00f3f37..1cecdbf 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -35,11 +35,6 @@
     IVirtualMachine::{BnVirtualMachine, IVirtualMachine},
     IVirtualMachineCallback::IVirtualMachineCallback,
     IVirtualizationService::IVirtualizationService,
-    IVirtualizationService::FEATURE_MULTI_TENANT,
-    IVirtualizationService::FEATURE_VENDOR_MODULES,
-    IVirtualizationService::FEATURE_DICE_CHANGES,
-    IVirtualizationService::FEATURE_LLPVM_CHANGES,
-    IVirtualizationService::FEATURE_REMOTE_ATTESTATION,
     MemoryTrimLevel::MemoryTrimLevel,
     Partition::Partition,
     PartitionType::PartitionType,
@@ -307,20 +302,7 @@
     /// Returns whether given feature is enabled
     fn isFeatureEnabled(&self, feature: &str) -> binder::Result<bool> {
         check_manage_access()?;
-
-        // This approach is quite cumbersome, but will do the work for the short term.
-        // TODO(b/298012279): make this scalable.
-        match feature {
-            FEATURE_DICE_CHANGES => Ok(cfg!(dice_changes)),
-            FEATURE_LLPVM_CHANGES => Ok(cfg!(llpvm_changes)),
-            FEATURE_MULTI_TENANT => Ok(cfg!(multi_tenant)),
-            FEATURE_REMOTE_ATTESTATION => Ok(cfg!(remote_attestation)),
-            FEATURE_VENDOR_MODULES => Ok(cfg!(vendor_modules)),
-            _ => {
-                warn!("unknown feature {feature}");
-                Ok(false)
-            }
-        }
+        Ok(avf_features::is_feature_enabled(feature))
     }
 
     fn enableTestAttestation(&self) -> binder::Result<()> {
diff --git a/vm/Android.bp b/vm/Android.bp
index 04aff5e..c1d9b6b 100644
--- a/vm/Android.bp
+++ b/vm/Android.bp
@@ -12,6 +12,7 @@
     rustlibs: [
         "android.system.virtualizationservice-rust",
         "libanyhow",
+        "libavf_features",
         "libbinder_rs",
         "libclap",
         "libenv_logger",
diff --git a/vm/src/main.rs b/vm/src/main.rs
index de9291c..ea8c682 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -232,6 +232,8 @@
 
 #[derive(Parser)]
 enum Opt {
+    /// Check if the feature is enabled on device.
+    CheckFeatureEnabled { feature: String },
     /// Run a virtual machine with a config in APK
     RunApp {
         #[command(flatten)]
@@ -304,6 +306,13 @@
     virtmgr.connect().context("Failed to connect to VirtualizationService")
 }
 
+fn command_check_feature_enabled(feature: &str) {
+    println!(
+        "Feature {feature} is {}",
+        if avf_features::is_feature_enabled(feature) { "enabled" } else { "disabled" }
+    );
+}
+
 fn main() -> Result<(), Error> {
     env_logger::init();
     let opt = Opt::parse();
@@ -312,6 +321,10 @@
     ProcessState::start_thread_pool();
 
     match opt {
+        Opt::CheckFeatureEnabled { feature } => {
+            command_check_feature_enabled(&feature);
+            Ok(())
+        }
         Opt::RunApp { config } => command_run_app(config),
         Opt::RunMicrodroid { config } => command_run_microdroid(config),
         Opt::Run { config } => command_run(config),