Merge changes from topic "apex-aidl" into main

* changes:
  Populate apex module info
  Include module info in dump output
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 9f27b5a..66b123e 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -3049,4 +3049,11 @@
         let app_uids_vec: Vec<i64> = app_uids_affected_by_sid.into_iter().collect();
         Ok(app_uids_vec)
     }
+
+    /// Retrieve a database PRAGMA config value.
+    pub fn pragma<T: FromSql>(&mut self, name: &str) -> Result<T> {
+        self.conn
+            .query_row(&format!("PRAGMA persistent.{name}"), (), |row| row.get(0))
+            .context(format!("failed to read pragma {name}"))
+    }
 }
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 16cc34f..acca942 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -55,6 +55,9 @@
 /// Reexport Domain for the benefit of DeleteListener
 pub use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
 
+#[cfg(test)]
+mod tests;
+
 /// Version number of KeyMint V4.
 pub const KEYMINT_V4: i32 = 400;
 
@@ -428,6 +431,34 @@
         }
         writeln!(f)?;
 
+        // Display database config information.
+        writeln!(f, "Database configuration:")?;
+        DB.with(|db| -> std::io::Result<()> {
+            let pragma_str = |f: &mut dyn std::io::Write, name| -> std::io::Result<()> {
+                let mut db = db.borrow_mut();
+                let value: String = db
+                    .pragma(name)
+                    .unwrap_or_else(|e| format!("unknown value for '{name}', failed: {e:?}"));
+                writeln!(f, "  {name} = {value}")
+            };
+            let pragma_i32 = |f: &mut dyn std::io::Write, name| -> std::io::Result<()> {
+                let mut db = db.borrow_mut();
+                let value: i32 = db.pragma(name).unwrap_or_else(|e| {
+                    log::error!("unknown value for '{name}', failed: {e:?}");
+                    -1
+                });
+                writeln!(f, "  {name} = {value}")
+            };
+            pragma_i32(f, "auto_vacuum")?;
+            pragma_str(f, "journal_mode")?;
+            pragma_i32(f, "journal_size_limit")?;
+            pragma_i32(f, "synchronous")?;
+            pragma_i32(f, "schema_version")?;
+            pragma_i32(f, "user_version")?;
+            Ok(())
+        })?;
+        writeln!(f)?;
+
         // Display accumulated metrics.
         writeln!(f, "Metrics information:")?;
         writeln!(f)?;
