Merge "Support running protected VMs."
diff --git a/apex/Android.bp b/apex/Android.bp
index bf38860..2194c67 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -47,6 +47,7 @@
     binaries: [
         "fd_server",
         "vm",
+        "compos_key_cmd",
 
         // tools to create composite images
         "mk_cdisk",
diff --git a/compos/Android.bp b/compos/Android.bp
index 858f64c..0cb6894 100644
--- a/compos/Android.bp
+++ b/compos/Android.bp
@@ -66,6 +66,24 @@
     ],
 }
 
+rust_binary {
+    name: "compos_key_service",
+    srcs: ["src/compos_key_service.rs"],
+    edition: "2018",
+    rustlibs: [
+        "compos_aidl_interface-rust",
+        "android.system.keystore2-V1-rust",
+        "android.hardware.security.keymint-V1-rust",
+        "libandroid_logger",
+        "libanyhow",
+        "liblog_rust",
+        "libring",
+        "libscopeguard",
+    ],
+    prefer_rlib: true,
+    apex_available: ["com.android.compos"],
+}
+
 // TODO(b/190503456) Remove this when vm/virtualizationservice generates payload.img from vm_config
 prebuilt_etc {
     name: "compos_payload_config",
diff --git a/compos/aidl/Android.bp b/compos/aidl/Android.bp
index 3639775..07bec09 100644
--- a/compos/aidl/Android.bp
+++ b/compos/aidl/Android.bp
@@ -15,5 +15,10 @@
                 "com.android.compos",
             ],
         },
+        ndk: {
+            apex_available: [
+                "com.android.virt",
+            ],
+        },
     },
 }
diff --git a/compos/aidl/com/android/compos/CompOsKeyData.aidl b/compos/aidl/com/android/compos/CompOsKeyData.aidl
new file mode 100644
index 0000000..381ec0d
--- /dev/null
+++ b/compos/aidl/com/android/compos/CompOsKeyData.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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 CompOsKeyData {
+    /**
+     * Self-signed certificate (X.509 DER) containing the public key.
+     */
+    byte[] certificate;
+
+    /**
+     * Opaque encrypted blob containing the private key and related metadata.
+     */
+    byte[] keyBlob;
+}
diff --git a/compos/aidl/com/android/compos/ICompOsKeyService.aidl b/compos/aidl/com/android/compos/ICompOsKeyService.aidl
new file mode 100644
index 0000000..2ddae58
--- /dev/null
+++ b/compos/aidl/com/android/compos/ICompOsKeyService.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import com.android.compos.CompOsKeyData;
+
+/** {@hide} */
+interface ICompOsKeyService {
+    /**
+     * 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
+     */
+    CompOsKeyData generateSigningKey();
+
+    /**
+     * Check that the supplied encrypted private key is valid for signing CompOs output files, and
+     * corresponds to the public key.
+     *
+     * @param keyBlob The encrypted blob containing the private key, as returned by
+     *                generateSigningKey().
+     * @param publicKey The public key, as a DER encoded RSAPublicKey (RFC 3447 Appendix-A.1.1).
+     * @return whether the inputs are valid and correspond to each other.
+     */
+    boolean verifySigningKey(in byte[] keyBlob, in byte[] publicKey);
+}
diff --git a/compos/apex/Android.bp b/compos/apex/Android.bp
index 3a8f601..95463d0 100644
--- a/compos/apex/Android.bp
+++ b/compos/apex/Android.bp
@@ -36,6 +36,7 @@
     updatable: false,
 
     binaries: [
+        "compos_key_service",
         "compsvc",
         "compsvc_worker",
         "pvm_exec",
diff --git a/compos/compos_key_cmd/Android.bp b/compos/compos_key_cmd/Android.bp
new file mode 100644
index 0000000..e03dfdf
--- /dev/null
+++ b/compos/compos_key_cmd/Android.bp
@@ -0,0 +1,16 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+    name: "compos_key_cmd",
+    srcs: ["compos_key_cmd.cpp"],
+    apex_available: ["com.android.virt"],
+
+    shared_libs: [
+        "compos_aidl_interface-ndk_platform",
+        "libbase",
+        "libbinder_ndk",
+        "libcrypto",
+    ],
+}
diff --git a/compos/compos_key_cmd/compos_key_cmd.cpp b/compos/compos_key_cmd/compos_key_cmd.cpp
new file mode 100644
index 0000000..d98dac5
--- /dev/null
+++ b/compos/compos_key_cmd/compos_key_cmd.cpp
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+#include <aidl/com/android/compos/ICompOsKeyService.h>
+#include <android-base/file.h>
+#include <android-base/result.h>
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+#include <iostream>
+#include <string>
+
+using android::base::Error;
+using android::base::Result;
+
+using aidl::com::android::compos::CompOsKeyData;
+using aidl::com::android::compos::ICompOsKeyService;
+
+static bool writeBytesToFile(const std::vector<uint8_t>& bytes, const std::string& path) {
+    std::string str(bytes.begin(), bytes.end());
+    return android::base::WriteStringToFile(str, path);
+}
+
+static Result<std::vector<uint8_t>> readBytesFromFile(const std::string& path) {
+    std::string str;
+    if (!android::base::ReadFileToString(path, &str)) {
+        return Error() << "Failed to read " << path;
+    }
+    return std::vector<uint8_t>(str.begin(), str.end());
+}
+
+static Result<std::vector<uint8_t>> extractRsaPublicKey(
+        const std::vector<uint8_t>& der_certificate) {
+    auto data = der_certificate.data();
+    bssl::UniquePtr<X509> x509(d2i_X509(nullptr, &data, der_certificate.size()));
+    if (!x509) {
+        return Error() << "Failed to parse certificate";
+    }
+    if (data != der_certificate.data() + der_certificate.size()) {
+        return Error() << "Certificate has unexpected trailing data";
+    }
+
+    bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509.get()));
+    if (EVP_PKEY_base_id(pkey.get()) != EVP_PKEY_RSA) {
+        return Error() << "Subject key is not RSA";
+    }
+    RSA* rsa = EVP_PKEY_get0_RSA(pkey.get());
+    if (!rsa) {
+        return Error() << "Failed to extract RSA key";
+    }
+
+    uint8_t* out = nullptr;
+    int size = i2d_RSAPublicKey(rsa, &out);
+    if (size < 0 || !out) {
+        return Error() << "Failed to convert to RSAPublicKey";
+    }
+
+    bssl::UniquePtr<uint8_t> buffer(out);
+    std::vector<uint8_t> result(out, out + size);
+    return result;
+}
+
+static Result<void> generate(const std::string& blob_file, const std::string& public_key_file) {
+    ndk::SpAIBinder binder(AServiceManager_getService("android.system.composkeyservice"));
+    auto service = ICompOsKeyService::fromBinder(binder);
+    if (!service) {
+        return Error() << "No service";
+    }
+
+    CompOsKeyData key_data;
+    auto status = service->generateSigningKey(&key_data);
+    if (!status.isOk()) {
+        return Error() << "Failed to generate key: " << status.getDescription();
+    }
+
+    auto public_key = extractRsaPublicKey(key_data.certificate);
+    if (!public_key.ok()) {
+        return Error() << "Failed to extract public key from cert: " << public_key.error();
+    }
+    if (!writeBytesToFile(key_data.keyBlob, blob_file)) {
+        return Error() << "Failed to write keyBlob to " << blob_file;
+    }
+
+    if (!writeBytesToFile(public_key.value(), public_key_file)) {
+        return Error() << "Failed to write public key to " << public_key_file;
+    }
+
+    return {};
+}
+
+static Result<bool> verify(const std::string& blob_file, const std::string& public_key_file) {
+    ndk::SpAIBinder binder(AServiceManager_getService("android.system.composkeyservice"));
+    auto service = ICompOsKeyService::fromBinder(binder);
+    if (!service) {
+        return Error() << "No service";
+    }
+
+    auto blob = readBytesFromFile(blob_file);
+    if (!blob.ok()) {
+        return blob.error();
+    }
+
+    auto public_key = readBytesFromFile(public_key_file);
+    if (!public_key.ok()) {
+        return public_key.error();
+    }
+
+    bool result = false;
+    auto status = service->verifySigningKey(blob.value(), public_key.value(), &result);
+    if (!status.isOk()) {
+        return Error() << "Failed to verify key: " << status.getDescription();
+    }
+
+    return result;
+}
+
+int main(int argc, char** argv) {
+    if (argc == 4 && std::string(argv[1]) == "--generate") {
+        auto result = generate(argv[2], argv[3]);
+        if (result.ok()) {
+            return 0;
+        } else {
+            std::cerr << result.error() << '\n';
+        }
+    } else if (argc == 4 && std::string(argv[1]) == "--verify") {
+        auto result = verify(argv[2], argv[3]);
+        if (result.ok()) {
+            if (result.value()) {
+                std::cerr << "Key files are valid.\n";
+                return 0;
+            } else {
+                std::cerr << "Key files are not valid.\n";
+            }
+        } else {
+            std::cerr << result.error() << '\n';
+        }
+    } else {
+        std::cerr << "Usage: \n"
+                  << "  --generate <blob file> <public key file> Generate new key pair and "
+                     "write\n"
+                  << "    the private key blob and public key to the specified files.\n "
+                  << "  --verify <blob file> <public key file> Verify that the content of the\n"
+                  << "    specified private key blob and public key files are valid.\n ";
+    }
+    return 1;
+}
diff --git a/compos/src/compos_key_service.rs b/compos/src/compos_key_service.rs
new file mode 100644
index 0000000..97fd855
--- /dev/null
+++ b/compos/src/compos_key_service.rs
@@ -0,0 +1,196 @@
+// 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.
+
+//! Provides a binder service for key generation & verification for CompOs. We assume we have
+//! access to Keystore in the VM, but not persistent storage; instead the host stores the key
+//! on our behalf via this service.
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    Algorithm::Algorithm, Digest::Digest, KeyParameter::KeyParameter,
+    KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+    SecurityLevel::SecurityLevel, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
+    IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor,
+};
+use anyhow::{anyhow, Context, Result};
+use compos_aidl_interface::aidl::com::android::compos::{
+    CompOsKeyData::CompOsKeyData,
+    ICompOsKeyService::{BnCompOsKeyService, ICompOsKeyService},
+};
+use compos_aidl_interface::binder::{
+    self, add_service, get_interface, BinderFeatures, ExceptionCode, Interface, ProcessState,
+    Status, Strong,
+};
+use log::{info, warn, Level};
+use ring::rand::{SecureRandom, SystemRandom};
+use ring::signature;
+use scopeguard::ScopeGuard;
+use std::ffi::CString;
+use std::sync::Mutex;
+
+const LOG_TAG: &str = "CompOsKeyService";
+const OUR_SERVICE_NAME: &str = "android.system.composkeyservice";
+
+const KEYSTORE_SERVICE_NAME: &str = "android.system.keystore2.IKeystoreService/default";
+const COMPOS_NAMESPACE: i64 = 101;
+const PURPOSE_SIGN: KeyParameter =
+    KeyParameter { tag: Tag::PURPOSE, value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN) };
+const ALGORITHM: KeyParameter =
+    KeyParameter { tag: Tag::ALGORITHM, value: KeyParameterValue::Algorithm(Algorithm::RSA) };
+const PADDING: KeyParameter = KeyParameter {
+    tag: Tag::PADDING,
+    value: KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
+};
+const DIGEST: KeyParameter =
+    KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(Digest::SHA_2_256) };
+const KEY_SIZE: KeyParameter =
+    KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(2048) };
+const EXPONENT: KeyParameter =
+    KeyParameter { tag: Tag::RSA_PUBLIC_EXPONENT, value: KeyParameterValue::LongInteger(65537) };
+const NO_AUTH_REQUIRED: KeyParameter =
+    KeyParameter { tag: Tag::NO_AUTH_REQUIRED, value: KeyParameterValue::BoolValue(true) };
+
+const KEY_DESCRIPTOR: KeyDescriptor =
+    KeyDescriptor { domain: Domain::BLOB, nspace: COMPOS_NAMESPACE, alias: None, blob: None };
+
+struct CompOsKeyService {
+    random: SystemRandom,
+    state: Mutex<State>,
+}
+
+struct State {
+    security_level: Strong<dyn IKeystoreSecurityLevel>,
+}
+
+impl Interface for CompOsKeyService {}
+
+impl ICompOsKeyService for CompOsKeyService {
+    fn generateSigningKey(&self) -> binder::Result<CompOsKeyData> {
+        self.do_generate()
+            .map_err(|e| new_binder_exception(ExceptionCode::ILLEGAL_STATE, e.to_string()))
+    }
+
+    fn verifySigningKey(&self, key_blob: &[u8], public_key: &[u8]) -> binder::Result<bool> {
+        Ok(if let Err(e) = self.do_verify(key_blob, public_key) {
+            warn!("Signing key verification failed: {}", e.to_string());
+            false
+        } else {
+            true
+        })
+    }
+}
+
+/// Constructs a new Binder error `Status` with the given `ExceptionCode` and message.
+fn new_binder_exception<T: AsRef<str>>(exception: ExceptionCode, message: T) -> Status {
+    Status::new_exception(exception, CString::new(message.as_ref()).ok().as_deref())
+}
+
+impl CompOsKeyService {
+    fn new(keystore_service: &Strong<dyn IKeystoreService>) -> Self {
+        Self {
+            random: SystemRandom::new(),
+            state: Mutex::new(State {
+                security_level: keystore_service
+                    .getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT)
+                    .unwrap(),
+            }),
+        }
+    }
+
+    fn security_level(&self) -> Strong<dyn IKeystoreSecurityLevel> {
+        // We need the Mutex because Strong<_> isn't sync. But we don't need to keep it locked
+        // to make the call, once we've cloned the pointer.
+        self.state.lock().unwrap().security_level.clone()
+    }
+
+    fn do_generate(&self) -> Result<CompOsKeyData> {
+        let key_parameters =
+            [PURPOSE_SIGN, ALGORITHM, PADDING, DIGEST, KEY_SIZE, EXPONENT, NO_AUTH_REQUIRED];
+        let attestation_key = None;
+        let flags = 0;
+        let entropy = [];
+
+        let key_metadata = self
+            .security_level()
+            .generateKey(&KEY_DESCRIPTOR, attestation_key, &key_parameters, flags, &entropy)
+            .context("Generating key failed")?;
+
+        if let (Some(certificate), Some(blob)) = (key_metadata.certificate, key_metadata.key.blob) {
+            Ok(CompOsKeyData { certificate, keyBlob: blob })
+        } else {
+            Err(anyhow!("Missing cert or blob"))
+        }
+    }
+
+    fn do_verify(&self, key_blob: &[u8], public_key: &[u8]) -> Result<()> {
+        let mut data = [0u8; 32];
+        self.random.fill(&mut data).context("No random data")?;
+
+        let signature = self.sign(key_blob, &data)?;
+
+        let public_key =
+            signature::UnparsedPublicKey::new(&signature::RSA_PKCS1_2048_8192_SHA256, public_key);
+        public_key.verify(&data, &signature).context("Signature verification failed")?;
+
+        Ok(())
+    }
+
+    fn sign(&self, key_blob: &[u8], data: &[u8]) -> Result<Vec<u8>> {
+        let key_descriptor = KeyDescriptor { blob: Some(key_blob.to_vec()), ..KEY_DESCRIPTOR };
+        let operation_parameters = [PURPOSE_SIGN, ALGORITHM, PADDING, DIGEST];
+        let forced = false;
+
+        let response = self
+            .security_level()
+            .createOperation(&key_descriptor, &operation_parameters, forced)
+            .context("Creating key failed")?;
+        let operation = scopeguard::guard(
+            response.iOperation.ok_or_else(|| anyhow!("No operation created"))?,
+            |op| op.abort().unwrap_or_default(),
+        );
+
+        if response.operationChallenge.is_some() {
+            return Err(anyhow!("Key requires user authorization"));
+        }
+
+        let signature = operation.finish(Some(&data), None).context("Signing failed")?;
+        // Operation has finished, we're no longer responsible for aborting it
+        ScopeGuard::into_inner(operation);
+
+        signature.ok_or_else(|| anyhow!("No signature returned"))
+    }
+}
+
+fn main() -> Result<()> {
+    android_logger::init_once(
+        android_logger::Config::default().with_tag(LOG_TAG).with_min_level(Level::Trace),
+    );
+
+    // We need to start the thread pool for Binder to work properly.
+    ProcessState::start_thread_pool();
+
+    let keystore_service = get_interface::<dyn IKeystoreService>(KEYSTORE_SERVICE_NAME)
+        .context("No Keystore service")?;
+    let service = CompOsKeyService::new(&keystore_service);
+    let service = BnCompOsKeyService::new_binder(service, BinderFeatures::default());
+
+    add_service(OUR_SERVICE_NAME, service.as_binder()).context("Adding service failed")?;
+    info!("It's alive!");
+
+    ProcessState::join_thread_pool();
+
+    Ok(())
+}
diff --git a/launcher/Android.bp b/launcher/Android.bp
index 2c3f093..93cae96 100644
--- a/launcher/Android.bp
+++ b/launcher/Android.bp
@@ -5,5 +5,8 @@
 cc_binary {
     name: "microdroid_launcher",
     srcs: ["main.cpp"],
-    shared_libs: ["libdl"],
+    shared_libs: [
+        "libdl",
+        "libdl_android",
+    ],
 }
diff --git a/launcher/main.cpp b/launcher/main.cpp
index fc9477d..4ecef3f 100644
--- a/launcher/main.cpp
+++ b/launcher/main.cpp
@@ -18,6 +18,24 @@
 
 #include <cstdlib>
 #include <iostream>
+#include <string>
+
+#include <android/dlext.h>
+
+extern "C" {
+enum {
+    ANDROID_NAMESPACE_TYPE_REGULAR = 0,
+    ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
+    ANDROID_NAMESPACE_TYPE_SHARED = 2,
+};
+
+extern struct android_namespace_t* android_create_namespace(
+        const char* name, const char* ld_library_path, const char* default_library_path,
+        uint64_t type, const char* permitted_when_isolated_path,
+        struct android_namespace_t* parent);
+} // extern "C"
+
+static void* load(const std::string& libname);
 
 int main(int argc, char* argv[]) {
     if (argc < 2) {
@@ -27,7 +45,7 @@
     }
 
     const char* libname = argv[1];
-    void* handle = dlopen(libname, RTLD_NOW);
+    void* handle = load(libname);
     if (handle == nullptr) {
         std::cerr << "Failed to load " << libname << ": " << dlerror() << "\n";
         return EXIT_FAILURE;
@@ -42,3 +60,31 @@
 
     return entry(argc - 1, argv + 1);
 }
+
+// Create a new linker namespace whose search path is set to the directory of the library. Then
+// load it from there. Returns the handle to the loaded library if successful. Returns nullptr
+// if failed.
+void* load(const std::string& libname) {
+    // Parent as nullptr means the default namespace
+    android_namespace_t* parent = nullptr;
+    // The search paths of the new namespace are inherited from the parent namespace.
+    const uint64_t type = ANDROID_NAMESPACE_TYPE_SHARED;
+    // The directory of the library is appended to the search paths
+    const std::string libdir = libname.substr(0, libname.find_last_of("/"));
+    const char* ld_library_path = libdir.c_str();
+    const char* default_library_path = libdir.c_str();
+
+    android_namespace_t* new_ns = nullptr;
+    new_ns = android_create_namespace("microdroid_app", ld_library_path, default_library_path, type,
+                                      /* permitted_when_isolated_path */ nullptr, parent);
+    if (new_ns == nullptr) {
+        std::cerr << "Failed to create linker namespace: " << dlerror() << "\n";
+        return nullptr;
+    }
+
+    const android_dlextinfo info = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE,
+            .library_namespace = new_ns,
+    };
+    return android_dlopen_ext(libname.c_str(), RTLD_NOW, &info);
+}
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 55d1eae..f942349 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -23,7 +23,6 @@
     "apex",
     "linkerconfig",
     "second_stage_resources",
