diff --git a/services/core/java/com/android/server/integrity/parser/RuleIndexingController.java b/services/core/java/com/android/server/integrity/parser/RuleIndexingController.java index 03392abf478f4..87eee4ea7be42 100644 --- a/services/core/java/com/android/server/integrity/parser/RuleIndexingController.java +++ b/services/core/java/com/android/server/integrity/parser/RuleIndexingController.java @@ -28,9 +28,9 @@ import com.android.server.integrity.model.BitInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; -import java.util.TreeSet; import java.util.stream.Collectors; /** Helper class to identify the necessary indexes that needs to be read. */ @@ -93,19 +93,28 @@ public class RuleIndexingController { return keyToIndexMap; } - private RuleIndexRange searchIndexingKeysRangeContainingKey( + private static RuleIndexRange searchIndexingKeysRangeContainingKey( LinkedHashMap indexMap, String searchedKey) { - TreeSet keyTreeSet = - indexMap.keySet().stream() - .filter(key -> !key.matches(START_INDEXING_KEY) && !key.matches( - END_INDEXING_KEY)) - .collect(Collectors.toCollection(TreeSet::new)); - - String minIndex = keyTreeSet.floor(searchedKey); - String maxIndex = keyTreeSet.higher(searchedKey); - + List keys = indexMap.keySet().stream().collect(Collectors.toList()); + List identifiedKeyRange = + searchKeysRangeContainingKey(keys, searchedKey, 0, keys.size() - 1); return new RuleIndexRange( - indexMap.get(minIndex == null ? START_INDEXING_KEY : minIndex), - indexMap.get(maxIndex == null ? END_INDEXING_KEY : maxIndex)); + indexMap.get(identifiedKeyRange.get(0)), indexMap.get(identifiedKeyRange.get(1))); + } + + private static List searchKeysRangeContainingKey( + List sortedKeyList, String key, int startIndex, int endIndex) { + if (endIndex - startIndex == 1) { + return Arrays.asList(sortedKeyList.get(startIndex), sortedKeyList.get(endIndex)); + } + + int midKeyIndex = startIndex + ((endIndex - startIndex) / 2); + String midKey = sortedKeyList.get(midKeyIndex); + + if (key.compareTo(midKey) >= 0) { + return searchKeysRangeContainingKey(sortedKeyList, key, midKeyIndex, endIndex); + } else { + return searchKeysRangeContainingKey(sortedKeyList, key, startIndex, midKeyIndex); + } } } diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java index 47c7e56febe09..a1810b971b097 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java @@ -16,6 +16,8 @@ package com.android.server.integrity; +import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE; + import static com.google.common.truth.Truth.assertThat; import android.content.integrity.AppInstallMetadata; @@ -159,13 +161,14 @@ public class IntegrityFileManagerTest { // Create a rule set with 2500 package name indexed, 2500 app certificate indexed and // 500 unindexed rules. List rules = new ArrayList<>(); + int unindexedRuleCount = 70; for (int i = 0; i < 2500; i++) { rules.add(getPackageNameIndexedRule(String.format("%s%04d", packageName, i))); rules.add(getAppCertificateIndexedRule(String.format("%s%04d", appCertificate, i))); } - for (int i = 0; i < 70; i++) { + for (int i = 0; i < unindexedRuleCount; i++) { rules.add(getInstallerCertificateRule(String.format("%s%04d", installerName, i))); } @@ -187,7 +190,8 @@ public class IntegrityFileManagerTest { List rulesFetched = mIntegrityFileManager.readRules(appInstallMetadata); // Verify that we do not load all the rules and we have the necessary rules to evaluate. - assertThat(rulesFetched.size()).isEqualTo(270); + assertThat(rulesFetched.size()) + .isEqualTo(INDEXING_BLOCK_SIZE * 2 + unindexedRuleCount); assertThat(rulesFetched) .containsAllOf( getPackageNameIndexedRule(installedPackageName),