Loading services/core/java/com/android/server/integrity/IntegrityFileManager.java +11 −5 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Optional; Loading Loading @@ -153,14 +154,19 @@ public class IntegrityFileManager { throws IOException, RuleParseException { synchronized (RULES_LOCK) { // Try to identify indexes from the index file. List<RuleIndexRange> ruleReadingIndexes = List<RuleIndexRange> ruleReadingIndexes; try { ruleReadingIndexes = mRuleIndexingController.identifyRulesToEvaluate(appInstallMetadata); } catch (Exception e) { Slog.w(TAG, "Error identifying the rule indexes. Trying unindexed.", e); ruleReadingIndexes = Collections.emptyList(); } // Read the rules based on the index information. // TODO(b/145493956): Provide the identified indexes to the rule reader. // Read the rules based on the index information when available. try (FileInputStream inputStream = new FileInputStream(new File(mRulesDir, RULES_FILE))) { List<Rule> rules = mRuleParser.parse(inputStream); List<Rule> rules = mRuleParser.parse(inputStream, ruleReadingIndexes); return rules; } } Loading services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java +39 −5 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.server.integrity.model.BitTrackedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** A helper class to parse rules into the {@link Rule} model from Binary representation. */ Loading @@ -51,28 +52,40 @@ public class RuleBinaryParser implements RuleParser { public List<Rule> parse(byte[] ruleBytes) throws RuleParseException { try { BitTrackedInputStream bitTrackedInputStream = new BitTrackedInputStream(ruleBytes); return parseRules(bitTrackedInputStream); return parseRules(bitTrackedInputStream, /* indexRanges= */ Collections.emptyList()); } catch (Exception e) { throw new RuleParseException(e.getMessage(), e); } } @Override public List<Rule> parse(InputStream inputStream) throws RuleParseException { public List<Rule> parse(InputStream inputStream, List<RuleIndexRange> indexRanges) throws RuleParseException { try { BitTrackedInputStream bitTrackedInputStream = new BitTrackedInputStream(inputStream); return parseRules(bitTrackedInputStream); return parseRules(bitTrackedInputStream, indexRanges); } catch (Exception e) { throw new RuleParseException(e.getMessage(), e); } } private List<Rule> parseRules(BitTrackedInputStream bitTrackedInputStream) throws IOException { List<Rule> parsedRules = new ArrayList<>(); private List<Rule> parseRules( BitTrackedInputStream bitTrackedInputStream, List<RuleIndexRange> indexRanges) throws IOException { // Read the rule binary file format version. bitTrackedInputStream.getNext(FORMAT_VERSION_BITS); return indexRanges.isEmpty() ? parseAllRules(bitTrackedInputStream) : parseIndexedRules(bitTrackedInputStream, indexRanges); } private List<Rule> parseAllRules(BitTrackedInputStream bitTrackedInputStream) throws IOException { List<Rule> parsedRules = new ArrayList<>(); while (bitTrackedInputStream.hasNext()) { if (bitTrackedInputStream.getNext(SIGNAL_BIT) == 1) { parsedRules.add(parseRule(bitTrackedInputStream)); Loading @@ -82,6 +95,27 @@ public class RuleBinaryParser implements RuleParser { return parsedRules; } private List<Rule> parseIndexedRules( BitTrackedInputStream bitTrackedInputStream, List<RuleIndexRange> indexRanges) throws IOException { List<Rule> parsedRules = new ArrayList<>(); for (RuleIndexRange range : indexRanges) { // Skip the rules that are not in the range. bitTrackedInputStream.setCursorToByteLocation(range.getStartIndex()); // Read the rules until we reach the end index. while (bitTrackedInputStream.hasNext() && bitTrackedInputStream.getReadBitsCount() < range.getEndIndex()) { if (bitTrackedInputStream.getNext(SIGNAL_BIT) == 1) { parsedRules.add(parseRule(bitTrackedInputStream)); } } } return parsedRules; } private Rule parseRule(BitTrackedInputStream bitTrackedInputStream) throws IOException { Formula formula = parseFormula(bitTrackedInputStream); int effect = bitTrackedInputStream.getNext(EFFECT_BITS); Loading services/core/java/com/android/server/integrity/parser/RuleParser.java +2 −1 Original line number Diff line number Diff line Loading @@ -28,5 +28,6 @@ public interface RuleParser { List<Rule> parse(byte[] ruleBytes) throws RuleParseException; /** Parse rules from an input stream. */ List<Rule> parse(InputStream inputStream) throws RuleParseException; List<Rule> parse(InputStream inputStream, List<RuleIndexRange> ruleIndexRanges) throws RuleParseException; } services/core/java/com/android/server/integrity/parser/RuleXmlParser.java +2 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ public final class RuleXmlParser implements RuleParser { } @Override public List<Rule> parse(InputStream inputStream) throws RuleParseException { public List<Rule> parse(InputStream inputStream, List<RuleIndexRange> indexRanges) throws RuleParseException { try { XmlPullParser xmlPullParser = Xml.newPullParser(); xmlPullParser.setInput(inputStream, StandardCharsets.UTF_8.name()); Loading services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java +83 −19 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; Loading Loading @@ -97,8 +98,10 @@ public class RuleBinaryParserTest { private static final byte[] DEFAULT_FORMAT_VERSION_BYTES = getBytes(getBits(DEFAULT_FORMAT_VERSION, FORMAT_VERSION_BITS)); private static final List<RuleIndexRange> NO_INDEXING = Collections.emptyList(); @Test public void testBinaryStream_validCompoundFormula() throws Exception { public void testBinaryStream_validCompoundFormula_noIndexing() throws Exception { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -131,13 +134,13 @@ public class RuleBinaryParserTest { /* isHashedValue= */ false))), Rule.DENY); List<Rule> rules = binaryParser.parse(inputStream); List<Rule> rules = binaryParser.parse(inputStream, NO_INDEXING); assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); } @Test public void testBinaryString_validCompoundFormula_notConnector() throws Exception { public void testBinaryString_validCompoundFormula_notConnector_noIndexing() throws Exception { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -175,7 +178,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validCompoundFormula_andConnector() throws Exception { public void testBinaryString_validCompoundFormula_andConnector_noIndexing() throws Exception { String packageName = "com.test.app"; String appCertificate = "test_cert"; String ruleBits = Loading Loading @@ -223,7 +226,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validCompoundFormula_orConnector() throws Exception { public void testBinaryString_validCompoundFormula_orConnector_noIndexing() throws Exception { String packageName = "com.test.app"; String appCertificate = "test_cert"; String ruleBits = Loading Loading @@ -272,7 +275,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_stringValue() throws Exception { public void testBinaryString_validAtomicFormula_stringValue_noIndexing() throws Exception { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -304,7 +307,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_hashedValue() throws Exception { public void testBinaryString_validAtomicFormula_hashedValue_noIndexing() throws Exception { String appCertificate = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; String ruleBits = START_BIT Loading Loading @@ -337,7 +340,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_integerValue() throws Exception { public void testBinaryString_validAtomicFormula_integerValue_noIndexing() throws Exception { int versionCode = 1; String ruleBits = START_BIT Loading Loading @@ -365,7 +368,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_booleanValue() throws Exception { public void testBinaryString_validAtomicFormula_booleanValue_noIndexing() throws Exception { String isPreInstalled = "1"; String ruleBits = START_BIT Loading @@ -392,7 +395,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidAtomicFormula() throws Exception { public void testBinaryString_invalidAtomicFormula_noIndexing() { int versionCode = 1; String ruleBits = START_BIT Loading @@ -415,7 +418,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_withNoRuleList() throws RuleParseException { public void testBinaryString_withNoRuleList_noIndexing() throws RuleParseException { ByteBuffer rule = ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length); rule.put(DEFAULT_FORMAT_VERSION_BYTES); RuleParser binaryParser = new RuleBinaryParser(); Loading @@ -426,7 +429,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_withEmptyRule() throws RuleParseException { public void testBinaryString_withEmptyRule_noIndexing() { String ruleBits = START_BIT; byte[] ruleBytes = getBytes(ruleBits); ByteBuffer rule = Loading @@ -442,7 +445,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidCompoundFormula_invalidNumberOfFormulas() throws Exception { public void testBinaryString_invalidCompoundFormula_invalidNumberOfFormulas_noIndexing() { String packageName = "com.test.app"; String appCertificate = "test_cert"; String ruleBits = Loading Loading @@ -478,7 +481,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidOperator() throws Exception { public void testBinaryString_invalidRule_invalidOperator_noIndexing() { int versionCode = 1; String ruleBits = START_BIT Loading Loading @@ -506,7 +509,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidEffect() throws Exception { public void testBinaryString_invalidRule_invalidEffect_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -536,7 +539,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidConnector() throws Exception { public void testBinaryString_invalidRule_invalidConnector_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -566,7 +569,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidKey() throws Exception { public void testBinaryString_invalidRule_invalidKey_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -596,7 +599,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidSeparator() throws Exception { public void testBinaryString_invalidRule_invalidSeparator_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -626,7 +629,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidEndMarker() throws Exception { public void testBinaryString_invalidRule_invalidEndMarker_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading @@ -653,4 +656,65 @@ public class RuleBinaryParserTest { /* expectedExceptionMessageRegex */ "A rule must end with a '1' bit", () -> binaryParser.parse(rule.array())); } @Test public void testBinaryStream_multipleRules_indexingIdentifiesParsesIndexRangeCorrectly() throws Exception { String packageName2 = "com.test.2"; byte[] ruleBytes1 = getBytes(getRulesWithPackageName("com.test.1")); byte[] ruleBytes2 = getBytes(getRulesWithPackageName(packageName2)); byte[] ruleBytes3 = getBytes(getRulesWithPackageName("com.test.3")); ByteBuffer rule = ByteBuffer.allocate( DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes1.length + ruleBytes2.length + ruleBytes3.length); rule.put(DEFAULT_FORMAT_VERSION_BYTES); rule.put(ruleBytes1); rule.put(ruleBytes2); rule.put(ruleBytes3); InputStream inputStream = new ByteArrayInputStream(rule.array()); RuleParser binaryParser = new RuleBinaryParser(); List<RuleIndexRange> indexRanges = new ArrayList<>(); indexRanges.add( new RuleIndexRange( DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes1.length, DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes1.length + ruleBytes2.length)); List<Rule> rules = binaryParser.parse(inputStream, indexRanges); Rule expectedRule = new Rule( new CompoundFormula( CompoundFormula.NOT, Collections.singletonList( new AtomicFormula.StringAtomicFormula( AtomicFormula.PACKAGE_NAME, packageName2, /* isHashedValue= */ false))), Rule.DENY); assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); } private static String getRulesWithPackageName(String packageName) { return START_BIT + COMPOUND_FORMULA_START_BITS + NOT + ATOMIC_FORMULA_START_BITS + PACKAGE_NAME + EQ + IS_NOT_HASHED + getBits(packageName.length(), VALUE_SIZE_BITS) + getValueBits(packageName) + COMPOUND_FORMULA_END_BITS + DENY + END_BIT; } } Loading
services/core/java/com/android/server/integrity/IntegrityFileManager.java +11 −5 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Optional; Loading Loading @@ -153,14 +154,19 @@ public class IntegrityFileManager { throws IOException, RuleParseException { synchronized (RULES_LOCK) { // Try to identify indexes from the index file. List<RuleIndexRange> ruleReadingIndexes = List<RuleIndexRange> ruleReadingIndexes; try { ruleReadingIndexes = mRuleIndexingController.identifyRulesToEvaluate(appInstallMetadata); } catch (Exception e) { Slog.w(TAG, "Error identifying the rule indexes. Trying unindexed.", e); ruleReadingIndexes = Collections.emptyList(); } // Read the rules based on the index information. // TODO(b/145493956): Provide the identified indexes to the rule reader. // Read the rules based on the index information when available. try (FileInputStream inputStream = new FileInputStream(new File(mRulesDir, RULES_FILE))) { List<Rule> rules = mRuleParser.parse(inputStream); List<Rule> rules = mRuleParser.parse(inputStream, ruleReadingIndexes); return rules; } } Loading
services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java +39 −5 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.server.integrity.model.BitTrackedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** A helper class to parse rules into the {@link Rule} model from Binary representation. */ Loading @@ -51,28 +52,40 @@ public class RuleBinaryParser implements RuleParser { public List<Rule> parse(byte[] ruleBytes) throws RuleParseException { try { BitTrackedInputStream bitTrackedInputStream = new BitTrackedInputStream(ruleBytes); return parseRules(bitTrackedInputStream); return parseRules(bitTrackedInputStream, /* indexRanges= */ Collections.emptyList()); } catch (Exception e) { throw new RuleParseException(e.getMessage(), e); } } @Override public List<Rule> parse(InputStream inputStream) throws RuleParseException { public List<Rule> parse(InputStream inputStream, List<RuleIndexRange> indexRanges) throws RuleParseException { try { BitTrackedInputStream bitTrackedInputStream = new BitTrackedInputStream(inputStream); return parseRules(bitTrackedInputStream); return parseRules(bitTrackedInputStream, indexRanges); } catch (Exception e) { throw new RuleParseException(e.getMessage(), e); } } private List<Rule> parseRules(BitTrackedInputStream bitTrackedInputStream) throws IOException { List<Rule> parsedRules = new ArrayList<>(); private List<Rule> parseRules( BitTrackedInputStream bitTrackedInputStream, List<RuleIndexRange> indexRanges) throws IOException { // Read the rule binary file format version. bitTrackedInputStream.getNext(FORMAT_VERSION_BITS); return indexRanges.isEmpty() ? parseAllRules(bitTrackedInputStream) : parseIndexedRules(bitTrackedInputStream, indexRanges); } private List<Rule> parseAllRules(BitTrackedInputStream bitTrackedInputStream) throws IOException { List<Rule> parsedRules = new ArrayList<>(); while (bitTrackedInputStream.hasNext()) { if (bitTrackedInputStream.getNext(SIGNAL_BIT) == 1) { parsedRules.add(parseRule(bitTrackedInputStream)); Loading @@ -82,6 +95,27 @@ public class RuleBinaryParser implements RuleParser { return parsedRules; } private List<Rule> parseIndexedRules( BitTrackedInputStream bitTrackedInputStream, List<RuleIndexRange> indexRanges) throws IOException { List<Rule> parsedRules = new ArrayList<>(); for (RuleIndexRange range : indexRanges) { // Skip the rules that are not in the range. bitTrackedInputStream.setCursorToByteLocation(range.getStartIndex()); // Read the rules until we reach the end index. while (bitTrackedInputStream.hasNext() && bitTrackedInputStream.getReadBitsCount() < range.getEndIndex()) { if (bitTrackedInputStream.getNext(SIGNAL_BIT) == 1) { parsedRules.add(parseRule(bitTrackedInputStream)); } } } return parsedRules; } private Rule parseRule(BitTrackedInputStream bitTrackedInputStream) throws IOException { Formula formula = parseFormula(bitTrackedInputStream); int effect = bitTrackedInputStream.getNext(EFFECT_BITS); Loading
services/core/java/com/android/server/integrity/parser/RuleParser.java +2 −1 Original line number Diff line number Diff line Loading @@ -28,5 +28,6 @@ public interface RuleParser { List<Rule> parse(byte[] ruleBytes) throws RuleParseException; /** Parse rules from an input stream. */ List<Rule> parse(InputStream inputStream) throws RuleParseException; List<Rule> parse(InputStream inputStream, List<RuleIndexRange> ruleIndexRanges) throws RuleParseException; }
services/core/java/com/android/server/integrity/parser/RuleXmlParser.java +2 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ public final class RuleXmlParser implements RuleParser { } @Override public List<Rule> parse(InputStream inputStream) throws RuleParseException { public List<Rule> parse(InputStream inputStream, List<RuleIndexRange> indexRanges) throws RuleParseException { try { XmlPullParser xmlPullParser = Xml.newPullParser(); xmlPullParser.setInput(inputStream, StandardCharsets.UTF_8.name()); Loading
services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java +83 −19 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; Loading Loading @@ -97,8 +98,10 @@ public class RuleBinaryParserTest { private static final byte[] DEFAULT_FORMAT_VERSION_BYTES = getBytes(getBits(DEFAULT_FORMAT_VERSION, FORMAT_VERSION_BITS)); private static final List<RuleIndexRange> NO_INDEXING = Collections.emptyList(); @Test public void testBinaryStream_validCompoundFormula() throws Exception { public void testBinaryStream_validCompoundFormula_noIndexing() throws Exception { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -131,13 +134,13 @@ public class RuleBinaryParserTest { /* isHashedValue= */ false))), Rule.DENY); List<Rule> rules = binaryParser.parse(inputStream); List<Rule> rules = binaryParser.parse(inputStream, NO_INDEXING); assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); } @Test public void testBinaryString_validCompoundFormula_notConnector() throws Exception { public void testBinaryString_validCompoundFormula_notConnector_noIndexing() throws Exception { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -175,7 +178,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validCompoundFormula_andConnector() throws Exception { public void testBinaryString_validCompoundFormula_andConnector_noIndexing() throws Exception { String packageName = "com.test.app"; String appCertificate = "test_cert"; String ruleBits = Loading Loading @@ -223,7 +226,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validCompoundFormula_orConnector() throws Exception { public void testBinaryString_validCompoundFormula_orConnector_noIndexing() throws Exception { String packageName = "com.test.app"; String appCertificate = "test_cert"; String ruleBits = Loading Loading @@ -272,7 +275,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_stringValue() throws Exception { public void testBinaryString_validAtomicFormula_stringValue_noIndexing() throws Exception { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -304,7 +307,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_hashedValue() throws Exception { public void testBinaryString_validAtomicFormula_hashedValue_noIndexing() throws Exception { String appCertificate = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; String ruleBits = START_BIT Loading Loading @@ -337,7 +340,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_integerValue() throws Exception { public void testBinaryString_validAtomicFormula_integerValue_noIndexing() throws Exception { int versionCode = 1; String ruleBits = START_BIT Loading Loading @@ -365,7 +368,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_validAtomicFormula_booleanValue() throws Exception { public void testBinaryString_validAtomicFormula_booleanValue_noIndexing() throws Exception { String isPreInstalled = "1"; String ruleBits = START_BIT Loading @@ -392,7 +395,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidAtomicFormula() throws Exception { public void testBinaryString_invalidAtomicFormula_noIndexing() { int versionCode = 1; String ruleBits = START_BIT Loading @@ -415,7 +418,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_withNoRuleList() throws RuleParseException { public void testBinaryString_withNoRuleList_noIndexing() throws RuleParseException { ByteBuffer rule = ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length); rule.put(DEFAULT_FORMAT_VERSION_BYTES); RuleParser binaryParser = new RuleBinaryParser(); Loading @@ -426,7 +429,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_withEmptyRule() throws RuleParseException { public void testBinaryString_withEmptyRule_noIndexing() { String ruleBits = START_BIT; byte[] ruleBytes = getBytes(ruleBits); ByteBuffer rule = Loading @@ -442,7 +445,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidCompoundFormula_invalidNumberOfFormulas() throws Exception { public void testBinaryString_invalidCompoundFormula_invalidNumberOfFormulas_noIndexing() { String packageName = "com.test.app"; String appCertificate = "test_cert"; String ruleBits = Loading Loading @@ -478,7 +481,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidOperator() throws Exception { public void testBinaryString_invalidRule_invalidOperator_noIndexing() { int versionCode = 1; String ruleBits = START_BIT Loading Loading @@ -506,7 +509,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidEffect() throws Exception { public void testBinaryString_invalidRule_invalidEffect_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -536,7 +539,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidConnector() throws Exception { public void testBinaryString_invalidRule_invalidConnector_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -566,7 +569,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidKey() throws Exception { public void testBinaryString_invalidRule_invalidKey_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -596,7 +599,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidSeparator() throws Exception { public void testBinaryString_invalidRule_invalidSeparator_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading Loading @@ -626,7 +629,7 @@ public class RuleBinaryParserTest { } @Test public void testBinaryString_invalidRule_invalidEndMarker() throws Exception { public void testBinaryString_invalidRule_invalidEndMarker_noIndexing() { String packageName = "com.test.app"; String ruleBits = START_BIT Loading @@ -653,4 +656,65 @@ public class RuleBinaryParserTest { /* expectedExceptionMessageRegex */ "A rule must end with a '1' bit", () -> binaryParser.parse(rule.array())); } @Test public void testBinaryStream_multipleRules_indexingIdentifiesParsesIndexRangeCorrectly() throws Exception { String packageName2 = "com.test.2"; byte[] ruleBytes1 = getBytes(getRulesWithPackageName("com.test.1")); byte[] ruleBytes2 = getBytes(getRulesWithPackageName(packageName2)); byte[] ruleBytes3 = getBytes(getRulesWithPackageName("com.test.3")); ByteBuffer rule = ByteBuffer.allocate( DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes1.length + ruleBytes2.length + ruleBytes3.length); rule.put(DEFAULT_FORMAT_VERSION_BYTES); rule.put(ruleBytes1); rule.put(ruleBytes2); rule.put(ruleBytes3); InputStream inputStream = new ByteArrayInputStream(rule.array()); RuleParser binaryParser = new RuleBinaryParser(); List<RuleIndexRange> indexRanges = new ArrayList<>(); indexRanges.add( new RuleIndexRange( DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes1.length, DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes1.length + ruleBytes2.length)); List<Rule> rules = binaryParser.parse(inputStream, indexRanges); Rule expectedRule = new Rule( new CompoundFormula( CompoundFormula.NOT, Collections.singletonList( new AtomicFormula.StringAtomicFormula( AtomicFormula.PACKAGE_NAME, packageName2, /* isHashedValue= */ false))), Rule.DENY); assertThat(rules).isEqualTo(Collections.singletonList(expectedRule)); } private static String getRulesWithPackageName(String packageName) { return START_BIT + COMPOUND_FORMULA_START_BITS + NOT + ATOMIC_FORMULA_START_BITS + PACKAGE_NAME + EQ + IS_NOT_HASHED + getBits(packageName.length(), VALUE_SIZE_BITS) + getValueBits(packageName) + COMPOUND_FORMULA_END_BITS + DENY + END_BIT; } }