Merge changes I95602b2c,Id531da9f

* changes:
  Declare module at top of file rather than bottom.
  Add test for collect_apex_names.
diff --git a/binder_common/lazy_service.rs b/binder_common/lazy_service.rs
index a2b85db..9d605b6 100644
--- a/binder_common/lazy_service.rs
+++ b/binder_common/lazy_service.rs
@@ -17,7 +17,7 @@
 //! Rust API for lazy (aka dynamic) AIDL services.
 //! See https://source.android.com/devices/architecture/aidl/dynamic-aidl.
 
-use binder::public_api::force_lazy_services_persist;
+use binder::force_lazy_services_persist;
 use lazy_static::lazy_static;
 use std::sync::Mutex;
 
diff --git a/binder_common/lib.rs b/binder_common/lib.rs
index fa91f5a..fd81da5 100644
--- a/binder_common/lib.rs
+++ b/binder_common/lib.rs
@@ -20,7 +20,7 @@
 pub mod rpc_client;
 pub mod rpc_server;
 
-use binder::public_api::{ExceptionCode, Status};
+use binder::{ExceptionCode, Status};
 use std::ffi::CString;
 
 /// Constructs a new Binder error `Status` with the given `ExceptionCode` and message.
diff --git a/binder_common/rpc_client.rs b/binder_common/rpc_client.rs
index 262a689..1aabe84 100644
--- a/binder_common/rpc_client.rs
+++ b/binder_common/rpc_client.rs
@@ -16,14 +16,14 @@
 
 //! Helpers for implementing an RPC Binder client.
 
-use binder::public_api::{StatusCode, Strong};
 use binder::unstable_api::{new_spibinder, AIBinder};