diff --git a/keystore2/src/maintenance/tests.rs b/keystore2/src/maintenance/tests.rs
new file mode 100644
index 0000000..fbafa73
--- /dev/null
+++ b/keystore2/src/maintenance/tests.rs
@@ -0,0 +1,182 @@
+// Copyright 2024, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Maintenance tests.
+use super::*;
+use der::ErrorKind;
+
+#[test]
+fn test_encode_module_info_empty() {
+    let expected = vec![0x31, 0x00];
+    assert_eq!(expected, Maintenance::encode_module_info(Vec::new()).unwrap());
+}
+
+#[test]
+fn test_encode_module_info_same_name() {
+    // Same versions
+    let module_info: Vec<ModuleInfo> = vec![
+        ModuleInfo {
+            name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+            version: 25,
+        },
+        ModuleInfo {
+            name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+            version: 25,
+        },
+    ];
+    let actual = Maintenance::encode_module_info(module_info);
+    assert!(actual.is_err());
+    assert_eq!(ErrorKind::SetDuplicate, actual.unwrap_err().kind());
+
+    // Different versions
+    let module_info: Vec<ModuleInfo> = vec![
+        ModuleInfo {
+            name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+            version: 3,
+        },
+        ModuleInfo {
+            name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+            version: 789,
+        },
+    ];
+    let actual = Maintenance::encode_module_info(module_info);
+    assert!(actual.is_err());
+    assert_eq!(ErrorKind::SetDuplicate, actual.unwrap_err().kind());
+}
+
+#[test]
+fn test_encode_module_info_same_name_length() {
+    let module_info: Vec<ModuleInfo> = vec![
+        ModuleInfo { name: OctetString::new("com.android.wifi".to_string()).unwrap(), version: 2 },
+        ModuleInfo { name: OctetString::new("com.android.virt".to_string()).unwrap(), version: 1 },
+    ];
+    let actual = Maintenance::encode_module_info(module_info).unwrap();
+    let expected = hex::decode(concat!(
+        "312e",                             // SET OF, len 46
+        "3015",                             // SEQUENCE, len 21
+        "0410",                             // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e76697274", // "com.android.virt"
+        "020101",                           // INTEGER len 1 value 1
+        "3015",                             // SEQUENCE, len 21
+        "0410",                             // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e77696669", // "com.android.wifi"
+        "020102",                           // INTEGER len 1 value 2
+    ))
+    .unwrap();
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info_version_irrelevant() {
+    // Versions of the modules are irrelevant for determining encoding order since differing names
+    // guarantee a unique ascending order. See Maintenance::ModuleInfo::der_cmp for more detail.
+    let module_info: Vec<ModuleInfo> = vec![
+        ModuleInfo {
+            name: OctetString::new("com.android.extservices".to_string()).unwrap(),
+            version: 1,
+        },
+        ModuleInfo { name: OctetString::new("com.android.adbd".to_string()).unwrap(), version: 14 },
+    ];
+    let actual = Maintenance::encode_module_info(module_info).unwrap();
+    let expected = hex::decode(concat!(
+        "3135",                                           // SET OF, len 53
+        "3015",                                           // SEQUENCE, len 21
+        "0410",                                           // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e61646264",               // "com.android.abdb"
+        "02010e",                                         // INTEGER len 2 value 14
+        "301c",                                           // SEQUENCE, len 28
+        "0417",                                           // OCTET STRING, len 23
+        "636f6d2e616e64726f69642e6578747365727669636573", // "com.android.extservices"
+        "020101",                                         // INTEGER len 1 value 1
+    ))
+    .unwrap();
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info_alphaordering_irrelevant() {
+    // Character ordering of the names of modules is irrelevant for determining encoding order since
+    // differing name lengths guarantee a unique ascending order. See
+    // Maintenance::ModuleInfo::der_cmp for more detail.
+    let module_info: Vec<ModuleInfo> = vec![
+        ModuleInfo {
+            name: OctetString::new("com.android.crashrecovery".to_string()).unwrap(),
+            version: 3,
+        },
+        ModuleInfo { name: OctetString::new("com.android.rkpd".to_string()).unwrap(), version: 8 },
+    ];
+    let actual = Maintenance::encode_module_info(module_info).unwrap();
+    let expected = hex::decode(concat!(
+        "3137",                                               // SET OF, len 55
+        "3015",                                               // SEQUENCE, len 21
+        "0410",                                               // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e726b7064",                   // "com.android.rkpd"
+        "020108",                                             // INTEGER len 1 value 8
+        "301e",                                               // SEQUENCE, len 30
+        "0419",                                               // OCTET STRING, len 25
+        "636f6d2e616e64726f69642e63726173687265636f76657279", // "com.android.crashrecovery"
+        "020103",                                             // INTEGER len 1 value 3
+    ))
+    .unwrap();
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info() {
+    // Collection of `ModuleInfo`s from a few of the other test_encode_module_info_* tests
+    let module_info: Vec<ModuleInfo> = vec![
+        ModuleInfo { name: OctetString::new("com.android.rkpd".to_string()).unwrap(), version: 8 },
+        ModuleInfo {
+            name: OctetString::new("com.android.extservices".to_string()).unwrap(),
+            version: 1,
+        },
+        ModuleInfo {
+            name: OctetString::new("com.android.crashrecovery".to_string()).unwrap(),
+            version: 3,
+        },
+        ModuleInfo { name: OctetString::new("com.android.wifi".to_string()).unwrap(), version: 2 },
+        ModuleInfo { name: OctetString::new("com.android.virt".to_string()).unwrap(), version: 1 },
+        ModuleInfo { name: OctetString::new("com.android.adbd".to_string()).unwrap(), version: 14 },
+    ];
+    let actual = Maintenance::encode_module_info(module_info).unwrap();
+    let expected = hex::decode(concat!(
+        "31819a",                                             // SET OF, len 154
+        "3015",                                               // SEQUENCE, len 21
+        "0410",                                               // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e61646264",                   // "com.android.abdb"
+        "02010e",                                             // INTEGER len 2 value 14
+        "3015",                                               // SEQUENCE, len 21
+        "0410",                                               // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e726b7064",                   // "com.android.rkpd"
+        "020108",                                             // INTEGER len 1 value 8
+        "3015",                                               // SEQUENCE, len 21
+        "0410",                                               // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e76697274",                   // "com.android.virt"
+        "020101",                                             // INTEGER len 1 value 1
+        "3015",                                               // SEQUENCE, len 21
+        "0410",                                               // OCTET STRING, len 16
+        "636f6d2e616e64726f69642e77696669",                   // "com.android.wifi"
+        "020102",                                             // INTEGER len 1 value 2
+        "301c",                                               // SEQUENCE, len 28
+        "0417",                                               // OCTET STRING, len 23
+        "636f6d2e616e64726f69642e6578747365727669636573",     // "com.android.extservices"
+        "020101",                                             // INTEGER len 1 value 1
+        "301e",                                               // SEQUENCE, len 30
+        "0419",                                               // OCTET STRING, len 25
+        "636f6d2e616e64726f69642e63726173687265636f76657279", // "com.android.crashrecovery"
+        "020103",                                             // INTEGER len 1 value 3
+    ))
+    .unwrap();
+    assert_eq!(expected, actual);
+}
diff --git a/keystore2/test_utils/lib.rs b/keystore2/test_utils/lib.rs
index 825657f..8e74f92 100644
--- a/keystore2/test_utils/lib.rs
+++ b/keystore2/test_utils/lib.rs
@@ -21,7 +21,7 @@
 
 use android_system_keystore2::aidl::android::system::keystore2::{
     IKeystoreService::IKeystoreService,
-    IKeystoreSecurityLevel::IKeystoreSecurityLevel,
+    IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
 };
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     ErrorCode::ErrorCode, IKeyMintDevice::IKeyMintDevice, SecurityLevel::SecurityLevel,
@@ -193,4 +193,18 @@
             0
         }
     }
+
+    /// Delete a key.
+    pub fn delete_key(&self, key: &KeyDescriptor) -> binder::Result<()> {
+        match self.binder.deleteKey(key) {
+            Ok(()) => Ok(()),
+            Err(s)
+                if s.exception_code() == binder::ExceptionCode::SERVICE_SPECIFIC
+                    && s.service_specific_error() == ErrorCode::UNIMPLEMENTED.0 =>
+            {
+                Ok(())
+            }
+            Err(e) => Err(e),
+        }
+    }
 }
