Limit the number of key descriptors sent back

In case the number of key descriptors and their content exceeds the
binder transaction size limit, only return a subset that does fit.

This is a temporary fix - long-term fix is to introduce new API that
lets the caller specify the range of aliases to be fetched.

Bug: 222287335
Test: Manual: Generate 100 keys with a 6k characters name each.
Change-Id: I5e8543a25dd9f1bb504fbc23f35779da0a0153b0
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 75d98e2..1bae75e 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -276,7 +276,40 @@
     );
     result.sort_unstable();
     result.dedup();
-    Ok(result)
+
+    let mut items_to_return = 0;
+    let mut returned_bytes: usize = 0;
+    const RESPONSE_SIZE_LIMIT: usize = 358400;
+    // Estimate the transaction size to avoid returning more items than what
+    // could fit in a binder transaction.
+    for kd in result.iter() {
+        // 4 bytes for the Domain enum
+        // 8 bytes for the Namespace long.
+        returned_bytes += 4 + 8;
+        // Size of the alias string. Includes 4 bytes for length encoding.
+        if let Some(alias) = &kd.alias {
+            returned_bytes += 4 + alias.len();
+        }
+        // Size of the blob. Includes 4 bytes for length encoding.
+        if let Some(blob) = &kd.blob {
+            returned_bytes += 4 + blob.len();
+        }
+        // The binder transaction size limit is 1M. Empirical measurements show
+        // that the binder overhead is 60% (to be confirmed). So break after
+        // 350KB and return a partial list.
+        if returned_bytes > RESPONSE_SIZE_LIMIT {
+            log::warn!(
+                "Key descriptors list ({} items) may exceed binder \
+                       size, returning {} items est {} bytes.",
+                result.len(),
+                items_to_return,
+                returned_bytes
+            );
+            break;
+        }
+        items_to_return += 1;
+    }
+    Ok(result[..items_to_return].to_vec())
 }
 
 /// This module provides helpers for simplified use of the watchdog module.