+use binder::{StatusCode, Strong};
 
 /// Connects to a binder RPC server.
 pub fn connect_rpc_binder<T: binder::FromIBinder + ?Sized>(
     cid: u32,
     port: u32,
-) -> binder::Result<Strong<T>> {
+) -> Result<Strong<T>, StatusCode> {
     // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can be
     // safely taken by new_spibinder.
     let ibinder = unsafe {
diff --git a/binder_common/rpc_server.rs b/binder_common/rpc_server.rs
index 36075cf..5c9d2a0 100644
--- a/binder_common/rpc_server.rs
+++ b/binder_common/rpc_server.rs
@@ -16,8 +16,8 @@
 
 //! Helpers for implementing an RPC Binder server.
 
-use binder::public_api::SpIBinder;
 use binder::unstable_api::AsNative;
+use binder::SpIBinder;
 use std::os::raw;
 
 /// Run a binder RPC server, serving the supplied binder service implementation on the given vsock
diff --git a/compos/aidl/com/android/compos/FdAnnotation.aidl b/compos/aidl/com/android/compos/FdAnnotation.aidl
deleted file mode 100644
index b910391..0000000
--- a/compos/aidl/com/android/compos/FdAnnotation.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-package com.android.compos;
-
-/** {@hide} */
-parcelable FdAnnotation {
-    /**
-     * Input file descriptor numbers to be passed to the program.  This is currently assumed to be
-     * same as the file descriptor number used in the backend server.
-     */
-    int[] input_fds;
-
-    /**
-     * Output file descriptor numbers to be passed to the program.  This is currently assumed to be
-     * same as the file descriptor number used in the backend server.
-     */
-    int[] output_fds;
-}
diff --git a/compos/aidl/com/android/compos/ICompOsService.aidl b/compos/aidl/com/android/compos/ICompOsService.aidl
index b2b961a..39e9d61 100644
--- a/compos/aidl/com/android/compos/ICompOsService.aidl
+++ b/compos/aidl/com/android/compos/ICompOsService.aidl
@@ -17,7 +17,6 @@
 package com.android.compos;
 
 import com.android.compos.CompOsKeyData;
-import com.android.compos.FdAnnotation;
 
 /** {@hide} */
 interface ICompOsService {
@@ -51,21 +50,6 @@
             String zygoteArch, String systemServerCompilerFilter);
 
     /**
-     * Runs dexopt compilation encoded in the marshaled dexopt arguments.
-     *
-     * To keep ART indepdendantly updatable, the compilation arguments are not stabilized. As a
-     * result, the arguments are marshaled into byte array.  Upon received, the service asks ART to
-     * return relevant information (since ART is able to unmarshal its own encoding), in order to
-     * set up the execution context (mainly file descriptors for compiler input and output) then
-     * invokes the compiler.
-     *
-     * @param marshaledArguments The marshaled dexopt arguments.
-     * @param fd_annotation Additional file descriptor information of the execution.
-     * @return exit code
-     */
-    byte compile(in byte[] marshaledArguments, in FdAnnotation fd_annotation);
-
-    /**
      * Generate a new public/private key pair suitable for signing CompOs output files.
      *
      * @return a certificate for the public key and the encrypted private key
diff --git a/compos/apex/composd.rc b/compos/apex/composd.rc
index bf34335..3e2efb1 100644
--- a/compos/apex/composd.rc
+++ b/compos/apex/composd.rc
@@ -17,6 +17,5 @@
     user root
     group system
     interface aidl android.system.composd
-    interface aidl android.system.composd.internal
     disabled
     oneshot
diff --git a/compos/common/binder.rs b/compos/common/binder.rs
index 6bd3957..ae857e0 100644
--- a/compos/common/binder.rs
+++ b/compos/common/binder.rs
@@ -17,7 +17,7 @@
 //! Helper for converting Error types to what Binder expects
 
 use anyhow::Result;
-use binder::public_api::{ExceptionCode, Result as BinderResult};
+use binder::{ExceptionCode, Result as BinderResult};
 use binder_common::new_binder_exception;
 use log::warn;
 use std::fmt::Debug;
diff --git a/compos/composd/Android.bp b/compos/composd/Android.bp
index 3190395..3b545e5 100644
--- a/compos/composd/Android.bp
+++ b/compos/composd/Android.bp
@@ -9,7 +9,6 @@
     prefer_rlib: true,
     rustlibs: [
         "android.system.composd-rust",
-        "android.system.composd.internal-rust",
         "android.system.virtualizationservice-rust",
         "compos_aidl_interface-rust",
         "libandroid_logger",
diff --git a/compos/composd/aidl/Android.bp b/compos/composd/aidl/Android.bp
index 376313b..56b0b60 100644
--- a/compos/composd/aidl/Android.bp
+++ b/compos/composd/aidl/Android.bp
@@ -19,19 +19,3 @@
         },
     },
 }
-
-aidl_interface {
-    name: "android.system.composd.internal",
-    srcs: ["android/system/composd/internal/*.aidl"],
-    imports: ["compos_aidl_interface"],
-    // TODO: Make this stable when the APEX becomes updatable.
-    unstable: true,
-    backend: {
-        rust: {
-            enabled: true,
-            apex_available: [
-                "com.android.compos",
-            ],
-        },
-    },
-}
diff --git a/compos/composd/aidl/android/system/composd/internal/ICompilationInternal.aidl b/compos/composd/aidl/android/system/composd/internal/ICompilationInternal.aidl
deleted file mode 100644
index a16a0a3..0000000
--- a/compos/composd/aidl/android/system/composd/internal/ICompilationInternal.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2021 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.
- */
-package android.system.composd.internal;
-
-import com.android.compos.FdAnnotation;
-
-interface ICompilationInternal {
-    /**
-     * Run dex2oat in the currently running instance of the CompOS VM. This is a simple proxy
-     * to ICompOsService#compile.
-     *
-     * This method can only be called from libcompos_client. If there is no currently running
-     * instance an error is returned.
-     */
-    byte compile(in byte[] marshaledArguments, in FdAnnotation fd_annotation);
-}
diff --git a/compos/composd/src/composd_main.rs b/compos/composd/src/composd_main.rs
index 6acf470..235c107 100644
--- a/compos/composd/src/composd_main.rs
+++ b/compos/composd/src/composd_main.rs
@@ -21,7 +21,6 @@
 mod fd_server_helper;
 mod instance_manager;
 mod instance_starter;
-mod internal_service;
 mod odrefresh_task;
 mod service;
 
@@ -47,10 +46,6 @@
     register_lazy_service("android.system.composd", composd_service.as_binder())
         .context("Registering composd service")?;
 
-    let internal_service = internal_service::new_binder();
-    register_lazy_service("android.system.composd.internal", internal_service.as_binder())
-        .context("Registering internal service")?;
-
     info!("Registered services, joining threadpool");
     ProcessState::join_thread_pool();
 
diff --git a/compos/composd/src/internal_service.rs b/compos/composd/src/internal_service.rs
deleted file mode 100644
index 33935ef..0000000
--- a/compos/composd/src/internal_service.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-//! Implementation of ICompilationInternal, called from odrefresh during compilation.
-
-use android_system_composd_internal::aidl::android::system::composd::internal::ICompilationInternal::{
-    BnCompilationInternal, ICompilationInternal,
-};
-use android_system_composd::binder::{self, BinderFeatures, Interface, Strong};
-use binder_common::new_binder_service_specific_error;
-use compos_aidl_interface::aidl::com::android::compos::FdAnnotation::FdAnnotation;
-
-pub struct CompilationInternalService {}
-
-pub fn new_binder() -> Strong<dyn ICompilationInternal> {
-    let service = CompilationInternalService {};
-    BnCompilationInternal::new_binder(service, BinderFeatures::default())
-}
-
-impl Interface for CompilationInternalService {}
-
-impl ICompilationInternal for CompilationInternalService {
-    fn compile(&self, _marshaled: &[u8], _fd_annotation: &FdAnnotation) -> binder::Result<i8> {
-        Err(new_binder_service_specific_error(-1, "Not yet implemented"))
-    }
-}
diff --git a/compos/src/compsvc.rs b/compos/src/compsvc.rs
index 356cc7e..b4af9b5 100644
--- a/compos/src/compsvc.rs
+++ b/compos/src/compsvc.rs
@@ -32,7 +32,6 @@
 use authfs_aidl_interface::aidl::com::android::virt::fs::IAuthFsService::IAuthFsService;
 use compos_aidl_interface::aidl::com::android::compos::{
     CompOsKeyData::CompOsKeyData,
-    FdAnnotation::FdAnnotation,
     ICompOsService::{BnCompOsService, ICompOsService},
 };
 use compos_aidl_interface::binder::{
@@ -113,10 +112,6 @@
         Ok(exit_code as i8)
     }
 
-    fn compile(&self, _marshaled: &[u8], _fd_annotation: &FdAnnotation) -> BinderResult<i8> {
-        Err(new_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION, "Not yet implemented"))
-    }
-
     fn generateSigningKey(&self) -> BinderResult<CompOsKeyData> {
         to_binder_result(self.key_service.generate())
     }
diff --git a/compos/tests/java/android/compos/test/ComposTestCase.java b/compos/tests/java/android/compos/test/ComposTestCase.java
index 1e439af..ff3baa2 100644
--- a/compos/tests/java/android/compos/test/ComposTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposTestCase.java
@@ -181,8 +181,8 @@
             throws Exception {
         // Sort by filename (second column) to make comparison easier. Filter out compos.info and
         // compos.info.signature since it's only generated by CompOS.
-        // TODO(b/210473615): Remove irrelevant APEXes (i.e. those aren't contributing to the
-        // classpaths, thus not in the VM) from cache-info.xml.
+        // TODO(b/211458160): Remove cache-info.xml once we can plumb timestamp and isFactory of
+        // APEXes to the VM.
         return runner.run("cd " + path + "; find -type f -exec sha256sum {} \\;"
                 + "| grep -v cache-info.xml | grep -v compos.info"
                 + "| sort -k2");
diff --git a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
index cdcb2bd..208d61f 100644
--- a/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
+++ b/tests/aidl/com/android/microdroid/testservice/ITestService.aidl
@@ -21,4 +21,7 @@
 
     /* add two integers. */
     int addInteger(int a, int b);
+
+    /* read a system property. */
+    String readProperty(String prop);
 }
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index 69638d8..6aa7566 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -97,15 +97,6 @@
         final String label = "u:object_r:system_file:s0";
         assertThat(runOnMicrodroid("ls", "-Z", testLib), is(label + " " + testLib));
 
-        // Check if the command in vm_config.json was executed by examining the side effect of the
-        // command
-        assertThat(runOnMicrodroid("getprop", "debug.microdroid.app.run"), is("true"));
-        assertThat(runOnMicrodroid("getprop", "debug.microdroid.app.sublib.run"), is("true"));
-
-        // Check that keystore was found by the payload. Wait until the property is set.
-        tryRunOnMicrodroid("watch -e \"getprop debug.microdroid.test.keystore | grep '^$'\"");
-        assertThat(runOnMicrodroid("getprop", "debug.microdroid.test.keystore"), is("PASS"));
-
         // Check that no denials have happened so far
         assertThat(runOnMicrodroid("logcat -d -e 'avc:[[:space:]]{1,2}denied'"), is(""));
 
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 32c47dd..6cd16c2 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -9,6 +9,7 @@
     static_libs: [
         "androidx.test.runner",
         "androidx.test.ext.junit",
+        "com.android.microdroid.testservice-java",
     ],
     libs: ["android.system.virtualmachine"],
     jni_libs: ["MicrodroidTestNativeLib"],
@@ -29,6 +30,11 @@
         "libbinder_rpc_unstable",
         "MicrodroidTestNativeLibSub",
     ],
