Keystore2: Batching listing of key entries

Support for listing key entries in batches, so that a large number of
key entries, or entries with long key aliases, could be listed.

The list of key descriptors (which contain the key alias) is returned
to JCA from Keystore2 service via the Binder interface.
The size of a single Binder transaction is limited. Thus, we have run
into http://b/222287335 , where an app can create too many Keystore2
keys than can be returned in a single Binder transaction. Effectively,
this prevents the app from listing the keys it generated at all.

This is solved by adding a method to the Keystore2 interface for
obtaining all the key descriptors whose alias is past a given value
(with the intention that this value is the last key alias from the
previous batch). Keystore2 already limits the number of entries
returned to a number estimated to fit under the Binder transaction size
limit. Together, this enables callers to receive the list of key
descriptors in batches.

Additionally, add a method to Keystore2 to return the total number of
key entries by querying the DB for the number of rows, rather than count
the number of entries returned (which may be truncated).

Bug: 222287335
Test: atest KeystoreTests
Test: atest CtsKeystoreTestCases:android.keystore.cts.AndroidKeyStoreTest
Test: atest keystore2_test
Change-Id: I4a8efef2303beadd2cf6db992833d87bf58d7aec
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index 1040228..7ba8cbc 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -22,7 +22,7 @@
 use crate::permission::{KeyPerm, KeystorePerm};
 use crate::security_level::KeystoreSecurityLevel;
 use crate::utils::{
-    check_grant_permission, check_key_permission, check_keystore_permission,
+    check_grant_permission, check_key_permission, check_keystore_permission, count_key_entries,
     key_parameters_to_authorizations, list_key_entries, uid_to_android_user, watchdog as wd,
 };
 use crate::{
@@ -251,7 +251,11 @@
         .context(ks_err!())
     }
 
-    fn list_entries(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
+    fn get_key_descriptor_for_lookup(
+        &self,
+        domain: Domain,
+        namespace: i64,
+    ) -> Result<KeyDescriptor> {
         let mut k = match domain {
             Domain::APP => KeyDescriptor {
                 domain,
@@ -284,8 +288,29 @@
                 return Err(e).context(ks_err!("While checking key permission."))?;
             }
         }
+        Ok(k)
+    }
 
-        DB.with(|db| list_key_entries(&mut db.borrow_mut(), k.domain, k.nspace))
+    fn list_entries(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
+        let k = self.get_key_descriptor_for_lookup(domain, namespace)?;
+
+        DB.with(|db| list_key_entries(&mut db.borrow_mut(), k.domain, k.nspace, None))
+    }
+
+    fn count_num_entries(&self, domain: Domain, namespace: i64) -> Result<i32> {
+        let k = self.get_key_descriptor_for_lookup(domain, namespace)?;
+
+        DB.with(|db| count_key_entries(&mut db.borrow_mut(), k.domain, k.nspace))
+    }
+
+    fn list_entries_batched(
+        &self,
+        domain: Domain,
+        namespace: i64,
+        start_past_alias: Option<&str>,
+    ) -> Result<Vec<KeyDescriptor>> {
+        let k = self.get_key_descriptor_for_lookup(domain, namespace)?;
+        DB.with(|db| list_key_entries(&mut db.borrow_mut(), k.domain, k.nspace, start_past_alias))
     }
 
     fn delete_key(&self, key: &KeyDescriptor) -> Result<()> {
@@ -389,4 +414,18 @@
         let _wp = wd::watch_millis("IKeystoreService::ungrant", 500);
         map_or_log_err(self.ungrant(key, grantee_uid), Ok)
     }
+    fn listEntriesBatched(
+        &self,
+        domain: Domain,
+        namespace: i64,
+        start_past_alias: Option<&str>,
+    ) -> binder::Result<Vec<KeyDescriptor>> {
+        let _wp = wd::watch_millis("IKeystoreService::listEntriesBatched", 500);
+        map_or_log_err(self.list_entries_batched(domain, namespace, start_past_alias), Ok)
+    }
+
+    fn getNumberOfEntries(&self, domain: Domain, namespace: i64) -> binder::Result<i32> {
+        let _wp = wd::watch_millis("IKeystoreService::getNumberOfEntries", 500);
+        map_or_log_err(self.count_num_entries(domain, namespace), Ok)
+    }
 }