compos: compiling system server JARs in /system_ext

Bug: 246000387
Test: atest ComposHostTestCases odsign_e2e_tests (with and without
      extra jar from /system_ext in SYSTEMSERVERCLASSPATH)
Change-Id: Ibf6b81e65a635dded5ec38ba5313ed00e9584acc
diff --git a/compos/aidl/com/android/compos/ICompOsService.aidl b/compos/aidl/com/android/compos/ICompOsService.aidl
index 4df22da..9b45e13 100644
--- a/compos/aidl/com/android/compos/ICompOsService.aidl
+++ b/compos/aidl/com/android/compos/ICompOsService.aidl
@@ -44,12 +44,14 @@
     /**
      * Run odrefresh in the VM context.
      *
-     * The execution is based on the VM's APEX mounts, files on Android's /system (by accessing
-     * through systemDirFd over AuthFS), and *CLASSPATH derived in the VM, to generate the same
-     * odrefresh output artifacts to the output directory (through outputDirFd).
+     * The execution is based on the VM's APEX mounts, files on Android's /system and optionally
+     * /system_ext (by accessing through systemDirFd and systemExtDirFd over AuthFS), and
+     * *CLASSPATH derived in the VM, to generate the same odrefresh output artifacts to the output
+     * directory (through outputDirFd).
      *
      * @param compilationMode The type of compilation to be performed
      * @param systemDirFd An fd referring to /system
+     * @param systemExtDirFd An optional fd referring to /system_ext. Negative number means none.
      * @param outputDirFd An fd referring to the output directory, ART_APEX_DATA
      * @param stagingDirFd An fd referring to the staging directory, e.g. ART_APEX_DATA/staging
      * @param targetDirName The sub-directory of the output directory to which artifacts are to be
@@ -58,8 +60,8 @@
      * @param systemServerCompilerFilter The compiler filter used to compile system server
      * @return odrefresh exit code
      */
