Merge "[getService] Retry get_interface in keystore2" into main
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 28bdfea..c482e84 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -30,7 +30,10 @@
"keystore2_use_latest_aidl_rust",
"structured_log_rust_defaults",
],
-
+ cfgs: select(release_flag("RELEASE_AVF_ENABLE_EARLY_VM"), {
+ true: ["early_vm"],
+ default: [],
+ }),
rustlibs: [
"android.hardware.security.rkp-V3-rust",
"android.hardware.security.secureclock-V1-rust",
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index a90ba79..bde83fd 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -23,7 +23,7 @@
use crate::legacy_blob::LegacyBlobLoader;
use crate::legacy_importer::LegacyImporter;
use crate::super_key::SuperKeyManager;
-use crate::utils::watchdog as wd;
+use crate::utils::{retry_get_interface, watchdog as wd};
use crate::{
database::KeystoreDB,
database::Uuid,
@@ -225,8 +225,12 @@
let (keymint, hal_version) = if let Some(service_name) = service_name {
let km: Strong<dyn IKeyMintDevice> =
- map_binder_status_code(binder::get_interface(&service_name))
- .context(ks_err!("Trying to connect to genuine KeyMint service."))?;
+ if SecurityLevel::TRUSTED_ENVIRONMENT == *security_level {
+ map_binder_status_code(retry_get_interface(&service_name))
+ } else {
+ map_binder_status_code(binder::get_interface(&service_name))
+ }
+ .context(ks_err!("Trying to connect to genuine KeyMint service."))?;
// Map the HAL version code for KeyMint to be <AIDL version> * 100, so
// - V1 is 100
// - V2 is 200
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 0a545f7..03c0626 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -40,14 +40,17 @@
Authorization::Authorization, Domain::Domain, KeyDescriptor::KeyDescriptor,
};
use anyhow::{Context, Result};
-use binder::{Strong, ThreadState};
+use binder::{FromIBinder, StatusCode, Strong, ThreadState};
use keystore2_apc_compat::{
ApcCompatUiOptions, APC_COMPAT_ERROR_ABORTED, APC_COMPAT_ERROR_CANCELLED,
APC_COMPAT_ERROR_IGNORED, APC_COMPAT_ERROR_OK, APC_COMPAT_ERROR_OPERATION_PENDING,
APC_COMPAT_ERROR_SYSTEM_ERROR,
};
use keystore2_crypto::{aes_gcm_decrypt, aes_gcm_encrypt, ZVec};
+use log::{info, warn};
use std::iter::IntoIterator;
+use std::thread::sleep;
+use std::time::Duration;
#[cfg(test)]
mod tests;
@@ -634,3 +637,25 @@
aes_gcm_encrypt(plaintext, self.key()).context(ks_err!("Encryption failed."))
}
}
+
+pub(crate) fn retry_get_interface<T: FromIBinder + ?Sized>(
+ name: &str,
+) -> Result<Strong<T>, StatusCode> {
+ let retry_count = if cfg!(early_vm) { 5 } else { 1 };
+
+ let mut wait_time = Duration::from_secs(5);
+ for i in 1..retry_count {
+ match binder::get_interface(name) {
+ Ok(res) => return Ok(res),
+ Err(e) => {
+ warn!("failed to get interface {name}. Retry {i}/{retry_count}: {e:?}");
+ sleep(wait_time);
+ wait_time *= 2;
+ }
+ }
+ }
+ if retry_count > 1 {
+ info!("{retry_count}-th (last) retry to get interface: {name}");
+ }
+ binder::get_interface(name)
+}