-    "postinstall",
 ]
 
 microdroid_symlinks = [
@@ -77,8 +76,6 @@
         "cgroups.json",
         "public.libraries.android.txt",
 
-        "android.system.keystore2-V1-ndk_platform",
-
         // TODO(b/185767624): remove hidl after full keymint support
         "hwservicemanager",
 
@@ -158,7 +155,7 @@
     name: "microdroid_vendor",
     use_avb: true,
     deps: [
-        "android.hardware.security.keymint-service",
+        "android.hardware.security.keymint-service.microdroid",
         "microdroid_fstab",
         "microdroid_precompiled_sepolicy",
         "microdroid_precompiled_sepolicy.plat_sepolicy_and_mapping.sha256",
diff --git a/microdroid/README.md b/microdroid/README.md
index 6d3491c..802e847 100644
--- a/microdroid/README.md
+++ b/microdroid/README.md
@@ -7,7 +7,7 @@
 
 ## Prerequisites
 
-Any 64-bit target (either x86_64 or arm64) is supported. 32-bit target is not
+Any 64-bit target (either x86\_64 or arm64) is supported. 32-bit target is not
 supported. Note that we currently don't support user builds; only userdebug
 builds are supported.
 
@@ -39,7 +39,7 @@
 adb reboot
 ```
 
-If your target is x86_64 (e.g. `aosp_cf_x86_64_phone`), replace `aosp_arm64`
+If your target is x86\_64 (e.g. `aosp_cf_x86_64_phone`), replace `aosp_arm64`
 with `aosp_x86_64`.
 
 ## Building an app
@@ -72,7 +72,7 @@
   "os": {"name": "microdroid"},
   "task": {
     "type": "microdroid_launcher",
-    "command": "MyMicrodroidApp.so",
+    "command": "MyMicrodroidApp.so"
   },
   "apexes": [
     {"name": "com.android.adbd"},
@@ -107,9 +107,9 @@
 Finally, you build and sign the APK.
 
 ```sh
-TARGET_BUILD_APPS=MyMicrodroidApp m dist
+TARGET_BUILD_APPS=MyApp m dist
 m apksigner
-apksigner sign --ks path_to_keystore out/dist/MyMicrodroidApp.apk
+apksigner sign --ks path_to_keystore out/dist/MyApp.apk
 ```
 
 `path_to_keystore` should be replaced with the actual path to the keystore,
@@ -127,7 +127,7 @@
 First of all, install the signed APK to the target device.
 
 ```sh
-adb install out/dist/MyMicrodroidApp.apk
+adb install out/dist/MyApp.apk
 ```
 
 ### Creating `payload.img` manually (temporary step)
@@ -148,8 +148,9 @@
     "com.android.sdkext"
   ],
   "apk": {
-    "name": "PACKAGE_NAME_OF_YOUR_APP"
+    "name": "PACKAGE_NAME_OF_YOUR_APP",
     "path": "PATH_TO_YOUR_APP",
+    "idsig_path": "PATH_TO_APK_IDSIG"
   }
 }
 ```
@@ -169,12 +170,16 @@
 It shall report a cryptic path similar to
 `/data/app/~~OgZq==/com.acme.app-HudMahQ==/base.apk`.
 
+* `PATH_TO_APK_IDSIG`: path to the pushed APK idsig on the device. See below
+  `adb push` command: it will be `/data/local/tmp/virt/MyApp.apk.idsig` in this
+  example.
+
 Once the file is done, execute the following command to push it to the device
 and run `mk_payload` to create `payload.img`:
 
 ```sh
 TEST_ROOT=/data/local/tmp/virt
-adb push out/dist/MyMicrodroidApp.apk.idsig $TEST_ROOT/MyMicrodroidApp.apk.idsig
+adb push out/dist/MyApp.apk.idsig $TEST_ROOT/MyApp.apk.idsig
 adb push path_to_payload.json $TEST_ROOT/payload.json
 adb shell /apex/com.android.virt/bin/my_payload $TEST_ROOT/payload.json $TEST_ROOT/payload.img
 adb shell chmod go+r $TEST_ROOT/payload*
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 4410b82..b683230 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -101,7 +101,7 @@
     start keystore2
 
 on late-fs
-    start vendor.keymint-default
+    start vendor.keymint-microdroid
 
     # TODO(b/185767624): change the hard-coded size?
     mount tmpfs tmpfs /data noatime nosuid nodev rw size=128M
diff --git a/microdroid/keymint/Android.bp b/microdroid/keymint/Android.bp
new file mode 100644
index 0000000..5a87145
--- /dev/null
+++ b/microdroid/keymint/Android.bp
@@ -0,0 +1,37 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+    name: "android.hardware.security.keymint-service.microdroid",
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.security.keymint-service.microdroid.rc"],
+    vintf_fragments: [
+        "android.hardware.security.keymint-service.microdroid.xml",
+    ],
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "android.hardware.security.keymint-V1-ndk_platform",
+        "lib_android_keymaster_keymint_utils",
+        "libbase",
+        "libbinder_ndk",
+        "libcppbor_external",
+        "libcrypto",
+        "libkeymaster_portable",
+        "libkeymint",
+        "liblog",
+        "libpuresoftkeymasterdevice",
+        "libutils",
+    ],
+    local_include_dirs: [
+        "include",
+    ],
+    srcs: [
+        "MicrodroidKeyMintDevice.cpp",
+        "service.cpp",
+    ],
+}
diff --git a/microdroid/keymint/MicrodroidKeyMintDevice.cpp b/microdroid/keymint/MicrodroidKeyMintDevice.cpp
new file mode 100644
index 0000000..62d6942
--- /dev/null
+++ b/microdroid/keymint/MicrodroidKeyMintDevice.cpp
@@ -0,0 +1,472 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include "MicrodroidKeyMintDevice.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <android-base/logging.h>
+#include <keymaster/android_keymaster.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include "AndroidKeyMintOperation.h"
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using namespace keymaster; // NOLINT(google-build-using-namespace)
+
+using km_utils::authToken2AidlVec;
+using km_utils::kmBlob2vector;
+using km_utils::kmError2ScopedAStatus;
+using km_utils::kmParam2Aidl;
+using km_utils::KmParamSet;
+using km_utils::kmParamSet2Aidl;
+using km_utils::legacy_enum_conversion;
+using secureclock::TimeStampToken;
+
+namespace {
+
+vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecurityLevel,
+                                                     const AuthorizationSet& requestParams,
+                                                     const AuthorizationSet& sw_enforced,
+                                                     const AuthorizationSet& hw_enforced,
+                                                     bool include_keystore_enforced = true) {
+    KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};
+
+    if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
+        // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
+        keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
+        if (include_keystore_enforced) {
+            // Put all the software authorizations in the keystore list.
+            KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
+                                                kmParamSet2Aidl(sw_enforced)};
+            return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
+        } else {
+            return {std::move(keyMintEnforced)};
+        }
+    }
+
+    KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
+    CHECK(hw_enforced.empty()) << "Hardware-enforced list is non-empty for pure SW KeyMint";
+
+    // This is a pure software implementation, so all tags are in sw_enforced.
+    // We need to walk through the SW-enforced list and figure out which tags to
+    // return in the software list and which in the keystore list.
+
+    for (auto& entry : sw_enforced) {
+        switch (entry.tag) {
+            /* Invalid and unused */
+            case KM_TAG_ECIES_SINGLE_HASH_MODE:
+            case KM_TAG_INVALID:
+            case KM_TAG_KDF:
+            case KM_TAG_ROLLBACK_RESISTANCE:
+                CHECK(false) << "We shouldn't see tag " << entry.tag;
+                break;
+
+            /* Unimplemented */
+            case KM_TAG_ALLOW_WHILE_ON_BODY:
+            case KM_TAG_BOOTLOADER_ONLY:
+            case KM_TAG_EARLY_BOOT_ONLY:
+            case KM_TAG_ROLLBACK_RESISTANT:
+            case KM_TAG_STORAGE_KEY:
+            case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+            case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+                break;
+
+            /* Keystore-enforced if not locally generated. */
+            case KM_TAG_CREATION_DATETIME:
+                // A KeyMaster implementation is required to add this tag to generated/imported
+                // keys. A KeyMint implementation is not required to create this tag, only to echo
+                // it back if it was included in the key generation/import request.
+                if (requestParams.Contains(KM_TAG_CREATION_DATETIME)) {
+                    keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+                }
+                break;
+
+            /* Disallowed in KeyCharacteristics */
+            case KM_TAG_APPLICATION_DATA:
+            case KM_TAG_ATTESTATION_APPLICATION_ID:
+                break;
+
+            /* Not key characteristics */
+            case KM_TAG_ASSOCIATED_DATA:
+            case KM_TAG_ATTESTATION_CHALLENGE:
+            case KM_TAG_ATTESTATION_ID_BRAND:
+            case KM_TAG_ATTESTATION_ID_DEVICE:
+            case KM_TAG_ATTESTATION_ID_IMEI:
+            case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+            case KM_TAG_ATTESTATION_ID_MEID:
+            case KM_TAG_ATTESTATION_ID_MODEL:
+            case KM_TAG_ATTESTATION_ID_PRODUCT:
+            case KM_TAG_ATTESTATION_ID_SERIAL:
+            case KM_TAG_AUTH_TOKEN:
+            case KM_TAG_CERTIFICATE_SERIAL:
+            case KM_TAG_CERTIFICATE_SUBJECT:
+            case KM_TAG_CERTIFICATE_NOT_AFTER:
+            case KM_TAG_CERTIFICATE_NOT_BEFORE:
+            case KM_TAG_CONFIRMATION_TOKEN:
+            case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+            case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+            case KM_TAG_MAC_LENGTH:
+            case KM_TAG_NONCE:
+            case KM_TAG_RESET_SINCE_ID_ROTATION:
+            case KM_TAG_ROOT_OF_TRUST:
+            case KM_TAG_UNIQUE_ID:
+                break;
+
+            /* KeyMint-enforced */
+            case KM_TAG_ALGORITHM:
+            case KM_TAG_APPLICATION_ID:
+            case KM_TAG_AUTH_TIMEOUT:
+            case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+            case KM_TAG_BLOCK_MODE:
+            case KM_TAG_BOOT_PATCHLEVEL:
+            case KM_TAG_CALLER_NONCE:
+            case KM_TAG_DIGEST:
+            case KM_TAG_EC_CURVE:
+            case KM_TAG_EXPORTABLE:
+            case KM_TAG_INCLUDE_UNIQUE_ID:
+            case KM_TAG_KEY_SIZE:
+            case KM_TAG_MAX_USES_PER_BOOT:
+            case KM_TAG_MIN_MAC_LENGTH:
+            case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+            case KM_TAG_NO_AUTH_REQUIRED:
+            case KM_TAG_ORIGIN:
+            case KM_TAG_OS_PATCHLEVEL:
+            case KM_TAG_OS_VERSION:
+            case KM_TAG_PADDING:
+            case KM_TAG_PURPOSE:
+            case KM_TAG_RSA_OAEP_MGF_DIGEST:
+            case KM_TAG_RSA_PUBLIC_EXPONENT:
+            case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+            case KM_TAG_USER_AUTH_TYPE:
+            case KM_TAG_USER_SECURE_ID:
+            case KM_TAG_VENDOR_PATCHLEVEL:
+                keyMintEnforced.authorizations.push_back(kmParam2Aidl(entry));
+                break;
+
+            /* Keystore-enforced */
+            case KM_TAG_ACTIVE_DATETIME:
+            case KM_TAG_ALL_APPLICATIONS:
+            case KM_TAG_ALL_USERS:
+            case KM_TAG_MAX_BOOT_LEVEL:
+            case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
+            case KM_TAG_USAGE_EXPIRE_DATETIME:
+            case KM_TAG_USER_ID:
+            case KM_TAG_USAGE_COUNT_LIMIT:
+                keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+                break;
+        }
+    }
+
+    vector<KeyCharacteristics> retval;
+    retval.reserve(2);
+    if (!keyMintEnforced.authorizations.empty()) retval.push_back(std::move(keyMintEnforced));
+    if (include_keystore_enforced && !keystoreEnforced.authorizations.empty()) {
+        retval.push_back(std::move(keystoreEnforced));
+    }
+
+    return retval;
+}
+
+Certificate convertCertificate(const keymaster_blob_t& cert) {
+    return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
+}
+
+vector<Certificate> convertCertificateChain(const CertificateChain& chain) {
+    vector<Certificate> retval;
+    retval.reserve(chain.entry_count);
+    std::transform(chain.begin(), chain.end(), std::back_inserter(retval), convertCertificate);
+    return retval;
+}
+
+void addClientAndAppData(const std::vector<uint8_t>& appId, const std::vector<uint8_t>& appData,
+                         ::keymaster::AuthorizationSet* params) {
+    params->Clear();
+    if (appId.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_ID, appId.data(), appId.size());
+    }
+    if (appData.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
+    }
+}
+
+} // namespace
+
+constexpr size_t kOperationTableSize = 16;
+
+MicrodroidKeyMintDevice::MicrodroidKeyMintDevice(SecurityLevel securityLevel)
+      : impl_(new ::keymaster::AndroidKeymaster(
+                [&]() -> auto {
+                    auto context =
+                            new PureSoftKeymasterContext(KmVersion::KEYMINT_1,
+                                                         static_cast<keymaster_security_level_t>(
+                                                                 securityLevel));
+                    context->SetSystemVersion(::keymaster::GetOsVersion(),
+                                              ::keymaster::GetOsPatchlevel());
+                    return context;
+                }(),
+                kOperationTableSize)),
+        securityLevel_(securityLevel) {}
+
+MicrodroidKeyMintDevice::~MicrodroidKeyMintDevice() {}
+
+ScopedAStatus MicrodroidKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
+    info->versionNumber = 1;
+    info->securityLevel = securityLevel_;
+    info->keyMintName = "FakeKeyMintDevice";
+    info->keyMintAuthorName = "Google";
+    info->timestampTokenRequired = false;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
+    if (data.size() == 0) {
+        return ScopedAStatus::ok();
+    }
+
+    AddEntropyRequest request(impl_->message_version());
+    request.random_data.Reinitialize(data.data(), data.size());
+
+    AddEntropyResponse response(impl_->message_version());
+    impl_->AddRngEntropy(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::generateKey(const vector<KeyParameter>& keyParams,
+                                                   const optional<AttestationKey>& attestationKey,
+                                                   KeyCreationResult* creationResult) {
+    GenerateKeyRequest request(impl_->message_version());
+    request.key_description.Reinitialize(KmParamSet(keyParams));
+    if (attestationKey) {
+        request.attestation_signing_key_blob =
+                KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+        request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
+        request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
+                                               attestationKey->issuerSubjectName.size());
+    }
+
+    GenerateKeyResponse response(impl_->message_version());
+    impl_->GenerateKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        // Note a key difference between this current aidl and previous hal, is
+        // that hal returns void where as aidl returns the error status.  If
+        // aidl returns error, then aidl will not return any change you may make
+        // to the out parameters.  This is quite different from hal where all
+        // output variable can be modified due to hal returning void.
+        //
+        // So the caller need to be aware not to expect aidl functions to clear
+        // the output variables for you in case of error.  If you left some
+        // wrong data set in the out parameters, they will stay there.
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    creationResult->keyBlob = kmBlob2vector(response.key_blob);
+    creationResult->keyCharacteristics =
+            convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
+                                      response.enforced);
+    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::importKey(const vector<KeyParameter>& keyParams,
+                                                 KeyFormat keyFormat,
+                                                 const vector<uint8_t>& keyData,
+                                                 const optional<AttestationKey>& attestationKey,
+                                                 KeyCreationResult* creationResult) {
+    ImportKeyRequest request(impl_->message_version());
+    request.key_description.Reinitialize(KmParamSet(keyParams));
+    request.key_format = legacy_enum_conversion(keyFormat);
+    request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
+    if (attestationKey) {
+        request.attestation_signing_key_blob =
+                KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+        request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
+        request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
+                                               attestationKey->issuerSubjectName.size());
+    }
+
+    ImportKeyResponse response(impl_->message_version());
+    impl_->ImportKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    creationResult->keyBlob = kmBlob2vector(response.key_blob);
+    creationResult->keyCharacteristics =
+            convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
+                                      response.enforced);
+    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::importWrappedKey(
+        const vector<uint8_t>& wrappedKeyData,        //
+        const vector<uint8_t>& wrappingKeyBlob,       //
+        const vector<uint8_t>& maskingKey,            //
+        const vector<KeyParameter>& unwrappingParams, //
+        int64_t passwordSid, int64_t biometricSid,    //
+        KeyCreationResult* creationResult) {
+    ImportWrappedKeyRequest request(impl_->message_version());
+    request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
+    request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
+    request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
+    request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
+    request.password_sid = static_cast<uint64_t>(passwordSid);
+    request.biometric_sid = static_cast<uint64_t>(biometricSid);
+
+    ImportWrappedKeyResponse response(impl_->message_version());
+    impl_->ImportWrappedKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    creationResult->keyBlob = kmBlob2vector(response.key_blob);
+    creationResult->keyCharacteristics =
+            convertKeyCharacteristics(securityLevel_, request.additional_params,
+                                      response.unenforced, response.enforced);
+    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+                                                  const vector<KeyParameter>& upgradeParams,
+                                                  vector<uint8_t>* keyBlob) {
+    UpgradeKeyRequest request(impl_->message_version());
+    request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+    request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+    UpgradeKeyResponse response(impl_->message_version());
+    impl_->UpgradeKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    *keyBlob = kmBlob2vector(response.upgraded_key);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
+    DeleteKeyRequest request(impl_->message_version());
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+    DeleteKeyResponse response(impl_->message_version());
+    impl_->DeleteKey(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::deleteAllKeys() {
+    // There's nothing to be done to delete software key blobs.
+    DeleteAllKeysRequest request(impl_->message_version());
+    DeleteAllKeysResponse response(impl_->message_version());
+    impl_->DeleteAllKeys(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::destroyAttestationIds() {
+    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+                                             const vector<KeyParameter>& params,
+                                             const optional<HardwareAuthToken>& authToken,
+                                             BeginResult* result) {
+    BeginOperationRequest request(impl_->message_version());
+    request.purpose = legacy_enum_conversion(purpose);
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+    request.additional_params.Reinitialize(KmParamSet(params));
+
+    vector<uint8_t> vector_token = authToken2AidlVec(authToken);
+    request.additional_params.push_back(TAG_AUTH_TOKEN,
+                                        reinterpret_cast<uint8_t*>(vector_token.data()),
+                                        vector_token.size());
+
+    BeginOperationResponse response(impl_->message_version());
+    impl_->BeginOperation(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    result->params = kmParamSet2Aidl(response.output_params);
+    result->challenge = response.op_handle;
+    result->operation =
+            ndk::SharedRefBase::make<AndroidKeyMintOperation>(impl_, response.op_handle);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::deviceLocked(
+        bool passwordOnly, const std::optional<secureclock::TimeStampToken>& timestampToken) {
+    DeviceLockedRequest request(impl_->message_version());
+    request.passwordOnly = passwordOnly;
+    if (timestampToken.has_value()) {
+        request.token.challenge = timestampToken->challenge;
+        request.token.mac = {timestampToken->mac.data(), timestampToken->mac.size()};
+        request.token.timestamp = timestampToken->timestamp.milliSeconds;
+    }
+    DeviceLockedResponse response = impl_->DeviceLocked(request);
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::earlyBootEnded() {
+    EarlyBootEndedResponse response = impl_->EarlyBootEnded();
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::convertStorageKeyToEphemeral(
+        const std::vector<uint8_t>& /* storageKeyBlob */,
+        std::vector<uint8_t>* /* ephemeralKeyBlob */) {
+    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::getKeyCharacteristics(
+        const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
+        const std::vector<uint8_t>& appData, std::vector<KeyCharacteristics>* keyCharacteristics) {
+    GetKeyCharacteristicsRequest request(impl_->message_version());
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+    addClientAndAppData(appId, appData, &request.additional_params);
+
+    GetKeyCharacteristicsResponse response(impl_->message_version());
+    impl_->GetKeyCharacteristics(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    AuthorizationSet emptySet;
+    *keyCharacteristics = convertKeyCharacteristics(securityLevel_, emptySet, response.unenforced,
+                                                    response.enforced,
+                                                    /* include_keystore_enforced = */ false);
+
+    return ScopedAStatus::ok();
+}
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel) {
+    return ::new MicrodroidKeyMintDevice(securityLevel);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/microdroid/keymint/android.hardware.security.keymint-service.microdroid.rc b/microdroid/keymint/android.hardware.security.keymint-service.microdroid.rc
new file mode 100644
index 0000000..d6851bd
--- /dev/null
+++ b/microdroid/keymint/android.hardware.security.keymint-service.microdroid.rc
@@ -0,0 +1,3 @@
+service vendor.keymint-microdroid /vendor/bin/hw/android.hardware.security.keymint-service.microdroid
+    class early_hal
+    user nobody
diff --git a/microdroid/keymint/android.hardware.security.keymint-service.microdroid.xml b/microdroid/keymint/android.hardware.security.keymint-service.microdroid.xml
new file mode 100644
index 0000000..73d15a8
--- /dev/null
+++ b/microdroid/keymint/android.hardware.security.keymint-service.microdroid.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.security.keymint</name>
+        <fqname>IKeyMintDevice/default</fqname>
+    </hal>
+</manifest>
diff --git a/microdroid/keymint/include/MicrodroidKeyMintDevice.h b/microdroid/keymint/include/MicrodroidKeyMintDevice.h
new file mode 100644
index 0000000..34d09bf
--- /dev/null
+++ b/microdroid/keymint/include/MicrodroidKeyMintDevice.h
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::keymint {
+using ::ndk::ScopedAStatus;
+using std::optional;
+using std::shared_ptr;
+using std::vector;
+
+using secureclock::TimeStampToken;
+
+class MicrodroidKeyMintDevice : public BnKeyMintDevice {
+public:
+    explicit MicrodroidKeyMintDevice(SecurityLevel securityLevel);
+    virtual ~MicrodroidKeyMintDevice();
+
+    ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
+
+    ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
+
+    ScopedAStatus generateKey(const vector<KeyParameter>& keyParams,
+                              const optional<AttestationKey>& attestationKey,
+                              KeyCreationResult* creationResult) override;
+
+    ScopedAStatus importKey(const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
+                            const vector<uint8_t>& keyData,
+                            const optional<AttestationKey>& attestationKey,
+                            KeyCreationResult* creationResult) override;
+
+    ScopedAStatus importWrappedKey(const vector<uint8_t>& wrappedKeyData,
+                                   const vector<uint8_t>& wrappingKeyBlob,
+                                   const vector<uint8_t>& maskingKey,
+                                   const vector<KeyParameter>& unwrappingParams,
+                                   int64_t passwordSid, int64_t biometricSid,
+                                   KeyCreationResult* creationResult) override;
+
+    ScopedAStatus upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+                             const vector<KeyParameter>& upgradeParams,
+                             vector<uint8_t>* keyBlob) override;
+
+    ScopedAStatus deleteKey(const vector<uint8_t>& keyBlob) override;
+    ScopedAStatus deleteAllKeys() override;
+    ScopedAStatus destroyAttestationIds() override;
+
+    ScopedAStatus begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+                        const vector<KeyParameter>& params,
+                        const optional<HardwareAuthToken>& authToken, BeginResult* result) override;
+
+    ScopedAStatus deviceLocked(bool passwordOnly,
+                               const optional<TimeStampToken>& timestampToken) override;
+    ScopedAStatus earlyBootEnded() override;
+
+    ScopedAStatus convertStorageKeyToEphemeral(const std::vector<uint8_t>& storageKeyBlob,
+                                               std::vector<uint8_t>* ephemeralKeyBlob) override;
+
+    ScopedAStatus getKeyCharacteristics(
+            const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
+            const std::vector<uint8_t>& appData,
+            std::vector<KeyCharacteristics>* keyCharacteristics) override;
+
+    shared_ptr<::keymaster::AndroidKeymaster>& getKeymasterImpl() { return impl_; }
+
+protected:
+    std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
+    SecurityLevel securityLevel_;
+};
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel);
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/microdroid/keymint/service.cpp b/microdroid/keymint/service.cpp
new file mode 100644
index 0000000..8467b33
--- /dev/null
+++ b/microdroid/keymint/service.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-service"
+
+#include <AndroidKeyMintDevice.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <keymaster/soft_keymaster_logger.h>
+
+#include "MicrodroidKeyMintDevice.h"
+
+using aidl::android::hardware::security::keymint::MicrodroidKeyMintDevice;
+using aidl::android::hardware::security::keymint::SecurityLevel;
+
+template <typename T, class... Args>
+std::shared_ptr<T> addService(Args&&... args) {
+    std::shared_ptr<T> ser = ndk::SharedRefBase::make<T>(std::forward<Args>(args)...);
+    auto instanceName = std::string(T::descriptor) + "/default";
+    LOG(INFO) << "adding keymint service instance: " << instanceName;
+    binder_status_t status =
+            AServiceManager_addService(ser->asBinder().get(), instanceName.c_str());
+    CHECK(status == STATUS_OK);
+    return ser;
+}
+
+int main() {
+    // Zero threads seems like a useless pool, but below we'll join this thread to it, increasing
+    // the pool size to 1.
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    // Add Keymint Service
+    std::shared_ptr<MicrodroidKeyMintDevice> keyMint =
+            addService<MicrodroidKeyMintDevice>(SecurityLevel::SOFTWARE);
+
+    // VMs cannot implement the Secure Clock Service
+    // addService<AndroidSecureClock>(keyMint);
+
+    // VMs don't need to implement the Shared Secret Service as the host
+    // facilities the establishment of the shared secret.
+    // addService<AndroidSharedSecret>(keyMint);
+
+    // VMs don't implement the Remotely Provisioned Component Service as the
+    // host facilities provisioning.
+    // addService<AndroidRemotelyProvisionedComponentDevice>(keyMint);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE; // should not reach
+}
diff --git a/microdroid/microdroid_compatibility_matrix.xml b/microdroid/microdroid_compatibility_matrix.xml
index 7293d22..dbc12a8 100644
--- a/microdroid/microdroid_compatibility_matrix.xml
+++ b/microdroid/microdroid_compatibility_matrix.xml
@@ -6,30 +6,6 @@
         <interface>
             <name>IKeyMintDevice</name>
             <instance>default</instance>
-            <instance>strongbox</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.security.keymint</name>
-        <interface>
-            <name>IRemotelyProvisionedComponent</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.security.secureclock</name>
-        <version>1</version>
-        <interface>
-            <name>ISecureClock</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="aidl" optional="true">
-        <name>android.hardware.security.sharedsecret</name>
-        <version>1</version>
-        <interface>
-            <name>ISharedSecret</name>
-            <instance>default</instance>
         </interface>
     </hal>
 </compatibility-matrix>
diff --git a/microdroid/sepolicy/system/private/domain.te b/microdroid/sepolicy/system/private/domain.te
index 4a59f73..e979f3e 100644
--- a/microdroid/sepolicy/system/private/domain.te
+++ b/microdroid/sepolicy/system/private/domain.te
@@ -216,7 +216,7 @@
     -appdomain # for oemfs
     -bootanim # for oemfs
     -recovery # for /tmp/update_binary in tmpfs
-    -microdroid_launcher -microdroid_manager # for executing shared libs on /mnt/apk in Microdroid
+    -microdroid_app -microdroid_manager # for executing shared libs on /mnt/apk in Microdroid
 } { fs_type -rootfs }:file execute;
 
 #
diff --git a/microdroid/sepolicy/system/private/file_contexts b/microdroid/sepolicy/system/private/file_contexts
index c4b4b2c..4318bb0 100644
--- a/microdroid/sepolicy/system/private/file_contexts
+++ b/microdroid/sepolicy/system/private/file_contexts
@@ -1,33 +1,19 @@
-# This is a copy of system/sepolicy/private/file_contexts to build microdroid.img.
-# TODO(inseob): Remove unnecessary entries after experiment
-
 ###########################################
 # Root
 /                   u:object_r:rootfs:s0
 
 # Data files
-/adb_keys           u:object_r:adb_keys_file:s0
 /build\.prop        u:object_r:rootfs:s0
-/default\.prop      u:object_r:rootfs:s0
-/fstab\..*          u:object_r:rootfs:s0
 /init\..*           u:object_r:rootfs:s0
-/res(/.*)?          u:object_r:rootfs:s0
-/selinux_version    u:object_r:rootfs:s0
-/ueventd\..*        u:object_r:rootfs:s0
-/verity_key         u:object_r:rootfs:s0
 
 # Executables
 /init               u:object_r:init_exec:s0
-/sbin(/.*)?         u:object_r:rootfs:s0
 
 # For kernel modules
 /lib(/.*)?          u:object_r:rootfs:s0
 
 # Empty directories
 /lost\+found        u:object_r:rootfs:s0
-/acct               u:object_r:cgroup:s0
-/config             u:object_r:rootfs:s0
-/data_mirror        u:object_r:mirror_data_file:s0
 /debug_ramdisk      u:object_r:tmpfs:s0
 /mnt                u:object_r:tmpfs:s0
 /proc               u:object_r:rootfs:s0
@@ -35,170 +21,69 @@
 /sys                u:object_r:sysfs:s0
 /apex               u:object_r:apex_mnt_dir:s0
 
-# Postinstall directories
-/postinstall         u:object_r:postinstall_mnt_dir:s0
-/postinstall/apex    u:object_r:postinstall_apex_mnt_dir:s0
-
 /apex/(\.(bootstrap|default)-)?apex-info-list.xml u:object_r:apex_info_file:s0
 
 # Symlinks
 /bin                u:object_r:rootfs:s0
-/bugreports         u:object_r:rootfs:s0
-/charger            u:object_r:rootfs:s0
 /d                  u:object_r:rootfs:s0
 /etc                u:object_r:rootfs:s0
-/sdcard             u:object_r:rootfs:s0
-
-# SELinux policy files
-/vendor_file_contexts   u:object_r:file_contexts_file:s0
-/nonplat_file_contexts  u:object_r:file_contexts_file:s0
-/plat_file_contexts     u:object_r:file_contexts_file:s0
-/product_file_contexts  u:object_r:file_contexts_file:s0
-/mapping_sepolicy\.cil   u:object_r:sepolicy_file:s0
-/nonplat_sepolicy\.cil   u:object_r:sepolicy_file:s0
-/plat_sepolicy\.cil      u:object_r:sepolicy_file:s0
-/plat_property_contexts  u:object_r:property_contexts_file:s0
-/product_property_contexts  u:object_r:property_contexts_file:s0
-/nonplat_property_contexts  u:object_r:property_contexts_file:s0
-/vendor_property_contexts   u:object_r:property_contexts_file:s0
-/seapp_contexts     u:object_r:seapp_contexts_file:s0
-/nonplat_seapp_contexts     u:object_r:seapp_contexts_file:s0
-/vendor_seapp_contexts      u:object_r:seapp_contexts_file:s0
-/plat_seapp_contexts     u:object_r:seapp_contexts_file:s0
-/sepolicy           u:object_r:sepolicy_file:s0
-/plat_service_contexts   u:object_r:service_contexts_file:s0
-/plat_hwservice_contexts   u:object_r:hwservice_contexts_file:s0
-/plat_keystore2_key_contexts u:object_r:keystore2_key_contexts_file:s0
-/nonplat_service_contexts   u:object_r:nonplat_service_contexts_file:s0
-# Use nonplat_service_contexts_file to allow servicemanager to read it
-# on non full-treble devices.
-/vendor_service_contexts    u:object_r:nonplat_service_contexts_file:s0
-/nonplat_hwservice_contexts   u:object_r:hwservice_contexts_file:s0
-/vendor_hwservice_contexts    u:object_r:hwservice_contexts_file:s0
-/vndservice_contexts   u:object_r:vndservice_contexts_file:s0
 
 ##########################
 # Devices
 #
 /dev(/.*)?		u:object_r:device:s0
-/dev/adf[0-9]*		u:object_r:graphics_device:s0
-/dev/adf-interface[0-9]*\.[0-9]*	u:object_r:graphics_device:s0
-/dev/adf-overlay-engine[0-9]*\.[0-9]*	u:object_r:graphics_device:s0
 /dev/ashmem		u:object_r:ashmem_device:s0
 /dev/ashmem(.*)?	u:object_r:ashmem_libcutils_device:s0
-/dev/audio.*		u:object_r:audio_device:s0
 /dev/binder		u:object_r:binder_device:s0
 /dev/block(/.*)?	u:object_r:block_device:s0
 /dev/block/dm-[0-9]+	u:object_r:dm_device:s0
 /dev/block/loop[0-9]*	u:object_r:loop_device:s0
 /dev/block/vd[a-z][0-9]*  u:object_r:vd_device:s0
-/dev/block/vold/.+	u:object_r:vold_device:s0
 /dev/block/ram[0-9]*	u:object_r:ram_device:s0
 /dev/block/zram[0-9]*	u:object_r:ram_device:s0
-/dev/boringssl/selftest(/.*)?	u:object_r:boringssl_self_test_marker:s0
-/dev/bus/usb(.*)?       u:object_r:usb_device:s0
 /dev/console		u:object_r:console_device:s0
-/dev/cpu_variant:.*     u:object_r:dev_cpu_variant:s0
 /dev/dma_heap(/.*)?     u:object_r:dmabuf_heap_device:s0
 /dev/dma_heap/system    u:object_r:dmabuf_system_heap_device:s0
 /dev/dma_heap/system-uncached    u:object_r:dmabuf_system_heap_device:s0
 /dev/dma_heap/system-secure(.*)	 u:object_r:dmabuf_system_secure_heap_device:s0
 /dev/dm-user(/.*)?	u:object_r:dm_user_device:s0
 /dev/device-mapper	u:object_r:dm_device:s0
-/dev/eac		u:object_r:audio_device:s0
 /dev/event-log-tags     u:object_r:runtime_event_log_tags_file:s0
 /dev/cgroup_info(/.*)?  u:object_r:cgroup_rc_file:s0
-/dev/fscklogs(/.*)?	u:object_r:fscklogs:s0
 /dev/fuse		u:object_r:fuse_device:s0
-/dev/gnss[0-9]+		u:object_r:gnss_device:s0
-/dev/graphics(/.*)?	u:object_r:graphics_device:s0
 /dev/hw_random		u:object_r:hw_random_device:s0
 /dev/hwbinder		u:object_r:hwbinder_device:s0
-/dev/input(/.*)?	u:object_r:input_device:s0
-/dev/iio:device[0-9]+   u:object_r:iio_device:s0
-/dev/ion		u:object_r:ion_device:s0
-/dev/keychord   u:object_r:keychord_device:s0
 /dev/loop-control	u:object_r:loop_control_device:s0
-/dev/modem.*		u:object_r:radio_device:s0
-/dev/mtp_usb		u:object_r:mtp_device:s0
-/dev/pmsg0		u:object_r:pmsg_device:s0
-/dev/pn544		u:object_r:nfc_device:s0
-/dev/port		u:object_r:port_device:s0
 /dev/ppp		u:object_r:ppp_device:s0
 /dev/ptmx		u:object_r:ptmx_device:s0
-/dev/pvrsrvkm		u:object_r:gpu_device:s0
 /dev/kmsg		u:object_r:kmsg_device:s0
 /dev/kmsg_debug	u:object_r:kmsg_debug_device:s0
 /dev/kvm		u:object_r:kvm_device:s0
 /dev/null		u:object_r:null_device:s0
-/dev/nvhdcp1		u:object_r:video_device:s0
 /dev/random		u:object_r:random_device:s0
-/dev/rpmsg-omx[0-9]	u:object_r:rpmsg_device:s0
-/dev/rproc_user	u:object_r:rpmsg_device:s0
 /dev/rtc[0-9]      u:object_r:rtc_device:s0
-/dev/snd(/.*)?		u:object_r:audio_device:s0
 /dev/socket(/.*)?	u:object_r:socket_device:s0
 /dev/socket/adbd	u:object_r:adbd_socket:s0
-/dev/socket/dnsproxyd	u:object_r:dnsproxyd_socket:s0
 /dev/socket/dumpstate	u:object_r:dumpstate_socket:s0
-/dev/socket/fwmarkd	u:object_r:fwmarkd_socket:s0
-/dev/socket/lmkd        u:object_r:lmkd_socket:s0
 /dev/socket/logd	u:object_r:logd_socket:s0
 /dev/socket/logdr	u:object_r:logdr_socket:s0
 /dev/socket/logdw	u:object_r:logdw_socket:s0
-/dev/socket/statsdw	u:object_r:statsdw_socket:s0
-/dev/socket/mdns	u:object_r:mdns_socket:s0
-/dev/socket/mdnsd	u:object_r:mdnsd_socket:s0
-/dev/socket/mtpd	u:object_r:mtpd_socket:s0
-/dev/socket/pdx/system/buffer_hub	u:object_r:pdx_bufferhub_dir:s0
-/dev/socket/pdx/system/buffer_hub/client	u:object_r:pdx_bufferhub_client_endpoint_socket:s0
-/dev/socket/pdx/system/performance	u:object_r:pdx_performance_dir:s0
-/dev/socket/pdx/system/performance/client	u:object_r:pdx_performance_client_endpoint_socket:s0
-/dev/socket/pdx/system/vr/display	u:object_r:pdx_display_dir:s0
-/dev/socket/pdx/system/vr/display/client	u:object_r:pdx_display_client_endpoint_socket:s0
-/dev/socket/pdx/system/vr/display/manager	u:object_r:pdx_display_manager_endpoint_socket:s0
-/dev/socket/pdx/system/vr/display/screenshot	u:object_r:pdx_display_screenshot_endpoint_socket:s0
-/dev/socket/pdx/system/vr/display/vsync	u:object_r:pdx_display_vsync_endpoint_socket:s0
 /dev/socket/property_service	u:object_r:property_socket:s0
-/dev/socket/racoon	u:object_r:racoon_socket:s0
-/dev/socket/recovery    u:object_r:recovery_socket:s0
-/dev/socket/rild	u:object_r:rild_socket:s0
-/dev/socket/rild-debug	u:object_r:rild_debug_socket:s0
-/dev/socket/snapuserd u:object_r:snapuserd_socket:s0
 /dev/socket/tombstoned_crash u:object_r:tombstoned_crash_socket:s0
 /dev/socket/tombstoned_java_trace u:object_r:tombstoned_java_trace_socket:s0
 /dev/socket/tombstoned_intercept u:object_r:tombstoned_intercept_socket:s0
-/dev/socket/traced_consumer	u:object_r:traced_consumer_socket:s0
-/dev/socket/traced_perf	u:object_r:traced_perf_socket:s0
-/dev/socket/traced_producer	u:object_r:traced_producer_socket:s0
-/dev/socket/heapprofd	u:object_r:heapprofd_socket:s0
-/dev/socket/uncrypt	u:object_r:uncrypt_socket:s0
-/dev/socket/wpa_eth[0-9] u:object_r:wpa_socket:s0
-/dev/socket/wpa_wlan[0-9] u:object_r:wpa_socket:s0
-/dev/socket/zygote	u:object_r:zygote_socket:s0
-/dev/socket/zygote_secondary	u:object_r:zygote_socket:s0
-/dev/socket/usap_pool_primary	u:object_r:zygote_socket:s0
-/dev/socket/usap_pool_secondary	u:object_r:zygote_socket:s0
-/dev/spdif_out.*	u:object_r:audio_device:s0
 /dev/sys/block/by-name/userdata(/.*)?	u:object_r:userdata_sysdev:s0
 /dev/sys/fs/by-name/userdata(/.*)?	u:object_r:userdata_sysdev:s0
 /dev/tty		u:object_r:owntty_device:s0
 /dev/tty[0-9]*		u:object_r:tty_device:s0
 /dev/ttyS[0-9]*		u:object_r:serial_device:s0
-/dev/ttyUSB[0-9]*	u:object_r:usb_serial_device:s0
-/dev/ttyACM[0-9]*	u:object_r:usb_serial_device:s0
 /dev/tun		u:object_r:tun_device:s0
 /dev/uhid		u:object_r:uhid_device:s0
 /dev/uinput		u:object_r:uhid_device:s0
 /dev/uio[0-9]*		u:object_r:uio_device:s0
 /dev/urandom		u:object_r:random_device:s0
-/dev/usb_accessory	u:object_r:usbaccessory_device:s0
-/dev/v4l-touch[0-9]*	u:object_r:input_device:s0
 /dev/vhost-vsock	u:object_r:kvm_device:s0
-/dev/video[0-9]*	u:object_r:video_device:s0
 /dev/vndbinder		u:object_r:vndbinder_device:s0
-/dev/watchdog		u:object_r:watchdog_device:s0
-/dev/xt_qtaguid	u:object_r:qtaguid_device:s0
 /dev/zero		u:object_r:zero_device:s0
 /dev/__properties__ u:object_r:properties_device:s0
 /dev/__properties__/property_info   u:object_r:property_info:s0
@@ -209,134 +94,29 @@
 #############################
 # System files
 #
-/system(/.*)?		u:object_r:system_file:s0
-/system/apex/com.android.art	u:object_r:art_apex_dir:s0
-/system/lib(64)?(/.*)?		u:object_r:system_lib_file:s0
+/system(/.*)?          u:object_r:system_file:s0
+/system/lib(64)?(/.*)?         u:object_r:system_lib_file:s0
 /system/lib(64)?/bootstrap(/.*)? u:object_r:system_bootstrap_lib_file:s0
-/system/bin/mm_events		u:object_r:mm_events_exec:s0
-/system/bin/atrace	u:object_r:atrace_exec:s0
-/system/bin/auditctl	u:object_r:auditctl_exec:s0
-/system/bin/bcc                 u:object_r:rs_exec:s0
-/system/bin/blank_screen	u:object_r:blank_screen_exec:s0
-/system/bin/boringssl_self_test(32|64) u:object_r:boringssl_self_test_exec:s0
-/system/bin/charger		u:object_r:charger_exec:s0
-/system/bin/canhalconfigurator  u:object_r:canhalconfigurator_exec:s0
-/system/bin/e2fsdroid		u:object_r:e2fs_exec:s0
-/system/bin/mke2fs		u:object_r:e2fs_exec:s0
-/system/bin/e2fsck	--	u:object_r:fsck_exec:s0
-/system/bin/fsck\.exfat	--	u:object_r:fsck_exec:s0
-/system/bin/fsck\.f2fs	--	u:object_r:fsck_exec:s0
-/system/bin/init		u:object_r:init_exec:s0
-# TODO(/123600489): merge mini-keyctl into toybox
-/system/bin/mini-keyctl	--	u:object_r:toolbox_exec:s0
-/system/bin/fsverity_init	u:object_r:fsverity_init_exec:s0
-/system/bin/sload_f2fs	--	u:object_r:e2fs_exec:s0
-/system/bin/make_f2fs	--	u:object_r:e2fs_exec:s0
-/system/bin/fsck_msdos	--	u:object_r:fsck_exec:s0
-/system/bin/tcpdump	--	u:object_r:tcpdump_exec:s0
-/system/bin/tune2fs	--	u:object_r:fsck_exec:s0
-/system/bin/resize2fs	--	u:object_r:fsck_exec:s0
-/system/bin/toolbox	--	u:object_r:toolbox_exec:s0
-/system/bin/toybox	--	u:object_r:toolbox_exec:s0
-/system/bin/ld\.mc              u:object_r:rs_exec:s0
-/system/bin/logcat	--	u:object_r:logcat_exec:s0
-/system/bin/logcatd	--	u:object_r:logcat_exec:s0
-/system/bin/sh		--	u:object_r:shell_exec:s0
-/system/bin/run-as	--	u:object_r:runas_exec:s0
-/system/bin/bootanimation u:object_r:bootanim_exec:s0
-/system/bin/bootstat		u:object_r:bootstat_exec:s0
-/system/bin/app_process32	u:object_r:zygote_exec:s0
-/system/bin/app_process64	u:object_r:zygote_exec:s0
-/system/bin/servicemanager	u:object_r:servicemanager_exec:s0
-/system/bin/hwservicemanager	u:object_r:hwservicemanager_exec:s0
-/system/bin/surfaceflinger	u:object_r:surfaceflinger_exec:s0
-/system/bin/gpuservice	u:object_r:gpuservice_exec:s0
-/system/bin/bufferhubd	u:object_r:bufferhubd_exec:s0
-/system/bin/performanced	u:object_r:performanced_exec:s0
-/system/bin/drmserver	u:object_r:drmserver_exec:s0
-/system/bin/dumpstate   u:object_r:dumpstate_exec:s0
-/system/bin/incident   u:object_r:incident_exec:s0
-/system/bin/incidentd   u:object_r:incidentd_exec:s0
-/system/bin/incident_helper  u:object_r:incident_helper_exec:s0
-/system/bin/iw                   u:object_r:iw_exec:s0
-/system/bin/netutils-wrapper-1\.0    u:object_r:netutils_wrapper_exec:s0
-/system/bin/vold	u:object_r:vold_exec:s0
-/system/bin/netd	u:object_r:netd_exec:s0
-/system/bin/wificond	u:object_r:wificond_exec:s0
-/system/bin/audioserver	u:object_r:audioserver_exec:s0
-/system/bin/mediadrmserver	u:object_r:mediadrmserver_exec:s0
-/system/bin/mediaserver	u:object_r:mediaserver_exec:s0
-/system/bin/mediametrics	u:object_r:mediametrics_exec:s0
-/system/bin/cameraserver	u:object_r:cameraserver_exec:s0
-/system/bin/mediaextractor	u:object_r:mediaextractor_exec:s0
-/system/bin/mediaswcodec	u:object_r:mediaswcodec_exec:s0
-/system/bin/mediatranscoding	u:object_r:mediatranscoding_exec:s0
-/system/bin/mediatuner	        u:object_r:mediatuner_exec:s0
-/system/bin/mdnsd	u:object_r:mdnsd_exec:s0
-/system/bin/installd	u:object_r:installd_exec:s0
-/system/bin/otapreopt_chroot   u:object_r:otapreopt_chroot_exec:s0
-/system/bin/otapreopt_slot   u:object_r:otapreopt_slot_exec:s0
-/system/bin/credstore	u:object_r:credstore_exec:s0
-/system/bin/keystore	u:object_r:keystore_exec:s0
-/system/bin/keystore2	u:object_r:keystore_exec:s0
-/system/bin/fingerprintd u:object_r:fingerprintd_exec:s0
-/system/bin/gatekeeperd u:object_r:gatekeeperd_exec:s0
-/system/bin/tombstoned u:object_r:tombstoned_exec:s0
-/system/bin/recovery-persist     u:object_r:recovery_persist_exec:s0
-/system/bin/recovery-refresh     u:object_r:recovery_refresh_exec:s0
-/system/bin/sdcard      u:object_r:sdcardd_exec:s0
-/system/bin/snapshotctl      u:object_r:snapshotctl_exec:s0
-/system/bin/dhcpcd      u:object_r:dhcp_exec:s0
-/system/bin/dhcpcd-6\.8\.2	u:object_r:dhcp_exec:s0
-/system/bin/mtpd	u:object_r:mtp_exec:s0
-/system/bin/pppd	u:object_r:ppp_exec:s0
-/system/bin/racoon	u:object_r:racoon_exec:s0
-/system/xbin/su		u:object_r:su_exec:s0
-/system/bin/dnsmasq     u:object_r:dnsmasq_exec:s0
-/system/bin/healthd     u:object_r:healthd_exec:s0
-/system/bin/clatd	u:object_r:clatd_exec:s0
+/system/bin/apexd                u:object_r:apexd_exec:s0
 /system/bin/linker(64)? u:object_r:system_linker_exec:s0
 /system/bin/linkerconfig u:object_r:linkerconfig_exec:s0
 /system/bin/bootstrap/linker(64)? u:object_r:system_linker_exec:s0
 /system/bin/bootstrap/linkerconfig u:object_r:linkerconfig_exec:s0
-/system/bin/llkd        u:object_r:llkd_exec:s0
-/system/bin/lmkd        u:object_r:lmkd_exec:s0
-/system/bin/usbd   u:object_r:usbd_exec:s0
-/system/bin/inputflinger u:object_r:inputflinger_exec:s0
+/system/bin/servicemanager	u:object_r:servicemanager_exec:s0
+/system/bin/hwservicemanager	u:object_r:hwservicemanager_exec:s0
+/system/bin/init		u:object_r:init_exec:s0
+/system/bin/keystore2	u:object_r:keystore_exec:s0
+/system/bin/logcat	--	u:object_r:logcat_exec:s0
 /system/bin/logd        u:object_r:logd_exec:s0
-/system/bin/lpdumpd        u:object_r:lpdumpd_exec:s0
-/system/bin/rss_hwm_reset	u:object_r:rss_hwm_reset_exec:s0
-/system/bin/perfetto        u:object_r:perfetto_exec:s0
-/system/bin/traced        u:object_r:traced_exec:s0
-/system/bin/traced_perf        u:object_r:traced_perf_exec:s0
-/system/bin/traced_probes        u:object_r:traced_probes_exec:s0
-/system/bin/heapprofd        u:object_r:heapprofd_exec:s0
-/system/bin/uncrypt     u:object_r:uncrypt_exec:s0
-/system/bin/update_verifier u:object_r:update_verifier_exec:s0
-/system/bin/logwrapper  u:object_r:system_file:s0
-/system/bin/vdc         u:object_r:vdc_exec:s0
-/system/bin/cppreopts\.sh   u:object_r:cppreopts_exec:s0
-/system/bin/preloads_copy\.sh u:object_r:preloads_copy_exec:s0
-/system/bin/preopt2cachename u:object_r:preopt2cachename_exec:s0
-/system/bin/viewcompiler     u:object_r:viewcompiler_exec:s0
-/system/bin/iorapd          u:object_r:iorapd_exec:s0
-/system/bin/iorap\.inode2filename u:object_r:iorap_inode2filename_exec:s0
-/system/bin/iorap\.prefetcherd u:object_r:iorap_prefetcherd_exec:s0
-/system/bin/sgdisk      u:object_r:sgdisk_exec:s0
-/system/bin/blkid       u:object_r:blkid_exec:s0
-/system/bin/tzdatacheck u:object_r:tzdatacheck_exec:s0
-/system/bin/flags_health_check -- u:object_r:flags_health_check_exec:s0
-/system/bin/idmap u:object_r:idmap_exec:s0
-/system/bin/idmap2(d)?           u:object_r:idmap_exec:s0
-/system/bin/update_engine        u:object_r:update_engine_exec:s0
-/system/bin/profcollectd         u:object_r:profcollectd_exec:s0
-/system/bin/profcollectctl       u:object_r:profcollectd_exec:s0
-/system/bin/storaged             u:object_r:storaged_exec:s0
-/system/bin/wpantund             u:object_r:wpantund_exec:s0
-/system/bin/virtual_touchpad     u:object_r:virtual_touchpad_exec:s0
-/system/bin/hw/android\.frameworks\.bufferhub@1\.0-service    u:object_r:fwk_bufferhub_exec:s0
-/system/bin/hw/android\.hidl\.allocator@1\.0-service          u:object_r:hal_allocator_default_exec:s0
-/system/bin/hw/android\.system\.suspend@1\.0-service          u:object_r:system_suspend_exec:s0
+/system/bin/run-as	--	u:object_r:runas_exec:s0
+/system/bin/sh		--	u:object_r:shell_exec:s0
+/system/bin/tombstoned u:object_r:tombstoned_exec:s0
+/system/bin/toolbox	--	u:object_r:toolbox_exec:s0
+/system/bin/toybox	--	u:object_r:toolbox_exec:s0
+/system/bin/zipfuse              u:object_r:zipfuse_exec:s0
+/system/bin/microdroid_launcher  u:object_r:microdroid_app_exec:s0
+/system/bin/microdroid_manager   u:object_r:microdroid_manager_exec:s0
+/system/bin/apkdmverity          u:object_r:apkdmverity_exec:s0
 /system/etc/cgroups\.json               u:object_r:cgroup_desc_file:s0
 /system/etc/task_profiles/cgroups_[0-9]+\.json               u:object_r:cgroup_desc_api_file:s0
 /system/etc/event-log-tags              u:object_r:system_event_log_tags_file:s0
@@ -357,154 +137,13 @@
 /system/etc/selinux/plat_and_mapping_sepolicy\.cil\.sha256 u:object_r:sepolicy_file:s0
 /system/etc/task_profiles\.json  u:object_r:task_profiles_file:s0
 /system/etc/task_profiles/task_profiles_[0-9]+\.json  u:object_r:task_profiles_api_file:s0
-/system/usr/share/zoneinfo(/.*)? u:object_r:system_zoneinfo_file:s0
-/system/bin/vr_hwc               u:object_r:vr_hwc_exec:s0
-/system/bin/adbd                 u:object_r:adbd_exec:s0
-/system/bin/vold_prepare_subdirs u:object_r:vold_prepare_subdirs_exec:s0
-/system/bin/stats                u:object_r:stats_exec:s0
-/system/bin/statsd               u:object_r:statsd_exec:s0
-/system/bin/bpfloader            u:object_r:bpfloader_exec:s0
-/system/bin/watchdogd            u:object_r:watchdogd_exec:s0
-/system/bin/apexd                u:object_r:apexd_exec:s0
-/system/bin/gsid                 u:object_r:gsid_exec:s0
-/system/bin/simpleperf           u:object_r:simpleperf_exec:s0
-/system/bin/simpleperf_app_runner    u:object_r:simpleperf_app_runner_exec:s0
-/system/bin/migrate_legacy_obb_data\.sh u:object_r:migrate_legacy_obb_data_exec:s0
-/system/bin/android\.frameworks\.automotive\.display@1\.0-service u:object_r:automotive_display_service_exec:s0
-/system/bin/snapuserd            u:object_r:snapuserd_exec:s0
-/system/bin/odsign               u:object_r:odsign_exec:s0
-/system/bin/zipfuse              u:object_r:zipfuse_exec:s0
-/system/bin/microdroid_launcher  u:object_r:microdroid_launcher_exec:s0
-/system/bin/microdroid_manager   u:object_r:microdroid_manager_exec:s0
-/system/bin/apkdmverity          u:object_r:apkdmverity_exec:s0
 
 #############################
 # Vendor files
 #
-/(vendor|system/vendor)(/.*)?                  u:object_r:vendor_file:s0
-/(vendor|system/vendor)/bin/sh                 u:object_r:vendor_shell_exec:s0
-/(vendor|system/vendor)/bin/toybox_vendor      u:object_r:vendor_toolbox_exec:s0
-/(vendor|system/vendor)/bin/toolbox            u:object_r:vendor_toolbox_exec:s0
-/(vendor|system/vendor)/etc(/.*)?              u:object_r:vendor_configs_file:s0
-/(vendor|system/vendor)/etc/cgroups\.json      u:object_r:vendor_cgroup_desc_file:s0
-/(vendor|system/vendor)/etc/task_profiles\.json    u:object_r:vendor_task_profiles_file:s0
-
-/(vendor|system/vendor)/lib(64)?/egl(/.*)?     u:object_r:same_process_hal_file:s0
-
-/(vendor|system/vendor)/lib(64)?/vndk-sp(/.*)? u:object_r:vndk_sp_file:s0
-
-/(vendor|system/vendor)/manifest\.xml           u:object_r:vendor_configs_file:s0
-/(vendor|system/vendor)/compatibility_matrix\.xml u:object_r:vendor_configs_file:s0
-/(vendor|system/vendor)/etc/vintf(/.*)?        u:object_r:vendor_configs_file:s0
-/(vendor|system/vendor)/app(/.*)?              u:object_r:vendor_app_file:s0
-/(vendor|system/vendor)/priv-app(/.*)?         u:object_r:vendor_app_file:s0
-/(vendor|system/vendor)/overlay(/.*)?          u:object_r:vendor_overlay_file:s0
-/(vendor|system/vendor)/framework(/.*)?        u:object_r:vendor_framework_file:s0
-
-/(vendor|system/vendor)/apex(/[^/]+){0,2}                      u:object_r:vendor_apex_file:s0
-/(vendor|system/vendor)/bin/misc_writer                        u:object_r:vendor_misc_writer_exec:s0
-/(vendor|system/vendor)/bin/boringssl_self_test(32|64)         u:object_r:vendor_boringssl_self_test_exec:s0
-
-# HAL location
-/(vendor|system/vendor)/lib(64)?/hw            u:object_r:vendor_hal_file:s0
-
-/(vendor|system/vendor)/etc/selinux/nonplat_service_contexts u:object_r:nonplat_service_contexts_file:s0
-
-/(vendor|system/vendor)/etc/selinux/vendor_service_contexts u:object_r:vendor_service_contexts_file:s0
-
-#############################
-# OEM and ODM files
-#
-/(odm|vendor/odm)(/.*)?                       u:object_r:vendor_file:s0
-/(odm|vendor/odm)/lib(64)?/egl(/.*)?          u:object_r:same_process_hal_file:s0
-/(odm|vendor/odm)/lib(64)?/hw                 u:object_r:vendor_hal_file:s0
-/(odm|vendor/odm)/lib(64)?/vndk-sp(/.*)?      u:object_r:vndk_sp_file:s0
-/(odm|vendor/odm)/bin/sh                      u:object_r:vendor_shell_exec:s0
-/(odm|vendor/odm)/etc(/.*)?                   u:object_r:vendor_configs_file:s0
-/(odm|vendor/odm)/app(/.*)?                   u:object_r:vendor_app_file:s0
-/(odm|vendor/odm)/priv-app(/.*)?              u:object_r:vendor_app_file:s0
-/(odm|vendor/odm)/overlay(/.*)?               u:object_r:vendor_overlay_file:s0
-/(odm|vendor/odm)/framework(/.*)?             u:object_r:vendor_framework_file:s0
-
-# Input configuration
-/(odm|vendor/odm|vendor|system/vendor)/usr/keylayout(/.*)?\.kl        u:object_r:vendor_keylayout_file:s0
-/(odm|vendor/odm|vendor|system/vendor)/usr/keychars(/.*)?\.kcm        u:object_r:vendor_keychars_file:s0
-/(odm|vendor/odm|vendor|system/vendor)/usr/idc(/.*)?\.idc             u:object_r:vendor_idc_file:s0
-
-/oem(/.*)?              u:object_r:oemfs:s0
-/oem/overlay(/.*)?      u:object_r:vendor_overlay_file:s0
-
-# The precompiled monolithic sepolicy will be under /odm only when
-# BOARD_USES_ODMIMAGE is true: a separate odm.img is built.
-/odm/etc/selinux/precompiled_sepolicy                           u:object_r:sepolicy_file:s0
-/odm/etc/selinux/precompiled_sepolicy\.plat_and_mapping\.sha256 u:object_r:sepolicy_file:s0
-
-/(odm|vendor/odm)/etc/selinux/odm_sepolicy\.cil                  u:object_r:sepolicy_file:s0
-/(odm|vendor/odm)/etc/selinux/odm_file_contexts                 u:object_r:file_contexts_file:s0
-/(odm|vendor/odm)/etc/selinux/odm_seapp_contexts                u:object_r:seapp_contexts_file:s0
-/(odm|vendor/odm)/etc/selinux/odm_property_contexts             u:object_r:property_contexts_file:s0
-/(odm|vendor/odm)/etc/selinux/odm_hwservice_contexts            u:object_r:hwservice_contexts_file:s0
-/(odm|vendor/odm)/etc/selinux/odm_keystore2_key_contexts         u:object_r:keystore2_key_contexts_file:s0
-/(odm|vendor/odm)/etc/selinux/odm_mac_permissions\.xml           u:object_r:mac_perms_file:s0
-
-#############################
-# Product files
-#
-/(product|system/product)(/.*)?                                 u:object_r:system_file:s0
-/(product|system/product)/etc/group                             u:object_r:system_group_file:s0
-/(product|system/product)/etc/passwd                            u:object_r:system_passwd_file:s0
-/(product|system/product)/overlay(/.*)?                         u:object_r:vendor_overlay_file:s0
-
-/(product|system/product)/etc/selinux/product_file_contexts      u:object_r:file_contexts_file:s0
-/(product|system/product)/etc/selinux/product_hwservice_contexts u:object_r:hwservice_contexts_file:s0
-/(product|system/product)/etc/selinux/product_keystore2_key_contexts u:object_r:keystore2_key_contexts_file:s0
-/(product|system/product)/etc/selinux/product_property_contexts  u:object_r:property_contexts_file:s0
-/(product|system/product)/etc/selinux/product_seapp_contexts     u:object_r:seapp_contexts_file:s0
-/(product|system/product)/etc/selinux/product_service_contexts   u:object_r:service_contexts_file:s0
-/(product|system/product)/etc/selinux/product_mac_permissions\.xml u:object_r:mac_perms_file:s0
-
-/(product|system/product)/lib(64)?(/.*)?                         u:object_r:system_lib_file:s0
-
-#############################
-# SystemExt files
-#
-/(system_ext|system/system_ext)(/.*)?               u:object_r:system_file:s0
-/(system_ext|system/system_ext)/etc/group           u:object_r:system_group_file:s0
-/(system_ext|system/system_ext)/etc/passwd          u:object_r:system_passwd_file:s0
-/(system_ext|system/system_ext)/overlay(/.*)?       u:object_r:vendor_overlay_file:s0
-
-/(system_ext|system/system_ext)/etc/selinux/system_ext_file_contexts        u:object_r:file_contexts_file:s0
-/(system_ext|system/system_ext)/etc/selinux/system_ext_hwservice_contexts   u:object_r:hwservice_contexts_file:s0
-/(system_ext|system/system_ext)/etc/selinux/system_ext_keystore2_key_contexts u:object_r:keystore2_key_contexts_file:s0
-/(system_ext|system/system_ext)/etc/selinux/system_ext_property_contexts    u:object_r:property_contexts_file:s0
-/(system_ext|system/system_ext)/etc/selinux/system_ext_seapp_contexts       u:object_r:seapp_contexts_file:s0
-/(system_ext|system/system_ext)/etc/selinux/system_ext_service_contexts     u:object_r:service_contexts_file:s0
-/(system_ext|system/system_ext)/etc/selinux/system_ext_mac_permissions\.xml u:object_r:mac_perms_file:s0
-
-/(system_ext|system/system_ext)/bin/aidl_lazy_test_server   u:object_r:aidl_lazy_test_server_exec:s0
-/(system_ext|system/system_ext)/bin/hidl_lazy_test_server   u:object_r:hidl_lazy_test_server_exec:s0
-
-/(system_ext|system/system_ext)/lib(64)?(/.*)?      u:object_r:system_lib_file:s0
-
-#############################
-# VendorDlkm files
-# This includes VENDOR Dynamically Loadable Kernel Modules and other misc files.
-#
-/(vendor_dlkm|vendor/vendor_dlkm|system/vendor/vendor_dlkm)(/.*)?         u:object_r:vendor_file:s0
-
-#############################
-# OdmDlkm files
-# This includes ODM Dynamically Loadable Kernel Modules and other misc files.
-#
-/(odm_dlkm|vendor/odm_dlkm|system/vendor/odm_dlkm)(/.*)?                  u:object_r:vendor_file:s0
-
-#############################
-# Vendor files from /(product|system/product)/vendor_overlay
-#
-# NOTE: For additional vendor file contexts for vendor overlay files,
-# use device specific file_contexts.
-#
-/(product|system/product)/vendor_overlay/[0-9]+/.*          u:object_r:vendor_file:s0
+/vendor(/.*)?                  u:object_r:vendor_file:s0
+/vendor/etc(/.*)?              u:object_r:vendor_configs_file:s0
+/vendor/etc/vintf(/.*)?        u:object_r:vendor_configs_file:s0
 
 #############################
 # Data files
@@ -514,305 +153,11 @@
 #
 /data		u:object_r:system_data_root_file:s0
 /data/(.*)?		u:object_r:system_data_file:s0
-/data/system/environ(/.*)? u:object_r:environ_system_data_file:s0
-/data/system/packages\.list u:object_r:packages_list_file:s0
-/data/unencrypted(/.*)?         u:object_r:unencrypted_data_file:s0
-/data/backup(/.*)?		u:object_r:backup_data_file:s0
-/data/secure/backup(/.*)?	u:object_r:backup_data_file:s0
-/data/system/ndebugsocket	u:object_r:system_ndebug_socket:s0
-/data/system/unsolzygotesocket  u:object_r:system_unsolzygote_socket:s0
-/data/drm(/.*)?		u:object_r:drm_data_file:s0
-/data/resource-cache(/.*)? u:object_r:resourcecache_data_file:s0
-/data/dalvik-cache(/.*)? u:object_r:dalvikcache_data_file:s0
-/data/ota(/.*)? u:object_r:ota_data_file:s0
-/data/ota_package(/.*)? u:object_r:ota_package_file:s0
-/data/adb(/.*)?		u:object_r:adb_data_file:s0
 /data/anr(/.*)?		u:object_r:anr_data_file:s0
-/data/apex(/.*)?		u:object_r:apex_data_file:s0
-/data/apex/active/(.*)?		u:object_r:staging_data_file:s0
-/data/apex/backup/(.*)?		u:object_r:staging_data_file:s0
-/data/apex/decompressed/(.*)?    u:object_r:staging_data_file:s0
-/data/apex/ota_reserved(/.*)?       u:object_r:apex_ota_reserved_file:s0
-/data/app(/.*)?                       u:object_r:apk_data_file:s0
-# Traditional /data/app/[packageName]-[randomString]/base.apk location
-/data/app/[^/]+/oat(/.*)?                u:object_r:dalvikcache_data_file:s0
-# /data/app/[randomStringA]/[packageName]-[randomStringB]/base.apk layout
-/data/app/[^/]+/[^/]+/oat(/.*)?                u:object_r:dalvikcache_data_file:s0
-/data/app/vmdl[^/]+\.tmp(/.*)?           u:object_r:apk_tmp_file:s0
-/data/app/vmdl[^/]+\.tmp/oat(/.*)?           u:object_r:dalvikcache_data_file:s0
-/data/app-private(/.*)?               u:object_r:apk_private_data_file:s0
-/data/app-private/vmdl.*\.tmp(/.*)?   u:object_r:apk_private_tmp_file:s0
-/data/gsi(/.*)?        u:object_r:gsi_data_file:s0
-/data/gsi_persistent_data    u:object_r:gsi_persistent_data_file:s0
-/data/gsi/ota(/.*)?    u:object_r:ota_image_data_file:s0
-/data/tombstones(/.*)?	u:object_r:tombstone_data_file:s0
-/data/vendor/tombstones/wifi(/.*)? u:object_r:tombstone_wifi_data_file:s0
 /data/local/tests(/.*)?	u:object_r:shell_test_data_file:s0
 /data/local/tmp(/.*)?	u:object_r:shell_data_file:s0
 /data/local/tmp/ltp(/.*)?   u:object_r:nativetest_data_file:s0
 /data/local/traces(/.*)?	u:object_r:trace_data_file:s0
-/data/media(/.*)?	u:object_r:media_rw_data_file:s0
-/data/mediadrm(/.*)?	u:object_r:media_data_file:s0
-/data/nativetest(/.*)?	u:object_r:nativetest_data_file:s0
-/data/nativetest64(/.*)?	u:object_r:nativetest_data_file:s0
-# This directory was removed after Q Beta 2, but we need to preserve labels for upgrading devices.
-/data/pkg_staging(/.*)?		u:object_r:staging_data_file:s0
-/data/property(/.*)?	u:object_r:property_data_file:s0
-/data/preloads(/.*)?	u:object_r:preloads_data_file:s0
-/data/preloads/media(/.*)?	u:object_r:preloads_media_file:s0
-/data/preloads/demo(/.*)?	u:object_r:preloads_media_file:s0
-/data/server_configurable_flags(/.*)? u:object_r:server_configurable_flags_data_file:s0
-/data/app-staging(/.*)?		u:object_r:staging_data_file:s0
-# Ensure we have the same labels as /data/app or /data/apex/active
-# to avoid restorecon conflicts
-/data/rollback/\d+/[^/]+/.*\.apk  u:object_r:apk_data_file:s0
-/data/rollback/\d+/[^/]+/.*\.apex u:object_r:staging_data_file:s0
-/data/fonts/files(/.*)?     u:object_r:font_data_file:s0
-
-# Misc data
-/data/misc/adb(/.*)?            u:object_r:adb_keys_file:s0
-/data/misc/a11ytrace(/.*)?      u:object_r:accessibility_trace_data_file:s0
-/data/misc/apexdata(/.*)?       u:object_r:apex_module_data_file:s0
-/data/misc/apexdata/com\.android\.art(/.*)?           u:object_r:apex_art_data_file:s0
-/data/misc/apexdata/com\.android\.permission(/.*)?    u:object_r:apex_permission_data_file:s0
-/data/misc/apexdata/com\.android\.scheduling(/.*)?    u:object_r:apex_scheduling_data_file:s0
-/data/misc/apexdata/com\.android\.wifi(/.*)?          u:object_r:apex_wifi_data_file:s0
-/data/misc/apexrollback(/.*)?   u:object_r:apex_rollback_data_file:s0
-/data/misc/apns(/.*)?           u:object_r:radio_data_file:s0
-/data/misc/appcompat(/.*)?      u:object_r:appcompat_data_file:s0
-/data/misc/audio(/.*)?          u:object_r:audio_data_file:s0
-/data/misc/audioserver(/.*)?    u:object_r:audioserver_data_file:s0
-/data/misc/audiohal(/.*)?       u:object_r:audiohal_data_file:s0
-/data/misc/bootstat(/.*)?       u:object_r:bootstat_data_file:s0
-/data/misc/boottrace(/.*)?      u:object_r:boottrace_data_file:s0
-/data/misc/bluetooth(/.*)?      u:object_r:bluetooth_data_file:s0
-/data/misc/bluetooth/logs(/.*)? u:object_r:bluetooth_logs_data_file:s0
-/data/misc/bluedroid(/.*)?      u:object_r:bluetooth_data_file:s0
-/data/misc/bluedroid/\.a2dp_ctrl u:object_r:bluetooth_socket:s0
-/data/misc/bluedroid/\.a2dp_data u:object_r:bluetooth_socket:s0
-/data/misc/camera(/.*)?         u:object_r:camera_data_file:s0
-/data/misc/carrierid(/.*)?      u:object_r:radio_data_file:s0
-/data/misc/dhcp(/.*)?           u:object_r:dhcp_data_file:s0
-/data/misc/dhcp-6\.8\.2(/.*)?     u:object_r:dhcp_data_file:s0
-/data/misc/emergencynumberdb(/.*)?     u:object_r:emergency_data_file:s0
-/data/misc/gatekeeper(/.*)?     u:object_r:gatekeeper_data_file:s0
-/data/misc/incidents(/.*)?	    u:object_r:incident_data_file:s0
-/data/misc/installd(/.*)?		u:object_r:install_data_file:s0
-/data/misc/keychain(/.*)?       u:object_r:keychain_data_file:s0
-/data/misc/credstore(/.*)?       u:object_r:credstore_data_file:s0
 /data/misc/keystore(/.*)?       u:object_r:keystore_data_file:s0
-/data/misc/logd(/.*)?           u:object_r:misc_logd_file:s0
-/data/misc/media(/.*)?          u:object_r:media_data_file:s0
-/data/misc/net(/.*)?            u:object_r:net_data_file:s0
-/data/misc/network_watchlist(/.*)? u:object_r:network_watchlist_data_file:s0
-/data/misc/nfc/logs(/.*)?       u:object_r:nfc_logs_data_file:s0
-/data/misc/odrefresh(/.*)?      u:object_r:odrefresh_data_file:s0
-/data/misc/odsign(/.*)?         u:object_r:odsign_data_file:s0
-/data/misc/perfetto-traces/bugreport(.*)? u:object_r:perfetto_traces_bugreport_data_file:s0
-/data/misc/perfetto-traces(/.*)?          u:object_r:perfetto_traces_data_file:s0
-/data/misc/perfetto-configs(/.*)?         u:object_r:perfetto_configs_data_file:s0
-/data/misc/prereboot(/.*)?      u:object_r:prereboot_data_file:s0
-/data/misc/profcollectd(/.*)?   u:object_r:profcollectd_data_file:s0
-/data/misc/radio(/.*)?          u:object_r:radio_core_data_file:s0
-/data/misc/recovery(/.*)?       u:object_r:recovery_data_file:s0
-/data/misc/shared_relro(/.*)?   u:object_r:shared_relro_file:s0
-/data/misc/sms(/.*)?            u:object_r:radio_data_file:s0
-/data/misc/snapshotctl_log(/.*)?      u:object_r:snapshotctl_log_data_file:s0
-/data/misc/stats-active-metric(/.*)? u:object_r:stats_data_file:s0
-/data/misc/stats-data(/.*)?     u:object_r:stats_data_file:s0
-/data/misc/stats-service(/.*)?  u:object_r:stats_data_file:s0
-/data/misc/stats-metadata(/.*)? u:object_r:stats_data_file:s0
-/data/misc/systemkeys(/.*)?     u:object_r:systemkeys_data_file:s0
-/data/misc/textclassifier(/.*)?       u:object_r:textclassifier_data_file:s0
-/data/misc/train-info(/.*)?     u:object_r:stats_data_file:s0
-/data/misc/user(/.*)?           u:object_r:misc_user_data_file:s0
-/data/misc/virtualizationservice(/.*)? u:object_r:virtualizationservice_data_file:s0
-/data/misc/vpn(/.*)?            u:object_r:vpn_data_file:s0
-/data/misc/wifi(/.*)?           u:object_r:wifi_data_file:s0
-/data/misc_ce/[0-9]+/wifi(/.*)? u:object_r:wifi_data_file:s0
-/data/misc/wifi/sockets(/.*)?   u:object_r:wpa_socket:s0
-/data/misc/wifi/sockets/wpa_ctrl.*   u:object_r:system_wpa_socket:s0
-/data/misc/zoneinfo(/.*)?       u:object_r:zoneinfo_data_file:s0
-/data/misc/vold(/.*)?           u:object_r:vold_data_file:s0
-/data/misc/iorapd(/.*)?         u:object_r:iorapd_data_file:s0
-/data/misc/update_engine(/.*)?  u:object_r:update_engine_data_file:s0
-/data/misc/update_engine_log(/.*)?  u:object_r:update_engine_log_data_file:s0
-/data/system/dropbox(/.*)?      u:object_r:dropbox_data_file:s0
-/data/system/heapdump(/.*)?     u:object_r:heapdump_data_file:s0
-/data/misc/trace(/.*)?          u:object_r:method_trace_data_file:s0
-/data/misc/wmtrace(/.*)?        u:object_r:wm_trace_data_file:s0
-# TODO(calin) label profile reference differently so that only
-# profman run as a special user can write to them
-/data/misc/profiles/cur(/[0-9]+)?   u:object_r:user_profile_root_file:s0
-/data/misc/profiles/cur/[0-9]+/.*   u:object_r:user_profile_data_file:s0
-/data/misc/profiles/ref(/.*)?       u:object_r:user_profile_data_file:s0
-/data/misc/profman(/.*)?        u:object_r:profman_dump_data_file:s0
+/data/tombstones(/.*)?	u:object_r:tombstone_data_file:s0
 /data/vendor(/.*)?              u:object_r:vendor_data_file:s0
-/data/vendor_ce(/.*)?           u:object_r:vendor_data_file:s0
-/data/vendor_de(/.*)?           u:object_r:vendor_data_file:s0
-
-# storaged proto files
-/data/misc_de/[0-9]+/storaged(/.*)?       u:object_r:storaged_data_file:s0
-/data/misc_ce/[0-9]+/storaged(/.*)?       u:object_r:storaged_data_file:s0
-
-# Fingerprint data
-/data/system/users/[0-9]+/fpdata(/.*)? u:object_r:fingerprintd_data_file:s0
-
-# Fingerprint vendor data file
-/data/vendor_de/[0-9]+/fpdata(/.*)? u:object_r:fingerprint_vendor_data_file:s0
-
-# Face vendor data file
-/data/vendor_de/[0-9]+/facedata(/.*)? u:object_r:face_vendor_data_file:s0
-/data/vendor_ce/[0-9]+/facedata(/.*)? u:object_r:face_vendor_data_file:s0
-
-# Iris vendor data file
-/data/vendor_de/[0-9]+/irisdata(/.*)? u:object_r:iris_vendor_data_file:s0
-
-# Bootchart data
-/data/bootchart(/.*)?		u:object_r:bootchart_data_file:s0
-
-# App data snapshots (managed by installd).
-/data/misc_de/[0-9]+/rollback(/.*)?       u:object_r:rollback_data_file:s0
-/data/misc_ce/[0-9]+/rollback(/.*)?       u:object_r:rollback_data_file:s0
-
-# Apex data directories
-/data/misc_de/[0-9]+/apexdata(/.*)?       u:object_r:apex_module_data_file:s0
-/data/misc_ce/[0-9]+/apexdata(/.*)?       u:object_r:apex_module_data_file:s0
-/data/misc_ce/[0-9]+/apexdata/com\.android\.appsearch(/.*)?   u:object_r:apex_appsearch_data_file:s0
-/data/misc_de/[0-9]+/apexdata/com\.android\.permission(/.*)?  u:object_r:apex_permission_data_file:s0
-/data/misc_ce/[0-9]+/apexdata/com\.android\.permission(/.*)?  u:object_r:apex_permission_data_file:s0
-/data/misc_de/[0-9]+/apexdata/com\.android\.wifi(/.*)?  u:object_r:apex_wifi_data_file:s0
-/data/misc_ce/[0-9]+/apexdata/com\.android\.wifi(/.*)?  u:object_r:apex_wifi_data_file:s0
-
-# Apex rollback directories
-/data/misc_de/[0-9]+/apexrollback(/.*)?   u:object_r:apex_rollback_data_file:s0
-/data/misc_ce/[0-9]+/apexrollback(/.*)?   u:object_r:apex_rollback_data_file:s0
-
-# Incremental directories
-/data/incremental(/.*)?                                 u:object_r:apk_data_file:s0
-/data/incremental/MT_[^/]+/mount/.pending_reads         u:object_r:incremental_control_file:s0
-/data/incremental/MT_[^/]+/mount/.log                   u:object_r:incremental_control_file:s0
-/data/incremental/MT_[^/]+/mount/.blocks_written        u:object_r:incremental_control_file:s0
-
-#############################
-# Expanded data files
-#
-/mnt/expand(/.*)?                                   u:object_r:mnt_expand_file:s0
-/mnt/expand/[^/]+(/.*)?                             u:object_r:system_data_file:s0
-/mnt/expand/[^/]+/app(/.*)?                         u:object_r:apk_data_file:s0
-/mnt/expand/[^/]+/app/[^/]+/oat(/.*)?               u:object_r:dalvikcache_data_file:s0
-# /mnt/expand/..../app/[randomStringA]/[packageName]-[randomStringB]/base.apk layout
-/mnt/expand/[^/]+/app/[^/]+/[^/]+/oat(/.*)?        u:object_r:dalvikcache_data_file:s0
-/mnt/expand/[^/]+/app/vmdl[^/]+\.tmp(/.*)?          u:object_r:apk_tmp_file:s0
-/mnt/expand/[^/]+/app/vmdl[^/]+\.tmp/oat(/.*)?      u:object_r:dalvikcache_data_file:s0
-/mnt/expand/[^/]+/local/tmp(/.*)?                   u:object_r:shell_data_file:s0
-/mnt/expand/[^/]+/media(/.*)?                       u:object_r:media_rw_data_file:s0
-/mnt/expand/[^/]+/misc/vold(/.*)?                   u:object_r:vold_data_file:s0
-
-# coredump directory for userdebug/eng devices
-/cores(/.*)?                    u:object_r:coredump_file:s0
-
-# Wallpaper files
-/data/system/users/[0-9]+/wallpaper_lock_orig	u:object_r:wallpaper_file:s0
-/data/system/users/[0-9]+/wallpaper_lock	u:object_r:wallpaper_file:s0
-/data/system/users/[0-9]+/wallpaper_orig	u:object_r:wallpaper_file:s0
-/data/system/users/[0-9]+/wallpaper		u:object_r:wallpaper_file:s0
-
-# Ringtone files
-/data/system_de/[0-9]+/ringtones(/.*)?          u:object_r:ringtone_file:s0
-
-# ShortcutManager icons, e.g.
-#   /data/system_ce/0/shortcut_service/bitmaps/com.example.app/1457472879282.png
-/data/system_ce/[0-9]+/shortcut_service/bitmaps(/.*)? u:object_r:shortcut_manager_icons:s0
-
-# User icon files
-/data/system/users/[0-9]+/photo\.png             u:object_r:icon_file:s0
-
-# vold per-user data
-/data/misc_de/[0-9]+/vold(/.*)?           u:object_r:vold_data_file:s0
-/data/misc_ce/[0-9]+/vold(/.*)?           u:object_r:vold_data_file:s0
-
-# iorapd per-user data
-/data/misc_ce/[0-9]+/iorapd(/.*)?           u:object_r:iorapd_data_file:s0
-
-# Backup service persistent per-user bookkeeping
-/data/system_ce/[0-9]+/backup(/.*)?		u:object_r:backup_data_file:s0
-# Backup service temporary per-user data for inter-change with apps
-/data/system_ce/[0-9]+/backup_stage(/.*)?	u:object_r:backup_data_file:s0
-
-#############################
-# efs files
-#
-/efs(/.*)?		u:object_r:efs_file:s0
-
-#############################
-# Cache files
-#
-/cache(/.*)?		u:object_r:cache_file:s0
-/cache/recovery(/.*)?	u:object_r:cache_recovery_file:s0
-# General backup/restore interchange with apps
-/cache/backup_stage(/.*)?	u:object_r:cache_backup_file:s0
-# LocalTransport (backup) uses this subtree
-/cache/backup(/.*)?		u:object_r:cache_private_backup_file:s0
-
-#############################
-# Overlayfs support directories
-#
-/cache/overlay(/.*)?            u:object_r:overlayfs_file:s0
-/mnt/scratch(/.*)?              u:object_r:overlayfs_file:s0
-
-/data/cache(/.*)?		u:object_r:cache_file:s0
-/data/cache/recovery(/.*)?	u:object_r:cache_recovery_file:s0
-# General backup/restore interchange with apps
-/data/cache/backup_stage(/.*)?	u:object_r:cache_backup_file:s0
-# LocalTransport (backup) uses this subtree
-/data/cache/backup(/.*)?	u:object_r:cache_private_backup_file:s0
-
-#############################
-# Metadata files
-#
-/metadata(/.*)?           u:object_r:metadata_file:s0
-/metadata/apex(/.*)?      u:object_r:apex_metadata_file:s0
-/metadata/vold(/.*)?      u:object_r:vold_metadata_file:s0
-/metadata/gsi(/.*)?       u:object_r:gsi_metadata_file:s0
-/metadata/gsi/dsu/active  u:object_r:gsi_public_metadata_file:s0
-/metadata/gsi/dsu/booted  u:object_r:gsi_public_metadata_file:s0
-/metadata/gsi/dsu/lp_names  u:object_r:gsi_public_metadata_file:s0
-/metadata/gsi/dsu/[^/]+/metadata_encryption_dir u:object_r:gsi_public_metadata_file:s0
-/metadata/gsi/ota(/.*)?   u:object_r:ota_metadata_file:s0
-/metadata/password_slots(/.*)?    u:object_r:password_slot_metadata_file:s0
-/metadata/ota(/.*)?       u:object_r:ota_metadata_file:s0
-/metadata/bootstat(/.*)?  u:object_r:metadata_bootstat_file:s0
-/metadata/staged-install(/.*)?    u:object_r:staged_install_file:s0
-/metadata/userspacereboot(/.*)?    u:object_r:userspace_reboot_metadata_file:s0
-/metadata/watchdog(/.*)?    u:object_r:watchdog_metadata_file:s0
-
-#############################
-# asec containers
-/mnt/asec(/.*)?             u:object_r:asec_apk_file:s0
-/mnt/asec/[^/]+/[^/]+\.zip  u:object_r:asec_public_file:s0
-/mnt/asec/[^/]+/lib(/.*)?   u:object_r:asec_public_file:s0
-/data/app-asec(/.*)?        u:object_r:asec_image_file:s0
-
-#############################
-# external storage
-/mnt/media_rw(/.*)?         u:object_r:mnt_media_rw_file:s0
-/mnt/user(/.*)?             u:object_r:mnt_user_file:s0
-/mnt/pass_through(/.*)?     u:object_r:mnt_pass_through_file:s0
-/mnt/sdcard                 u:object_r:mnt_sdcard_file:s0
-/mnt/runtime(/.*)?          u:object_r:storage_file:s0
-/storage(/.*)?              u:object_r:storage_file:s0
-
-#############################
-# mount point for read-write vendor partitions
-/mnt/vendor(/.*)?           u:object_r:mnt_vendor_file:s0
-
-#############################
-# mount point for read-write product partitions
-/mnt/product(/.*)?          u:object_r:mnt_product_file:s0
-
-#############################
-# /postinstall file contexts
-/(system|product)/bin/check_dynamic_partitions  u:object_r:postinstall_exec:s0
-/(system|product)/bin/otapreopt_script          u:object_r:postinstall_exec:s0
-/(system|product)/bin/otapreopt                 u:object_r:postinstall_dexopt_exec:s0
diff --git a/microdroid/sepolicy/system/private/keystore2_key_contexts b/microdroid/sepolicy/system/private/keystore2_key_contexts
index 3833971..4e7c260 100644
--- a/microdroid/sepolicy/system/private/keystore2_key_contexts
+++ b/microdroid/sepolicy/system/private/keystore2_key_contexts
@@ -26,3 +26,7 @@
 # resume_on_reboot_key is a keystore2_key namespace intended for resume on reboot.
 120            u:object_r:resume_on_reboot_key:s0
 
+# vm_payload_key is a keystore2_key namespace intended for microdroid VM payloads.
+# TODO(b/191843770): sort out a longer term policy
+140            u:object_r:vm_payload_key:s0
+
diff --git a/microdroid/sepolicy/system/private/microdroid_app.te b/microdroid/sepolicy/system/private/microdroid_app.te
new file mode 100644
index 0000000..eff9120
--- /dev/null
+++ b/microdroid/sepolicy/system/private/microdroid_app.te
@@ -0,0 +1,45 @@
+# microdroid_app is a domain for microdroid_launcher, which is a binary that
+# loads a shared library from an apk and executes it by calling an entry point
+# in the library. This can be considered as the native counterpart of
+# app_process for Java.
+#
+# Both microdroid_launcher and payload from the shared library run in the
+# context of microdroid_app.
+
+type microdroid_app, domain, coredomain;
+type microdroid_app_exec, exec_type, file_type, system_file_type;
+
+# Allow to communicate use, read and write over the adb connection.
+allow microdroid_app adbd:fd use;
+allow microdroid_app adbd:unix_stream_socket { read write };
+
+# microdroid_launcher is launched by microdroid_manager with fork/execvp.
+allow microdroid_app microdroid_manager:fd use;
+
+# Allow to use FDs inherited from the shell. This includes the FD opened for
+# the microdroid_launcher executable itself and the FD for adb connection.
+# TODO(b/186396070) remove this when this is executed from microdroid_manager
+userdebug_or_eng(`
+  allow microdroid_app shell:fd use;
+')
+
+# Allow to use terminal
+allow microdroid_app devpts:chr_file rw_file_perms;
+
+# Allow to set debug prop
+set_prop(microdroid_app, debug_prop)
+
+# Talk to binder services (for keystore)
+binder_use(microdroid_app);
+
+# Allow payloads to use keystore
+use_keystore(microdroid_app);
+
+# Allow payloads to use and manage their keys
+allow microdroid_app vm_payload_key:keystore2_key {
+    delete
+    get_info
+    manage_blob
+    rebind
+    use
+};
diff --git a/microdroid/sepolicy/system/private/microdroid_launcher.te b/microdroid/sepolicy/system/private/microdroid_launcher.te
deleted file mode 100644
index 6bcd4f1..0000000
--- a/microdroid/sepolicy/system/private/microdroid_launcher.te
+++ /dev/null
@@ -1,41 +0,0 @@
-# microdroid_launcher is a binary that loads a shared library from an apk and
-# executes it by calling an entry point in the library. This can be considered
-# as the native counterpart of app_process for Java.
-
-type microdroid_launcher, domain, coredomain;
-type microdroid_launcher_exec, exec_type, file_type, system_file_type;
-
-# Allow to communicate use, read and write over the adb connection.
-allow microdroid_launcher adbd:fd use;
-allow microdroid_launcher adbd:unix_stream_socket { read write };
-
-# microdroid_launcher is launched by microdroid_manager with fork/execvp.
-allow microdroid_launcher microdroid_manager:fd use;
-
-# Allow to use FDs inherited from the shell. This includes the FD opened for
-# the microdroid_launcher executable itself and the FD for adb connection.
-# TODO(b/186396070) remove this when this is executed from microdroid_manager
-userdebug_or_eng(`
-  allow microdroid_launcher shell:fd use;
-')
-
-# Allow to use terminal
-allow microdroid_launcher devpts:chr_file rw_file_perms;
-
-# Allow to set debug prop
-set_prop(microdroid_launcher, debug_prop)
-
-# Talk to binder services (for keystore)
-binder_use(microdroid_launcher);
-
-# Allow payloads to use keystore
-use_keystore(microdroid_launcher);
-
-# Allow payloads to use and manage their keys
-allow microdroid_launcher vm_payload_key:keystore2_key {
-    delete
-    get_info
-    manage_blob
-    rebind
-    use
-};
diff --git a/microdroid/sepolicy/system/private/microdroid_manager.te b/microdroid/sepolicy/system/private/microdroid_manager.te
index deb969c..fba3e71 100644
--- a/microdroid/sepolicy/system/private/microdroid_manager.te
+++ b/microdroid/sepolicy/system/private/microdroid_manager.te
@@ -13,7 +13,7 @@
 allow microdroid_manager vd_device:blk_file r_file_perms;
 
 # microdroid_manager start payload task via microdroid_launcher
-domain_auto_trans(microdroid_manager, microdroid_launcher_exec, microdroid_launcher);
+domain_auto_trans(microdroid_manager, microdroid_app_exec, microdroid_app);
 
 # Let microdroid_manager exec other files (e.g. payload command) in the same domain.
 # TODO(b/189706019) we need to a domain for the app process.
diff --git a/microdroid/sepolicy/system/private/property_contexts b/microdroid/sepolicy/system/private/property_contexts
index 605e912..1483f6f 100644
--- a/microdroid/sepolicy/system/private/property_contexts
+++ b/microdroid/sepolicy/system/private/property_contexts
@@ -1,151 +1,11 @@
-##########################
-# property service keys
-#
-#
-net.rmnet               u:object_r:net_radio_prop:s0
-net.gprs                u:object_r:net_radio_prop:s0
-net.ppp                 u:object_r:net_radio_prop:s0
-net.qmi                 u:object_r:net_radio_prop:s0
-net.lte                 u:object_r:net_radio_prop:s0
-net.cdma                u:object_r:net_radio_prop:s0
-net.dns                 u:object_r:net_dns_prop:s0
-ril.                    u:object_r:radio_prop:s0
-ro.ril.                 u:object_r:radio_prop:s0
-gsm.                    u:object_r:radio_prop:s0
-persist.radio           u:object_r:radio_prop:s0
+# property contexts for microdroid
+# microdroid only uses much fewer properties than normal Android, so every property is listed here.
+# The only exceptions are "debug.", "init.svc_debug_pid.", and "ctl." properties.
 
-net.                    u:object_r:system_prop:s0
-dev.                    u:object_r:system_prop:s0
-ro.runtime.             u:object_r:system_prop:s0
-ro.runtime.firstboot    u:object_r:firstboot_prop:s0
-hw.                     u:object_r:system_prop:s0
-ro.hw.                  u:object_r:system_prop:s0
-sys.                    u:object_r:system_prop:s0
-sys.audio.              u:object_r:audio_prop:s0
-sys.init.perf_lsm_hooks u:object_r:init_perf_lsm_hooks_prop:s0
-sys.cppreopt            u:object_r:cppreopt_prop:s0
-sys.lpdumpd             u:object_r:lpdumpd_prop:s0
-sys.powerctl            u:object_r:powerctl_prop:s0
-service.                u:object_r:system_prop:s0
-dhcp.                   u:object_r:dhcp_prop:s0
-dhcp.bt-pan.result      u:object_r:pan_result_prop:s0
-bluetooth.              u:object_r:bluetooth_prop:s0
+debug. u:object_r:debug_prop:s0 prefix
 
-debug.                  u:object_r:debug_prop:s0
-debug.db.               u:object_r:debuggerd_prop:s0
-dumpstate.              u:object_r:dumpstate_prop:s0
-dumpstate.options       u:object_r:dumpstate_options_prop:s0
-init.svc_debug_pid.     u:object_r:init_svc_debug_prop:s0
-llk.                    u:object_r:llkd_prop:s0
-khungtask.              u:object_r:llkd_prop:s0
-ro.llk.                 u:object_r:llkd_prop:s0
-ro.khungtask.           u:object_r:llkd_prop:s0
-log.                    u:object_r:log_prop:s0
-log.tag                 u:object_r:log_tag_prop:s0
-log.tag.WifiHAL         u:object_r:wifi_log_prop:s0
-security.perf_harden    u:object_r:shell_prop:s0
-security.lower_kptr_restrict u:object_r:lower_kptr_restrict_prop:s0
-service.adb.root        u:object_r:shell_prop:s0
-service.adb.tls.port    u:object_r:adbd_prop:s0
-persist.adb.wifi.       u:object_r:adbd_prop:s0
-persist.adb.tls_server.enable  u:object_r:system_adbd_prop:s0
+init.svc_debug_pid. u:object_r:init_svc_debug_prop:s0 prefix int
 
-persist.audio.          u:object_r:audio_prop:s0
-persist.bluetooth.      u:object_r:bluetooth_prop:s0
-persist.nfc_cfg.        u:object_r:nfc_prop:s0
-persist.debug.          u:object_r:persist_debug_prop:s0
-logd.                   u:object_r:logd_prop:s0
-persist.logd.           u:object_r:logd_prop:s0
-ro.logd.                u:object_r:logd_prop:s0
-persist.logd.security   u:object_r:device_logging_prop:s0
-persist.logd.logpersistd        u:object_r:logpersistd_logging_prop:s0
-logd.logpersistd        u:object_r:logpersistd_logging_prop:s0
-persist.log.tag         u:object_r:log_tag_prop:s0
-persist.mmc.            u:object_r:mmc_prop:s0
-persist.netd.stable_secret      u:object_r:netd_stable_secret_prop:s0
-persist.pm.mock-upgrade u:object_r:mock_ota_prop:s0
-persist.profcollectd.node_id    u:object_r:profcollectd_node_id_prop:s0     exact   string
-persist.sys.            u:object_r:system_prop:s0
-persist.sys.safemode    u:object_r:safemode_prop:s0
-persist.sys.theme       u:object_r:theme_prop:s0
-persist.sys.fflag.override.settings_dynamic_system    u:object_r:dynamic_system_prop:s0
-ro.sys.safemode         u:object_r:safemode_prop:s0
-persist.sys.audit_safemode      u:object_r:safemode_prop:s0
-persist.sys.dalvik.jvmtiagent   u:object_r:system_jvmti_agent_prop:s0
-persist.service.        u:object_r:system_prop:s0
-persist.service.bdroid. u:object_r:bluetooth_prop:s0
-persist.security.       u:object_r:system_prop:s0
-persist.traced.enable   u:object_r:traced_enabled_prop:s0
-traced.lazy.            u:object_r:traced_lazy_prop:s0
-persist.heapprofd.enable u:object_r:heapprofd_enabled_prop:s0
-persist.traced_perf.enable u:object_r:traced_perf_enabled_prop:s0
-persist.vendor.debug.wifi. u:object_r:persist_vendor_debug_wifi_prop:s0
-persist.vendor.overlay.  u:object_r:overlay_prop:s0
-ro.boot.vendor.overlay.  u:object_r:overlay_prop:s0
-ro.boottime.             u:object_r:boottime_prop:s0
-ro.serialno             u:object_r:serialno_prop:s0
-ro.boot.btmacaddr       u:object_r:bluetooth_prop:s0
-ro.boot.serialno        u:object_r:serialno_prop:s0
-ro.bt.                  u:object_r:bluetooth_prop:s0
-ro.boot.bootreason      u:object_r:bootloader_boot_reason_prop:s0
-persist.sys.boot.reason u:object_r:last_boot_reason_prop:s0
-sys.boot.reason         u:object_r:system_boot_reason_prop:s0
-sys.boot.reason.last    u:object_r:last_boot_reason_prop:s0
-pm.                     u:object_r:pm_prop:s0
-test.sys.boot.reason    u:object_r:test_boot_reason_prop:s0
-test.userspace_reboot.requested u:object_r:userspace_reboot_test_prop:s0
-sys.lmk.                u:object_r:system_lmk_prop:s0
-sys.trace.              u:object_r:system_trace_prop:s0
-wrap.                   u:object_r:zygote_wrap_prop:s0 prefix string
-
-# Suspend service properties
-suspend.max_sleep_time_millis u:object_r:suspend_prop:s0 exact uint
-suspend.base_sleep_time_millis u:object_r:suspend_prop:s0 exact uint
-suspend.backoff_threshold_count u:object_r:suspend_prop:s0 exact uint
-suspend.short_suspend_threshold_millis u:object_r:suspend_prop:s0 exact uint
-suspend.sleep_time_scale_factor u:object_r:suspend_prop:s0 exact double
-suspend.failed_suspend_backoff_enabled u:object_r:suspend_prop:s0 exact bool
-suspend.short_suspend_backoff_enabled u:object_r:suspend_prop:s0 exact bool
-
-# Fastbootd protocol control property
-fastbootd.protocol    u:object_r:fastbootd_protocol_prop:s0 exact enum usb tcp
-
-# adbd protoctl configuration property
-service.adb.tcp.port    u:object_r:adbd_config_prop:s0 exact int
-service.adb.transport   u:object_r:adbd_config_prop:s0 exact string
-
-# Boolean property set by system server upon boot indicating
-# if device is fully owned by organization instead of being
-# a personal device.
-ro.organization_owned   u:object_r:device_logging_prop:s0
-
-# selinux non-persistent properties
-selinux.restorecon_recursive   u:object_r:restorecon_prop:s0
-
-# default property context
-*                       u:object_r:default_prop:s0
-
-# data partition encryption properties
-vold.                   u:object_r:vold_prop:s0
-ro.crypto.              u:object_r:vold_prop:s0
-
-# ro.build.fingerprint is either set in /system/build.prop, or is
-# set at runtime by system_server.
-ro.build.fingerprint    u:object_r:fingerprint_prop:s0 exact string
-
-ro.persistent_properties.ready  u:object_r:persistent_properties_ready_prop:s0
-
-# ctl properties
-ctl.bootanim            u:object_r:ctl_bootanim_prop:s0
-ctl.dumpstate           u:object_r:ctl_dumpstate_prop:s0
-ctl.fuse_               u:object_r:ctl_fuse_prop:s0
-ctl.mdnsd               u:object_r:ctl_mdnsd_prop:s0
-ctl.ril-daemon          u:object_r:ctl_rildaemon_prop:s0
-ctl.bugreport           u:object_r:ctl_bugreport_prop:s0
-ctl.console             u:object_r:ctl_console_prop:s0
-ctl.                    u:object_r:ctl_default_prop:s0
-
-# Don't allow uncontrolled access to all services
 ctl.sigstop_on$         u:object_r:ctl_sigstop_prop:s0
 ctl.sigstop_off$        u:object_r:ctl_sigstop_prop:s0
 ctl.start$              u:object_r:ctl_start_prop:s0
@@ -155,1045 +15,86 @@
 ctl.interface_stop$     u:object_r:ctl_interface_stop_prop:s0
 ctl.interface_restart$  u:object_r:ctl_interface_restart_prop:s0
 
- # Restrict access to starting/stopping adbd
-ctl.start$adbd             u:object_r:ctl_adbd_prop:s0
-ctl.stop$adbd              u:object_r:ctl_adbd_prop:s0
-ctl.restart$adbd           u:object_r:ctl_adbd_prop:s0
+ctl.start$adbd   u:object_r:ctl_adbd_prop:s0
+ctl.stop$adbd    u:object_r:ctl_adbd_prop:s0
+ctl.restart$adbd u:object_r:ctl_adbd_prop:s0
 
-# Restrict access to starting/stopping gsid.
-ctl.start$gsid          u:object_r:ctl_gsid_prop:s0
-ctl.stop$gsid           u:object_r:ctl_gsid_prop:s0
-ctl.restart$gsid        u:object_r:ctl_gsid_prop:s0
+ctl.stop$apexd u:object_r:ctl_apexd_prop:s0
 
-# Restrict access to stopping apexd.
-ctl.stop$apexd          u:object_r:ctl_apexd_prop:s0
+ctl.fuse_   u:object_r:ctl_fuse_prop:s0
+ctl.console u:object_r:ctl_console_prop:s0
+ctl.        u:object_r:ctl_default_prop:s0
 
-# Restrict access to starting media.transcoding.
-ctl.start$media.transcoding  u:object_r:ctl_mediatranscoding_prop:s0
+dev.mnt.blk.root   u:object_r:system_prop:s0 exact string
+dev.mnt.blk.vendor u:object_r:system_prop:s0 exact string
 
-# Restrict access to restart dumpstate
-ctl.interface_restart$android.hardware.dumpstate u:object_r:ctl_dumpstate_prop:s0
+sys.init.perf_lsm_hooks u:object_r:init_perf_lsm_hooks_prop:s0 exact bool
 
-# Restrict access to control snapuserd
-ctl.start$snapuserd     u:object_r:ctl_snapuserd_prop:s0
-ctl.stop$snapuserd      u:object_r:ctl_snapuserd_prop:s0
-ctl.restart$snapuserd   u:object_r:ctl_snapuserd_prop:s0
+service.adb.root u:object_r:shell_prop:s0 exact bool
 
-# NFC properties
-nfc.                    u:object_r:nfc_prop:s0
+ro.logd.kernel u:object_r:logd_prop:s0 exact bool
 
-# These properties are not normally set by processes other than init.
-# They are only distinguished here for setting by qemu-props on the
-# emulator/goldfish.
-config.                 u:object_r:config_prop:s0
-ro.config.              u:object_r:config_prop:s0
-dalvik.                 u:object_r:dalvik_prop:s0
-ro.dalvik.              u:object_r:dalvik_prop:s0
+ro.boottime.adbd                      u:object_r:boottime_prop:s0 exact int
+ro.boottime.derive_sdk                u:object_r:boottime_prop:s0 exact int
+ro.boottime.hwservicemanager          u:object_r:boottime_prop:s0 exact int
+ro.boottime.init                      u:object_r:boottime_prop:s0 exact int
+ro.boottime.init.cold_boot_wait       u:object_r:boottime_prop:s0 exact int
+ro.boottime.init.first_stage          u:object_r:boottime_prop:s0 exact int
+ro.boottime.init.modules              u:object_r:boottime_prop:s0 exact int
+ro.boottime.init.selinux              u:object_r:boottime_prop:s0 exact int
+ro.boottime.keystore2                 u:object_r:boottime_prop:s0 exact int
+ro.boottime.logd                      u:object_r:boottime_prop:s0 exact int
+ro.boottime.logd-reinit               u:object_r:boottime_prop:s0 exact int
+ro.boottime.microdroid_manager        u:object_r:boottime_prop:s0 exact int
+ro.boottime.servicemanager            u:object_r:boottime_prop:s0 exact int
+ro.boottime.tombstoned                u:object_r:boottime_prop:s0 exact int
+ro.boottime.ueventd                   u:object_r:boottime_prop:s0 exact int
+ro.boottime.vendor.keymint-microdroid u:object_r:boottime_prop:s0 exact int
+ro.boottime.zipfuse                   u:object_r:boottime_prop:s0 exact int
 
-# qemu_hw_prop is read/written by both system and vendor.
-qemu.hw.mainkeys        u:object_r:qemu_hw_prop:s0 exact string
+ro.build.fingerprint u:object_r:fingerprint_prop:s0 exact string
 
-# qemu_sf_lcd_density_prop is read/written by both system and vendor.
-qemu.sf.lcd_density     u:object_r:qemu_sf_lcd_density_prop:s0 exact int
-
-# Shared between system server and wificond
-wifi.                   u:object_r:wifi_prop:s0
-wlan.                   u:object_r:wifi_prop:s0
-
-# Lowpan properties
-lowpan.                 u:object_r:lowpan_prop:s0
-ro.lowpan.              u:object_r:lowpan_prop:s0
-
-# heapprofd properties
-heapprofd.              u:object_r:heapprofd_prop:s0
-
-# hwservicemanager properties
-hwservicemanager.       u:object_r:hwservicemanager_prop:s0
-
-# Common default properties for vendor, odm, vendor_dlkm, and odm_dlkm.
-init.svc.odm.           u:object_r:vendor_default_prop:s0
-init.svc.vendor.        u:object_r:vendor_default_prop:s0
-ro.hardware.            u:object_r:vendor_default_prop:s0
-ro.odm.                 u:object_r:vendor_default_prop:s0
-ro.vendor.              u:object_r:vendor_default_prop:s0
-ro.vendor_dlkm.         u:object_r:vendor_default_prop:s0
-ro.odm_dlkm.            u:object_r:vendor_default_prop:s0
-odm.                    u:object_r:vendor_default_prop:s0
-persist.odm.            u:object_r:vendor_default_prop:s0
-persist.vendor.         u:object_r:vendor_default_prop:s0
-vendor.                 u:object_r:vendor_default_prop:s0
-
-# Properties that relate to time / time zone detection behavior.
-persist.time.           u:object_r:time_prop:s0
-
-# Properties that relate to server configurable flags
-device_config.reset_performed                       u:object_r:device_config_reset_performed_prop:s0
-persist.device_config.activity_manager_native_boot. u:object_r:device_config_activity_manager_native_boot_prop:s0
-persist.device_config.attempted_boot_count          u:object_r:device_config_boot_count_prop:s0
-persist.device_config.configuration.                u:object_r:device_config_configuration_prop:s0
-persist.device_config.connectivity.                 u:object_r:device_config_connectivity_prop:s0
-persist.device_config.input_native_boot.            u:object_r:device_config_input_native_boot_prop:s0
-persist.device_config.media_native.                 u:object_r:device_config_media_native_prop:s0
-persist.device_config.netd_native.                  u:object_r:device_config_netd_native_prop:s0
-persist.device_config.profcollect_native_boot.      u:object_r:device_config_profcollect_native_boot_prop:s0
-persist.device_config.runtime_native.               u:object_r:device_config_runtime_native_prop:s0
-persist.device_config.runtime_native_boot.          u:object_r:device_config_runtime_native_boot_prop:s0
-persist.device_config.statsd_native.                u:object_r:device_config_statsd_native_prop:s0
-persist.device_config.statsd_native_boot.           u:object_r:device_config_statsd_native_boot_prop:s0
-persist.device_config.storage_native_boot.          u:object_r:device_config_storage_native_boot_prop:s0
-persist.device_config.swcodec_native.               u:object_r:device_config_swcodec_native_prop:s0
-persist.device_config.window_manager_native_boot.   u:object_r:device_config_window_manager_native_boot_prop:s0
-
-# MM Events config props
-persist.mm_events.enabled                           u:object_r:mm_events_config_prop:s0 exact bool
-
-# Properties that relate to legacy server configurable flags
-persist.device_config.global_settings.sys_traced u:object_r:device_config_sys_traced_prop:s0
-
-apexd.                  u:object_r:apexd_prop:s0
-apexd.config.dm_delete.timeout           u:object_r:apexd_config_prop:s0 exact uint
-apexd.config.dm_create.timeout           u:object_r:apexd_config_prop:s0 exact uint
-persist.apexd.          u:object_r:apexd_prop:s0
-
-bpf.progs_loaded        u:object_r:bpf_progs_loaded_prop:s0
-
-gsid.                   u:object_r:gsid_prop:s0
-ro.gsid.                u:object_r:gsid_prop:s0
-
-# Property for disabling NNAPI vendor extensions on product image (used on GSI /product image,
-# which can't use NNAPI vendor extensions).
-ro.nnapi.extensions.deny_on_product                u:object_r:nnapi_ext_deny_product_prop:s0
-
-# Property that is set once ueventd finishes cold boot.
-ro.cold_boot_done       u:object_r:cold_boot_done_prop:s0
-
-# Properties that control performance operations.
-# Leave space to later set drop_caches to 1, 2, and 4.
-perf.drop_caches        u:object_r:perf_drop_caches_prop:s0 exact enum 0 3
-
-# Charger properties
-ro.charger.                 u:object_r:charger_prop:s0
-sys.boot_from_charger_mode  u:object_r:charger_status_prop:s0 exact int
-ro.enable_boot_charger_mode u:object_r:charger_config_prop:s0 exact bool
-
-# Virtual A/B properties
-ro.virtual_ab.enabled   u:object_r:virtual_ab_prop:s0 exact bool
-ro.virtual_ab.retrofit  u:object_r:virtual_ab_prop:s0 exact bool
-ro.virtual_ab.compression.enabled  u:object_r:virtual_ab_prop:s0 exact bool
-
-ro.product.ab_ota_partitions u:object_r:ota_prop:s0 exact string
-# Property to set/clear the warm reset flag after an OTA update.
-ota.warm_reset  u:object_r:ota_prop:s0
-# The vbmeta digest for the inactive slot. It can be set after installing
-# ota updates to the b partition of a/b devices.
-ota.other.vbmeta_digest  u:object_r:ota_prop:s0 exact string
-
-# Module properties
-com.android.sdkext.                  u:object_r:module_sdkextensions_prop:s0
-persist.com.android.sdkext.          u:object_r:module_sdkextensions_prop:s0
-
-# Connectivity module
-net.464xlat.cellular.enabled         u:object_r:net_464xlat_fromvendor_prop:s0 exact bool
-net.tcp_def_init_rwnd                u:object_r:net_connectivity_prop:s0 exact int
-
-# Userspace reboot properties
-sys.userspace_reboot.log.         u:object_r:userspace_reboot_log_prop:s0
-persist.sys.userspace_reboot.log. u:object_r:userspace_reboot_log_prop:s0
-
-# Integer property which is used in libgui to configure the number of frames
-# tracked by buffer queue's frame event timing history. The property is set
-# by devices with video decoding pipelines long enough to overflow the default
-# history size.
-ro.lib_gui.frame_event_history_size u:object_r:bq_config_prop:s0
-
-af.fast_track_multiplier         u:object_r:audio_config_prop:s0 exact int
-ro.af.client_heap_size_kbyte     u:object_r:audio_config_prop:s0 exact int
-ro.audio.flinger_standbytime_ms  u:object_r:audio_config_prop:s0 exact int
-
-audio.camerasound.force         u:object_r:audio_config_prop:s0 exact bool
-audio.deep_buffer.media         u:object_r:audio_config_prop:s0 exact bool
-audio.offload.video             u:object_r:audio_config_prop:s0 exact bool
-audio.offload.min.duration.secs u:object_r:audio_config_prop:s0 exact int
-
-ro.audio.ignore_effects   u:object_r:audio_config_prop:s0 exact bool
-ro.audio.monitorRotation  u:object_r:audio_config_prop:s0 exact bool
-ro.audio.offload_wakelock u:object_r:audio_config_prop:s0 exact bool
-
-persist.config.calibration_fac u:object_r:camera_calibration_prop:s0 exact string
-
-config.disable_cameraservice u:object_r:camera_config_prop:s0 exact bool
-
-camera.disable_zsl_mode u:object_r:camera_config_prop:s0 exact bool
-camera.fifo.disable     u:object_r:camera_config_prop:s0 exact bool
-ro.camera.notify_nfc    u:object_r:camera_config_prop:s0 exact bool
-ro.camera.enableLazyHal u:object_r:camera_config_prop:s0 exact bool
-
-ro.camerax.extensions.enabled u:object_r:camerax_extensions_prop:s0 exact bool
-
-# ART properties
-dalvik.vm.                 u:object_r:dalvik_config_prop:s0
-ro.dalvik.vm.              u:object_r:dalvik_config_prop:s0
-ro.zygote                  u:object_r:dalvik_config_prop:s0 exact string
-
-# A set of ART properties listed explicitly for compatibility purposes.
-ro.dalvik.vm.native.bridge u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.always_debuggable                   u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.appimageformat                      u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.backgroundgctype                    u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.boot-dex2oat-cpu-set                u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.boot-dex2oat-threads                u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.boot-image                          u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.bgdexopt.new-classes-percent        u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.bgdexopt.new-methods-percent        u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.checkjni                            u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.dex2oat-Xms                         u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.dex2oat-Xmx                         u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.dex2oat-cpu-set                     u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.dex2oat-filter                      u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.dex2oat-flags                       u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.dex2oat-max-image-block-size        u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.dex2oat-minidebuginfo               u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.dex2oat-resolve-startup-strings     u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.dex2oat-threads                     u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.dex2oat-updatable-bcp-packages-file u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.dex2oat-very-large                  u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.dex2oat-swap                        u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.dex2oat64.enabled                   u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.dexopt.secondary                    u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.dexopt.thermal-cutoff               u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.execution-mode                      u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.extra-opts                          u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.foreground-heap-growth-multiplier   u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.gctype                              u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.heapgrowthlimit                     u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.heapmaxfree                         u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.heapminfree                         u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.heapsize                            u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.heapstartsize                       u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.heaptargetutilization               u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.hot-startup-method-samples          u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.image-dex2oat-Xms                   u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.image-dex2oat-Xmx                   u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.image-dex2oat-cpu-set               u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.image-dex2oat-filter                u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.image-dex2oat-flags                 u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.image-dex2oat-threads               u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.isa.arm.features                    u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.arm.variant                     u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.arm64.features                  u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.arm64.variant                   u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.mips.features                   u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.mips.variant                    u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.mips64.features                 u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.mips64.variant                  u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.unknown.features                u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.unknown.variant                 u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.x86.features                    u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.x86.variant                     u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.x86_64.features                 u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.isa.x86_64.variant                  u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.jitinitialsize                      u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.jitmaxsize                          u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.jitprithreadweight                  u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.jitthreshold                        u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.jittransitionweight                 u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.jniopts                             u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.lockprof.threshold                  u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.method-trace                        u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.method-trace-file                   u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.method-trace-file-siz               u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.method-trace-stream                 u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.profilesystemserver                 u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.profilebootclasspath                u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.ps-min-save-period-ms               u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.ps-resolved-classes-delay-ms        u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.restore-dex2oat-cpu-set             u:object_r:dalvik_config_prop:s0 exact string
-dalvik.vm.restore-dex2oat-threads             u:object_r:dalvik_config_prop:s0 exact int
-dalvik.vm.usejit                              u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.usejitprofiles                      u:object_r:dalvik_config_prop:s0 exact bool
-dalvik.vm.zygote.max-boot-retry               u:object_r:dalvik_config_prop:s0 exact int
-
-persist.sys.dalvik.vm.lib.2 u:object_r:dalvik_runtime_prop:s0 exact string
-
-keyguard.no_require_sim u:object_r:keyguard_config_prop:s0 exact bool
-
-media.c2.dmabuf.padding                      u:object_r:codec2_config_prop:s0 exact int
-
-media.recorder.show_manufacturer_and_model   u:object_r:media_config_prop:s0 exact bool
-media.stagefright.cache-params               u:object_r:media_config_prop:s0 exact string
-media.stagefright.enable-aac                 u:object_r:media_config_prop:s0 exact bool
-media.stagefright.enable-fma2dp              u:object_r:media_config_prop:s0 exact bool
-media.stagefright.enable-http                u:object_r:media_config_prop:s0 exact bool
-media.stagefright.enable-player              u:object_r:media_config_prop:s0 exact bool
-media.stagefright.enable-qcp                 u:object_r:media_config_prop:s0 exact bool
-media.stagefright.enable-scan                u:object_r:media_config_prop:s0 exact bool
-media.stagefright.thumbnail.prefer_hw_codecs u:object_r:media_config_prop:s0 exact bool
-persist.sys.media.avsync                     u:object_r:media_config_prop:s0 exact bool
-
-persist.bluetooth.a2dp_offload.cap             u:object_r:bluetooth_a2dp_offload_prop:s0 exact string
-persist.bluetooth.a2dp_offload.disabled        u:object_r:bluetooth_a2dp_offload_prop:s0 exact bool
-persist.bluetooth.bluetooth_audio_hal.disabled u:object_r:bluetooth_audio_hal_prop:s0 exact bool
-persist.bluetooth.btsnoopenable                u:object_r:exported_bluetooth_prop:s0 exact bool
-
-persist.radio.multisim.config u:object_r:radio_control_prop:s0 exact string
-
-persist.sys.hdmi.keep_awake                                        u:object_r:hdmi_config_prop:s0 exact bool
-ro.hdmi.cec_device_types                                           u:object_r:hdmi_config_prop:s0 exact string
-ro.hdmi.device_type                                                u:object_r:hdmi_config_prop:s0 exact string
-ro.hdmi.set_menu_language                                          u:object_r:hdmi_config_prop:s0 exact bool
-ro.hdmi.cec.source.set_menu_language.enabled                       u:object_r:hdmi_config_prop:s0 exact bool
-ro.hdmi.property_sytem_audio_device_arc_port                       u:object_r:hdmi_config_prop:s0 exact string
-ro.hdmi.cec_audio_device_forward_volume_keys_system_audio_mode_off u:object_r:hdmi_config_prop:s0 exact bool
-ro.hdmi.property_is_device_hdmi_cec_switch                         u:object_r:hdmi_config_prop:s0 exact bool
-ro.hdmi.wake_on_hotplug                                            u:object_r:hdmi_config_prop:s0 exact bool
-ro.hdmi.cec.source.send_standby_on_sleep                           u:object_r:hdmi_config_prop:s0 exact enum to_tv broadcast none
-ro.hdmi.cec.source.playback_device_action_on_routing_control       u:object_r:hdmi_config_prop:s0 exact enum none wake_up_only wake_up_and_send_active_source
-
-pm.dexopt.ab-ota                            u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.bg-dexopt                         u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.boot                              u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.cmdline                           u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.disable_bg_dexopt                 u:object_r:exported_pm_prop:s0 exact bool
-pm.dexopt.downgrade_after_inactive_days     u:object_r:exported_pm_prop:s0 exact int
-pm.dexopt.first-boot                        u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.inactive                          u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.install                           u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.install-fast                      u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.install-bulk                      u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.install-bulk-secondary            u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.install-bulk-downgraded           u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.install-bulk-secondary-downgraded u:object_r:exported_pm_prop:s0 exact string
-pm.dexopt.shared                            u:object_r:exported_pm_prop:s0 exact string
-
-ro.apk_verity.mode u:object_r:apk_verity_prop:s0 exact int
-
-ro.bluetooth.a2dp_offload.supported u:object_r:bluetooth_a2dp_offload_prop:s0 exact bool
-
-ro.boot.vendor.overlay.theme u:object_r:exported_overlay_prop:s0 exact string
-
-ro.bt.bdaddr_path u:object_r:exported_bluetooth_prop:s0 exact string
-
-ro.config.alarm_alert         u:object_r:systemsound_config_prop:s0 exact string
-ro.config.alarm_vol_default   u:object_r:systemsound_config_prop:s0 exact int
-ro.config.alarm_vol_steps     u:object_r:systemsound_config_prop:s0 exact int
-ro.config.media_vol_default   u:object_r:systemsound_config_prop:s0 exact int
-ro.config.media_vol_steps     u:object_r:systemsound_config_prop:s0 exact int
-ro.config.notification_sound  u:object_r:systemsound_config_prop:s0 exact string
-ro.config.ringtone            u:object_r:systemsound_config_prop:s0 exact string
-ro.config.system_vol_default  u:object_r:systemsound_config_prop:s0 exact int
-ro.config.system_vol_steps    u:object_r:systemsound_config_prop:s0 exact int
-ro.config.vc_call_vol_default u:object_r:systemsound_config_prop:s0 exact int
-
-ro.control_privapp_permissions u:object_r:packagemanager_config_prop:s0 exact enum disable enforce log
-ro.cp_system_other_odex        u:object_r:packagemanager_config_prop:s0 exact bool
-
-ro.crypto.allow_encrypt_override                u:object_r:vold_config_prop:s0 exact bool
-ro.crypto.dm_default_key.options_format.version u:object_r:vold_config_prop:s0 exact int
-ro.crypto.fde_algorithm                         u:object_r:vold_config_prop:s0 exact string
-ro.crypto.fde_sector_size                       u:object_r:vold_config_prop:s0 exact int
-ro.crypto.scrypt_params                         u:object_r:vold_config_prop:s0 exact string
-ro.crypto.set_dun                               u:object_r:vold_config_prop:s0 exact bool
-ro.crypto.volume.contents_mode                  u:object_r:vold_config_prop:s0 exact string
-ro.crypto.volume.filenames_mode                 u:object_r:vold_config_prop:s0 exact string
-ro.crypto.volume.metadata.encryption            u:object_r:vold_config_prop:s0 exact string
-ro.crypto.volume.metadata.method                u:object_r:vold_config_prop:s0 exact string
-ro.crypto.volume.options                        u:object_r:vold_config_prop:s0 exact string
-
-external_storage.projid.enabled   u:object_r:storage_config_prop:s0 exact bool
-external_storage.casefold.enabled u:object_r:storage_config_prop:s0 exact bool
-external_storage.sdcardfs.enabled u:object_r:storage_config_prop:s0 exact bool
-external_storage.cross_user.enabled u:object_r:storage_config_prop:s0 exact bool
-
-ro.config.per_app_memcg         u:object_r:lmkd_config_prop:s0 exact bool
-ro.lmk.critical                 u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.critical_upgrade         u:object_r:lmkd_config_prop:s0 exact bool
-ro.lmk.debug                    u:object_r:lmkd_config_prop:s0 exact bool
-ro.lmk.downgrade_pressure       u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.kill_heaviest_task       u:object_r:lmkd_config_prop:s0 exact bool
-ro.lmk.kill_timeout_ms          u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.log_stats                u:object_r:lmkd_config_prop:s0 exact bool
-ro.lmk.low                      u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.medium                   u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.psi_partial_stall_ms     u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.psi_complete_stall_ms    u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.swap_free_low_percentage u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.swap_util_max            u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.thrashing_limit          u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.thrashing_limit_critical u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.thrashing_limit_decay    u:object_r:lmkd_config_prop:s0 exact int
-ro.lmk.use_minfree_levels       u:object_r:lmkd_config_prop:s0 exact bool
-ro.lmk.upgrade_pressure         u:object_r:lmkd_config_prop:s0 exact int
-lmkd.reinit                     u:object_r:lmkd_prop:s0 exact int
-
-ro.media.xml_variant.codecs             u:object_r:media_variant_prop:s0 exact string
-ro.media.xml_variant.codecs_performance u:object_r:media_variant_prop:s0 exact string
-ro.media.xml_variant.profiles           u:object_r:media_variant_prop:s0 exact string
-
-ro.minui.default_rotation u:object_r:recovery_config_prop:s0 exact string
-ro.minui.overscan_percent u:object_r:recovery_config_prop:s0 exact int
-ro.minui.pixel_format     u:object_r:recovery_config_prop:s0 exact string
-
-ro.oem_unlock_supported u:object_r:oem_unlock_prop:s0 exact int
-
-ro.rebootescrow.device u:object_r:rebootescrow_hal_prop:s0 exact string
-
-ro.storage_manager.enabled     u:object_r:storagemanager_config_prop:s0 exact bool
-ro.storage_manager.show_opt_in u:object_r:storagemanager_config_prop:s0 exact bool
-
-ro.vehicle.hal u:object_r:vehicle_hal_prop:s0 exact string
-
-ro.vendor.build.security_patch u:object_r:vendor_security_patch_level_prop:s0 exact string
-
-ro.zram.mark_idle_delay_mins    u:object_r:zram_config_prop:s0 exact int
-ro.zram.first_wb_delay_mins     u:object_r:zram_config_prop:s0 exact int
-ro.zram.periodic_wb_delay_hours u:object_r:zram_config_prop:s0 exact int
-zram.force_writeback            u:object_r:zram_config_prop:s0 exact bool
-persist.sys.zram_enabled        u:object_r:zram_control_prop:s0 exact bool
-
-sendbug.preferred.domain u:object_r:sendbug_config_prop:s0 exact string
-
-persist.sys.usb.usbradio.config u:object_r:usb_control_prop:s0 exact string
-
-sys.usb.config     u:object_r:usb_control_prop:s0 exact string
-sys.usb.configfs   u:object_r:usb_control_prop:s0 exact int
-sys.usb.controller u:object_r:usb_control_prop:s0 exact string
-sys.usb.state      u:object_r:usb_control_prop:s0 exact string
-
-sys.usb.mtp.device_type u:object_r:usb_config_prop:s0 exact int
-
-sys.usb.config. u:object_r:usb_prop:s0
-
-sys.usb.ffs.aio_compat u:object_r:ffs_config_prop:s0 exact bool
-sys.usb.ffs.max_read   u:object_r:ffs_config_prop:s0 exact int
-sys.usb.ffs.max_write  u:object_r:ffs_config_prop:s0 exact int
-
-sys.usb.ffs.ready     u:object_r:ffs_control_prop:s0 exact bool
-sys.usb.ffs.mtp.ready u:object_r:ffs_control_prop:s0 exact bool
-
-tombstoned.max_tombstone_count u:object_r:tombstone_config_prop:s0 exact int
-
-vold.post_fs_data_done u:object_r:vold_post_fs_data_prop:s0 exact int
+hwservicemanager.ready u:object_r:hwservicemanager_prop:s0 exact bool
 
 apexd.status u:object_r:apexd_prop:s0 exact enum starting activated ready
 
-odsign.key.done u:object_r:odsign_prop:s0 exact bool
-odsign.verification.done u:object_r:odsign_prop:s0 exact bool
-odsign.verification.success u:object_r:odsign_prop:s0 exact bool
+ro.cold_boot_done u:object_r:cold_boot_done_prop:s0 exact bool
 
-dev.bootcomplete   u:object_r:boot_status_prop:s0 exact bool
-sys.boot_completed u:object_r:boot_status_prop:s0 exact bool
+sys.usb.controller u:object_r:usb_control_prop:s0 exact string
 
-persist.sys.device_provisioned u:object_r:provisioned_prop:s0 exact string
+init.svc.derive_sdk                u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.hwservicemanager          u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.keystore2                 u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.logd                      u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.logd-reinit               u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.microdroid_manager        u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.servicemanager            u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.ueventd                   u:object_r:init_service_status_private_prop:s0 exact string
+init.svc.zipfuse                   u:object_r:init_service_status_private_prop:s0 exact string
 
-persist.sys.theme               u:object_r:theme_prop:s0 exact string
+init.svc.adbd       u:object_r:init_service_status_prop:s0 exact string
+init.svc.tombstoned u:object_r:init_service_status_prop:s0 exact string
 
-sys.retaildemo.enabled u:object_r:retaildemo_prop:s0 exact int
+init.svc.vendor.keymint-microdroid u:object_r:vendor_default_prop:s0 exact string
 
-sys.user.0.ce_available u:object_r:exported3_system_prop:s0 exact bool
+ro.boot.hardware u:object_r:bootloader_prop:s0 exact string
+ro.baseband      u:object_r:bootloader_prop:s0 exact string
+ro.bootloader    u:object_r:bootloader_prop:s0 exact string
+ro.bootmode      u:object_r:bootloader_prop:s0 exact string
+ro.hardware      u:object_r:bootloader_prop:s0 exact string
+ro.revision      u:object_r:bootloader_prop:s0 exact string
 
-aac_drc_boost            u:object_r:aac_drc_prop:s0 exact int
-aac_drc_cut              u:object_r:aac_drc_prop:s0 exact int
-aac_drc_enc_target_level u:object_r:aac_drc_prop:s0 exact int
-aac_drc_heavy            u:object_r:aac_drc_prop:s0 exact int
-aac_drc_reference_level  u:object_r:aac_drc_prop:s0 exact int
-ro.aac_drc_effect_type   u:object_r:aac_drc_prop:s0 exact int
-
-build.version.extensions. u:object_r:module_sdkextensions_prop:s0 prefix int
-
-drm.64bit.enabled            u:object_r:mediadrm_config_prop:s0 exact bool
-media.mediadrmservice.enable u:object_r:mediadrm_config_prop:s0 exact bool
-
-drm.service.enabled u:object_r:drm_service_config_prop:s0 exact bool
-
-dumpstate.dry_run u:object_r:exported_dumpstate_prop:s0 exact bool
-dumpstate.unroot  u:object_r:exported_dumpstate_prop:s0 exact bool
-persist.dumpstate.verbose_logging.enabled u:object_r:hal_dumpstate_config_prop:s0 exact bool
-
-hal.instrumentation.enable u:object_r:hal_instrumentation_prop:s0 exact bool
-
-# default contexts only accessible by coredomain
-init.svc. u:object_r:init_service_status_private_prop:s0 prefix string
-
-# Globally-readable init service props
-init.svc.adbd           u:object_r:init_service_status_prop:s0 exact string
-init.svc.bugreport      u:object_r:init_service_status_prop:s0 exact string
-init.svc.bugreportd     u:object_r:init_service_status_prop:s0 exact string
-init.svc.console        u:object_r:init_service_status_prop:s0 exact string
-init.svc.dumpstatez     u:object_r:init_service_status_prop:s0 exact string
-init.svc.mediadrm       u:object_r:init_service_status_prop:s0 exact string
-init.svc.statsd         u:object_r:init_service_status_prop:s0 exact string
-init.svc.surfaceflinger u:object_r:init_service_status_prop:s0 exact string
-init.svc.tombstoned     u:object_r:init_service_status_prop:s0 exact string
-init.svc.zygote         u:object_r:init_service_status_prop:s0 exact string
-
-libc.debug.malloc.options u:object_r:libc_debug_prop:s0 exact string
-libc.debug.malloc.program u:object_r:libc_debug_prop:s0 exact string
-libc.debug.hooks.enable   u:object_r:libc_debug_prop:s0 exact string
-
-# shell-only props for ARM memory tagging (MTE).
-arm64.memtag. u:object_r:arm64_memtag_prop:s0 prefix string
-
-net.redirect_socket_calls.hooked u:object_r:socket_hook_prop:s0 exact bool
-
-persist.sys.locale       u:object_r:exported_system_prop:s0 exact string
-persist.sys.timezone     u:object_r:exported_system_prop:s0 exact string
-persist.sys.test_harness u:object_r:test_harness_prop:s0 exact bool
-
-ro.arch u:object_r:build_prop:s0 exact string
-
-# ro.boot. properties are set based on kernel commandline arguments, which are vendor owned.
-ro.boot.                   u:object_r:bootloader_prop:s0
-ro.boot.avb_version        u:object_r:bootloader_prop:s0 exact string
-ro.boot.baseband           u:object_r:bootloader_prop:s0 exact string
-ro.boot.bootdevice         u:object_r:bootloader_prop:s0 exact string
-ro.boot.bootloader         u:object_r:bootloader_prop:s0 exact string
-ro.boot.boottime           u:object_r:bootloader_prop:s0 exact string
-ro.boot.console            u:object_r:bootloader_prop:s0 exact string
-ro.boot.hardware           u:object_r:bootloader_prop:s0 exact string
-ro.boot.hardware.color     u:object_r:bootloader_prop:s0 exact string
-ro.boot.hardware.sku       u:object_r:bootloader_prop:s0 exact string
-ro.boot.keymaster          u:object_r:bootloader_prop:s0 exact string
-ro.boot.mode               u:object_r:bootloader_prop:s0 exact string
-# Populated on Android Studio Emulator (for emulator specific workarounds)
-ro.boot.qemu               u:object_r:bootloader_prop:s0 exact bool
-ro.boot.revision           u:object_r:bootloader_prop:s0 exact string
-ro.boot.vbmeta.avb_version u:object_r:bootloader_prop:s0 exact string
-ro.boot.verifiedbootstate  u:object_r:bootloader_prop:s0 exact string
-ro.boot.veritymode         u:object_r:bootloader_prop:s0 exact string
-
-# These ro.X properties are set to values of ro.boot.X by property_service.
-ro.baseband   u:object_r:bootloader_prop:s0 exact string
-ro.bootloader u:object_r:bootloader_prop:s0 exact string
-ro.bootmode   u:object_r:bootloader_prop:s0 exact string
-ro.hardware   u:object_r:bootloader_prop:s0 exact string
-ro.revision   u:object_r:bootloader_prop:s0 exact string
-
-ro.boot.dynamic_partitions          u:object_r:exported_default_prop:s0 exact string
-ro.boot.dynamic_partitions_retrofit u:object_r:exported_default_prop:s0 exact string
-
-ro.boottime.init.mount.data u:object_r:boottime_public_prop:s0 exact string
-ro.boottime.init.fsck.data  u:object_r:boottime_public_prop:s0 exact string
-
-ro.build.characteristics                  u:object_r:build_prop:s0 exact string
-ro.build.date                             u:object_r:build_prop:s0 exact string
-ro.build.date.utc                         u:object_r:build_prop:s0 exact int
-ro.build.description                      u:object_r:build_prop:s0 exact string
-ro.build.display.id                       u:object_r:build_prop:s0 exact string
-ro.build.flavor                           u:object_r:build_prop:s0 exact string
-ro.build.host                             u:object_r:build_prop:s0 exact string
-ro.build.id                               u:object_r:build_prop:s0 exact string
-ro.build.product                          u:object_r:build_prop:s0 exact string
-ro.build.system_root_image                u:object_r:build_prop:s0 exact bool
-ro.build.tags                             u:object_r:build_prop:s0 exact string
-ro.build.type                             u:object_r:build_prop:s0 exact string
-ro.build.user                             u:object_r:build_prop:s0 exact string
-ro.build.version.all_codenames            u:object_r:build_prop:s0 exact string
-ro.build.version.base_os                  u:object_r:build_prop:s0 exact string
-ro.build.version.codename                 u:object_r:build_prop:s0 exact string
-ro.build.version.incremental              u:object_r:build_prop:s0 exact string
-ro.build.version.min_supported_target_sdk u:object_r:build_prop:s0 exact int
-ro.build.version.preview_sdk              u:object_r:build_prop:s0 exact int
-ro.build.version.preview_sdk_fingerprint  u:object_r:build_prop:s0 exact string
-ro.build.version.release                  u:object_r:build_prop:s0 exact string
-ro.build.version.release_or_codename      u:object_r:build_prop:s0 exact string
-ro.build.version.sdk                      u:object_r:build_prop:s0 exact int
-ro.build.version.security_patch           u:object_r:build_prop:s0 exact string
-
-ro.actionable_compatible_property.enabled u:object_r:build_prop:s0 exact bool
-
-ro.debuggable u:object_r:build_prop:s0 exact bool
-
-ro.treble.enabled u:object_r:build_prop:s0 exact bool
-
-ro.product.cpu.abi       u:object_r:build_prop:s0 exact string
-ro.product.cpu.abilist   u:object_r:build_prop:s0 exact string
-ro.product.cpu.abilist32 u:object_r:build_prop:s0 exact string
-ro.product.cpu.abilist64 u:object_r:build_prop:s0 exact string
-
-ro.product.system.brand        u:object_r:build_prop:s0 exact string
-ro.product.system.device       u:object_r:build_prop:s0 exact string
-ro.product.system.manufacturer u:object_r:build_prop:s0 exact string
-ro.product.system.model        u:object_r:build_prop:s0 exact string
-ro.product.system.name         u:object_r:build_prop:s0 exact string
-
-ro.system.build.date                        u:object_r:build_prop:s0 exact string
-ro.system.build.date.utc                    u:object_r:build_prop:s0 exact int
-ro.system.build.fingerprint                 u:object_r:build_prop:s0 exact string
-ro.system.build.id                          u:object_r:build_prop:s0 exact string
-ro.system.build.tags                        u:object_r:build_prop:s0 exact string
-ro.system.build.type                        u:object_r:build_prop:s0 exact string
-ro.system.build.version.incremental         u:object_r:build_prop:s0 exact string
-ro.system.build.version.release             u:object_r:build_prop:s0 exact string
-ro.system.build.version.release_or_codename u:object_r:build_prop:s0 exact string
-ro.system.build.version.sdk                 u:object_r:build_prop:s0 exact int
-
-ro.adb.secure u:object_r:build_prop:s0 exact bool
-ro.secure     u:object_r:build_prop:s0 exact int
-
-ro.product.system_ext.brand        u:object_r:build_prop:s0 exact string
-ro.product.system_ext.device       u:object_r:build_prop:s0 exact string
-ro.product.system_ext.manufacturer u:object_r:build_prop:s0 exact string
-ro.product.system_ext.model        u:object_r:build_prop:s0 exact string
-ro.product.system_ext.name         u:object_r:build_prop:s0 exact string
-
-ro.system_ext.build.date                        u:object_r:build_prop:s0 exact string
-ro.system_ext.build.date.utc                    u:object_r:build_prop:s0 exact int
-ro.system_ext.build.fingerprint                 u:object_r:build_prop:s0 exact string
-ro.system_ext.build.id                          u:object_r:build_prop:s0 exact string
-ro.system_ext.build.tags                        u:object_r:build_prop:s0 exact string
-ro.system_ext.build.type                        u:object_r:build_prop:s0 exact string
-ro.system_ext.build.version.incremental         u:object_r:build_prop:s0 exact string
-ro.system_ext.build.version.release             u:object_r:build_prop:s0 exact string
-ro.system_ext.build.version.release_or_codename u:object_r:build_prop:s0 exact string
-ro.system_ext.build.version.sdk                 u:object_r:build_prop:s0 exact int
-
-# These ro.product.product.* and ro.product.build.* are set by /product/etc/build.prop
-ro.product.product.brand        u:object_r:build_prop:s0 exact string
-ro.product.product.device       u:object_r:build_prop:s0 exact string
-ro.product.product.manufacturer u:object_r:build_prop:s0 exact string
-ro.product.product.model        u:object_r:build_prop:s0 exact string
-ro.product.product.name         u:object_r:build_prop:s0 exact string
-
-ro.product.build.date                        u:object_r:build_prop:s0 exact string
-ro.product.build.date.utc                    u:object_r:build_prop:s0 exact int
-ro.product.build.fingerprint                 u:object_r:build_prop:s0 exact string
-ro.product.build.id                          u:object_r:build_prop:s0 exact string
-ro.product.build.tags                        u:object_r:build_prop:s0 exact string
-ro.product.build.type                        u:object_r:build_prop:s0 exact string
-ro.product.build.version.incremental         u:object_r:build_prop:s0 exact string
-ro.product.build.version.release             u:object_r:build_prop:s0 exact string
-ro.product.build.version.release_or_codename u:object_r:build_prop:s0 exact string
-ro.product.build.version.sdk                 u:object_r:build_prop:s0 exact int
-
-# These 5 properties are set by property_service
-ro.product.brand         u:object_r:build_prop:s0 exact string
-ro.product.device        u:object_r:build_prop:s0 exact string
-ro.product.manufacturer  u:object_r:build_prop:s0 exact string
-ro.product.model         u:object_r:build_prop:s0 exact string
-ro.product.name          u:object_r:build_prop:s0 exact string
-
-# Sanitizer properties
-ro.sanitize.address          u:object_r:build_prop:s0 exact bool
-ro.sanitize.cfi              u:object_r:build_prop:s0 exact bool
-ro.sanitize.default-ub       u:object_r:build_prop:s0 exact bool
-ro.sanitize.fuzzer           u:object_r:build_prop:s0 exact bool
-ro.sanitize.hwaddress        u:object_r:build_prop:s0 exact bool
-ro.sanitize.integer_overflow u:object_r:build_prop:s0 exact bool
-ro.sanitize.safe-stack       u:object_r:build_prop:s0 exact bool
-ro.sanitize.scudo            u:object_r:build_prop:s0 exact bool
-ro.sanitize.thread           u:object_r:build_prop:s0 exact bool
-ro.sanitize.undefined        u:object_r:build_prop:s0 exact bool
-
-# All odm build props are set by /odm/build.prop
-ro.odm.build.date                u:object_r:build_odm_prop:s0 exact string
-ro.odm.build.date.utc            u:object_r:build_odm_prop:s0 exact int
-ro.odm.build.fingerprint         u:object_r:build_odm_prop:s0 exact string
-ro.odm.build.version.incremental u:object_r:build_odm_prop:s0 exact string
-ro.odm.build.media_performance_class   u:object_r:build_odm_prop:s0 exact int
-
-ro.product.odm.brand        u:object_r:build_odm_prop:s0 exact string
-ro.product.odm.device       u:object_r:build_odm_prop:s0 exact string
-ro.product.odm.manufacturer u:object_r:build_odm_prop:s0 exact string
-ro.product.odm.model        u:object_r:build_odm_prop:s0 exact string
-ro.product.odm.name         u:object_r:build_odm_prop:s0 exact string
-
-# All vendor_dlkm build props are set by /vendor_dlkm/etc/build.prop
-ro.vendor_dlkm.build.date                        u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.date.utc                    u:object_r:build_vendor_prop:s0 exact int
-ro.vendor_dlkm.build.fingerprint                 u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.id                          u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.tags                        u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.type                        u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.version.incremental         u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.version.release             u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.version.release_or_codename u:object_r:build_vendor_prop:s0 exact string
-ro.vendor_dlkm.build.version.sdk                 u:object_r:build_vendor_prop:s0 exact int
-
-# All odm_dlkm build props are set by /odm_dlkm/etc/build.prop
-ro.product.odm_dlkm.brand        u:object_r:build_odm_prop:s0 exact string
-ro.product.odm_dlkm.device       u:object_r:build_odm_prop:s0 exact string
-ro.product.odm_dlkm.manufacturer u:object_r:build_odm_prop:s0 exact string
-ro.product.odm_dlkm.model        u:object_r:build_odm_prop:s0 exact string
-ro.product.odm_dlkm.name         u:object_r:build_odm_prop:s0 exact string
-
-ro.odm_dlkm.build.date                        u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.date.utc                    u:object_r:build_odm_prop:s0 exact int
-ro.odm_dlkm.build.fingerprint                 u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.id                          u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.tags                        u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.type                        u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.version.incremental         u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.version.release             u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.version.release_or_codename u:object_r:build_odm_prop:s0 exact string
-ro.odm_dlkm.build.version.sdk                 u:object_r:build_odm_prop:s0 exact int
-
-# enforces debugfs restrictions in non-user builds, set by /vendor/build.prop
-ro.product.debugfs_restrictions.enabled u:object_r:debugfs_restriction_prop:s0 exact bool
-
-# All vendor build props are set by /vendor/build.prop
-ro.vendor.build.date                        u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.date.utc                    u:object_r:build_vendor_prop:s0 exact int
-ro.vendor.build.fingerprint                 u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.fingerprint_has_digest      u:object_r:build_vendor_prop:s0 exact bool
-ro.vendor.build.id                          u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.tags                        u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.type                        u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.version.incremental         u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.version.release             u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.version.release_or_codename u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.build.version.sdk                 u:object_r:build_vendor_prop:s0 exact int
-
-# All vendor CPU abilist props are set by /vendor/build.prop
-ro.vendor.product.cpu.abilist   u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.product.cpu.abilist32 u:object_r:build_vendor_prop:s0 exact string
-ro.vendor.product.cpu.abilist64 u:object_r:build_vendor_prop:s0 exact string
-
-ro.product.board                    u:object_r:build_vendor_prop:s0 exact string
-ro.product.first_api_level          u:object_r:build_vendor_prop:s0 exact int
-ro.product.vendor.brand             u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor.device            u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor.manufacturer      u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor.model             u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor.name              u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor_dlkm.brand        u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor_dlkm.device       u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor_dlkm.manufacturer u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor_dlkm.model        u:object_r:build_vendor_prop:s0 exact string
-ro.product.vendor_dlkm.name         u:object_r:build_vendor_prop:s0 exact string
-
-# GRF property for the first api level of the vendor partition
-ro.board.first_api_level u:object_r:build_vendor_prop:s0 exact int
-ro.board.api_level       u:object_r:build_vendor_prop:s0 exact int
-
-# Boot image build props set by /{second_stage_resources/,}boot/etc/build.prop
-ro.bootimage.build.date                        u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.date.utc                    u:object_r:build_bootimage_prop:s0 exact int
-ro.bootimage.build.fingerprint                 u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.id                          u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.tags                        u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.type                        u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.version.incremental         u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.version.release             u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.version.release_or_codename u:object_r:build_bootimage_prop:s0 exact string
-ro.bootimage.build.version.sdk                 u:object_r:build_bootimage_prop:s0 exact int
-
-ro.product.bootimage.brand        u:object_r:build_bootimage_prop:s0 exact string
-ro.product.bootimage.device       u:object_r:build_bootimage_prop:s0 exact string
-ro.product.bootimage.manufacturer u:object_r:build_bootimage_prop:s0 exact string
-ro.product.bootimage.model        u:object_r:build_bootimage_prop:s0 exact string
-ro.product.bootimage.name         u:object_r:build_bootimage_prop:s0 exact string
-
-# ro.product.property_source_order is settable from any build.prop
-ro.product.property_source_order u:object_r:build_config_prop:s0 exact string
-
-ro.crypto.state u:object_r:vold_status_prop:s0 exact enum encrypted unencrypted unsupported
-ro.crypto.type  u:object_r:vold_status_prop:s0 exact enum block file none
+ro.build.id                     u:object_r:build_prop:s0 exact string
+ro.build.version.release        u:object_r:build_prop:s0 exact string
+ro.build.version.security_patch u:object_r:build_prop:s0 exact string
+ro.debuggable                   u:object_r:build_prop:s0 exact bool
+ro.product.cpu.abilist          u:object_r:build_prop:s0 exact string
+ro.adb.secure                   u:object_r:build_prop:s0 exact bool
 
 ro.property_service.version u:object_r:property_service_version_prop:s0 exact int
 
-ro.vendor.redirect_socket_calls u:object_r:vendor_socket_hook_prop:s0 exact bool
-
-service.bootanim.exit u:object_r:bootanim_system_prop:s0 exact int
-service.bootanim.progress u:object_r:bootanim_system_prop:s0 exact int
-
-sys.init.userspace_reboot.in_progress u:object_r:userspace_reboot_exported_prop:s0 exact bool
-sys.use_memfd                         u:object_r:use_memfd_prop:s0 exact bool
-
-vold.decrypt u:object_r:vold_status_prop:s0 exact string
-
-aaudio.hw_burst_min_usec     u:object_r:aaudio_config_prop:s0 exact int
-aaudio.minimum_sleep_usec    u:object_r:aaudio_config_prop:s0 exact int
-aaudio.mixer_bursts          u:object_r:aaudio_config_prop:s0 exact int
-aaudio.mmap_exclusive_policy u:object_r:aaudio_config_prop:s0 exact int
-aaudio.mmap_policy           u:object_r:aaudio_config_prop:s0 exact int
-aaudio.wakeup_delay_usec     u:object_r:aaudio_config_prop:s0 exact int
-
-persist.rcs.supported u:object_r:exported_default_prop:s0 exact int
-
-ro.bionic.2nd_arch        u:object_r:cpu_variant_prop:s0 exact string
-ro.bionic.2nd_cpu_variant u:object_r:cpu_variant_prop:s0 exact string
-ro.bionic.arch            u:object_r:cpu_variant_prop:s0 exact string
-ro.bionic.cpu_variant     u:object_r:cpu_variant_prop:s0 exact string
-
-ro.board.platform u:object_r:exported_default_prop:s0 exact string
-
-ro.boot.fake_battery         u:object_r:exported_default_prop:s0 exact int
-ro.boot.fstab_suffix         u:object_r:exported_default_prop:s0 exact string
-ro.boot.hardware.revision    u:object_r:exported_default_prop:s0 exact string
-ro.boot.product.hardware.sku u:object_r:exported_default_prop:s0 exact string
-ro.boot.product.vendor.sku   u:object_r:exported_default_prop:s0 exact string
-ro.boot.slot_suffix          u:object_r:exported_default_prop:s0 exact string
-
-ro.boringcrypto.hwrand u:object_r:exported_default_prop:s0 exact bool
-
-# Update related props
-ro.build.ab_update                                u:object_r:exported_default_prop:s0 exact string
-ro.build.ab_update.gki.prevent_downgrade_version  u:object_r:ab_update_gki_prop:s0 exact bool
-ro.build.ab_update.gki.prevent_downgrade_spl      u:object_r:ab_update_gki_prop:s0 exact bool
-
-ro.build.expect.baseband   u:object_r:exported_default_prop:s0 exact string
-ro.build.expect.bootloader u:object_r:exported_default_prop:s0 exact string
-
-ro.carrier u:object_r:exported_default_prop:s0 exact string
-
-ro.config.low_ram           u:object_r:exported_config_prop:s0 exact bool
-ro.config.vc_call_vol_steps u:object_r:exported_config_prop:s0 exact int
-
-ro.frp.pst u:object_r:exported_default_prop:s0 exact string
-
-ro.hardware.activity_recognition u:object_r:exported_default_prop:s0 exact string
-ro.hardware.audio                u:object_r:exported_default_prop:s0 exact string
-ro.hardware.audio.a2dp           u:object_r:exported_default_prop:s0 exact string
-ro.hardware.audio.hearing_aid    u:object_r:exported_default_prop:s0 exact string
-ro.hardware.audio.primary        u:object_r:exported_default_prop:s0 exact string
-ro.hardware.audio.usb            u:object_r:exported_default_prop:s0 exact string
-ro.hardware.audio_policy         u:object_r:exported_default_prop:s0 exact string
-ro.hardware.bootctrl             u:object_r:exported_default_prop:s0 exact string
-ro.hardware.camera               u:object_r:exported_default_prop:s0 exact string
-ro.hardware.consumerir           u:object_r:exported_default_prop:s0 exact string
-ro.hardware.context_hub          u:object_r:exported_default_prop:s0 exact string
-ro.hardware.egl                  u:object_r:exported_default_prop:s0 exact string
-ro.hardware.fingerprint          u:object_r:exported_default_prop:s0 exact string
-ro.hardware.flp                  u:object_r:exported_default_prop:s0 exact string
-ro.hardware.gatekeeper           u:object_r:exported_default_prop:s0 exact string
-ro.hardware.gps                  u:object_r:exported_default_prop:s0 exact string
-ro.hardware.gralloc              u:object_r:exported_default_prop:s0 exact string
-ro.hardware.hdmi_cec             u:object_r:exported_default_prop:s0 exact string
-ro.hardware.hwcomposer           u:object_r:exported_default_prop:s0 exact string
-ro.hardware.input                u:object_r:exported_default_prop:s0 exact string
-ro.hardware.keystore             u:object_r:exported_default_prop:s0 exact string
-ro.hardware.keystore_desede      u:object_r:exported_default_prop:s0 exact string
-ro.hardware.lights               u:object_r:exported_default_prop:s0 exact string
-ro.hardware.local_time           u:object_r:exported_default_prop:s0 exact string
-ro.hardware.memtrack             u:object_r:exported_default_prop:s0 exact string
-ro.hardware.nfc                  u:object_r:exported_default_prop:s0 exact string
-ro.hardware.nfc_nci              u:object_r:exported_default_prop:s0 exact string
-ro.hardware.nfc_tag              u:object_r:exported_default_prop:s0 exact string
-ro.hardware.nvram                u:object_r:exported_default_prop:s0 exact string
-ro.hardware.power                u:object_r:exported_default_prop:s0 exact string
-ro.hardware.radio                u:object_r:exported_default_prop:s0 exact string
-ro.hardware.sensors              u:object_r:exported_default_prop:s0 exact string
-ro.hardware.sound_trigger        u:object_r:exported_default_prop:s0 exact string
-ro.hardware.thermal              u:object_r:exported_default_prop:s0 exact string
-ro.hardware.tv_input             u:object_r:exported_default_prop:s0 exact string
-ro.hardware.type                 u:object_r:exported_default_prop:s0 exact string
-ro.hardware.vehicle              u:object_r:exported_default_prop:s0 exact string
-ro.hardware.vibrator             u:object_r:exported_default_prop:s0 exact string
-ro.hardware.virtual_device       u:object_r:exported_default_prop:s0 exact string
-ro.hardware.vulkan               u:object_r:exported_default_prop:s0 exact string
-
-ro.hw_timeout_multiplier u:object_r:hw_timeout_multiplier_prop:s0 exact int
-
-ro.hwui.use_vulkan u:object_r:exported_default_prop:s0 exact bool
-
-# ro.kernel.* properties are emulator specific and deprecated. Do not use.
-# Should be retired once presubmit allows.
-ro.kernel.qemu             u:object_r:exported_default_prop:s0 exact bool
-ro.kernel.qemu.            u:object_r:exported_default_prop:s0
-ro.kernel.android.bootanim u:object_r:exported_default_prop:s0 exact int
-
-ro.oem.key1 u:object_r:exported_default_prop:s0 exact string
-
-ro.product.vndk.version u:object_r:vndk_prop:s0 exact string
-
-ro.vndk.lite    u:object_r:vndk_prop:s0 exact bool
-ro.vndk.version u:object_r:vndk_prop:s0 exact string
-
-ro.vts.coverage u:object_r:vts_config_prop:s0 exact int
-
-vts.native_server.on u:object_r:vts_status_prop:s0 exact bool
-
-wifi.active.interface     u:object_r:wifi_hal_prop:s0 exact string
-wifi.aware.interface      u:object_r:wifi_hal_prop:s0 exact string
-wifi.concurrent.interface u:object_r:wifi_hal_prop:s0 exact string
-wifi.direct.interface     u:object_r:wifi_hal_prop:s0 exact string
-wifi.interface            u:object_r:wifi_hal_prop:s0 exact string
-wlan.driver.status        u:object_r:wifi_hal_prop:s0 exact enum ok unloaded
-
-ro.boot.wificountrycode u:object_r:wifi_config_prop:s0 exact string
+ro.boot.slot_suffix u:object_r:exported_default_prop:s0 exact string
 
 ro.apex.updatable u:object_r:exported_default_prop:s0 exact bool
 
-# Property to enable incremental feature
-ro.incremental.enable      u:object_r:incremental_prop:s0
-
-# Properties to configure userspace reboot.
-init.userspace_reboot.is_supported u:object_r:userspace_reboot_config_prop:s0 exact bool
-init.userspace_reboot.sigkill.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
-init.userspace_reboot.sigterm.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
-init.userspace_reboot.started.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
-init.userspace_reboot.userdata_remount.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
-init.userspace_reboot.watchdog.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
-
-sys.shutdown.requested u:object_r:exported_system_prop:s0 exact string
-
-# surfaceflinger properties
-ro.surface_flinger.default_composition_dataspace          u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.default_composition_pixel_format       u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.force_hwc_copy_for_virtual_displays    u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.has_HDR_display                        u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.has_wide_color_display                 u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.max_frame_buffer_acquired_buffers      u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.max_graphics_height                    u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.max_graphics_width                     u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.max_virtual_display_dimension          u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.primary_display_orientation            u:object_r:surfaceflinger_prop:s0 exact enum ORIENTATION_0 ORIENTATION_180 ORIENTATION_270 ORIENTATION_90
-ro.surface_flinger.present_time_offset_from_vsync_ns      u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.running_without_sync_framework         u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.start_graphics_allocator_service       u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.use_color_management                   u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.use_context_priority                   u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.use_vr_flinger                         u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.vsync_event_phase_offset_ns            u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.vsync_sf_event_phase_offset_ns         u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.wcg_composition_dataspace              u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.wcg_composition_pixel_format           u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.display_primary_red                    u:object_r:surfaceflinger_prop:s0 exact string
-ro.surface_flinger.display_primary_green                  u:object_r:surfaceflinger_prop:s0 exact string
-ro.surface_flinger.display_primary_blue                   u:object_r:surfaceflinger_prop:s0 exact string
-ro.surface_flinger.display_primary_white                  u:object_r:surfaceflinger_prop:s0 exact string
-ro.surface_flinger.protected_contents                     u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.set_idle_timer_ms                      u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.set_touch_timer_ms                     u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.set_display_power_timer_ms             u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.support_kernel_idle_timer              u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.supports_background_blur               u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.use_smart_90_for_video                 u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.use_content_detection_for_refresh_rate u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.color_space_agnostic_dataspace         u:object_r:surfaceflinger_prop:s0 exact int
-ro.surface_flinger.refresh_rate_switching                 u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.update_device_product_info_on_hotplug_reconnect u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.enable_frame_rate_override             u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.enable_layer_caching                   u:object_r:surfaceflinger_prop:s0 exact bool
-ro.surface_flinger.display_update_imminent_timeout_ms     u:object_r:surfaceflinger_prop:s0 exact int
-
-ro.sf.disable_triple_buffer u:object_r:surfaceflinger_prop:s0 exact bool
-ro.sf.lcd_density           u:object_r:surfaceflinger_prop:s0 exact int
-
-persist.sys.sf.color_mode       u:object_r:surfaceflinger_color_prop:s0 exact int
-persist.sys.sf.color_saturation u:object_r:surfaceflinger_color_prop:s0 exact string
-persist.sys.sf.native_mode      u:object_r:surfaceflinger_color_prop:s0 exact int
-
-# Binder cache properties.  These are world-readable
-cache_key.app_inactive                   u:object_r:binder_cache_system_server_prop:s0
-cache_key.is_compat_change_enabled       u:object_r:binder_cache_system_server_prop:s0
-cache_key.get_packages_for_uid           u:object_r:binder_cache_system_server_prop:s0
-cache_key.has_system_feature             u:object_r:binder_cache_system_server_prop:s0
-cache_key.is_interactive                 u:object_r:binder_cache_system_server_prop:s0
-cache_key.is_power_save_mode             u:object_r:binder_cache_system_server_prop:s0
-cache_key.is_user_unlocked               u:object_r:binder_cache_system_server_prop:s0
-cache_key.volume_list                    u:object_r:binder_cache_system_server_prop:s0
-cache_key.display_info                   u:object_r:binder_cache_system_server_prop:s0
-cache_key.location_enabled               u:object_r:binder_cache_system_server_prop:s0
-cache_key.package_info                   u:object_r:binder_cache_system_server_prop:s0
-
-cache_key.bluetooth.                     u:object_r:binder_cache_bluetooth_server_prop:s0 prefix string
-cache_key.system_server.                 u:object_r:binder_cache_system_server_prop:s0 prefix string
-cache_key.telephony.                     u:object_r:binder_cache_telephony_server_prop:s0 prefix string
-
-# Framework watchdog configuration properties.
-framework_watchdog.fatal_count                u:object_r:framework_watchdog_config_prop:s0 exact int
-framework_watchdog.fatal_window.second        u:object_r:framework_watchdog_config_prop:s0 exact int
-
-gsm.sim.operator.numeric       u:object_r:telephony_status_prop:s0 exact string
-persist.radio.airplane_mode_on u:object_r:telephony_status_prop:s0 exact bool
-
-ro.cdma.home.operator.alpha       u:object_r:telephony_config_prop:s0 exact string
-ro.cdma.home.operator.numeric     u:object_r:telephony_config_prop:s0 exact string
-ro.com.android.dataroaming        u:object_r:telephony_config_prop:s0 exact bool
-ro.com.android.prov_mobiledata    u:object_r:telephony_config_prop:s0 exact bool
-ro.radio.noril                    u:object_r:telephony_config_prop:s0 exact string
-ro.telephony.call_ring.multiple   u:object_r:telephony_config_prop:s0 exact bool
-ro.telephony.default_cdma_sub     u:object_r:telephony_config_prop:s0 exact int
-ro.telephony.default_network      u:object_r:telephony_config_prop:s0 exact string
-ro.telephony.iwlan_operation_mode u:object_r:telephony_config_prop:s0 exact enum default legacy AP-assisted
-telephony.active_modems.max_count u:object_r:telephony_config_prop:s0 exact int
-telephony.lteOnCdmaDevice         u:object_r:telephony_config_prop:s0 exact int
-persist.dbg.volte_avail_ovr       u:object_r:telephony_config_prop:s0 exact int
-persist.dbg.vt_avail_ovr          u:object_r:telephony_config_prop:s0 exact int
-persist.dbg.wfc_avail_ovr         u:object_r:telephony_config_prop:s0 exact int
-
-# System locale list filter configuration
-ro.localization.locale_filter u:object_r:localization_prop:s0 exact string
-
-# Graphics related properties
-ro.opengles.version u:object_r:graphics_config_prop:s0 exact int
-
-ro.gfx.driver.0          u:object_r:graphics_config_prop:s0 exact string
-ro.gfx.driver.1          u:object_r:graphics_config_prop:s0 exact string
-ro.gfx.angle.supported   u:object_r:graphics_config_prop:s0 exact bool
-ro.gfx.driver_build_time u:object_r:graphics_config_prop:s0 exact int
-
-graphics.gpu.profiler.support          u:object_r:graphics_config_prop:s0 exact bool
-graphics.gpu.profiler.vulkan_layer_apk u:object_r:graphics_config_prop:s0 exact string
-
-ro.cpuvulkan.version u:object_r:graphics_config_prop:s0 exact int
-
-# surfaceflinger-settable
-graphics.display.kernel_idle_timer.enabled u:object_r:surfaceflinger_display_prop:s0 exact bool
-
-# Disable/enable charger input
-power.battery_input.suspended u:object_r:power_debug_prop:s0 exact bool
-
-# zygote config property
-zygote.critical_window.minute u:object_r:zygote_config_prop:s0 exact int
-
-ro.zygote.disable_gl_preload u:object_r:zygote_config_prop:s0 exact bool
-
-# Broadcast boot stages, which keystore listens to
 keystore.boot_level u:object_r:keystore_listen_prop:s0 exact int
-
-partition.system.verified     u:object_r:verity_status_prop:s0 exact string
-partition.system_ext.verified u:object_r:verity_status_prop:s0 exact string
-partition.product.verified    u:object_r:verity_status_prop:s0 exact string
-partition.vendor.verified     u:object_r:verity_status_prop:s0 exact string
-
-partition.system.verified.hash_alg     u:object_r:verity_status_prop:s0 exact string
-partition.system_ext.verified.hash_alg u:object_r:verity_status_prop:s0 exact string
-partition.product.verified.hash_alg    u:object_r:verity_status_prop:s0 exact string
-partition.vendor.verified.hash_alg     u:object_r:verity_status_prop:s0 exact string
-
-ro.setupwizard.enterprise_mode u:object_r:setupwizard_prop:s0 exact bool
-ro.setupwizard.esim_cid_ignore u:object_r:setupwizard_prop:s0 exact string
-ro.setupwizard.rotation_locked u:object_r:setupwizard_prop:s0 exact bool
-ro.setupwizard.wifi_on_exit    u:object_r:setupwizard_prop:s0 exact bool
-
-setupwizard.enable_assist_gesture_training                         u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.avoid_duplicate_tos                            u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.baseline_setupwizard_enabled                   u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.day_night_mode_enabled                         u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.deferred_setup_low_ram_filter                  u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.deferred_setup_notification                    u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.deferred_setup_suggestion                      u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.device_default_dark_mode                       u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.esim_enabled                                   u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.google_services_deferred_setup_pretend_not_suw u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.lock_mobile_data                               u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.lock_mobile_data.carrier-1                     u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.portal_notification                            u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.predeferred_enabled                            u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.return_partner_customization_bundle            u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.show_pixel_tos                                 u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.use_biometric_lock                             u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.feature.wallpaper_suggestion_after_restore             u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.logging                                                u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.metrics_debug_mode                                     u:object_r:setupwizard_prop:s0 exact bool
-setupwizard.theme                                                  u:object_r:setupwizard_prop:s0 exact string
-
-db.log.detailed              u:object_r:sqlite_log_prop:s0 exact bool
-db.log.slow_query_threshold  u:object_r:sqlite_log_prop:s0 exact int
-db.log.slow_query_threshold. u:object_r:sqlite_log_prop:s0 prefix int
-
-# SOC related props
-ro.soc.manufacturer u:object_r:soc_prop:s0 exact string
-ro.soc.model        u:object_r:soc_prop:s0 exact string
-
-# set to true when running rollback tests to disable fallback-to-copy when enabling rollbacks
-# to detect failures where hard linking should work otherwise
-persist.rollback.is_test u:object_r:rollback_test_prop:s0 exact bool
-
-# bootanimation properties
-ro.bootanim.quiescent.enabled u:object_r:bootanim_config_prop:s0 exact bool
-
-# dck properties
-ro.gms.dck.eligible_wcc u:object_r:dck_prop:s0 exact int
diff --git a/microdroid/sepolicy/system/private/shell.te b/microdroid/sepolicy/system/private/shell.te
index 7c786c9..03490b0 100644
--- a/microdroid/sepolicy/system/private/shell.te
+++ b/microdroid/sepolicy/system/private/shell.te
@@ -193,7 +193,7 @@
 
 # Allow shell to launch microdroid_launcher in its own domain
 # TODO(b/186396070) remove this when microdroid_manager can do this
-domain_auto_trans(shell, microdroid_launcher_exec, microdroid_launcher)
+domain_auto_trans(shell, microdroid_app_exec, microdroid_app)
 domain_auto_trans(shell, microdroid_manager_exec, microdroid_manager)
 
 # Never allow others to set or get the perf.drop_caches property.
diff --git a/microdroid/sepolicy/vendor/file_contexts b/microdroid/sepolicy/vendor/file_contexts
index 71b4fcd..0aa85cf 100644
--- a/microdroid/sepolicy/vendor/file_contexts
+++ b/microdroid/sepolicy/vendor/file_contexts
@@ -35,4 +35,4 @@
 
 /bin/install-recovery\.sh u:object_r:vendor_install_recovery_exec:s0
 
-/bin/hw/android\.hardware\.security\.keymint-service u:object_r:hal_keymint_default_exec:s0
+/bin/hw/android\.hardware\.security\.keymint-service\.microdroid u:object_r:hal_keymint_default_exec:s0
diff --git a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
index f9794f7..2457797 100644
--- a/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
+++ b/tests/hostside/java/android/virt/test/MicrodroidTestCase.java
@@ -97,6 +97,7 @@
         // 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"));
 
         // Manually execute the library and check the output
         final String microdroidLauncher = "system/bin/microdroid_launcher";
@@ -105,7 +106,7 @@
                 is("Hello Microdroid " + testLib + " arg1 arg2"));
 
         // Check that keystore was found by the payload
-        assertThat(runOnMicrodroid("getprop", "debug.microdroid.test_keystore"), is("PASS"));
+        assertThat(runOnMicrodroid("getprop", "debug.microdroid.test.keystore"), is("PASS"));
 
         // Shutdown microdroid
         runOnAndroid(VIRT_APEX + "bin/vm", "stop", cid);
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 1122b25..fc5681e 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -13,13 +13,20 @@
 // TODO(jiyong): make this a binary, not a shared library
 cc_library_shared {
     name: "MicrodroidTestNativeLib",
-    srcs: ["src/native/*.cpp"],
+    srcs: ["src/native/testbinary.cpp"],
     shared_libs: [
         "android.system.keystore2-V1-ndk_platform",
+        "libbase",
         "libbinder_ndk",
+        "MicrodroidTestNativeLibSub",
     ],
 }
 
+cc_library_shared {
+    name: "MicrodroidTestNativeLibSub",
+    srcs: ["src/native/testlib.cpp"],
+}
+
 genrule {
     name: "MicrodroidTestApp.signed",
     out: [
@@ -27,12 +34,12 @@
         "MicrodroidTestApp.apk.idsig",
     ],
     srcs: [":MicrodroidTestApp"],
-    tools:["apksigner"],
+    tools: ["apksigner"],
     tool_files: ["test.keystore"],
     cmd: "$(location apksigner) sign " +
-         "--ks $(location test.keystore) " +
-         "--ks-pass=pass:testkey --key-pass=pass:testkey " +
-         "--in $(in) " +
-         "--out $(genDir)/MicrodroidTestApp.apk",
-         // $(genDir)/MicrodroidTestApp.apk.idsig is generated implicitly
+        "--ks $(location test.keystore) " +
+        "--ks-pass=pass:testkey --key-pass=pass:testkey " +
+        "--in $(in) " +
+        "--out $(genDir)/MicrodroidTestApp.apk",
+    // $(genDir)/MicrodroidTestApp.apk.idsig is generated implicitly
 }
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 682ab2a..20519cd 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -14,31 +14,173 @@
  * limitations under the License.
  */
 #include <aidl/android/system/keystore2/IKeystoreService.h>
+#include <android-base/result.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
 #include <stdio.h>
 #include <sys/system_properties.h>
 
+using aidl::android::hardware::security::keymint::Algorithm;
+using aidl::android::hardware::security::keymint::Digest;
+using aidl::android::hardware::security::keymint::KeyParameter;
+using aidl::android::hardware::security::keymint::KeyParameterValue;
+using aidl::android::hardware::security::keymint::KeyPurpose;
 using aidl::android::hardware::security::keymint::SecurityLevel;
+using aidl::android::hardware::security::keymint::Tag;
 
+using aidl::android::system::keystore2::CreateOperationResponse;
+using aidl::android::system::keystore2::Domain;
 using aidl::android::system::keystore2::IKeystoreSecurityLevel;
 using aidl::android::system::keystore2::IKeystoreService;
+using aidl::android::system::keystore2::KeyDescriptor;
+using aidl::android::system::keystore2::KeyMetadata;
+
+using android::base::Error;
+using android::base::Result;
+
+extern void testlib_sub();
 
 namespace {
 
-bool test_keystore() {
+Result<void> test_keystore() {
+    // Connect to Keystore.
     ndk::SpAIBinder binder(
             AServiceManager_getService("android.system.keystore2.IKeystoreService/default"));
     auto service = IKeystoreService::fromBinder(binder);
     if (service == nullptr) {
-        return false;
+        return Error() << "Failed to find Keystore";
     }
     std::shared_ptr<IKeystoreSecurityLevel> securityLevel;
     auto status = service->getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT, &securityLevel);
     if (!status.isOk()) {
-        return false;
+        return Error() << "Failed to get security level";
     }
-    return true;
+
+    // Create a signing key.
+    std::vector<KeyParameter> params;
+
+    KeyParameter algo;
+    algo.tag = Tag::ALGORITHM;
+    algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::HMAC);
+    params.push_back(algo);
+
+    KeyParameter key_size;
+    key_size.tag = Tag::KEY_SIZE;
+    key_size.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
+    params.push_back(key_size);
+
+    KeyParameter min_mac_length;
+    min_mac_length.tag = Tag::MIN_MAC_LENGTH;
+    min_mac_length.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
+    params.push_back(min_mac_length);
+
+    KeyParameter digest;
+    digest.tag = Tag::DIGEST;
+    digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
+    params.push_back(digest);
+
+    KeyParameter purposeSign;
+    purposeSign.tag = Tag::PURPOSE;
+    purposeSign.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::SIGN);
+    params.push_back(purposeSign);
+
+    KeyParameter purposeVerify;
+    purposeVerify.tag = Tag::PURPOSE;
+    purposeVerify.value =
+            KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::VERIFY);
+    params.push_back(purposeVerify);
+
+    KeyParameter auth;
+    auth.tag = Tag::NO_AUTH_REQUIRED;
+    auth.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
+    params.push_back(auth);
+
+    KeyDescriptor descriptor;
+    descriptor.domain = Domain::SELINUX;
+    descriptor.alias = "payload-test-key";
+    descriptor.nspace = 140; // vm_payload_key
+
+    KeyMetadata metadata;
+    status = securityLevel->generateKey(descriptor, {}, params, 0, {}, &metadata);
+    if (!status.isOk()) {
+        return Error() << "Failed to create new HMAC key";
+    }
+
+    // Sign something.
+    params.clear();
+    params.push_back(algo);
+    params.push_back(digest);
+    params.push_back(purposeSign);
+
+    KeyParameter mac_length;
+    mac_length.tag = Tag::MAC_LENGTH;
+    mac_length.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
+    params.push_back(mac_length);
+
+    CreateOperationResponse opResponse;
+    status = securityLevel->createOperation(descriptor, params, false, &opResponse);
+    if (!status.isOk()) {
+        return Error() << "Failed to create keystore signing operation: "
+                       << status.getServiceSpecificError();
+    }
+    auto operation = opResponse.iOperation;
+
+    std::string message = "This is the message to sign";
+    std::optional<std::vector<uint8_t>> out;
+    status = operation->update({message.begin(), message.end()}, &out);
+    if (!status.isOk()) {
+        return Error() << "Failed to call keystore update operation.";
+    }
+
+    std::optional<std::vector<uint8_t>> signature;
+    status = operation->finish({}, {}, &signature);
+    if (!status.isOk()) {
+        return Error() << "Failed to call keystore finish operation.";
+    }
+
+    if (!signature.has_value()) {
+        return Error() << "Didn't receive a signature from keystore finish operation.";
+    }
+
+    // Verify the signature.
+    params.clear();
+    params.push_back(algo);
+    params.push_back(digest);
+    params.push_back(purposeVerify);
+
+    status = securityLevel->createOperation(descriptor, params, false, &opResponse);
+    if (!status.isOk()) {
+        return Error() << "Failed to create keystore verification operation: "
+                       << status.getServiceSpecificError();
+    }
+    operation = opResponse.iOperation;
+
+    status = operation->update({message.begin(), message.end()}, &out);
+    if (!status.isOk()) {
+        return Error() << "Failed to call keystore update operation.";
+    }
+
+    std::optional<std::vector<uint8_t>> out_signature;
+    status = operation->finish({}, signature.value(), &out_signature);
+    if (!status.isOk()) {
+        return Error() << "Failed to call keystore finish operation.";
+    }
+
+    return {};
+}
+
+template <typename T>
+void report_test(std::string name, Result<T> result) {
+    auto property = "debug.microdroid.test." + name;
+    std::stringstream outcome;
+    if (result.ok()) {
+        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";
+    }
+    __system_property_set(property.c_str(), outcome.str().c_str());
 }
 
 } // Anonymous namespace
@@ -52,9 +194,10 @@
             printf(" ");
         }
     }
+    testlib_sub();
     printf("\n");
 
     __system_property_set("debug.microdroid.app.run", "true");
-    __system_property_set("debug.microdroid.test_keystore", test_keystore() ? "PASS" : "FAIL");
+    report_test("keystore", test_keystore());
     return 0;
 }
diff --git a/tests/testapk/src/native/testlib.cpp b/tests/testapk/src/native/testlib.cpp
new file mode 100644
index 0000000..792c6c8
--- /dev/null
+++ b/tests/testapk/src/native/testlib.cpp
@@ -0,0 +1,5 @@
+#include <sys/system_properties.h>
+
+void testlib_sub() {
+    __system_property_set("debug.microdroid.app.sublib.run", "true");
+}
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index f5ad1f8..700d0fc 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -2,8 +2,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-rust_binary {
-    name: "virtualizationservice",
+rust_defaults {
+    name: "virtualizationservice_defaults",
     crate_name: "virtualizationservice",
     srcs: ["src/main.rs"],
     edition: "2018",
@@ -24,12 +24,26 @@
         "libandroid_logger",
         "libanyhow",
         "libcommand_fds",
-        "libcompositediskconfig",
+        "libcrc32fast",
         "libdisk",
         "liblog_rust",
+        "libprotobuf",
+        "libprotos",
         "libserde_json",
         "libserde",
         "libshared_child",
+        "libuuid",
     ],
+}
+
+rust_binary {
+    name: "virtualizationservice",
+    defaults: ["virtualizationservice_defaults"],
     apex_available: ["com.android.virt"],
 }
+
+rust_test {
+    name: "virtualizationservice_device_test",
+    defaults: ["virtualizationservice_defaults"],
+    test_suites: ["general-tests"],
+}
diff --git a/virtualizationservice/TEST_MAPPING b/virtualizationservice/TEST_MAPPING
new file mode 100644
index 0000000..6456a98
--- /dev/null
+++ b/virtualizationservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "virtualizationservice_device_test"
+    }
+  ]
+}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 6b889c6..b1b0b38 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -228,16 +228,21 @@
             ));
         }
 
-        let composite_image_filename =
-            make_composite_image_filename(temporary_directory, next_temporary_image_id);
-        let (image, partition_files) =
-            make_composite_image(&disk.partitions, &composite_image_filename).map_err(|e| {
-                error!("Failed to make composite image with config {:?}: {}", disk, e);
-                new_binder_exception(
-                    ExceptionCode::SERVICE_SPECIFIC,
-                    format!("Failed to make composite image: {}", e),
-                )
-            })?;
+        let composite_image_filenames =
+            make_composite_image_filenames(temporary_directory, next_temporary_image_id);
+        let (image, partition_files) = make_composite_image(
+            &disk.partitions,
+            &composite_image_filenames.composite,
+            &composite_image_filenames.header,
+            &composite_image_filenames.footer,
+        )
+        .map_err(|e| {
+            error!("Failed to make composite image with config {:?}: {}", disk, e);
+            new_binder_exception(
+                ExceptionCode::SERVICE_SPECIFIC,
+                format!("Failed to make composite image: {}", e),
+            )
+        })?;
 
         // Pass the file descriptors for the various partition files to crosvm when it
         // is run.
@@ -258,13 +263,28 @@
 }
 
 /// Generates a unique filename to use for a composite disk image.
-fn make_composite_image_filename(
+fn make_composite_image_filenames(
     temporary_directory: &Path,
     next_temporary_image_id: &mut u64,
-) -> PathBuf {
+) -> CompositeImageFilenames {
     let id = *next_temporary_image_id;
     *next_temporary_image_id += 1;
-    temporary_directory.join(format!("composite-{}.img", id))
+    CompositeImageFilenames {
+        composite: temporary_directory.join(format!("composite-{}.img", id)),
+        header: temporary_directory.join(format!("composite-{}-header.img", id)),
+        footer: temporary_directory.join(format!("composite-{}-footer.img", id)),
+    }
+}
+
+/// Filenames for a composite disk image, including header and footer partitions.
+#[derive(Clone, Debug, Eq, PartialEq)]
+struct CompositeImageFilenames {
+    /// The composite disk image itself.
+    composite: PathBuf,
+    /// The header partition image.
+    header: PathBuf,
+    /// The footer partition image.
+    footer: PathBuf,
 }
 
 /// Gets the calling SID of the current Binder thread.
diff --git a/virtualizationservice/src/composite.rs b/virtualizationservice/src/composite.rs
index 37428eb..5f792fd 100644
--- a/virtualizationservice/src/composite.rs
+++ b/virtualizationservice/src/composite.rs
@@ -12,76 +12,334 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Functions for running `mk_cdisk`.
+//! Functions for creating a composite disk image.
 
-use android_system_virtualizationservice::aidl::android::system::virtualizationservice::Partition::Partition as AidlPartition;
-use anyhow::{bail, Context, Error};
-use command_fds::{CommandFdExt, FdMapping};
-use compositediskconfig::{Config, Partition};
-use log::info;
-use std::fs::File;
+use crate::gpt::{
+    write_gpt_header, write_protective_mbr, GptPartitionEntry, GPT_BEGINNING_SIZE, GPT_END_SIZE,
+    GPT_HEADER_SIZE, GPT_NUM_PARTITIONS, GPT_PARTITION_ENTRY_SIZE, SECTOR_SIZE,
+};
+use android_system_virtualizationservice::aidl::android::system::virtualizationservice::Partition::Partition;
+use anyhow::{anyhow, bail, Context, Error};
+use crc32fast::Hasher;
+use disk::create_disk_file;
+use log::{trace, warn};
+use protobuf::Message;
+use protos::cdisk_spec::{ComponentDisk, CompositeDisk, ReadWriteCapability};
+use std::convert::TryInto;
+use std::fs::{File, OpenOptions};
+use std::io::Write;
 use std::os::unix::io::AsRawFd;
-use std::panic;
-use std::path::Path;
-use std::process::{Command, Stdio};
-use std::str;
-use std::thread;
+use std::path::{Path, PathBuf};
+use uuid::Uuid;
 
-const MK_CDISK_PATH: &str = "/apex/com.android.virt/bin/mk_cdisk";
+/// A magic string placed at the beginning of a composite disk file to identify it.
+const CDISK_MAGIC: &str = "composite_disk\x1d";
+/// The version of the composite disk format supported by this implementation.
+const COMPOSITE_DISK_VERSION: u64 = 1;
+/// The amount of padding needed between the last partition entry and the first partition, to align
+/// the partition appropriately. The two sectors are for the MBR and the GPT header.
+const PARTITION_ALIGNMENT_SIZE: usize = GPT_BEGINNING_SIZE as usize
+    - 2 * SECTOR_SIZE as usize
+    - GPT_NUM_PARTITIONS as usize * GPT_PARTITION_ENTRY_SIZE as usize;
+const HEADER_PADDING_LENGTH: usize = SECTOR_SIZE as usize - GPT_HEADER_SIZE as usize;
+// Keep all partitions 4k aligned for performance.
+const PARTITION_SIZE_SHIFT: u8 = 12;
+// Keep the disk size a multiple of 64k for crosvm's virtio_blk driver.
+const DISK_SIZE_SHIFT: u8 = 16;
 
-/// Calls `mk_cdisk` to construct a composite disk image for the given list of partitions, and opens
-/// it ready to use. Returns the composite disk image file, and a list of FD mappings which must be
-/// applied to any process which wants to use it. This is necessary because the composite image
-/// contains paths of the form `/proc/self/fd/N` for the partition images.
-pub fn make_composite_image(
-    partitions: &[AidlPartition],
-    output_filename: &Path,
-) -> Result<(File, Vec<File>), Error> {
-    let (config_json, files) = make_config_json(partitions)?;
-    let fd_mappings: Vec<_> = files
-        .iter()
-        .map(|file| FdMapping { parent_fd: file.as_raw_fd(), child_fd: file.as_raw_fd() })
-        .collect();
+const LINUX_FILESYSTEM_GUID: Uuid = Uuid::from_u128(0x0FC63DAF_8483_4772_8E79_3D69D8477DE4);
+const EFI_SYSTEM_PARTITION_GUID: Uuid = Uuid::from_u128(0xC12A7328_F81F_11D2_BA4B_00A0C93EC93B);
 
-    let mut command = Command::new(MK_CDISK_PATH);
-    command
-        .arg("-") // Read config JSON from stdin.
-        .arg(&output_filename)
-        .stdin(Stdio::piped())
-        .stdout(Stdio::piped())
-        .stderr(Stdio::piped());
-    command.fd_mappings(fd_mappings)?;
-    let mut child = command.spawn().context("Failed to spawn mk_cdisk")?;
-    let stdin = child.stdin.take().unwrap();
+/// Information about a single image file to be included in a partition.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct PartitionFileInfo {
+    path: PathBuf,
+    size: u64,
+}
 
-    // Write config to stdin of mk_cdisk on a separate thread to avoid deadlock, as it may not read
-    // all of stdin before it blocks on writing to stdout.
-    let writer_thread = thread::spawn(move || {
-        config_json.write_json(&stdin).context("Failed to write config JSON for mk_cdisk")
+/// Information about a partition to create, including the set of image files which make it up.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct PartitionInfo {
+    label: String,
+    files: Vec<PartitionFileInfo>,
+    partition_type: ImagePartitionType,
+    writable: bool,
+}
+
+/// Round `val` up to the next multiple of 2**`align_log`.
+fn align_to_power_of_2(val: u64, align_log: u8) -> u64 {
+    let align = 1 << align_log;
+    ((val + (align - 1)) / align) * align
+}
+
+impl PartitionInfo {
+    fn aligned_size(&self) -> u64 {
+        align_to_power_of_2(self.files.iter().map(|file| file.size).sum(), PARTITION_SIZE_SHIFT)
+    }
+}
+
+/// The type of partition.
+#[allow(dead_code)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum ImagePartitionType {
+    LinuxFilesystem,
+    EfiSystemPartition,
+}
+
+impl ImagePartitionType {
+    fn guid(self) -> Uuid {
+        match self {
+            Self::LinuxFilesystem => LINUX_FILESYSTEM_GUID,
+            Self::EfiSystemPartition => EFI_SYSTEM_PARTITION_GUID,
+        }
+    }
+}
+
+/// Write protective MBR and primary GPT table.
+fn write_beginning(
+    file: &mut impl Write,
+    disk_guid: Uuid,
+    partitions: &[u8],
+    partition_entries_crc32: u32,
+    secondary_table_offset: u64,
+    disk_size: u64,
+) -> Result<(), Error> {
+    // Write the protective MBR to the first sector.
+    write_protective_mbr(file, disk_size)?;
+
+    // Write the GPT header, and pad out to the end of the sector.
+    write_gpt_header(file, disk_guid, partition_entries_crc32, secondary_table_offset, false)?;
+    file.write_all(&[0; HEADER_PADDING_LENGTH])?;
+
+    // Write partition entries, including unused ones.
+    file.write_all(partitions)?;
+
+    // Write zeroes to align the first partition appropriately.
+    file.write_all(&[0; PARTITION_ALIGNMENT_SIZE])?;
+
+    Ok(())
+}
+
+/// Write secondary GPT table.
+fn write_end(
+    file: &mut impl Write,
+    disk_guid: Uuid,
+    partitions: &[u8],
+    partition_entries_crc32: u32,
+    secondary_table_offset: u64,
+    disk_size: u64,
+) -> Result<(), Error> {
+    // Write partition entries, including unused ones.
+    file.write_all(partitions)?;
+
+    // Write the GPT header, and pad out to the end of the sector.
+    write_gpt_header(file, disk_guid, partition_entries_crc32, secondary_table_offset, true)?;
+    file.write_all(&[0; HEADER_PADDING_LENGTH])?;
+
+    // Pad out to the aligned disk size.
+    let used_disk_size = secondary_table_offset + GPT_END_SIZE;
+    let padding = disk_size - used_disk_size;
+    file.write_all(&vec![0; padding as usize])?;
+
+    Ok(())
+}
+
+/// Create the `GptPartitionEntry` for the given partition.
+fn create_gpt_entry(partition: &PartitionInfo, offset: u64) -> GptPartitionEntry {
+    let mut partition_name: Vec<u16> = partition.label.encode_utf16().collect();
+    partition_name.resize(36, 0);
+
+    GptPartitionEntry {
+        partition_type_guid: partition.partition_type.guid(),
+        unique_partition_guid: Uuid::new_v4(),
+        first_lba: offset / SECTOR_SIZE,
+        last_lba: (offset + partition.aligned_size()) / SECTOR_SIZE - 1,
+        attributes: 0,
+        partition_name: partition_name.try_into().unwrap(),
+    }
+}
+
+/// Create one or more `ComponentDisk` proto messages for the given partition.
+fn create_component_disks(
+    partition: &PartitionInfo,
+    offset: u64,
+    header_path: &str,
+) -> Result<Vec<ComponentDisk>, Error> {
+    let aligned_size = partition.aligned_size();
+
+    if partition.files.is_empty() {
+        bail!("No image files for partition {:?}", partition);
+    }
+    let mut file_size_sum = 0;
+    let mut component_disks = vec![];
+    for file in &partition.files {
+        component_disks.push(ComponentDisk {
+            offset: offset + file_size_sum,
+            file_path: file.path.to_str().context("Invalid partition path")?.to_string(),
+            read_write_capability: if partition.writable {
+                ReadWriteCapability::READ_WRITE
+            } else {
+                ReadWriteCapability::READ_ONLY
+            },
+            ..ComponentDisk::new()
+        });
+        file_size_sum += file.size;
+    }
+
+    if file_size_sum != aligned_size {
+        if partition.writable {
+            bail!(
+                "Read-write partition {:?} size is not a multiple of {}.",
+                partition,
+                1 << PARTITION_SIZE_SHIFT
+            );
+        } else {
+            // Fill in the gap by reusing the header file, because we know it is always bigger
+            // than the alignment size (i.e. GPT_BEGINNING_SIZE > 1 << PARTITION_SIZE_SHIFT).
+            warn!(
+                "Read-only partition {:?} size is not a multiple of {}, filling gap.",
+                partition,
+                1 << PARTITION_SIZE_SHIFT
+            );
+            component_disks.push(ComponentDisk {
+                offset: offset + file_size_sum,
+                file_path: header_path.to_owned(),
+                read_write_capability: ReadWriteCapability::READ_ONLY,
+                ..ComponentDisk::new()
+            });
+        }
+    }
+
+    Ok(component_disks)
+}
+
+/// Create a new composite disk containing the given partitions, and write it out to the given
+/// files.
+pub fn create_composite_disk(
+    partitions: &[PartitionInfo],
+    header_path: &Path,
+    header_file: &mut File,
+    footer_path: &Path,
+    footer_file: &mut File,
+    output_composite: &mut File,
+) -> Result<(), Error> {
+    let header_path = header_path.to_str().context("Invalid header path")?.to_string();
+    let footer_path = footer_path.to_str().context("Invalid footer path")?.to_string();
+
+    let mut composite_proto = CompositeDisk::new();
+    composite_proto.version = COMPOSITE_DISK_VERSION;
+    composite_proto.component_disks.push(ComponentDisk {
+        file_path: header_path.clone(),
+        offset: 0,
+        read_write_capability: ReadWriteCapability::READ_ONLY,
+        ..ComponentDisk::new()
     });
-    info!("Running {:?}", command);
-    let output = child.wait_with_output()?;
-    match writer_thread.join() {
-        Ok(result) => result?,
-        Err(panic_payload) => panic::resume_unwind(panic_payload),
-    }
 
-    if !output.status.success() {
-        info!("mk_cdisk stdout: {}", str::from_utf8(&output.stdout)?);
-        info!("mk_cdisk stderr: {}", str::from_utf8(&output.stderr)?);
-        bail!("mk_cdisk exited with error {}", output.status);
-    }
+    // Write partitions to a temporary buffer so that we can calculate the CRC, and construct the
+    // ComponentDisk proto messages at the same time.
+    let mut partitions_buffer =
+        [0u8; GPT_NUM_PARTITIONS as usize * GPT_PARTITION_ENTRY_SIZE as usize];
+    let mut writer: &mut [u8] = &mut partitions_buffer;
+    let mut next_disk_offset = GPT_BEGINNING_SIZE;
+    for partition in partitions {
+        create_gpt_entry(partition, next_disk_offset).write_bytes(&mut writer)?;
 
-    let composite_image = File::open(&output_filename)
-        .with_context(|| format!("Failed to open composite image {:?}", output_filename))?;
+        for component_disk in create_component_disks(partition, next_disk_offset, &header_path)? {
+            composite_proto.component_disks.push(component_disk);
+        }
+
+        next_disk_offset += partition.aligned_size();
+    }
+    let secondary_table_offset = next_disk_offset;
+    let disk_size = align_to_power_of_2(secondary_table_offset + GPT_END_SIZE, DISK_SIZE_SHIFT);
+    trace!("Partitions: {:#?}", partitions);
+    trace!("Secondary table offset: {} disk size: {}", secondary_table_offset, disk_size);
+
+    composite_proto.component_disks.push(ComponentDisk {
+        file_path: footer_path,
+        offset: secondary_table_offset,
+        read_write_capability: ReadWriteCapability::READ_ONLY,
+        ..ComponentDisk::new()
+    });
+
+    // Calculate CRC32 of partition entries.
+    let mut hasher = Hasher::new();
+    hasher.update(&partitions_buffer);
+    let partition_entries_crc32 = hasher.finalize();
+
+    let disk_guid = Uuid::new_v4();
+    write_beginning(
+        header_file,
+        disk_guid,
+        &partitions_buffer,
+        partition_entries_crc32,
+        secondary_table_offset,
+        disk_size,
+    )?;
+    write_end(
+        footer_file,
+        disk_guid,
+        &partitions_buffer,
+        partition_entries_crc32,
+        secondary_table_offset,
+        disk_size,
+    )?;
+
+    composite_proto.length = disk_size;
+    output_composite.write_all(CDISK_MAGIC.as_bytes())?;
+    composite_proto.write_to_writer(output_composite)?;
+
+    Ok(())
+}
+
+/// Constructs a composite disk image for the given list of partitions, and opens it ready to use.
+///
+/// Returns the composite disk image file, and a list of FD mappings which must be applied to any
+/// process which wants to use it. This is necessary because the composite image contains paths of
+/// the form `/proc/self/fd/N` for the partition images.
+pub fn make_composite_image(
+    partitions: &[Partition],
+    output_path: &Path,
+    header_path: &Path,
+    footer_path: &Path,
+) -> Result<(File, Vec<File>), Error> {
+    let (partitions, files) = convert_partitions(partitions)?;
+
+    let mut composite_image = OpenOptions::new()
+        .create_new(true)
+        .read(true)
+        .write(true)
+        .open(output_path)
+        .with_context(|| format!("Failed to create composite image {:?}", output_path))?;
+    let mut header_file =
+        OpenOptions::new().create_new(true).read(true).write(true).open(header_path).with_context(
+            || format!("Failed to create composite image header {:?}", header_path),
+        )?;
+    let mut footer_file =
+        OpenOptions::new().create_new(true).read(true).write(true).open(footer_path).with_context(
+            || format!("Failed to create composite image header {:?}", footer_path),
+        )?;
+
+    create_composite_disk(
+        &partitions,
+        header_path,
+        &mut header_file,
+        footer_path,
+        &mut footer_file,
+        &mut composite_image,
+    )?;
+
+    // Re-open the composite image as read-only.
+    let composite_image = File::open(&output_path)
+        .with_context(|| format!("Failed to open composite image {:?}", output_path))?;
 
     Ok((composite_image, files))
 }
 
 /// Given the AIDL config containing a list of partitions, with a [`ParcelFileDescriptor`] for each
 /// partition, return the list of file descriptors which must be passed to the mk_cdisk child
-/// process and the JSON configuration for it.
-fn make_config_json(partitions: &[AidlPartition]) -> Result<(Config, Vec<File>), Error> {
+/// process and the composite disk image partition configuration for it.
+fn convert_partitions(partitions: &[Partition]) -> Result<(Vec<PartitionInfo>, Vec<File>), Error> {
     // File descriptors to pass to child process.
     let mut files = vec![];
 
@@ -96,17 +354,91 @@
                 .as_ref()
                 .try_clone()
                 .context("Failed to clone partition image file descriptor")?;
+            let size = get_partition_size(&file)?;
             let fd = file.as_raw_fd();
             files.push(file);
 
-            Ok(Partition {
-                writable: partition.writable,
+            Ok(PartitionInfo {
                 label: partition.label.to_owned(),
-                path: format!("/proc/self/fd/{}", fd).into(),
+                files: vec![PartitionFileInfo {
+                    path: format!("/proc/self/fd/{}", fd).into(),
+                    size,
+                }],
+                partition_type: ImagePartitionType::LinuxFilesystem,
+                writable: partition.writable,
             })
         })
         .collect::<Result<_, Error>>()?;
-    let config_json = Config { partitions };
 
-    Ok((config_json, files))
+    Ok((partitions, files))
+}
+
+/// Find the size of the partition image in the given file by parsing the header.
+///
+/// This will work for raw, QCOW2, composite and Android sparse images.
+fn get_partition_size(partition: &File) -> Result<u64, Error> {
+    // TODO: Use `context` once disk::Error implements std::error::Error.
+    Ok(create_disk_file(partition.try_clone()?)
+        .map_err(|e| anyhow!("Failed to open partition image: {}", e))?
+        .get_len()?)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn beginning_size() {
+        let mut buffer = vec![];
+        let partitions = [0u8; GPT_NUM_PARTITIONS as usize * GPT_PARTITION_ENTRY_SIZE as usize];
+        let disk_size = 1000 * SECTOR_SIZE;
+        write_beginning(
+            &mut buffer,
+            Uuid::from_u128(0x12345678_1234_5678_abcd_12345678abcd),
+            &partitions,
+            42,
+            disk_size - GPT_END_SIZE,
+            disk_size,
+        )
+        .unwrap();
+
+        assert_eq!(buffer.len(), GPT_BEGINNING_SIZE as usize);
+    }
+
+    #[test]
+    fn end_size() {
+        let mut buffer = vec![];
+        let partitions = [0u8; GPT_NUM_PARTITIONS as usize * GPT_PARTITION_ENTRY_SIZE as usize];
+        let disk_size = 1000 * SECTOR_SIZE;
+        write_end(
+            &mut buffer,
+            Uuid::from_u128(0x12345678_1234_5678_abcd_12345678abcd),
+            &partitions,
+            42,
+            disk_size - GPT_END_SIZE,
+            disk_size,
+        )
+        .unwrap();
+
+        assert_eq!(buffer.len(), GPT_END_SIZE as usize);
+    }
+
+    #[test]
+    fn end_size_with_padding() {
+        let mut buffer = vec![];
+        let partitions = [0u8; GPT_NUM_PARTITIONS as usize * GPT_PARTITION_ENTRY_SIZE as usize];
+        let disk_size = 1000 * SECTOR_SIZE;
+        let padding = 3 * SECTOR_SIZE;
+        write_end(
+            &mut buffer,
+            Uuid::from_u128(0x12345678_1234_5678_abcd_12345678abcd),
+            &partitions,
+            42,
+            disk_size - GPT_END_SIZE - padding,
+            disk_size,
+        )
+        .unwrap();
+
+        assert_eq!(buffer.len(), GPT_END_SIZE as usize + padding as usize);
+    }
 }
diff --git a/virtualizationservice/src/gpt.rs b/virtualizationservice/src/gpt.rs
new file mode 100644
index 0000000..346a40a
--- /dev/null
+++ b/virtualizationservice/src/gpt.rs
@@ -0,0 +1,240 @@
+// 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.
+
+//! Functions for writing GUID Partition Tables for use in a composite disk image.
+
+use anyhow::Error;
+use crc32fast::Hasher;
+use std::convert::TryInto;
+use std::io::Write;
+use uuid::Uuid;
+
+/// The size in bytes of a disk sector (also called a block).
+pub const SECTOR_SIZE: u64 = 1 << 9;
+/// The size in bytes on an MBR partition entry.
+const MBR_PARTITION_ENTRY_SIZE: usize = 16;
+/// The size in bytes of a GPT header.
+pub const GPT_HEADER_SIZE: u32 = 92;
+/// The number of partition entries in the GPT, which is the maximum number of partitions which are
+/// supported.
+pub const GPT_NUM_PARTITIONS: u32 = 128;
+/// The size in bytes of a single GPT partition entry.
+pub const GPT_PARTITION_ENTRY_SIZE: u32 = 128;
+/// The size in bytes of everything before the first partition: i.e. the MBR, GPT header and GPT
+/// partition entries.
+pub const GPT_BEGINNING_SIZE: u64 = SECTOR_SIZE * 40;
+/// The size in bytes of everything after the last partition: i.e. the GPT partition entries and GPT
+/// footer.
+pub const GPT_END_SIZE: u64 = SECTOR_SIZE * 33;
+
+/// Write a protective MBR for a disk of the given total size (in bytes).
+///
+/// This should be written at the start of the disk, before the GPT header. It
+/// is one `SECTOR_SIZE` long.
+pub fn write_protective_mbr(file: &mut impl Write, disk_size: u64) -> Result<(), Error> {
+    // Bootstrap code
+    file.write_all(&[0; 446])?;
+
+    // Partition status
+    file.write_all(&[0x00])?;
+    // Begin CHS
+    file.write_all(&[0; 3])?;
+    // Partition type
+    file.write_all(&[0xEE])?;
+    // End CHS
+    file.write_all(&[0; 3])?;
+    let first_lba: u32 = 1;
+    file.write_all(&first_lba.to_le_bytes())?;
+    let number_of_sectors: u32 = (disk_size / SECTOR_SIZE).try_into()?;
+    file.write_all(&number_of_sectors.to_le_bytes())?;
+
+    // Three more empty partitions
+    file.write_all(&[0; MBR_PARTITION_ENTRY_SIZE * 3])?;
+
+    // Boot signature
+    file.write_all(&[0x55, 0xAA])?;
+
+    Ok(())
+}
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+struct GptHeader {
+    signature: [u8; 8],
+    revision: [u8; 4],
+    header_size: u32,
+    header_crc32: u32,
+    current_lba: u64,
+    backup_lba: u64,
+    first_usable_lba: u64,
+    last_usable_lba: u64,
+    disk_guid: Uuid,
+    partition_entries_lba: u64,
+    num_partition_entries: u32,
+    partition_entry_size: u32,
+    partition_entries_crc32: u32,
+}
+
+impl GptHeader {
+    fn write_bytes(&self, out: &mut impl Write) -> Result<(), Error> {
+        out.write_all(&self.signature)?;
+        out.write_all(&self.revision)?;
+        out.write_all(&self.header_size.to_le_bytes())?;
+        out.write_all(&self.header_crc32.to_le_bytes())?;
+        // Reserved
+        out.write_all(&[0; 4])?;
+        out.write_all(&self.current_lba.to_le_bytes())?;
+        out.write_all(&self.backup_lba.to_le_bytes())?;
+        out.write_all(&self.first_usable_lba.to_le_bytes())?;
+        out.write_all(&self.last_usable_lba.to_le_bytes())?;
+
+        // GUID is mixed-endian for some reason, so we can't just use `Uuid::as_bytes()`.
+        write_guid(out, self.disk_guid)?;
+
+        out.write_all(&self.partition_entries_lba.to_le_bytes())?;
+        out.write_all(&self.num_partition_entries.to_le_bytes())?;
+        out.write_all(&self.partition_entry_size.to_le_bytes())?;
+        out.write_all(&self.partition_entries_crc32.to_le_bytes())?;
+        Ok(())
+    }
+}
+
+/// Write a GPT header for the disk.
+///
+/// It may either be a primary header (which should go at LBA 1) or a secondary header (which should
+/// go at the end of the disk).
+pub fn write_gpt_header(
+    out: &mut impl Write,
+    disk_guid: Uuid,
+    partition_entries_crc32: u32,
+    secondary_table_offset: u64,
+    secondary: bool,
+) -> Result<(), Error> {
+    let primary_header_lba = 1;
+    let secondary_header_lba = (secondary_table_offset + GPT_END_SIZE) / SECTOR_SIZE - 1;
+    let mut gpt_header = GptHeader {
+        signature: *b"EFI PART",
+        revision: [0, 0, 1, 0],
+        header_size: GPT_HEADER_SIZE,
+        current_lba: if secondary { secondary_header_lba } else { primary_header_lba },
+        backup_lba: if secondary { primary_header_lba } else { secondary_header_lba },
+        first_usable_lba: GPT_BEGINNING_SIZE / SECTOR_SIZE,
+        last_usable_lba: secondary_table_offset / SECTOR_SIZE - 1,
+        disk_guid,
+        partition_entries_lba: 2,
+        num_partition_entries: GPT_NUM_PARTITIONS,
+        partition_entry_size: GPT_PARTITION_ENTRY_SIZE,
+        partition_entries_crc32,
+        header_crc32: 0,
+    };
+
+    // Write once to a temporary buffer to calculate the CRC.
+    let mut header_without_crc = [0u8; GPT_HEADER_SIZE as usize];
+    gpt_header.write_bytes(&mut &mut header_without_crc[..])?;
+    let mut hasher = Hasher::new();
+    hasher.update(&header_without_crc);
+    gpt_header.header_crc32 = hasher.finalize();
+
+    gpt_header.write_bytes(out)?;
+
+    Ok(())
+}
+
+/// A GPT entry for a particular partition.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct GptPartitionEntry {
+    pub partition_type_guid: Uuid,
+    pub unique_partition_guid: Uuid,
+    pub first_lba: u64,
+    pub last_lba: u64,
+    pub attributes: u64,
+    /// UTF-16LE
+    pub partition_name: [u16; 36],
+}
+
+// TODO: Derive this once arrays of more than 32 elements have default values.
+impl Default for GptPartitionEntry {
+    fn default() -> Self {
+        Self {
+            partition_type_guid: Default::default(),
+            unique_partition_guid: Default::default(),
+            first_lba: 0,
+            last_lba: 0,
+            attributes: 0,
+            partition_name: [0; 36],
+        }
+    }
+}
+
+impl GptPartitionEntry {
+    /// Write out the partition table entry. It will take
+    /// `GPT_PARTITION_ENTRY_SIZE` bytes.
+    pub fn write_bytes(&self, out: &mut impl Write) -> Result<(), Error> {
+        write_guid(out, self.partition_type_guid)?;
+        write_guid(out, self.unique_partition_guid)?;
+        out.write_all(&self.first_lba.to_le_bytes())?;
+        out.write_all(&self.last_lba.to_le_bytes())?;
+        out.write_all(&self.attributes.to_le_bytes())?;
+        for code_unit in &self.partition_name {
+            out.write_all(&code_unit.to_le_bytes())?;
+        }
+        Ok(())
+    }
+}
+
+/// Write a UUID in the mixed-endian format which GPT uses for GUIDs.
+fn write_guid(out: &mut impl Write, guid: Uuid) -> Result<(), Error> {
+    let guid_fields = guid.as_fields();
+    out.write_all(&guid_fields.0.to_le_bytes())?;
+    out.write_all(&guid_fields.1.to_le_bytes())?;
+    out.write_all(&guid_fields.2.to_le_bytes())?;
+    out.write_all(guid_fields.3)?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn protective_mbr_size() {
+        let mut buffer = vec![];
+        write_protective_mbr(&mut buffer, 1000 * SECTOR_SIZE).unwrap();
+
+        assert_eq!(buffer.len(), SECTOR_SIZE as usize);
+    }
+
+    #[test]
+    fn header_size() {
+        let mut buffer = vec![];
+        write_gpt_header(
+            &mut buffer,
+            Uuid::from_u128(0x12345678_1234_5678_abcd_12345678abcd),
+            42,
+            1000 * SECTOR_SIZE,
+            false,
+        )
+        .unwrap();
+
+        assert_eq!(buffer.len(), GPT_HEADER_SIZE as usize);
+    }
+
+    #[test]
+    fn partition_entry_size() {
+        let mut buffer = vec![];
+        GptPartitionEntry::default().write_bytes(&mut buffer).unwrap();
+
+        assert_eq!(buffer.len(), GPT_PARTITION_ENTRY_SIZE as usize);
+    }
+}
diff --git a/virtualizationservice/src/main.rs b/virtualizationservice/src/main.rs
index a68e5eb..43b5fe4 100644
--- a/virtualizationservice/src/main.rs
+++ b/virtualizationservice/src/main.rs
@@ -17,6 +17,7 @@
 mod aidl;
 mod composite;
 mod crosvm;
+mod gpt;
 
 use crate::aidl::{VirtualizationService, BINDER_SERVICE_IDENTIFIER};
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::IVirtualizationService::BnVirtualizationService;