Loading services/core/java/com/android/server/integrity/IntegrityFileManager.java +8 −8 Original line number Diff line number Diff line Loading @@ -44,12 +44,9 @@ import java.util.Optional; public class IntegrityFileManager { private static final String TAG = "IntegrityFileManager"; // TODO: this is a prototype implementation of this class. Thus no tests are included. // Implementing rule indexing will likely overhaul this class and more tests should be included // then. private static final String METADATA_FILE = "metadata"; private static final String RULES_FILE = "rules"; private static final String INDEXING_FILE = "indexing"; private static final Object RULES_LOCK = new Object(); private static IntegrityFileManager sInstance = null; Loading Loading @@ -125,9 +122,12 @@ public class IntegrityFileManager { // We don't consider this fatal so we continue execution. } try (FileOutputStream fileOutputStream = new FileOutputStream(new File(mStagingDir, RULES_FILE))) { mRuleSerializer.serialize(rules, Optional.empty(), fileOutputStream); try (FileOutputStream ruleFileOutputStream = new FileOutputStream(new File(mStagingDir, RULES_FILE)); FileOutputStream indexingFileOutputStream = new FileOutputStream(new File(mStagingDir, INDEXING_FILE))) { mRuleSerializer.serialize( rules, Optional.empty(), ruleFileOutputStream, indexingFileOutputStream); } switchStagingRulesDir(); Loading services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java +2 −2 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import java.io.OutputStream; */ public class ByteTrackedOutputStream { private static long sWrittenBytesCount; private static int sWrittenBytesCount; private static OutputStream sOutputStream; public ByteTrackedOutputStream(OutputStream outputStream) { Loading @@ -47,7 +47,7 @@ public class ByteTrackedOutputStream { /** * Returns the total number of bytes written into the output stream at the requested time. */ public long getWrittenBytesCount() { public int getWrittenBytesCount() { return sWrittenBytesCount; } } services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java +61 −22 Original line number Diff line number Diff line Loading @@ -52,20 +52,21 @@ import java.util.TreeMap; /** A helper class to serialize rules from the {@link Rule} model to Binary representation. */ public class RuleBinarySerializer implements RuleSerializer { // The parsing time seems acceptable for 100 rules based on the tests in go/ic-rule-file-format. private static final int INDEXING_BLOCK_SIZE = 100; // The parsing time seems acceptable for this block size based on the tests in // go/ic-rule-file-format. public static final int INDEXING_BLOCK_SIZE = 100; private static final String START_INDEXING_KEY = "START_KEY"; private static final String END_INDEXING_KEY = "END_KEY"; public static final String START_INDEXING_KEY = "START_KEY"; public static final String END_INDEXING_KEY = "END_KEY"; // Get the byte representation for a list of rules. @Override public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) throws RuleSerializeException { try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); serialize(rules, formatVersion, byteArrayOutputStream); return byteArrayOutputStream.toByteArray(); ByteArrayOutputStream rulesOutputStream = new ByteArrayOutputStream(); serialize(rules, formatVersion, rulesOutputStream, new ByteArrayOutputStream()); return rulesOutputStream.toByteArray(); } catch (Exception e) { throw new RuleSerializeException(e.getMessage(), e); } Loading @@ -74,27 +75,38 @@ public class RuleBinarySerializer implements RuleSerializer { // Get the byte representation for a list of rules, and write them to an output stream. @Override public void serialize( List<Rule> rules, Optional<Integer> formatVersion, OutputStream originalOutputStream) List<Rule> rules, Optional<Integer> formatVersion, OutputStream rulesFileOutputStream, OutputStream indexingFileOutputStream) throws RuleSerializeException { try { // Determine the indexing groups and the order of the rules within each indexed group. Map<Integer, TreeMap<String, List<Rule>>> indexedRules = RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules); ByteTrackedOutputStream outputStream = new ByteTrackedOutputStream(originalOutputStream); ByteTrackedOutputStream ruleFileByteTrackedOutputStream = new ByteTrackedOutputStream(rulesFileOutputStream); serializeRuleFileMetadata(formatVersion, outputStream); serializeRuleFileMetadata(formatVersion, ruleFileByteTrackedOutputStream); Map<String, Long> packageNameIndexes = serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream); Map<String, Long> appCertificateIndexes = serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream); Map<String, Long> unindexedRulesIndex = serializeRuleList(indexedRules.get(NOT_INDEXED), outputStream); Map<String, Integer> packageNameIndexes = serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), ruleFileByteTrackedOutputStream); indexingFileOutputStream.write( serializeIndexes(packageNameIndexes, /* isIndexed= */true)); // TODO(b/145493956): Write these indexes into a index file provided by integrity file // manager. Map<String, Integer> appCertificateIndexes = serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), ruleFileByteTrackedOutputStream); indexingFileOutputStream.write( serializeIndexes(appCertificateIndexes, /* isIndexed= */true)); Map<String, Integer> unindexedRulesIndexes = serializeRuleList(indexedRules.get(NOT_INDEXED), ruleFileByteTrackedOutputStream); indexingFileOutputStream.write( serializeIndexes(unindexedRulesIndexes, /* isIndexed= */false)); } catch (Exception e) { throw new RuleSerializeException(e.getMessage(), e); } Loading @@ -109,15 +121,15 @@ public class RuleBinarySerializer implements RuleSerializer { outputStream.write(bitOutputStream.toByteArray()); } private Map<String, Long> serializeRuleList(TreeMap<String, List<Rule>> rulesMap, private Map<String, Integer> serializeRuleList(TreeMap<String, List<Rule>> rulesMap, ByteTrackedOutputStream outputStream) throws IOException { Preconditions.checkArgument(rulesMap != null, "serializeRuleList should never be called with null rule list."); BitOutputStream bitOutputStream = new BitOutputStream(); Map<String, Long> indexMapping = new TreeMap(); long indexTracker = 0; Map<String, Integer> indexMapping = new TreeMap(); int indexTracker = 0; indexMapping.put(START_INDEXING_KEY, outputStream.getWrittenBytesCount()); for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) { Loading Loading @@ -210,6 +222,33 @@ public class RuleBinarySerializer implements RuleSerializer { } } private byte[] serializeIndexes(Map<String, Integer> indexes, boolean isIndexed) { BitOutputStream bitOutputStream = new BitOutputStream(); // Output the starting location of this indexing group. serializeStringValue(START_INDEXING_KEY, /* isHashedValue= */false, bitOutputStream); serializeIntValue(indexes.get(START_INDEXING_KEY), bitOutputStream); // If the group is indexed, output the locations of the indexes. if (isIndexed) { for (Map.Entry<String, Integer> entry : indexes.entrySet()) { if (!entry.getKey().equals(START_INDEXING_KEY) && !entry.getKey().equals(END_INDEXING_KEY)) { serializeStringValue(entry.getKey(), /* isHashedValue= */false, bitOutputStream); serializeIntValue(entry.getValue(), bitOutputStream); } } } // Output the end location of this indexing group. serializeStringValue(END_INDEXING_KEY, /*isHashedValue= */ false, bitOutputStream); serializeIntValue(indexes.get(END_INDEXING_KEY), bitOutputStream); return bitOutputStream.toByteArray(); } private void serializeStringValue( String value, boolean isHashedValue, BitOutputStream bitOutputStream) { if (value == null) { Loading services/core/java/com/android/server/integrity/serializer/RuleSerializer.java +6 −2 Original line number Diff line number Diff line Loading @@ -26,10 +26,14 @@ import java.util.Optional; public interface RuleSerializer { /** Serialize rules to an output stream */ void serialize(List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream) void serialize( List<Rule> rules, Optional<Integer> formatVersion, OutputStream ruleFileOutputStream, OutputStream indexingFileOutputStream) throws RuleSerializeException; /** Serialize rules to a ByteArray. */ byte[] serialize(List<Rule> rule, Optional<Integer> formatVersion) byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) throws RuleSerializeException; } services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java +6 −1 Original line number Diff line number Diff line Loading @@ -56,12 +56,17 @@ public class RuleXmlSerializer implements RuleSerializer { @Override public void serialize( List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream) List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream, OutputStream indexingOutputStream) throws RuleSerializeException { try { XmlSerializer xmlSerializer = Xml.newSerializer(); xmlSerializer.setOutput(outputStream, StandardCharsets.UTF_8.name()); serializeRules(rules, xmlSerializer); // TODO(b/145493956): Implement the indexing logic. } catch (Exception e) { throw new RuleSerializeException(e.getMessage(), e); } Loading Loading
services/core/java/com/android/server/integrity/IntegrityFileManager.java +8 −8 Original line number Diff line number Diff line Loading @@ -44,12 +44,9 @@ import java.util.Optional; public class IntegrityFileManager { private static final String TAG = "IntegrityFileManager"; // TODO: this is a prototype implementation of this class. Thus no tests are included. // Implementing rule indexing will likely overhaul this class and more tests should be included // then. private static final String METADATA_FILE = "metadata"; private static final String RULES_FILE = "rules"; private static final String INDEXING_FILE = "indexing"; private static final Object RULES_LOCK = new Object(); private static IntegrityFileManager sInstance = null; Loading Loading @@ -125,9 +122,12 @@ public class IntegrityFileManager { // We don't consider this fatal so we continue execution. } try (FileOutputStream fileOutputStream = new FileOutputStream(new File(mStagingDir, RULES_FILE))) { mRuleSerializer.serialize(rules, Optional.empty(), fileOutputStream); try (FileOutputStream ruleFileOutputStream = new FileOutputStream(new File(mStagingDir, RULES_FILE)); FileOutputStream indexingFileOutputStream = new FileOutputStream(new File(mStagingDir, INDEXING_FILE))) { mRuleSerializer.serialize( rules, Optional.empty(), ruleFileOutputStream, indexingFileOutputStream); } switchStagingRulesDir(); Loading
services/core/java/com/android/server/integrity/serializer/ByteTrackedOutputStream.java +2 −2 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import java.io.OutputStream; */ public class ByteTrackedOutputStream { private static long sWrittenBytesCount; private static int sWrittenBytesCount; private static OutputStream sOutputStream; public ByteTrackedOutputStream(OutputStream outputStream) { Loading @@ -47,7 +47,7 @@ public class ByteTrackedOutputStream { /** * Returns the total number of bytes written into the output stream at the requested time. */ public long getWrittenBytesCount() { public int getWrittenBytesCount() { return sWrittenBytesCount; } }
services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java +61 −22 Original line number Diff line number Diff line Loading @@ -52,20 +52,21 @@ import java.util.TreeMap; /** A helper class to serialize rules from the {@link Rule} model to Binary representation. */ public class RuleBinarySerializer implements RuleSerializer { // The parsing time seems acceptable for 100 rules based on the tests in go/ic-rule-file-format. private static final int INDEXING_BLOCK_SIZE = 100; // The parsing time seems acceptable for this block size based on the tests in // go/ic-rule-file-format. public static final int INDEXING_BLOCK_SIZE = 100; private static final String START_INDEXING_KEY = "START_KEY"; private static final String END_INDEXING_KEY = "END_KEY"; public static final String START_INDEXING_KEY = "START_KEY"; public static final String END_INDEXING_KEY = "END_KEY"; // Get the byte representation for a list of rules. @Override public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) throws RuleSerializeException { try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); serialize(rules, formatVersion, byteArrayOutputStream); return byteArrayOutputStream.toByteArray(); ByteArrayOutputStream rulesOutputStream = new ByteArrayOutputStream(); serialize(rules, formatVersion, rulesOutputStream, new ByteArrayOutputStream()); return rulesOutputStream.toByteArray(); } catch (Exception e) { throw new RuleSerializeException(e.getMessage(), e); } Loading @@ -74,27 +75,38 @@ public class RuleBinarySerializer implements RuleSerializer { // Get the byte representation for a list of rules, and write them to an output stream. @Override public void serialize( List<Rule> rules, Optional<Integer> formatVersion, OutputStream originalOutputStream) List<Rule> rules, Optional<Integer> formatVersion, OutputStream rulesFileOutputStream, OutputStream indexingFileOutputStream) throws RuleSerializeException { try { // Determine the indexing groups and the order of the rules within each indexed group. Map<Integer, TreeMap<String, List<Rule>>> indexedRules = RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules); ByteTrackedOutputStream outputStream = new ByteTrackedOutputStream(originalOutputStream); ByteTrackedOutputStream ruleFileByteTrackedOutputStream = new ByteTrackedOutputStream(rulesFileOutputStream); serializeRuleFileMetadata(formatVersion, outputStream); serializeRuleFileMetadata(formatVersion, ruleFileByteTrackedOutputStream); Map<String, Long> packageNameIndexes = serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), outputStream); Map<String, Long> appCertificateIndexes = serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), outputStream); Map<String, Long> unindexedRulesIndex = serializeRuleList(indexedRules.get(NOT_INDEXED), outputStream); Map<String, Integer> packageNameIndexes = serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), ruleFileByteTrackedOutputStream); indexingFileOutputStream.write( serializeIndexes(packageNameIndexes, /* isIndexed= */true)); // TODO(b/145493956): Write these indexes into a index file provided by integrity file // manager. Map<String, Integer> appCertificateIndexes = serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), ruleFileByteTrackedOutputStream); indexingFileOutputStream.write( serializeIndexes(appCertificateIndexes, /* isIndexed= */true)); Map<String, Integer> unindexedRulesIndexes = serializeRuleList(indexedRules.get(NOT_INDEXED), ruleFileByteTrackedOutputStream); indexingFileOutputStream.write( serializeIndexes(unindexedRulesIndexes, /* isIndexed= */false)); } catch (Exception e) { throw new RuleSerializeException(e.getMessage(), e); } Loading @@ -109,15 +121,15 @@ public class RuleBinarySerializer implements RuleSerializer { outputStream.write(bitOutputStream.toByteArray()); } private Map<String, Long> serializeRuleList(TreeMap<String, List<Rule>> rulesMap, private Map<String, Integer> serializeRuleList(TreeMap<String, List<Rule>> rulesMap, ByteTrackedOutputStream outputStream) throws IOException { Preconditions.checkArgument(rulesMap != null, "serializeRuleList should never be called with null rule list."); BitOutputStream bitOutputStream = new BitOutputStream(); Map<String, Long> indexMapping = new TreeMap(); long indexTracker = 0; Map<String, Integer> indexMapping = new TreeMap(); int indexTracker = 0; indexMapping.put(START_INDEXING_KEY, outputStream.getWrittenBytesCount()); for (Map.Entry<String, List<Rule>> entry : rulesMap.entrySet()) { Loading Loading @@ -210,6 +222,33 @@ public class RuleBinarySerializer implements RuleSerializer { } } private byte[] serializeIndexes(Map<String, Integer> indexes, boolean isIndexed) { BitOutputStream bitOutputStream = new BitOutputStream(); // Output the starting location of this indexing group. serializeStringValue(START_INDEXING_KEY, /* isHashedValue= */false, bitOutputStream); serializeIntValue(indexes.get(START_INDEXING_KEY), bitOutputStream); // If the group is indexed, output the locations of the indexes. if (isIndexed) { for (Map.Entry<String, Integer> entry : indexes.entrySet()) { if (!entry.getKey().equals(START_INDEXING_KEY) && !entry.getKey().equals(END_INDEXING_KEY)) { serializeStringValue(entry.getKey(), /* isHashedValue= */false, bitOutputStream); serializeIntValue(entry.getValue(), bitOutputStream); } } } // Output the end location of this indexing group. serializeStringValue(END_INDEXING_KEY, /*isHashedValue= */ false, bitOutputStream); serializeIntValue(indexes.get(END_INDEXING_KEY), bitOutputStream); return bitOutputStream.toByteArray(); } private void serializeStringValue( String value, boolean isHashedValue, BitOutputStream bitOutputStream) { if (value == null) { Loading
services/core/java/com/android/server/integrity/serializer/RuleSerializer.java +6 −2 Original line number Diff line number Diff line Loading @@ -26,10 +26,14 @@ import java.util.Optional; public interface RuleSerializer { /** Serialize rules to an output stream */ void serialize(List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream) void serialize( List<Rule> rules, Optional<Integer> formatVersion, OutputStream ruleFileOutputStream, OutputStream indexingFileOutputStream) throws RuleSerializeException; /** Serialize rules to a ByteArray. */ byte[] serialize(List<Rule> rule, Optional<Integer> formatVersion) byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) throws RuleSerializeException; }
services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java +6 −1 Original line number Diff line number Diff line Loading @@ -56,12 +56,17 @@ public class RuleXmlSerializer implements RuleSerializer { @Override public void serialize( List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream) List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream, OutputStream indexingOutputStream) throws RuleSerializeException { try { XmlSerializer xmlSerializer = Xml.newSerializer(); xmlSerializer.setOutput(outputStream, StandardCharsets.UTF_8.name()); serializeRules(rules, xmlSerializer); // TODO(b/145493956): Implement the indexing logic. } catch (Exception e) { throw new RuleSerializeException(e.getMessage(), e); } Loading