diff --git a/keystore2/tests/keystore2_client_delete_key_tests.rs b/keystore2/tests/keystore2_client_delete_key_tests.rs
index a0fb9c2..13f8eef 100644
--- a/keystore2/tests/keystore2_client_delete_key_tests.rs
+++ b/keystore2/tests/keystore2_client_delete_key_tests.rs
@@ -100,7 +100,7 @@
     )
     .unwrap();
 
-    let result = sl.binder.deleteKey(&key_metadata.key);
+    let result = sl.delete_key(&key_metadata.key);
     assert!(result.is_ok());
 }
 
@@ -110,7 +110,7 @@
 fn keystore2_delete_key_fails_with_missing_key_blob() {
     let sl = SecLevel::tee();
 
-    let result = key_generations::map_ks_error(sl.binder.deleteKey(&KeyDescriptor {
+    let result = key_generations::map_ks_error(sl.delete_key(&KeyDescriptor {
         domain: Domain::BLOB,
         nspace: key_generations::SELINUX_SHELL_NAMESPACE,
         alias: None,
@@ -132,7 +132,7 @@
         key_generations::generate_ec_p256_signing_key(&sl, Domain::APP, -1, Some(alias), None)
             .unwrap();
 
-    let result = key_generations::map_ks_error(sl.binder.deleteKey(&key_metadata.key));
+    let result = key_generations::map_ks_error(sl.delete_key(&key_metadata.key));
     assert!(result.is_err());
     assert_eq!(Error::Km(ErrorCode::INVALID_ARGUMENT), result.unwrap_err());
 }
diff --git a/keystore2/tests/keystore2_client_ec_key_tests.rs b/keystore2/tests/keystore2_client_ec_key_tests.rs
index 526a339..17a88e7 100644
--- a/keystore2/tests/keystore2_client_ec_key_tests.rs
+++ b/keystore2/tests/keystore2_client_ec_key_tests.rs
@@ -211,7 +211,7 @@
     assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
 
     // Delete the generated key blob.
-    sl.binder.deleteKey(&key_metadata.key).unwrap();
+    sl.delete_key(&key_metadata.key).unwrap();
 }
 
 /// Try to generate a key with invalid Domain. `INVALID_ARGUMENT` error response is expected.
@@ -514,5 +514,5 @@
     );
 
     // Delete the generated key blob.
-    sl.binder.deleteKey(&key_metadata.key).unwrap();
+    sl.delete_key(&key_metadata.key).unwrap();
 }
diff --git a/provisioner/Android.bp b/provisioner/Android.bp
index ede1ae6..6a4dc24 100644
--- a/provisioner/Android.bp
+++ b/provisioner/Android.bp
@@ -36,6 +36,7 @@
     ],
     static_libs: [
         "android.hardware.common-V2-ndk",
+        "android.hardware.drm.common-V1-ndk",
         "android.hardware.drm-V1-ndk",
         "android.hardware.security.rkp-V3-ndk",
         "libbase",