summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/integrity/model/BitInputStream.java66
-rw-r--r--services/core/java/com/android/server/integrity/model/ComponentBitSize.java41
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java119
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleXmlParser.java15
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java26
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java628
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java131
7 files changed, 934 insertions, 92 deletions
diff --git a/services/core/java/com/android/server/integrity/model/BitInputStream.java b/services/core/java/com/android/server/integrity/model/BitInputStream.java
new file mode 100644
index 000000000000..09bc7e8b9861
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/BitInputStream.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 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 wrapper class for reading a stream of bits. */
+public class BitInputStream {
+
+ private byte[] mRuleBytes;
+ private long mBitPointer;
+
+ public BitInputStream(byte[] ruleBytes) {
+ this.mRuleBytes = ruleBytes;
+ this.mBitPointer = 0;
+ }
+
+ /**
+ * Read the next number of bits from the stream.
+ *
+ * @param numOfBits The number of bits to read.
+ * @return The value read from the stream.
+ */
+ public int getNext(int numOfBits) {
+ int component = 0;
+ int count = 0;
+
+ int idx = (int) (mBitPointer / 8);
+ int offset = 7 - (int) (mBitPointer % 8);
+
+ while (count++ < numOfBits) {
+ if (idx >= mRuleBytes.length) {
+ throw new IllegalArgumentException(String.format("Invalid byte index: %d", idx));
+ }
+
+ component <<= 1;
+ component |= (mRuleBytes[idx] >>> offset) & 1;
+
+ offset--;
+ if (offset == -1) {
+ idx++;
+ offset = 7;
+ }
+ }
+
+ mBitPointer += numOfBits;
+ return component;
+ }
+
+ /** Check if there are bits left in the stream. */
+ public boolean hasNext() {
+ return mBitPointer / 8 < mRuleBytes.length;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/model/ComponentBitSize.java b/services/core/java/com/android/server/integrity/model/ComponentBitSize.java
new file mode 100644
index 000000000000..d47ce2df45e1
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/ComponentBitSize.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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;
+
+import android.content.integrity.Rule;
+
+/**
+ * A helper class containing information about the binary representation of different {@link Rule}
+ * components.
+ */
+public final class ComponentBitSize {
+ public static final int FORMAT_VERSION_BITS = 5;
+ public static final int EFFECT_BITS = 3;
+ public static final int KEY_BITS = 4;
+ public static final int OPERATOR_BITS = 3;
+ public static final int CONNECTOR_BITS = 2;
+ public static final int SEPARATOR_BITS = 2;
+ public static final int VALUE_SIZE_BITS = 5;
+ public static final int IS_HASHED_BITS = 1;
+
+ public static final int ATOMIC_FORMULA_START = 0;
+ public static final int COMPOUND_FORMULA_START = 1;
+ public static final int COMPOUND_FORMULA_END = 2;
+
+ public static final int DEFAULT_FORMAT_VERSION = 1;
+ public static final int SIGNAL_BIT = 1;
+}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 54c0bd85d897..8aa0751af11c 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -16,23 +16,132 @@
package com.android.server.integrity.parser;
+import static com.android.server.integrity.model.ComponentBitSize.ATOMIC_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_END;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.CONNECTOR_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.EFFECT_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.FORMAT_VERSION_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.IS_HASHED_BITS;
+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.SIGNAL_BIT;
+import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
+
+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.model.BitInputStream;
+
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.List;
/** A helper class to parse rules into the {@link Rule} model from Binary representation. */
public class RuleBinaryParser implements RuleParser {
@Override
- public List<Rule> parse(byte[] ruleBytes) throws RuleParseException {
- // TODO: Implement binary text parser.
- return null;
+ public List<Rule> parse(byte[] ruleBytes) throws RuleParseException {
+ try {
+ BitInputStream bitInputStream = new BitInputStream(ruleBytes);
+ return parseRules(bitInputStream);
+ } catch (Exception e) {
+ throw new RuleParseException(e.getMessage(), e);
+ }
}
@Override
public List<Rule> parse(InputStream inputStream) throws RuleParseException {
- // TODO: Implement stream parser.
- return null;
+ try {
+ byte[] ruleBytes = new byte[inputStream.available()];
+ inputStream.read(ruleBytes);
+ return parse(ruleBytes);
+ } catch (Exception e) {
+ throw new RuleParseException(e.getMessage(), e);
+ }
+ }
+
+ private List<Rule> parseRules(BitInputStream bitInputStream) {
+ List<Rule> parsedRules = new ArrayList<>();
+
+ // Read the rule binary file format version.
+ bitInputStream.getNext(FORMAT_VERSION_BITS);
+
+ while (bitInputStream.hasNext()) {
+ if (bitInputStream.getNext(SIGNAL_BIT) == 1) {
+ parsedRules.add(parseRule(bitInputStream));
+ }
+ }
+
+ return parsedRules;
+ }
+
+ private Rule parseRule(BitInputStream bitInputStream) {
+ Formula formula = parseFormula(bitInputStream);
+ int effect = bitInputStream.getNext(EFFECT_BITS);
+
+ if (bitInputStream.getNext(SIGNAL_BIT) != 1) {
+ throw new IllegalArgumentException("A rule must end with a '1' bit.");
+ }
+
+ return new Rule(formula, effect);
+ }
+
+ private Formula parseFormula(BitInputStream bitInputStream) {
+ int separator = bitInputStream.getNext(SEPARATOR_BITS);
+ switch (separator) {
+ case ATOMIC_FORMULA_START:
+ return parseAtomicFormula(bitInputStream);
+ case COMPOUND_FORMULA_START:
+ return parseCompoundFormula(bitInputStream);
+ case COMPOUND_FORMULA_END:
+ return null;
+ default:
+ throw new IllegalArgumentException(
+ String.format("Unknown formula separator: %s", separator));
+ }
+ }
+
+ private CompoundFormula parseCompoundFormula(BitInputStream bitInputStream) {
+ int connector = bitInputStream.getNext(CONNECTOR_BITS);
+ List<Formula> formulas = new ArrayList<>();
+
+ Formula parsedFormula = parseFormula(bitInputStream);
+ while (parsedFormula != null) {
+ formulas.add(parsedFormula);
+ parsedFormula = parseFormula(bitInputStream);
+ }
+
+ return new CompoundFormula(connector, formulas);
+ }
+
+ private AtomicFormula parseAtomicFormula(BitInputStream bitInputStream) {
+ int key = bitInputStream.getNext(KEY_BITS);
+ int operator = bitInputStream.getNext(OPERATOR_BITS);
+
+ boolean isHashedValue = bitInputStream.getNext(IS_HASHED_BITS) == 1;
+ int valueSize = bitInputStream.getNext(VALUE_SIZE_BITS);
+ StringBuilder value = new StringBuilder();
+ while (valueSize-- > 0) {
+ value.append((char) bitInputStream.getNext(/* numOfBits= */ 8));
+ }
+
+ switch (key) {
+ case AtomicFormula.PACKAGE_NAME:
+ case AtomicFormula.APP_CERTIFICATE:
+ case AtomicFormula.INSTALLER_NAME:
+ case AtomicFormula.INSTALLER_CERTIFICATE:
+ return new AtomicFormula.StringAtomicFormula(key, value.toString(), isHashedValue);
+ case AtomicFormula.VERSION_CODE:
+ return new AtomicFormula.IntAtomicFormula(
+ key, operator, Integer.parseInt(value.toString()));
+ case AtomicFormula.PRE_INSTALLED:
+ return new AtomicFormula.BooleanAtomicFormula(key, value.toString().equals("1"));
+ default:
+ throw new IllegalArgumentException(String.format("Unknown key: %d", key));
+ }
}
}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
index 2e99d0f92109..d405583442bd 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
@@ -41,7 +41,7 @@ public final class RuleXmlParser implements RuleParser {
private static final String NAMESPACE = "";
private static final String RULE_LIST_TAG = "RL";
private static final String RULE_TAG = "R";
- private static final String OPEN_FORMULA_TAG = "OF";
+ private static final String COMPOUND_FORMULA_TAG = "OF";
private static final String ATOMIC_FORMULA_TAG = "AF";
private static final String EFFECT_ATTRIBUTE = "E";
private static final String KEY_ATTRIBUTE = "K";
@@ -118,8 +118,8 @@ public final class RuleXmlParser implements RuleParser {
if (eventType == XmlPullParser.START_TAG) {
switch (nodeName) {
- case OPEN_FORMULA_TAG:
- formula = parseOpenFormula(parser);
+ case COMPOUND_FORMULA_TAG:
+ formula = parseCompoundFormula(parser);
break;
case ATOMIC_FORMULA_TAG:
formula = parseAtomicFormula(parser);
@@ -137,7 +137,7 @@ public final class RuleXmlParser implements RuleParser {
return new Rule(formula, effect);
}
- private static Formula parseOpenFormula(XmlPullParser parser)
+ private static Formula parseCompoundFormula(XmlPullParser parser)
throws IOException, XmlPullParserException {
int connector =
Integer.parseInt(extractAttributeValue(parser, CONNECTOR_ATTRIBUTE).orElse("-1"));
@@ -147,7 +147,8 @@ public final class RuleXmlParser implements RuleParser {
while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
String nodeName = parser.getName();
- if (eventType == XmlPullParser.END_TAG && parser.getName().equals(OPEN_FORMULA_TAG)) {
+ if (eventType == XmlPullParser.END_TAG
+ && parser.getName().equals(COMPOUND_FORMULA_TAG)) {
break;
}
@@ -156,8 +157,8 @@ public final class RuleXmlParser implements RuleParser {
case ATOMIC_FORMULA_TAG:
formulas.add(parseAtomicFormula(parser));
break;
- case OPEN_FORMULA_TAG:
- formulas.add(parseOpenFormula(parser));
+ case COMPOUND_FORMULA_TAG:
+ formulas.add(parseCompoundFormula(parser));
break;
default:
throw new RuntimeException(
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index f782f7173da2..b988fd4c40f1 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -16,6 +16,18 @@
package com.android.server.integrity.serializer;
+import static com.android.server.integrity.model.ComponentBitSize.ATOMIC_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_END;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.CONNECTOR_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.DEFAULT_FORMAT_VERSION;
+import static com.android.server.integrity.model.ComponentBitSize.EFFECT_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.FORMAT_VERSION_BITS;
+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 android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Formula;
@@ -32,20 +44,6 @@ import java.util.Optional;
/** A helper class to serialize rules from the {@link Rule} model to Binary representation. */
public class RuleBinarySerializer implements RuleSerializer {
- public static final int FORMAT_VERSION_BITS = 5;
- public static final int EFFECT_BITS = 3;
- public static final int KEY_BITS = 4;
- public static final int OPERATOR_BITS = 3;
- public static final int CONNECTOR_BITS = 2;
- public static final int SEPARATOR_BITS = 2;
- public static final int VALUE_SIZE_BITS = 5;
-
- public static final int ATOMIC_FORMULA_START = 0;
- public static final int COMPOUND_FORMULA_START = 1;
- public static final int COMPOUND_FORMULA_END = 2;
-
- public static final int DEFAULT_FORMAT_VERSION = 1;
-
// Get the byte representation for a list of rules, and write them to an output stream.
@Override
public void serialize(
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
new file mode 100644
index 000000000000..88b6d70688ad
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2019 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.ATOMIC_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_END;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.CONNECTOR_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.DEFAULT_FORMAT_VERSION;
+import static com.android.server.integrity.model.ComponentBitSize.EFFECT_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.FORMAT_VERSION_BITS;
+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.utils.TestUtils.getBits;
+import static com.android.server.integrity.utils.TestUtils.getBytes;
+import static com.android.server.integrity.utils.TestUtils.getValueBits;
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Rule;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class RuleBinaryParserTest {
+
+ private static final String COMPOUND_FORMULA_START_BITS =
+ getBits(COMPOUND_FORMULA_START, SEPARATOR_BITS);
+ private static final String COMPOUND_FORMULA_END_BITS =
+ getBits(COMPOUND_FORMULA_END, SEPARATOR_BITS);
+ private static final String ATOMIC_FORMULA_START_BITS =
+ getBits(ATOMIC_FORMULA_START, SEPARATOR_BITS);
+ private static final int INVALID_FORMULA_SEPARATOR_VALUE = 3;
+ private static final String INVALID_FORMULA_SEPARATOR_BITS =
+ getBits(INVALID_FORMULA_SEPARATOR_VALUE, SEPARATOR_BITS);
+
+ private static final String NOT = getBits(CompoundFormula.NOT, CONNECTOR_BITS);
+ private static final String AND = getBits(CompoundFormula.AND, CONNECTOR_BITS);
+ private static final String OR = getBits(CompoundFormula.OR, CONNECTOR_BITS);
+ private static final int INVALID_CONNECTOR_VALUE = 3;
+ private static final String INVALID_CONNECTOR =
+ getBits(INVALID_CONNECTOR_VALUE, CONNECTOR_BITS);
+
+ private static final String PACKAGE_NAME = getBits(AtomicFormula.PACKAGE_NAME, KEY_BITS);
+ private static final String APP_CERTIFICATE = getBits(AtomicFormula.APP_CERTIFICATE, KEY_BITS);
+ private static final String VERSION_CODE = getBits(AtomicFormula.VERSION_CODE, KEY_BITS);
+ private static final String PRE_INSTALLED = getBits(AtomicFormula.PRE_INSTALLED, KEY_BITS);
+ private static final int INVALID_KEY_VALUE = 6;
+ private static final String INVALID_KEY = getBits(INVALID_KEY_VALUE, KEY_BITS);
+
+ private static final String EQ = getBits(AtomicFormula.EQ, OPERATOR_BITS);
+ private static final int INVALID_OPERATOR_VALUE = 5;
+ private static final String INVALID_OPERATOR = getBits(INVALID_OPERATOR_VALUE, OPERATOR_BITS);
+
+ private static final String IS_NOT_HASHED = "0";
+
+ private static final String DENY = getBits(Rule.DENY, EFFECT_BITS);
+ private static final int INVALID_EFFECT_VALUE = 5;
+ private static final String INVALID_EFFECT = getBits(INVALID_EFFECT_VALUE, EFFECT_BITS);
+
+ private static final String START_BIT = "1";
+ private static final String END_BIT = "1";
+ private static final String INVALID_MARKER_BIT = "0";
+
+ private static final byte[] DEFAULT_FORMAT_VERSION_BYTES =
+ getBytes(getBits(DEFAULT_FORMAT_VERSION, FORMAT_VERSION_BITS));
+
+ @Test
+ public void testBinaryStream_validCompoundFormula() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ 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;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ InputStream inputStream = new ByteArrayInputStream(rule.array());
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.NOT,
+ Collections.singletonList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+
+ List<Rule> rules = binaryParser.parse(inputStream);
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
+ public void testBinaryString_validCompoundFormula_notConnector() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ 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;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.NOT,
+ Collections.singletonList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
+ public void testBinaryString_validCompoundFormula_andConnector() throws Exception {
+ String packageName = "com.test.app";
+ String appCertificate = "test_cert";
+ String ruleBits =
+ START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + AND
+ + ATOMIC_FORMULA_START_BITS
+ + PACKAGE_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ + getValueBits(packageName)
+ + ATOMIC_FORMULA_START_BITS
+ + APP_CERTIFICATE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ + getValueBits(appCertificate)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ appCertificate,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
+ public void testBinaryString_validCompoundFormula_orConnector() throws Exception {
+ String packageName = "com.test.app";
+ String appCertificate = "test_cert";
+ String ruleBits =
+ START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + OR
+ + ATOMIC_FORMULA_START_BITS
+ + PACKAGE_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ + getValueBits(packageName)
+ + ATOMIC_FORMULA_START_BITS
+ + APP_CERTIFICATE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ + getValueBits(appCertificate)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.OR,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ appCertificate,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
+ public void testBinaryString_validAtomicFormula_stringValue() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ START_BIT
+ + ATOMIC_FORMULA_START_BITS
+ + PACKAGE_NAME
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ + getValueBits(packageName)
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ Rule.DENY);
+
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
+ public void testBinaryString_validAtomicFormula_integerValue() throws Exception {
+ String versionCode = "1";
+ String ruleBits =
+ START_BIT
+ + ATOMIC_FORMULA_START_BITS
+ + VERSION_CODE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(versionCode.length(), VALUE_SIZE_BITS)
+ + getValueBits(versionCode)
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.IntAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
+ Rule.DENY);
+
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
+ public void testBinaryString_validAtomicFormula_booleanValue() throws Exception {
+ String isPreInstalled = "1";
+ String ruleBits =
+ START_BIT
+ + ATOMIC_FORMULA_START_BITS
+ + PRE_INSTALLED
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(isPreInstalled.length(), VALUE_SIZE_BITS)
+ + getValueBits(isPreInstalled)
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
+
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
+ }
+
+ @Test
+ public void testBinaryString_invalidAtomicFormula() throws Exception {
+ String versionCode = "test";
+ String ruleBits =
+ START_BIT
+ + ATOMIC_FORMULA_START_BITS
+ + VERSION_CODE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(versionCode.length(), VALUE_SIZE_BITS)
+ + getValueBits(versionCode)
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ "For input string:",
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_withNoRuleList() throws RuleParseException {
+ ByteBuffer rule = ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ List<Rule> rules = binaryParser.parse(rule.array());
+
+ assertThat(rules).isEmpty();
+ }
+
+ @Test
+ public void testBinaryString_withEmptyRule() throws RuleParseException {
+ String ruleBits = START_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ "Invalid byte index",
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_invalidCompoundFormula_invalidNumberOfFormulas() throws Exception {
+ String packageName = "com.test.app";
+ String appCertificate = "test_cert";
+ String ruleBits =
+ 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)
+ + ATOMIC_FORMULA_START_BITS
+ + APP_CERTIFICATE
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ + getValueBits(appCertificate)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ "Connector NOT must have 1 formula only",
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_invalidRule_invalidOperator() throws Exception {
+ String versionCode = "1";
+ String ruleBits =
+ START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + NOT
+ + ATOMIC_FORMULA_START_BITS
+ + VERSION_CODE
+ + INVALID_OPERATOR
+ + IS_NOT_HASHED
+ + getBits(versionCode.length(), VALUE_SIZE_BITS)
+ + getValueBits(versionCode)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ String.format(
+ "Unknown operator: %d", INVALID_OPERATOR_VALUE),
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_invalidRule_invalidEffect() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ 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
+ + INVALID_EFFECT
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ String.format(
+ "Unknown effect: %d", INVALID_EFFECT_VALUE),
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_invalidRule_invalidConnector() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + INVALID_CONNECTOR
+ + 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;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ String.format(
+ "Unknown connector: %d", INVALID_CONNECTOR_VALUE),
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_invalidRule_invalidKey() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ START_BIT
+ + COMPOUND_FORMULA_START_BITS
+ + NOT
+ + ATOMIC_FORMULA_START_BITS
+ + INVALID_KEY
+ + EQ
+ + IS_NOT_HASHED
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ + getValueBits(packageName)
+ + COMPOUND_FORMULA_END_BITS
+ + DENY
+ + END_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ String.format(
+ "Unknown key: %d", INVALID_KEY_VALUE),
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_invalidRule_invalidSeparator() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ START_BIT
+ + INVALID_FORMULA_SEPARATOR_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;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ String.format(
+ "Unknown formula separator: %d", INVALID_FORMULA_SEPARATOR_VALUE),
+ () -> binaryParser.parse(rule.array()));
+ }
+
+ @Test
+ public void testBinaryString_invalidRule_invalidEndMarker() throws Exception {
+ String packageName = "com.test.app";
+ String ruleBits =
+ 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
+ + INVALID_MARKER_BIT;
+ byte[] ruleBytes = getBytes(ruleBits);
+ ByteBuffer rule =
+ ByteBuffer.allocate(DEFAULT_FORMAT_VERSION_BYTES.length + ruleBytes.length);
+ rule.put(DEFAULT_FORMAT_VERSION_BYTES);
+ rule.put(ruleBytes);
+ RuleParser binaryParser = new RuleBinaryParser();
+
+ assertExpectException(
+ RuleParseException.class,
+ /* expectedExceptionMessageRegex */ "A rule must end with a '1' bit",
+ () -> binaryParser.parse(rule.array()));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
index a43dbd77031a..901277ded5dd 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
@@ -16,6 +16,17 @@
package com.android.server.integrity.serializer;
+import static com.android.server.integrity.model.ComponentBitSize.ATOMIC_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_END;
+import static com.android.server.integrity.model.ComponentBitSize.COMPOUND_FORMULA_START;
+import static com.android.server.integrity.model.ComponentBitSize.CONNECTOR_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.DEFAULT_FORMAT_VERSION;
+import static com.android.server.integrity.model.ComponentBitSize.EFFECT_BITS;
+import static com.android.server.integrity.model.ComponentBitSize.FORMAT_VERSION_BITS;
+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.utils.TestUtils.getBits;
import static com.android.server.integrity.utils.TestUtils.getBytes;
import static com.android.server.integrity.utils.TestUtils.getValueBits;
@@ -43,45 +54,33 @@ import java.util.Optional;
@RunWith(JUnit4.class)
public class RuleBinarySerializerTest {
- private static final String COMPOUND_FORMULA_START =
- getBits(
- RuleBinarySerializer.COMPOUND_FORMULA_START,
- RuleBinarySerializer.SEPARATOR_BITS);
- private static final String COMPOUND_FORMULA_END =
- getBits(RuleBinarySerializer.COMPOUND_FORMULA_END, RuleBinarySerializer.SEPARATOR_BITS);
- private static final String ATOMIC_FORMULA_START =
- getBits(RuleBinarySerializer.ATOMIC_FORMULA_START, RuleBinarySerializer.SEPARATOR_BITS);
-
- private static final String NOT =
- getBits(CompoundFormula.NOT, RuleBinarySerializer.CONNECTOR_BITS);
- private static final String AND =
- getBits(CompoundFormula.AND, RuleBinarySerializer.CONNECTOR_BITS);
- private static final String OR =
- getBits(CompoundFormula.OR, RuleBinarySerializer.CONNECTOR_BITS);
-
- private static final String PACKAGE_NAME =
- getBits(AtomicFormula.PACKAGE_NAME, RuleBinarySerializer.KEY_BITS);
- private static final String APP_CERTIFICATE =
- getBits(AtomicFormula.APP_CERTIFICATE, RuleBinarySerializer.KEY_BITS);
- private static final String VERSION_CODE =
- getBits(AtomicFormula.VERSION_CODE, RuleBinarySerializer.KEY_BITS);
- private static final String PRE_INSTALLED =
- getBits(AtomicFormula.PRE_INSTALLED, RuleBinarySerializer.KEY_BITS);
-
- private static final String EQ = getBits(AtomicFormula.EQ, RuleBinarySerializer.OPERATOR_BITS);
+ private static final String COMPOUND_FORMULA_START_BITS =
+ getBits(COMPOUND_FORMULA_START, SEPARATOR_BITS);
+ private static final String COMPOUND_FORMULA_END_BITS =
+ getBits(COMPOUND_FORMULA_END, SEPARATOR_BITS);
+ private static final String ATOMIC_FORMULA_START_BITS =
+ getBits(ATOMIC_FORMULA_START, SEPARATOR_BITS);
+
+ private static final String NOT = getBits(CompoundFormula.NOT, CONNECTOR_BITS);
+ private static final String AND = getBits(CompoundFormula.AND, CONNECTOR_BITS);
+ private static final String OR = getBits(CompoundFormula.OR, CONNECTOR_BITS);
+
+ private static final String PACKAGE_NAME = getBits(AtomicFormula.PACKAGE_NAME, KEY_BITS);
+ private static final String APP_CERTIFICATE = getBits(AtomicFormula.APP_CERTIFICATE, KEY_BITS);
+ private static final String VERSION_CODE = getBits(AtomicFormula.VERSION_CODE, KEY_BITS);
+ private static final String PRE_INSTALLED = getBits(AtomicFormula.PRE_INSTALLED, KEY_BITS);
+
+ private static final String EQ = getBits(AtomicFormula.EQ, OPERATOR_BITS);
private static final String IS_NOT_HASHED = "0";
- private static final String DENY = getBits(Rule.DENY, RuleBinarySerializer.EFFECT_BITS);
+ private static final String DENY = getBits(Rule.DENY, EFFECT_BITS);
private static final String START_BIT = "1";
private static final String END_BIT = "1";
- private static final byte[] DEFAULT_FORMAT_VERSION =
- getBytes(
- getBits(
- RuleBinarySerializer.DEFAULT_FORMAT_VERSION,
- RuleBinarySerializer.FORMAT_VERSION_BITS));
+ private static final byte[] DEFAULT_FORMAT_VERSION_BYTES =
+ getBytes(getBits(DEFAULT_FORMAT_VERSION, FORMAT_VERSION_BITS));
@Test
public void testBinaryString_serializeEmptyRule() throws Exception {
@@ -114,19 +113,19 @@ public class RuleBinarySerializerTest {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
String expectedBits =
START_BIT
- + COMPOUND_FORMULA_START
+ + COMPOUND_FORMULA_START_BITS
+ NOT
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ PACKAGE_NAME
+ EQ
+ IS_NOT_HASHED
- + getBits(packageName.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ getValueBits(packageName)
- + COMPOUND_FORMULA_END
+ + COMPOUND_FORMULA_END_BITS
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION);
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
byteArrayOutputStream.write(getBytes(expectedBits));
byte[] expectedRules = byteArrayOutputStream.toByteArray();
@@ -155,19 +154,19 @@ public class RuleBinarySerializerTest {
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
START_BIT
- + COMPOUND_FORMULA_START
+ + COMPOUND_FORMULA_START_BITS
+ NOT
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ PACKAGE_NAME
+ EQ
+ IS_NOT_HASHED
- + getBits(packageName.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ getValueBits(packageName)
- + COMPOUND_FORMULA_END
+ + COMPOUND_FORMULA_END_BITS
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION);
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
byteArrayOutputStream.write(getBytes(expectedBits));
byte[] expectedRules = byteArrayOutputStream.toByteArray();
@@ -199,25 +198,25 @@ public class RuleBinarySerializerTest {
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
START_BIT
- + COMPOUND_FORMULA_START
+ + COMPOUND_FORMULA_START_BITS
+ AND
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ PACKAGE_NAME
+ EQ
+ IS_NOT_HASHED
- + getBits(packageName.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ getValueBits(packageName)
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ APP_CERTIFICATE
+ EQ
+ IS_NOT_HASHED
- + getBits(appCertificate.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ getValueBits(appCertificate)
- + COMPOUND_FORMULA_END
+ + COMPOUND_FORMULA_END_BITS
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION);
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
byteArrayOutputStream.write(getBytes(expectedBits));
byte[] expectedRules = byteArrayOutputStream.toByteArray();
@@ -249,25 +248,25 @@ public class RuleBinarySerializerTest {
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
START_BIT
- + COMPOUND_FORMULA_START
+ + COMPOUND_FORMULA_START_BITS
+ OR
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ PACKAGE_NAME
+ EQ
+ IS_NOT_HASHED
- + getBits(packageName.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ getValueBits(packageName)
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ APP_CERTIFICATE
+ EQ
+ IS_NOT_HASHED
- + getBits(appCertificate.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(appCertificate.length(), VALUE_SIZE_BITS)
+ getValueBits(appCertificate)
- + COMPOUND_FORMULA_END
+ + COMPOUND_FORMULA_END_BITS
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION);
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
byteArrayOutputStream.write(getBytes(expectedBits));
byte[] expectedRules = byteArrayOutputStream.toByteArray();
@@ -291,16 +290,16 @@ public class RuleBinarySerializerTest {
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
START_BIT
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ PACKAGE_NAME
+ EQ
+ IS_NOT_HASHED
- + getBits(packageName.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(packageName.length(), VALUE_SIZE_BITS)
+ getValueBits(packageName)
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION);
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
byteArrayOutputStream.write(getBytes(expectedBits));
byte[] expectedRules = byteArrayOutputStream.toByteArray();
@@ -324,16 +323,16 @@ public class RuleBinarySerializerTest {
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
START_BIT
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ EQ
+ IS_NOT_HASHED
- + getBits(versionCode.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(versionCode.length(), VALUE_SIZE_BITS)
+ getValueBits(versionCode)
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION);
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
byteArrayOutputStream.write(getBytes(expectedBits));
byte[] expectedRules = byteArrayOutputStream.toByteArray();
@@ -354,16 +353,16 @@ public class RuleBinarySerializerTest {
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
START_BIT
- + ATOMIC_FORMULA_START
+ + ATOMIC_FORMULA_START_BITS
+ PRE_INSTALLED
+ EQ
+ IS_NOT_HASHED
- + getBits(preInstalled.length(), RuleBinarySerializer.VALUE_SIZE_BITS)
+ + getBits(preInstalled.length(), VALUE_SIZE_BITS)
+ getValueBits(preInstalled)
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION);
+ byteArrayOutputStream.write(DEFAULT_FORMAT_VERSION_BYTES);
byteArrayOutputStream.write(getBytes(expectedBits));
byte[] expectedRules = byteArrayOutputStream.toByteArray();
@@ -393,7 +392,7 @@ public class RuleBinarySerializerTest {
public void testBinaryString_serializeFormatVersion() throws Exception {
int formatVersion = 1;
RuleSerializer binarySerializer = new RuleBinarySerializer();
- String expectedBits = getBits(formatVersion, RuleBinarySerializer.FORMAT_VERSION_BITS);
+ String expectedBits = getBits(formatVersion, FORMAT_VERSION_BITS);
byte[] expectedRules = getBytes(expectedBits);
byte[] actualRules =