+    static_libs: [
+        "libfsverity_digests_proto_cc",
+        "liblog",
+        "libprotobuf-cpp-lite-ndk",
+    ],
 }
 
 cc_library_shared {
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 b03a915..032ecfd 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -17,8 +17,10 @@
 
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeNoException;
 import static org.junit.Assume.assumeThat;
 
@@ -26,6 +28,7 @@
 
 import android.content.Context;
 import android.os.Build;
+import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
 import android.system.virtualmachine.VirtualMachine;
 import android.system.virtualmachine.VirtualMachineCallback;
@@ -36,6 +39,8 @@
 
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.microdroid.testservice.ITestService;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -49,6 +54,7 @@
 import java.nio.file.Files;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 @RunWith(JUnit4.class)
@@ -132,9 +138,10 @@
     private static final int MIN_MEM_X86_64 = 196;
 
     @Test
-    public void startAndStop() throws VirtualMachineException, InterruptedException {
+    public void connectToVmService() throws VirtualMachineException, InterruptedException {
         VirtualMachineConfig.Builder builder =
-                new VirtualMachineConfig.Builder(mInner.mContext, "assets/vm_config.json");
+                new VirtualMachineConfig.Builder(mInner.mContext,
+                        "assets/vm_config_extra_apk.json");
         if (Build.SUPPORTED_ABIS.length > 0) {
             String primaryAbi = Build.SUPPORTED_ABIS[0];
             switch(primaryAbi) {
@@ -148,24 +155,55 @@
         }
         VirtualMachineConfig config = builder.build();
 
-        mInner.mVm = mInner.mVmm.getOrCreate("test_vm", config);
+        mInner.mVm = mInner.mVmm.getOrCreate("test_vm_extra_apk", config);
         VmEventListener listener =
                 new VmEventListener() {
                     private boolean mPayloadReadyCalled = false;
                     private boolean mPayloadStartedCalled = false;
 
-                    @Override
-                    public void onPayloadStarted(VirtualMachine vm, ParcelFileDescriptor stream) {
-                        mPayloadStartedCalled = true;
+                    private void testVMService(Future<IBinder> service) {
+                        try {
+                            IBinder binder = service.get();
+
+                            ITestService testService = ITestService.Stub.asInterface(binder);
+                            assertEquals(
+                                    testService.addInteger(123, 456),
+                                    123 + 456);
+                            assertEquals(
+                                    testService.readProperty("debug.microdroid.app.run"),
+                                    "true");
+                            assertEquals(
+                                    testService.readProperty("debug.microdroid.app.sublib.run"),
+                                    "true");
+                            assertEquals(
+                                    testService.readProperty("debug.microdroid.test.keystore"),
+                                    "PASS");
+                            assertEquals(
+                                    testService.readProperty("debug.microdroid.test.extra_apk"),
+                                    "PASS");
+                        } catch (Exception e) {
+                            fail("Exception while testing service: " + e.toString());
+                        }
                     }
 
                     @Override
                     public void onPayloadReady(VirtualMachine vm) {
                         mPayloadReadyCalled = true;
+                        try {
+                            testVMService(vm.connectToVsockServer(ITestService.SERVICE_PORT));
+                        } catch (Exception e) {
+                            fail("Exception while connecting to service: " + e.toString());
+                        }
+
                         forceStop(vm);
                     }
 
                     @Override
+                    public void onPayloadStarted(VirtualMachine vm, ParcelFileDescriptor stream) {
+                        mPayloadStartedCalled = true;
+                    }
+
+                    @Override
                     public void onDied(VirtualMachine vm, @DeathReason int reason) {
                         assertTrue(mPayloadReadyCalled);
                         assertTrue(mPayloadStartedCalled);
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index f56b261..c748b2a 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -16,11 +16,14 @@
 #include <aidl/android/system/keystore2/IKeystoreService.h>
 #include <aidl/android/system/virtualmachineservice/IVirtualMachineService.h>
 #include <aidl/com/android/microdroid/testservice/BnTestService.h>
+#include <android-base/file.h>
+#include <android-base/properties.h>
 #include <android-base/result.h>
 #include <android-base/unique_fd.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
 #include <fcntl.h>
+#include <fsverity_digests.pb.h>
 #include <linux/vm_sockets.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -29,6 +32,7 @@
 #include <unistd.h>
 
 #include <binder_rpc_unstable.hpp>
+#include <string>
 
 using aidl::android::hardware::security::keymint::Algorithm;
 using aidl::android::hardware::security::keymint::Digest;
@@ -191,8 +195,8 @@
         outcome << "PASS";
     } else {
         outcome << "FAIL: " << result.error();
-        // Pollute stdout with the error in case the property is truncated.
-        std::cout << "[" << name << "] test failed: " << result.error() << "\n";
+        // Pollute stderr with the error in case the property is truncated.
+        std::cerr << "[" << name << "] test failed: " << result.error() << "\n";
     }
     __system_property_set(property.c_str(), outcome.str().c_str());
     return result;
@@ -204,6 +208,17 @@
             *out = a + b;
             return ndk::ScopedAStatus::ok();
         }
+
+        ndk::ScopedAStatus readProperty(const std::string& prop, std::string* out) override {
+            *out = android::base::GetProperty(prop, "");
+            if (out->empty()) {
+                std::string msg = "cannot find property " + prop;
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_SERVICE_SPECIFIC,
+                                                                        msg.c_str());
+            }
+
+            return ndk::ScopedAStatus::ok();
+        }
     };
     auto testService = ndk::SharedRefBase::make<TestService>();
 
@@ -230,6 +245,21 @@
     return {};
 }
 
+Result<void> verify_apk() {
+    const char* path = "/mnt/extra-apk/0/assets/build_manifest.pb";
+
+    std::string str;
+    if (!android::base::ReadFileToString(path, &str)) {
+        return ErrnoError() << "failed to read build_manifest.pb";
+    }
+
+    if (!android::security::fsverity::FSVerityDigests().ParseFromString(str)) {
+        return Error() << "invalid build_manifest.pb";
+    }
+
+    return {};
+}
+
 } // Anonymous namespace
 
 extern "C" int android_native_main(int argc, char* argv[]) {
@@ -249,6 +279,9 @@
     testlib_sub();
     printf("\n");
 
+    // Extra apks may be missing; this is not a fatal error
+    report_test("extra_apk", verify_apk());
+
     __system_property_set("debug.microdroid.app.run", "true");
     if (!report_test("keystore", test_keystore()).ok()) return 1;