Merge "Add options for configuring number of vCPUs and CPU affinity"
diff --git a/authfs/src/main.rs b/authfs/src/main.rs
index 3bd96f4..18b7b51 100644
--- a/authfs/src/main.rs
+++ b/authfs/src/main.rs
@@ -269,6 +269,7 @@
             Path::new("/system/framework/framework.jar"),
             Path::new("/system/framework/ims-common.jar"),
             Path::new("/system/framework/services.jar"),
+            Path::new("/system/framework/services.jar.prof"),
             Path::new("/system/framework/telephony-common.jar"),
             Path::new("/system/framework/voip-common.jar"),
             Path::new("/system/etc/boot-image.prof"),
diff --git a/compos/aidl/com/android/compos/ICompOsService.aidl b/compos/aidl/com/android/compos/ICompOsService.aidl
index 1a28a18..e3e0317 100644
--- a/compos/aidl/com/android/compos/ICompOsService.aidl
+++ b/compos/aidl/com/android/compos/ICompOsService.aidl
@@ -45,10 +45,11 @@
      * @param targetDirName The sub-directory of the output directory to which artifacts are to be
      *                      written (e.g. dalvik-cache)
      * @param zygoteArch The zygote architecture (ro.zygote)
+     * @param systemServerCompilerFilter The compiler filter used to compile system server
      * @return odrefresh exit code
      */
     byte odrefresh(int systemDirFd, int outputDirFd, int stagingDirFd, String targetDirName,
-            String zygoteArch);
+            String zygoteArch, String systemServerCompilerFilter);
 
     /**
      * Run dex2oat command with provided args, in a context that may be specified in FdAnnotation,
diff --git a/compos/composd/src/odrefresh_task.rs b/compos/composd/src/odrefresh_task.rs
index 56b697e..330f0ab 100644
--- a/compos/composd/src/odrefresh_task.rs
+++ b/compos/composd/src/odrefresh_task.rs
@@ -131,12 +131,15 @@
     let fd_server_raii = fd_server_config.into_fd_server()?;
 
     let zygote_arch = system_properties::read("ro.zygote")?;
+    let system_server_compiler_filter =
+        system_properties::read("dalvik.vm.systemservercompilerfilter").unwrap_or_default();
     let exit_code = service.odrefresh(
         system_dir.as_raw_fd(),
         output_dir.as_raw_fd(),
         staging_dir.as_raw_fd(),
         target_dir_name,
         &zygote_arch,
+        &system_server_compiler_filter,
     )?;
 
     drop(fd_server_raii);
diff --git a/compos/src/compilation.rs b/compos/src/compilation.rs
index af7a9b4..50d79c1 100644
--- a/compos/src/compilation.rs
+++ b/compos/src/compilation.rs
@@ -70,6 +70,7 @@
     staging_dir_fd: i32,
     target_dir_name: &'a str,
     zygote_arch: &'a str,
+    system_server_compiler_filter: &'a str,
 }
 
 impl<'a> OdrefreshContext<'a> {
@@ -79,11 +80,12 @@
         staging_dir_fd: i32,
         target_dir_name: &'a str,
         zygote_arch: &'a str,
+        system_server_compiler_filter: &'a str,
     ) -> Result<Self> {
         if system_dir_fd < 0 || output_dir_fd < 0 || staging_dir_fd < 0 {
             bail!("The remote FDs are expected to be non-negative");
         }
-        if zygote_arch != "zygote64" && zygote_arch != "zygote64_32" {
+        if !matches!(zygote_arch, "zygote64" | "zygote64_32") {
             bail!("Invalid zygote arch");
         }
         // Disallow any sort of path traversal
@@ -91,7 +93,20 @@
             bail!("Invalid target directory {}", target_dir_name);
         }
 
-        Ok(Self { system_dir_fd, output_dir_fd, staging_dir_fd, target_dir_name, zygote_arch })
+        // We're not validating/allowlisting the compiler filter, and just assume the compiler will
+        // reject an invalid string. We need to accept "verify" filter anyway, and potential
+        // performance degration by the attacker is not currently in scope. This also allows ART to
+        // specify new compiler filter and configure through system property without change to
+        // CompOS.
+
+        Ok(Self {
+            system_dir_fd,
+            output_dir_fd,
+            staging_dir_fd,
+            target_dir_name,
+            zygote_arch,
+            system_server_compiler_filter,
+        })
     }
 }
 
@@ -134,14 +149,22 @@
 
     set_classpaths(&android_root)?;
 
-    let args = vec![
+    let mut args = vec![
         "odrefresh".to_string(),
         format!("--zygote-arch={}", context.zygote_arch),
         format!("--dalvik-cache={}", context.target_dir_name),
-        "--no-refresh".to_string(),
         format!("--staging-dir={}", staging_dir.display()),
-        "--force-compile".to_string(),
+        "--no-refresh".to_string(),
     ];
+
+    if !context.system_server_compiler_filter.is_empty() {
+        args.push(format!(
+            "--system-server-compiler-filter={}",
+            context.system_server_compiler_filter
+        ));
+    }
+    args.push("--force-compile".to_string());
+
     debug!("Running odrefresh with args: {:?}", &args);
     let jail = spawn_jailed_task(odrefresh_path, &args, Vec::new() /* fd_mapping */)
         .context("Spawn odrefresh")?;
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index ef3ae2a..5a2c3ca 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -101,6 +101,7 @@
         staging_dir_fd: i32,
         target_dir_name: &str,
         zygote_arch: &str,