-    byte odrefresh(CompilationMode compilation_mode, int systemDirFd, int outputDirFd,
-            int stagingDirFd, String targetDirName, String zygoteArch,
+    byte odrefresh(CompilationMode compilation_mode, int systemDirFd, int systemExtDirFd,
+            int outputDirFd, int stagingDirFd, String targetDirName, String zygoteArch,
             String systemServerCompilerFilter);
 
     /**
diff --git a/compos/composd/src/odrefresh_task.rs b/compos/composd/src/odrefresh_task.rs
index a07a7f9..9276fb1 100644
--- a/compos/composd/src/odrefresh_task.rs
+++ b/compos/composd/src/odrefresh_task.rs
@@ -162,8 +162,7 @@
     let staging_dir_raw_fd = staging_dir_fd.as_raw_fd();
 
     // Get the /system_ext FD differently because it may not exist.
-    // TODO(245761690): pass system_ext_dir_raw_fd to service.odrefresh(...)
-    let (_system_ext_dir_raw_fd, ro_dir_fds) =
+    let (system_ext_dir_raw_fd, ro_dir_fds) =
         if let Ok(system_ext_dir_fd) = open_dir(Path::new("/system_ext")) {
             (system_ext_dir_fd.as_raw_fd(), vec![system_dir_fd, system_ext_dir_fd])
         } else {
@@ -184,6 +183,7 @@
     let exit_code = service.odrefresh(
         compilation_mode,
         system_dir_raw_fd,
+        system_ext_dir_raw_fd,
         output_dir_raw_fd,
         staging_dir_raw_fd,
         target_dir_name,
diff --git a/compos/src/compilation.rs b/compos/src/compilation.rs
index ab228e1..d165599 100644
--- a/compos/src/compilation.rs
+++ b/compos/src/compilation.rs
@@ -41,6 +41,7 @@
 pub struct OdrefreshContext<'a> {
     compilation_mode: CompilationMode,
     system_dir_fd: i32,
+    system_ext_dir_fd: Option<i32>,
     output_dir_fd: i32,
     staging_dir_fd: i32,
     target_dir_name: &'a str,
@@ -49,9 +50,11 @@
 }
 
 impl<'a> OdrefreshContext<'a> {
+    #[allow(clippy::too_many_arguments)]
     pub fn new(
         compilation_mode: CompilationMode,
         system_dir_fd: i32,
+        system_ext_dir_fd: Option<i32>,
         output_dir_fd: i32,
         staging_dir_fd: i32,
         target_dir_name: &'a str,
@@ -88,6 +91,7 @@
         Ok(Self {
             compilation_mode,
             system_dir_fd,
+            system_ext_dir_fd,
             output_dir_fd,
             staging_dir_fd,
             target_dir_name,
@@ -108,14 +112,25 @@
 {
     // Mount authfs (via authfs_service). The authfs instance unmounts once the `authfs` variable
     // is out of scope.
+
+    let mut input_dir_fd_annotations = vec![InputDirFdAnnotation {
+        fd: context.system_dir_fd,
+        // Use the 0th APK of the extra_apks in compos/apk/assets/vm_config*.json
+        manifestPath: "/mnt/extra-apk/0/assets/build_manifest.pb".to_string(),
+        prefix: "system/".to_string(),
+    }];
+    if let Some(fd) = context.system_ext_dir_fd {
+        input_dir_fd_annotations.push(InputDirFdAnnotation {
+            fd,
+            // Use the 1st APK of the extra_apks in compos/apk/assets/vm_config_system_ext_*.json
+            manifestPath: "/mnt/extra-apk/1/assets/build_manifest.pb".to_string(),
+            prefix: "system_ext/".to_string(),
+        });
+    }
+
     let authfs_config = AuthFsConfig {
         port: FD_SERVER_PORT,
-        inputDirFdAnnotations: vec![InputDirFdAnnotation {
-            fd: context.system_dir_fd,
-            // 0 is the index of extra_apks in vm_config_extra_apk.json
-            manifestPath: "/mnt/extra-apk/0/assets/build_manifest.pb".to_string(),
-            prefix: "system/".to_string(),
-        }],
+        inputDirFdAnnotations: input_dir_fd_annotations,
         outputDirFdAnnotations: vec![
             OutputDirFdAnnotation { fd: context.output_dir_fd },
             OutputDirFdAnnotation { fd: context.staging_dir_fd },
@@ -134,6 +149,14 @@
     odrefresh_vars.set("ANDROID_ROOT", path_to_str(&android_root)?);
     debug!("ANDROID_ROOT={:?}", &android_root);
 
+    if let Some(fd) = context.system_ext_dir_fd {
+        let mut system_ext_root = mountpoint.clone();
+        system_ext_root.push(fd.to_string());
+        system_ext_root.push("system_ext");
+        odrefresh_vars.set("SYSTEM_EXT_ROOT", path_to_str(&system_ext_root)?);
+        debug!("SYSTEM_EXT_ROOT={:?}", &system_ext_root);
+    }
+
     let art_apex_data = mountpoint.join(context.output_dir_fd.to_string());
     odrefresh_vars.set("ART_APEX_DATA", path_to_str(&art_apex_data)?);
     debug!("ART_APEX_DATA={:?}", &art_apex_data);
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index baf444e..7ce60cd 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -102,6 +102,7 @@
         &self,
         compilation_mode: CompilationMode,
         system_dir_fd: i32,
+        system_ext_dir_fd: i32,
         output_dir_fd: i32,
         staging_dir_fd: i32,
         target_dir_name: &str,
@@ -119,6 +120,7 @@
         let context = to_binder_result(OdrefreshContext::new(
             compilation_mode,
             system_dir_fd,
+            if system_ext_dir_fd >= 0 { Some(system_ext_dir_fd) } else { None },
             output_dir_fd,
             staging_dir_fd,
             target_dir_name,