Merge "Introduce a RuleIndexingParser class that will help us to identify the range of the bytes to be read and parsed."
This commit is contained in:
committed by
Android (Google) Code Review
commit
83d651f798
@@ -25,6 +25,7 @@ import android.util.Slog;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.integrity.model.RuleMetadata;
|
||||
import com.android.server.integrity.parser.RuleBinaryParser;
|
||||
import com.android.server.integrity.parser.RuleIndexingController;
|
||||
import com.android.server.integrity.parser.RuleMetadataParser;
|
||||
import com.android.server.integrity.parser.RuleParseException;
|
||||
import com.android.server.integrity.parser.RuleParser;
|
||||
@@ -61,7 +62,10 @@ public class IntegrityFileManager {
|
||||
// update rules atomically.
|
||||
private final File mStagingDir;
|
||||
|
||||
@Nullable private RuleMetadata mRuleMetadataCache;
|
||||
@Nullable
|
||||
private RuleMetadata mRuleMetadataCache;
|
||||
@Nullable
|
||||
private RuleIndexingController mRuleIndexingController;
|
||||
|
||||
/** Get the singleton instance of this class. */
|
||||
public static synchronized IntegrityFileManager getInstance() {
|
||||
@@ -100,6 +104,8 @@ public class IntegrityFileManager {
|
||||
Slog.e(TAG, "Error reading metadata file.", e);
|
||||
}
|
||||
}
|
||||
|
||||
updateRuleIndexingController();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +115,8 @@ public class IntegrityFileManager {
|
||||
*/
|
||||
public boolean initialized() {
|
||||
return new File(mRulesDir, RULES_FILE).exists()
|
||||
&& new File(mRulesDir, METADATA_FILE).exists();
|
||||
&& new File(mRulesDir, METADATA_FILE).exists()
|
||||
&& new File(mRulesDir, INDEXING_FILE).exists();
|
||||
}
|
||||
|
||||
/** Write rules to persistent storage. */
|
||||
@@ -131,6 +138,9 @@ public class IntegrityFileManager {
|
||||
}
|
||||
|
||||
switchStagingRulesDir();
|
||||
|
||||
// Update object holding the indexing information.
|
||||
updateRuleIndexingController();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,8 +150,13 @@ public class IntegrityFileManager {
|
||||
*/
|
||||
public List<Rule> readRules(AppInstallMetadata appInstallMetadata)
|
||||
throws IOException, RuleParseException {
|
||||
// TODO: select rules by index
|
||||
synchronized (RULES_LOCK) {
|
||||
// Try to identify indexes from the index file.
|
||||
List<List<Integer>> ruleReadingIndexes =
|
||||
mRuleIndexingController.identifyRulesToEvaluate(appInstallMetadata);
|
||||
|
||||
// Read the rules based on the index information.
|
||||
// TODO(b/145493956): Provide the identified indexes to the rule reader.
|
||||
try (FileInputStream inputStream =
|
||||
new FileInputStream(new File(mRulesDir, RULES_FILE))) {
|
||||
List<Rule> rules = mRuleParser.parse(inputStream);
|
||||
@@ -168,6 +183,17 @@ public class IntegrityFileManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRuleIndexingController() {
|
||||
File ruleIndexingFile = new File(mRulesDir, INDEXING_FILE);
|
||||
if (ruleIndexingFile.exists()) {
|
||||
try (FileInputStream inputStream = new FileInputStream(ruleIndexingFile)) {
|
||||
mRuleIndexingController = new RuleIndexingController(inputStream);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Error parsing the rule indexing file.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeMetadata(File directory, String ruleProvider, String version)
|
||||
throws IOException {
|
||||
mRuleMetadataCache = new RuleMetadata(ruleProvider, version);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.integrity.model;
|
||||
|
||||
/** A helper class containing special indexing file constants. */
|
||||
public final class IndexingFileConstants {
|
||||
// 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;
|
||||
|
||||
public static final String START_INDEXING_KEY = "START_KEY";
|
||||
public static final String END_INDEXING_KEY = "END_KEY";
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.integrity.parser;
|
||||
|
||||
import static com.android.server.integrity.model.ComponentBitSize.IS_HASHED_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
|
||||
|
||||
import com.android.server.integrity.IntegrityUtils;
|
||||
import com.android.server.integrity.model.BitInputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Helper methods for reading standard data structures from {@link BitInputStream}.
|
||||
*/
|
||||
public class BinaryFileOperations {
|
||||
|
||||
/**
|
||||
* Read an string value with the given size and hash status from a {@code BitInputStream}.
|
||||
*
|
||||
* If the value is hashed, get the hex-encoding of the value. Serialized values are in raw form.
|
||||
* All hashed values are hex-encoded.
|
||||
*/
|
||||
public static String getStringValue(BitInputStream bitInputStream) throws IOException {
|
||||
boolean isHashedValue = bitInputStream.getNext(IS_HASHED_BITS) == 1;
|
||||
int valueSize = bitInputStream.getNext(VALUE_SIZE_BITS);
|
||||
return getStringValue(bitInputStream, valueSize, isHashedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an string value with the given size and hash status from a {@code BitInputStream}.
|
||||
*
|
||||
* If the value is hashed, get the hex-encoding of the value. Serialized values are in raw form.
|
||||
* All hashed values are hex-encoded.
|
||||
*/
|
||||
public static String getStringValue(
|
||||
BitInputStream bitInputStream, int valueSize, boolean isHashedValue)
|
||||
throws IOException {
|
||||
if (!isHashedValue) {
|
||||
StringBuilder value = new StringBuilder();
|
||||
while (valueSize-- > 0) {
|
||||
value.append((char) bitInputStream.getNext(/* numOfBits= */ 8));
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(valueSize);
|
||||
while (valueSize-- > 0) {
|
||||
byteBuffer.put((byte) (bitInputStream.getNext(/* numOfBits= */ 8) & 0xFF));
|
||||
}
|
||||
return IntegrityUtils.getHexDigest(byteBuffer.array());
|
||||
}
|
||||
|
||||
/** Read an integer value from a {@code BitInputStream}. */
|
||||
public static int getIntValue(BitInputStream bitInputStream) throws IOException {
|
||||
return bitInputStream.getNext(/* numOfBits= */ 32);
|
||||
}
|
||||
|
||||
/** Read an boolean value from a {@code BitInputStream}. */
|
||||
public static boolean getBooleanValue(BitInputStream bitInputStream) throws IOException {
|
||||
return bitInputStream.getNext(/* numOfBits= */ 1) == 1;
|
||||
}
|
||||
}
|
||||
@@ -28,18 +28,19 @@ import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.SIGNAL_BIT;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getBooleanValue;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getIntValue;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getStringValue;
|
||||
|
||||
import android.content.integrity.AtomicFormula;
|
||||
import android.content.integrity.CompoundFormula;
|
||||
import android.content.integrity.Formula;
|
||||
import android.content.integrity.Rule;
|
||||
|
||||
import com.android.server.integrity.IntegrityUtils;
|
||||
import com.android.server.integrity.model.BitInputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -145,33 +146,4 @@ public class RuleBinaryParser implements RuleParser {
|
||||
throw new IllegalArgumentException(String.format("Unknown key: %d", key));
|
||||
}
|
||||
}
|
||||
|
||||
// Get value string from stream.
|
||||
// If the value is not hashed, get its raw form directly.
|
||||
// If the value is hashed, get the hex-encoding of the value. Serialized values are in raw form.
|
||||
// All hashed values are hex-encoded.
|
||||
private static String getStringValue(
|
||||
BitInputStream bitInputStream, int valueSize, boolean isHashedValue)
|
||||
throws IOException {
|
||||
if (!isHashedValue) {
|
||||
StringBuilder value = new StringBuilder();
|
||||
while (valueSize-- > 0) {
|
||||
value.append((char) bitInputStream.getNext(/* numOfBits= */ 8));
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(valueSize);
|
||||
while (valueSize-- > 0) {
|
||||
byteBuffer.put((byte) (bitInputStream.getNext(/* numOfBits= */ 8) & 0xFF));
|
||||
}
|
||||
return IntegrityUtils.getHexDigest(byteBuffer.array());
|
||||
}
|
||||
|
||||
private static int getIntValue(BitInputStream bitInputStream) throws IOException {
|
||||
return bitInputStream.getNext(/* numOfBits= */ 32);
|
||||
}
|
||||
|
||||
private static boolean getBooleanValue(BitInputStream bitInputStream) throws IOException {
|
||||
return bitInputStream.getNext(/* numOfBits= */ 1) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.integrity.parser;
|
||||
|
||||
import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getIntValue;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getStringValue;
|
||||
|
||||
import android.content.integrity.AppInstallMetadata;
|
||||
|
||||
import com.android.server.integrity.model.BitInputStream;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/** Helper class to identify the necessary indexes that needs to be read. */
|
||||
public class RuleIndexingController {
|
||||
|
||||
private static TreeMap<String, Integer> sPackageNameBasedIndexes;
|
||||
private static TreeMap<String, Integer> sAppCertificateBasedIndexes;
|
||||
private static TreeMap<String, Integer> sUnindexedRuleIndexes;
|
||||
|
||||
/**
|
||||
* Provide the indexing file to read and the object will be constructed by reading and
|
||||
* identifying the indexes.
|
||||
*/
|
||||
public RuleIndexingController(FileInputStream fileInputStream) throws IOException {
|
||||
BitInputStream bitInputStream = new BitInputStream(fileInputStream);
|
||||
sPackageNameBasedIndexes = getNextIndexGroup(bitInputStream);
|
||||
sAppCertificateBasedIndexes = getNextIndexGroup(bitInputStream);
|
||||
sUnindexedRuleIndexes = getNextIndexGroup(bitInputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of integers with the starting and ending bytes of the rules that needs to be
|
||||
* read and evaluated.
|
||||
*/
|
||||
public List<List<Integer>> identifyRulesToEvaluate(AppInstallMetadata appInstallMetadata) {
|
||||
// TODO(b/145493956): Identify and return the indexes that needs to be read.
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private TreeMap<String, Integer> getNextIndexGroup(BitInputStream bitInputStream)
|
||||
throws IOException {
|
||||
TreeMap<String, Integer> keyToIndexMap = new TreeMap<>();
|
||||
while (bitInputStream.hasNext()) {
|
||||
String key = getStringValue(bitInputStream);
|
||||
int value = getIntValue(bitInputStream);
|
||||
|
||||
keyToIndexMap.put(key, value);
|
||||
|
||||
if (key == END_INDEXING_KEY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return keyToIndexMap;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,9 @@ import static com.android.server.integrity.model.ComponentBitSize.KEY_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
|
||||
import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY;
|
||||
import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE;
|
||||
import static com.android.server.integrity.model.IndexingFileConstants.START_INDEXING_KEY;
|
||||
import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
|
||||
import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
|
||||
import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
|
||||
@@ -52,13 +55,6 @@ 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 this block size based on the tests in
|
||||
// go/ic-rule-file-format.
|
||||
public static final int INDEXING_BLOCK_SIZE = 100;
|
||||
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.integrity.parser;
|
||||
|
||||
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getBooleanValue;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getIntValue;
|
||||
import static com.android.server.integrity.parser.BinaryFileOperations.getStringValue;
|
||||
import static com.android.server.integrity.utils.TestUtils.getBits;
|
||||
import static com.android.server.integrity.utils.TestUtils.getBytes;
|
||||
import static com.android.server.integrity.utils.TestUtils.getValueBits;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.android.server.integrity.IntegrityUtils;
|
||||
import com.android.server.integrity.model.BitInputStream;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class BinaryFileOperationsTest {
|
||||
|
||||
private static final String IS_NOT_HASHED = "0";
|
||||
private static final String IS_HASHED = "1";
|
||||
private static final String PACKAGE_NAME = "com.test.app";
|
||||
private static final String APP_CERTIFICATE = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||
|
||||
@Test
|
||||
public void testGetStringValue() throws IOException {
|
||||
byte[] stringBytes =
|
||||
getBytes(
|
||||
IS_NOT_HASHED
|
||||
+ getBits(PACKAGE_NAME.length(), VALUE_SIZE_BITS)
|
||||
+ getValueBits(PACKAGE_NAME));
|
||||
ByteBuffer rule = ByteBuffer.allocate(stringBytes.length);
|
||||
rule.put(stringBytes);
|
||||
BitInputStream inputStream = new BitInputStream(rule.array());
|
||||
|
||||
String resultString = getStringValue(inputStream);
|
||||
|
||||
assertThat(resultString).isEqualTo(PACKAGE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetHashedStringValue() throws IOException {
|
||||
byte[] ruleBytes =
|
||||
getBytes(
|
||||
IS_HASHED
|
||||
+ getBits(APP_CERTIFICATE.length(), VALUE_SIZE_BITS)
|
||||
+ getValueBits(APP_CERTIFICATE));
|
||||
ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
|
||||
rule.put(ruleBytes);
|
||||
BitInputStream inputStream = new BitInputStream(rule.array());
|
||||
|
||||
String resultString = getStringValue(inputStream);
|
||||
|
||||
assertThat(resultString)
|
||||
.isEqualTo(IntegrityUtils.getHexDigest(
|
||||
APP_CERTIFICATE.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStringValue_withSizeAndHashingInfo() throws IOException {
|
||||
byte[] ruleBytes = getBytes(getValueBits(PACKAGE_NAME));
|
||||
ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
|
||||
rule.put(ruleBytes);
|
||||
BitInputStream inputStream = new BitInputStream(rule.array());
|
||||
|
||||
String resultString = getStringValue(inputStream,
|
||||
PACKAGE_NAME.length(), /* isHashedValue= */false);
|
||||
|
||||
assertThat(resultString).isEqualTo(PACKAGE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIntValue() throws IOException {
|
||||
int randomValue = 15;
|
||||
byte[] ruleBytes = getBytes(getBits(randomValue, /* numOfBits= */ 32));
|
||||
ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
|
||||
rule.put(ruleBytes);
|
||||
BitInputStream inputStream = new BitInputStream(rule.array());
|
||||
|
||||
assertThat(getIntValue(inputStream)).isEqualTo(randomValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBooleanValue_true() throws IOException {
|
||||
String booleanValue = "1";
|
||||
byte[] ruleBytes = getBytes(booleanValue);
|
||||
ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
|
||||
rule.put(ruleBytes);
|
||||
BitInputStream inputStream = new BitInputStream(rule.array());
|
||||
|
||||
assertThat(getBooleanValue(inputStream)).isEqualTo(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetBooleanValue_false() throws IOException {
|
||||
String booleanValue = "0";
|
||||
byte[] ruleBytes = getBytes(booleanValue);
|
||||
ByteBuffer rule = ByteBuffer.allocate(ruleBytes.length);
|
||||
rule.put(ruleBytes);
|
||||
BitInputStream inputStream = new BitInputStream(rule.array());
|
||||
|
||||
assertThat(getBooleanValue(inputStream)).isEqualTo(false);
|
||||
}
|
||||
}
|
||||
@@ -27,9 +27,9 @@ import static com.android.server.integrity.model.ComponentBitSize.KEY_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.OPERATOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.SEPARATOR_BITS;
|
||||
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
|
||||
import static com.android.server.integrity.serializer.RuleBinarySerializer.END_INDEXING_KEY;
|
||||
import static com.android.server.integrity.serializer.RuleBinarySerializer.INDEXING_BLOCK_SIZE;
|
||||
import static com.android.server.integrity.serializer.RuleBinarySerializer.START_INDEXING_KEY;
|
||||
import static com.android.server.integrity.model.IndexingFileConstants.END_INDEXING_KEY;
|
||||
import static com.android.server.integrity.model.IndexingFileConstants.INDEXING_BLOCK_SIZE;
|
||||
import static com.android.server.integrity.model.IndexingFileConstants.START_INDEXING_KEY;
|
||||
import static com.android.server.integrity.utils.TestUtils.getBits;
|
||||
import static com.android.server.integrity.utils.TestUtils.getBytes;
|
||||
import static com.android.server.integrity.utils.TestUtils.getValueBits;
|
||||
|
||||
Reference in New Issue
Block a user