+        system_server_compiler_filter: &str,
     ) -> BinderResult<i8> {
         let context = to_binder_result(OdrefreshContext::new(
             system_dir_fd,
@@ -108,6 +109,7 @@
             staging_dir_fd,
             target_dir_name,
             zygote_arch,
+            system_server_compiler_filter,
         ))?;
 
         let authfs_service = get_authfs_service()?;
diff --git a/compos/tests/java/android/compos/test/ComposTestCase.java b/compos/tests/java/android/compos/test/ComposTestCase.java
index 7b027de..1e439af 100644
--- a/compos/tests/java/android/compos/test/ComposTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposTestCase.java
@@ -55,9 +55,20 @@
     // Files that define the "test" instance of CompOS
     private static final String COMPOS_TEST_ROOT = "/data/misc/apexdata/com.android.compos/test/";
 
+    private static final String SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME =
+            "dalvik.vm.systemservercompilerfilter";
+    private String mBackupSystemServerCompilerFilter;
+
     @Before
     public void setUp() throws Exception {
         testIfDeviceIsCapable(getDevice());
+
+        String value = getDevice().getProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME);
+        if (value == null) {
+            mBackupSystemServerCompilerFilter = "";
+        } else {
+            mBackupSystemServerCompilerFilter = value;
+        }
     }
 
     @After
@@ -71,10 +82,28 @@
 
         // And any artifacts generated by odrefresh
         android.tryRun("rm", "-rf", ODREFRESH_OUTPUT_DIR);
+
+        if (mBackupSystemServerCompilerFilter != null) {
+            CLog.d("Restore dalvik.vm.systemservercompilerfilter to "
+                    + mBackupSystemServerCompilerFilter);
+            getDevice().setProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME,
+                    mBackupSystemServerCompilerFilter);
+        }
     }
 
     @Test
-    public void testOdrefresh() throws Exception {
+    public void testOdrefreshSpeed() throws Exception {
+        getDevice().setProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME, "speed");
+        testOdrefresh();
+    }
+
+    @Test
+    public void testOdrefreshSpeedProfile() throws Exception {
+        getDevice().setProperty(SYSTEM_SERVER_COMPILER_FILTER_PROP_NAME, "speed-profile");
+        testOdrefresh();
+    }
+
+    private void testOdrefresh() throws Exception {
         CommandRunner android = new CommandRunner(getDevice());
 
         // Prepare the groundtruth. The compilation on Android should finish successfully.
diff --git a/demo/README.md b/demo/README.md
index 37198ad..43d2ebc 100644
--- a/demo/README.md
+++ b/demo/README.md
@@ -9,10 +9,13 @@
 ## Installing
 
 ```
-adb install out/dist/MicrodroidDemoApp.apk
+adb install -t out/dist/MicrodroidDemoApp.apk
 adb shell pm grant com.android.microdroid.demo android.permission.MANAGE_VIRTUAL_MACHINE
 ```
 
+Don't run the app before granting the permission. Or you will have to uninstall
+the app, and then re-install it.
+
 ## Running
 
 Run the app by touching the icon on the launcher. Press the `run` button to