Add public API and stub implementations for app integrity manager (service).
App integrity manager will accept rules from verifier and evaluate these rules
during install (and accept/reject the install accordingly). For more
information, see the linked bug (and the blocked bug).
Design doc: go/integrity-component-android-infra
Bug: 143689885
Change-Id: Ie965c6cc77987e06e9dea4be8fb49785a7bd08c4
Test: moving only
diff --git a/api/system-current.txt b/api/system-current.txt
index adfda2f..83c03a3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1453,6 +1453,7 @@
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle);
method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle);
+ field public static final String APP_INTEGRITY_SERVICE = "app_integrity";
field public static final String APP_PREDICTION_SERVICE = "app_prediction";
field public static final String BACKUP_SERVICE = "backup";
field public static final String BATTERY_STATS_SERVICE = "batterystats";
@@ -1505,6 +1506,7 @@
field public static final String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_SPECIAL_APP_ACCESSES = "android.intent.action.MANAGE_SPECIAL_APP_ACCESSES";
field public static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
+ field public static final String ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION";
field public static final String ACTION_PENDING_INCIDENT_REPORTS_CHANGED = "android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED";
field public static final String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
@@ -1552,6 +1554,150 @@
}
+package android.content.integrity {
+
+ public final class AppInstallMetadata {
+ method @NonNull public String getAppCertificate();
+ method @Nullable public String getInstallerCertificate();
+ method @Nullable public String getInstallerName();
+ method @NonNull public String getPackageName();
+ method public int getVersionCode();
+ method public boolean isPreInstalled();
+ }
+
+ public static final class AppInstallMetadata.Builder {
+ ctor public AppInstallMetadata.Builder();
+ method @NonNull public android.content.integrity.AppInstallMetadata build();
+ method @NonNull public android.content.integrity.AppInstallMetadata.Builder setAppCertificate(@NonNull String);
+ method @NonNull public android.content.integrity.AppInstallMetadata.Builder setInstallerCertificate(@NonNull String);
+ method @NonNull public android.content.integrity.AppInstallMetadata.Builder setInstallerName(@NonNull String);
+ method @NonNull public android.content.integrity.AppInstallMetadata.Builder setIsPreInstalled(boolean);
+ method @NonNull public android.content.integrity.AppInstallMetadata.Builder setPackageName(@NonNull String);
+ method @NonNull public android.content.integrity.AppInstallMetadata.Builder setVersionCode(int);
+ }
+
+ public class AppIntegrityManager {
+ method @NonNull public String getCurrentRuleSetProvider();
+ method @NonNull public String getCurrentRuleSetVersion();
+ method public void updateRuleSet(@NonNull android.content.integrity.RuleSet, @NonNull android.content.IntentSender);
+ field public static final String EXTRA_STATUS = "android.content.integrity.extra.STATUS";
+ field public static final int STATUS_FAILURE = 1; // 0x1
+ field public static final int STATUS_SUCCESS = 0; // 0x0
+ }
+
+ public abstract class AtomicFormula implements android.content.integrity.Formula {
+ ctor public AtomicFormula(@android.content.integrity.AtomicFormula.Key int);
+ method public int getKey();
+ field public static final int APP_CERTIFICATE = 1; // 0x1
+ field public static final int EQ = 0; // 0x0
+ field public static final int GE = 4; // 0x4
+ field public static final int GT = 3; // 0x3
+ field public static final int INSTALLER_CERTIFICATE = 3; // 0x3
+ field public static final int INSTALLER_NAME = 2; // 0x2
+ field public static final int LE = 2; // 0x2
+ field public static final int LT = 1; // 0x1
+ field public static final int PACKAGE_NAME = 0; // 0x0
+ field public static final int PRE_INSTALLED = 5; // 0x5
+ field public static final int VERSION_CODE = 4; // 0x4
+ }
+
+ public static final class AtomicFormula.BooleanAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
+ ctor public AtomicFormula.BooleanAtomicFormula(@android.content.integrity.AtomicFormula.Key int, boolean);
+ method public int describeContents();
+ method public int getTag();
+ method public boolean getValue();
+ method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.BooleanAtomicFormula> CREATOR;
+ }
+
+ public static final class AtomicFormula.IntAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
+ ctor public AtomicFormula.IntAtomicFormula(@android.content.integrity.AtomicFormula.Key int, @android.content.integrity.AtomicFormula.Operator int, int);
+ method public int describeContents();
+ method public int getOperator();
+ method public int getTag();
+ method public int getValue();
+ method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.IntAtomicFormula> CREATOR;
+ }
+
+ @IntDef({android.content.integrity.AtomicFormula.PACKAGE_NAME, android.content.integrity.AtomicFormula.APP_CERTIFICATE, android.content.integrity.AtomicFormula.INSTALLER_NAME, android.content.integrity.AtomicFormula.INSTALLER_CERTIFICATE, android.content.integrity.AtomicFormula.VERSION_CODE, android.content.integrity.AtomicFormula.PRE_INSTALLED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface AtomicFormula.Key {
+ }
+
+ @IntDef({android.content.integrity.AtomicFormula.EQ, android.content.integrity.AtomicFormula.LT, android.content.integrity.AtomicFormula.LE, android.content.integrity.AtomicFormula.GT, android.content.integrity.AtomicFormula.GE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface AtomicFormula.Operator {
+ }
+
+ public static final class AtomicFormula.StringAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
+ ctor public AtomicFormula.StringAtomicFormula(@android.content.integrity.AtomicFormula.Key int, @NonNull String, boolean);
+ method public int describeContents();
+ method public boolean getIsHashedValue();
+ method public int getTag();
+ method @NonNull public String getValue();
+ method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.StringAtomicFormula> CREATOR;
+ }
+
+ public final class CompoundFormula implements android.content.integrity.Formula android.os.Parcelable {
+ ctor public CompoundFormula(@android.content.integrity.CompoundFormula.Connector int, @NonNull java.util.List<android.content.integrity.Formula>);
+ method public int describeContents();
+ method @android.content.integrity.CompoundFormula.Connector public int getConnector();
+ method @NonNull public java.util.List<android.content.integrity.Formula> getFormulas();
+ method public int getTag();
+ method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int AND = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.CompoundFormula> CREATOR;
+ field public static final int NOT = 2; // 0x2
+ field public static final int OR = 1; // 0x1
+ }
+
+ @IntDef({android.content.integrity.CompoundFormula.AND, android.content.integrity.CompoundFormula.OR, android.content.integrity.CompoundFormula.NOT}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface CompoundFormula.Connector {
+ }
+
+ public interface Formula {
+ method @android.content.integrity.Formula.Tag public int getTag();
+ method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
+ method @NonNull public static android.content.integrity.Formula readFromParcel(@NonNull android.os.Parcel);
+ method public static void writeToParcel(@NonNull android.content.integrity.Formula, @NonNull android.os.Parcel, int);
+ field public static final int BOOLEAN_ATOMIC_FORMULA_TAG = 3; // 0x3
+ field public static final int COMPOUND_FORMULA_TAG = 0; // 0x0
+ field public static final int INT_ATOMIC_FORMULA_TAG = 2; // 0x2
+ field public static final int STRING_ATOMIC_FORMULA_TAG = 1; // 0x1
+ }
+
+ @IntDef({android.content.integrity.Formula.COMPOUND_FORMULA_TAG, android.content.integrity.Formula.STRING_ATOMIC_FORMULA_TAG, android.content.integrity.Formula.INT_ATOMIC_FORMULA_TAG, android.content.integrity.Formula.BOOLEAN_ATOMIC_FORMULA_TAG}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface Formula.Tag {
+ }
+
+ public final class Rule implements android.os.Parcelable {
+ ctor public Rule(@NonNull android.content.integrity.Formula, @android.content.integrity.Rule.Effect int);
+ method public int describeContents();
+ method @android.content.integrity.Rule.Effect public int getEffect();
+ method @NonNull public android.content.integrity.Formula getFormula();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.Rule> CREATOR;
+ field public static final int DENY = 0; // 0x0
+ field public static final int FORCE_ALLOW = 1; // 0x1
+ }
+
+ @IntDef({android.content.integrity.Rule.DENY, android.content.integrity.Rule.FORCE_ALLOW}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface Rule.Effect {
+ }
+
+ public class RuleSet {
+ method @NonNull public java.util.List<android.content.integrity.Rule> getRules();
+ method @NonNull public String getVersion();
+ }
+
+ public static class RuleSet.Builder {
+ ctor public RuleSet.Builder();
+ method @NonNull public android.content.integrity.RuleSet.Builder addRules(@NonNull java.util.List<android.content.integrity.Rule>);
+ method @NonNull public android.content.integrity.RuleSet build();
+ method @NonNull public android.content.integrity.RuleSet.Builder setVersion(@NonNull String);
+ }
+
+}
+
package android.content.om {
public final class OverlayInfo implements android.os.Parcelable {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0fdb513..0c6fdc0 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4917,6 +4917,14 @@
public static final String APP_SEARCH_SERVICE = "app_search";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.content.integrity.AppIntegrityManager}.
+ * @hide
+ */
+ @SystemApi
+ public static final String APP_INTEGRITY_SERVICE = "app_integrity";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ca374f93..40aca0e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4417,6 +4417,22 @@
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_VIEW_LOCUS = "android.intent.action.VIEW_LOCUS";
+ /**
+ * Broadcast Action: Sent to the integrity component when a package
+ * needs to be verified. The data contains the package URI along with other relevant
+ * information.
+ *
+ * <p class="note">
+ * This is a protected intent that can only be sent by the system.
+ * </p>
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION =
+ "android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
diff --git a/services/core/java/com/android/server/integrity/model/AppInstallMetadata.java b/core/java/android/content/integrity/AppInstallMetadata.java
similarity index 98%
rename from services/core/java/com/android/server/integrity/model/AppInstallMetadata.java
rename to core/java/android/content/integrity/AppInstallMetadata.java
index dfc373b..c963475 100644
--- a/services/core/java/com/android/server/integrity/model/AppInstallMetadata.java
+++ b/core/java/android/content/integrity/AppInstallMetadata.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
diff --git a/core/java/android/content/integrity/AppIntegrityManager.java b/core/java/android/content/integrity/AppIntegrityManager.java
new file mode 100644
index 0000000..e53ef66
--- /dev/null
+++ b/core/java/android/content/integrity/AppIntegrityManager.java
@@ -0,0 +1,103 @@
+/*
+ * 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 android.content.integrity;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.content.IntentSender;
+import android.content.pm.ParceledListSlice;
+import android.os.RemoteException;
+
+/**
+ * Class for pushing rules used to check the integrity of app installs.
+ *
+ * <p>Note: applications using methods of this class must be a system app and have their package
+ * name whitelisted as an integrity rule provider. Otherwise a {@link SecurityException} will be
+ * thrown.
+ *
+ * @hide
+ */
+@SystemApi
+@SystemService(Context.APP_INTEGRITY_SERVICE)
+public class AppIntegrityManager {
+
+ /** The operation succeeded. */
+ public static final int STATUS_SUCCESS = 0;
+
+ /** The operation failed. */
+ public static final int STATUS_FAILURE = 1;
+
+ /**
+ * Current status of an operation. Will be one of {@link #STATUS_SUCCESS}, {@link
+ * #STATUS_FAILURE}.
+ *
+ * <p>More information about a status may be available through additional extras; see the
+ * individual status documentation for details.
+ *
+ * @see android.content.Intent#getIntExtra(String, int)
+ */
+ public static final String EXTRA_STATUS = "android.content.integrity.extra.STATUS";
+
+ IAppIntegrityManager mManager;
+
+ /** @hide */
+ public AppIntegrityManager(IAppIntegrityManager manager) {
+ mManager = manager;
+ }
+
+ /**
+ * Update the rules to evaluate during install time.
+ *
+ * @param updateRequest request containing the data of the rule set update
+ * @param statusReceiver Called when the state of the session changes. Intents sent to this
+ * receiver contain {@link #EXTRA_STATUS}. Refer to the individual status codes on how to
+ * handle them.
+ */
+ public void updateRuleSet(
+ @NonNull RuleSet updateRequest, @NonNull IntentSender statusReceiver) {
+ try {
+ mManager.updateRuleSet(
+ updateRequest.getVersion(),
+ new ParceledListSlice<>(updateRequest.getRules()),
+ statusReceiver);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** Get the current version of the rule set. */
+ @NonNull
+ public String getCurrentRuleSetVersion() {
+ try {
+ return mManager.getCurrentRuleSetVersion();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** Get the name of the package that provided the current rule set. */
+ @NonNull
+ public String getCurrentRuleSetProvider() {
+ try {
+ return mManager.getCurrentRuleSetProvider();
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/model/AtomicFormula.java b/core/java/android/content/integrity/AtomicFormula.java
similarity index 99%
rename from services/core/java/com/android/server/integrity/model/AtomicFormula.java
rename to core/java/android/content/integrity/AtomicFormula.java
index a16f6b9..c8e164f 100644
--- a/services/core/java/com/android/server/integrity/model/AtomicFormula.java
+++ b/core/java/android/content/integrity/AtomicFormula.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
import static com.android.internal.util.Preconditions.checkArgument;
diff --git a/services/core/java/com/android/server/integrity/model/OpenFormula.java b/core/java/android/content/integrity/CompoundFormula.java
similarity index 85%
rename from services/core/java/com/android/server/integrity/model/OpenFormula.java
rename to core/java/android/content/integrity/CompoundFormula.java
index f7ea920..53a9953 100644
--- a/services/core/java/com/android/server/integrity/model/OpenFormula.java
+++ b/core/java/android/content/integrity/CompoundFormula.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
import static com.android.internal.util.Preconditions.checkArgument;
@@ -35,7 +35,8 @@
import java.util.Objects;
/**
- * Represents a complex formula consisting of other simple and complex formulas.
+ * Represents a compound formula formed by joining other simple and complex formulas with boolean
+ * connectors.
*
* <p>Instances of this class are immutable.
*
@@ -43,12 +44,12 @@
*/
@SystemApi
@VisibleForTesting
-public final class OpenFormula implements Formula, Parcelable {
+public final class CompoundFormula implements Formula, Parcelable {
private static final String TAG = "OpenFormula";
@IntDef(
value = {
- AND, OR, NOT,
+ AND, OR, NOT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Connector {}
@@ -66,16 +67,16 @@
private final @NonNull List<Formula> mFormulas;
@NonNull
- public static final Creator<OpenFormula> CREATOR =
- new Creator<OpenFormula>() {
+ public static final Creator<CompoundFormula> CREATOR =
+ new Creator<CompoundFormula>() {
@Override
- public OpenFormula createFromParcel(Parcel in) {
- return new OpenFormula(in);
+ public CompoundFormula createFromParcel(Parcel in) {
+ return new CompoundFormula(in);
}
@Override
- public OpenFormula[] newArray(int size) {
- return new OpenFormula[size];
+ public CompoundFormula[] newArray(int size) {
+ return new CompoundFormula[size];
}
};
@@ -85,15 +86,15 @@
* @throws IllegalArgumentException if the number of operands is not matching the requirements
* for that operator (at least 2 for {@link #AND} and {@link #OR}, 1 for {@link #NOT}).
*/
- public OpenFormula(@Connector int connector, @NonNull List<Formula> formulas) {
- checkArgument(isValidConnector(connector),
- String.format("Unknown connector: %d", connector));
+ public CompoundFormula(@Connector int connector, @NonNull List<Formula> formulas) {
+ checkArgument(
+ isValidConnector(connector), String.format("Unknown connector: %d", connector));
validateFormulas(connector, formulas);
this.mConnector = connector;
this.mFormulas = Collections.unmodifiableList(formulas);
}
- OpenFormula(Parcel in) {
+ CompoundFormula(Parcel in) {
mConnector = in.readInt();
int length = in.readInt();
checkArgument(length >= 0, "Must have non-negative length. Got " + length);
@@ -132,7 +133,7 @@
@Override
public int getTag() {
- return Formula.OPEN_FORMULA_TAG;
+ return Formula.COMPOUND_FORMULA_TAG;
}
@Override
@@ -160,7 +161,7 @@
if (o == null || getClass() != o.getClass()) {
return false;
}
- OpenFormula that = (OpenFormula) o;
+ CompoundFormula that = (CompoundFormula) o;
return mConnector == that.mConnector && mFormulas.equals(that.mFormulas);
}
@@ -217,8 +218,6 @@
}
private static boolean isValidConnector(int connector) {
- return connector == AND
- || connector == OR
- || connector == NOT;
+ return connector == AND || connector == OR || connector == NOT;
}
}
diff --git a/services/core/java/com/android/server/integrity/model/Formula.java b/core/java/android/content/integrity/Formula.java
similarity index 87%
rename from services/core/java/com/android/server/integrity/model/Formula.java
rename to core/java/android/content/integrity/Formula.java
index 6769827..030ff6b 100644
--- a/services/core/java/com/android/server/integrity/model/Formula.java
+++ b/core/java/android/content/integrity/Formula.java
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
+import android.content.integrity.AtomicFormula.IntAtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.integrity.model.AtomicFormula.BooleanAtomicFormula;
-import com.android.server.integrity.model.AtomicFormula.IntAtomicFormula;
-import com.android.server.integrity.model.AtomicFormula.StringAtomicFormula;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -40,7 +40,7 @@
public interface Formula {
@IntDef(
value = {
- OPEN_FORMULA_TAG,
+ COMPOUND_FORMULA_TAG,
STRING_ATOMIC_FORMULA_TAG,
INT_ATOMIC_FORMULA_TAG,
BOOLEAN_ATOMIC_FORMULA_TAG
@@ -48,7 +48,7 @@
@Retention(RetentionPolicy.SOURCE)
public @interface Tag {}
- int OPEN_FORMULA_TAG = 0;
+ int COMPOUND_FORMULA_TAG = 0;
int STRING_ATOMIC_FORMULA_TAG = 1;
int INT_ATOMIC_FORMULA_TAG = 2;
int BOOLEAN_ATOMIC_FORMULA_TAG = 3;
@@ -87,8 +87,8 @@
static Formula readFromParcel(@NonNull Parcel in) {
int tag = in.readInt();
switch (tag) {
- case OPEN_FORMULA_TAG:
- return OpenFormula.CREATOR.createFromParcel(in);
+ case COMPOUND_FORMULA_TAG:
+ return CompoundFormula.CREATOR.createFromParcel(in);
case STRING_ATOMIC_FORMULA_TAG:
return StringAtomicFormula.CREATOR.createFromParcel(in);
case INT_ATOMIC_FORMULA_TAG:
diff --git a/core/java/android/content/integrity/IAppIntegrityManager.aidl b/core/java/android/content/integrity/IAppIntegrityManager.aidl
new file mode 100644
index 0000000..6b73fd7
--- /dev/null
+++ b/core/java/android/content/integrity/IAppIntegrityManager.aidl
@@ -0,0 +1,28 @@
+/*
+**
+** Copyright 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 android.content.integrity;
+
+import android.content.integrity.Rule;
+import android.content.IntentSender;
+import android.content.pm.ParceledListSlice;
+
+/** @hide */
+interface IAppIntegrityManager {
+ void updateRuleSet(String version, in ParceledListSlice<Rule> rules, in IntentSender statusReceiver);
+ String getCurrentRuleSetVersion();
+ String getCurrentRuleSetProvider();
+}
diff --git a/core/java/android/content/integrity/Rule.aidl b/core/java/android/content/integrity/Rule.aidl
new file mode 100644
index 0000000..a6634ee
--- /dev/null
+++ b/core/java/android/content/integrity/Rule.aidl
@@ -0,0 +1,19 @@
+/*
+**
+** Copyright 2007, 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 android.content.integrity;
+
+parcelable Rule;
diff --git a/services/core/java/com/android/server/integrity/model/Rule.java b/core/java/android/content/integrity/Rule.java
similarity index 98%
rename from services/core/java/com/android/server/integrity/model/Rule.java
rename to core/java/android/content/integrity/Rule.java
index 3ad8762..914f147 100644
--- a/services/core/java/com/android/server/integrity/model/Rule.java
+++ b/core/java/android/content/integrity/Rule.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
diff --git a/core/java/android/content/integrity/RuleSet.java b/core/java/android/content/integrity/RuleSet.java
new file mode 100644
index 0000000..a78f8c9
--- /dev/null
+++ b/core/java/android/content/integrity/RuleSet.java
@@ -0,0 +1,92 @@
+/*
+ * 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 android.content.integrity;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Immutable data class encapsulating all parameters of a rule set.
+ *
+ * @hide
+ */
+@SystemApi
+public class RuleSet {
+ private final String mVersion;
+ private final List<Rule> mRules;
+
+ private RuleSet(String version, List<Rule> rules) {
+ mVersion = version;
+ mRules = Collections.unmodifiableList(rules);
+ }
+
+ /** @see Builder#setVersion(String). */
+ @NonNull
+ public String getVersion() {
+ return mVersion;
+ }
+
+ /** @see Builder#addRules(List). */
+ @NonNull
+ public List<Rule> getRules() {
+ return mRules;
+ }
+
+ /** Builder class for RuleSetUpdateRequest. */
+ public static class Builder {
+ private String mVersion;
+ private List<Rule> mRules;
+
+ public Builder() {
+ mRules = new ArrayList<>();
+ }
+
+ /**
+ * Set a version string to identify this rule set. This can be retrieved by {@link
+ * AppIntegrityManager#getCurrentRuleSetVersion()}.
+ */
+ @NonNull
+ public Builder setVersion(@NonNull String version) {
+ mVersion = version;
+ return this;
+ }
+
+ /** Add the rules to include. */
+ @NonNull
+ public Builder addRules(@NonNull List<Rule> rules) {
+ mRules.addAll(rules);
+ return this;
+ }
+
+ /**
+ * Builds a {@link RuleSet}.
+ *
+ * @throws IllegalArgumentException if version is null
+ */
+ @NonNull
+ public RuleSet build() {
+ checkNotNull(mVersion);
+ return new RuleSet(mVersion, mRules);
+ }
+ }
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 220fdd2..c3f4384 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -48,6 +48,7 @@
<protected-broadcast android:name="android.intent.action.PACKAGE_RESTARTED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
<protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION" />
<protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION" />
<protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
<protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 74bb2cf..2ede8d1 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4179,4 +4179,10 @@
<!-- Whether or not to show the built-in charging animation when the device begins charging
wirelessly. -->
<bool name="config_showBuiltinWirelessChargingAnim">true</bool>
+
+ <!-- A list of potential packages, in priority order, that can supply rules to
+ AppIntegrityManager. These need to be apps on the system partition. -->
+ <string-array name="config_integrityRuleProviderPackages" translatable="false">
+ <!-- Add packages here -->
+ </string-array>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1d51339..15de2f4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -456,6 +456,7 @@
<java-symbol type="string" name="config_deviceSpecificDevicePolicyManagerService" />
<java-symbol type="string" name="config_deviceSpecificAudioService" />
<java-symbol type="integer" name="config_num_physical_slots" />
+ <java-symbol type="array" name="config_integrityRuleProviderPackages" />
<java-symbol type="color" name="tab_indicator_text_v4" />
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/AtomicFormulaTest.java b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
similarity index 87%
rename from services/tests/servicestests/src/com/android/server/integrity/model/AtomicFormulaTest.java
rename to core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
index 988e18b..e48f1c3 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/model/AtomicFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
@@ -14,20 +14,19 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
-import static com.android.server.testutils.TestUtils.assertExpectException;
+import static android.content.integrity.TestUtils.assertExpectException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
+import android.content.integrity.AtomicFormula.IntAtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
import android.os.Parcel;
-import com.android.server.integrity.model.AtomicFormula.BooleanAtomicFormula;
-import com.android.server.integrity.model.AtomicFormula.IntAtomicFormula;
-import com.android.server.integrity.model.AtomicFormula.StringAtomicFormula;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -38,8 +37,8 @@
@Test
public void testValidAtomicFormula_stringValue() {
StringAtomicFormula stringAtomicFormula =
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
- "com.test.app", /* isHashedValue= */ false);
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
assertEquals(AtomicFormula.PACKAGE_NAME, stringAtomicFormula.getKey());
}
@@ -65,10 +64,12 @@
assertExpectException(
IllegalArgumentException.class,
/* expectedExceptionMessageRegex */
- String.format(
- "Key VERSION_CODE cannot be used with StringAtomicFormula"),
- () -> new StringAtomicFormula(AtomicFormula.VERSION_CODE, "test-value",
- /* isHashedValue= */ false));
+ String.format("Key VERSION_CODE cannot be used with StringAtomicFormula"),
+ () ->
+ new StringAtomicFormula(
+ AtomicFormula.VERSION_CODE,
+ "test-value",
+ /* isHashedValue= */ false));
}
@Test
@@ -76,8 +77,7 @@
assertExpectException(
IllegalArgumentException.class,
/* expectedExceptionMessageRegex */
- String.format(
- "Key PACKAGE_NAME cannot be used with IntAtomicFormula"),
+ String.format("Key PACKAGE_NAME cannot be used with IntAtomicFormula"),
() -> new IntAtomicFormula(AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
}
@@ -86,16 +86,15 @@
assertExpectException(
IllegalArgumentException.class,
/* expectedExceptionMessageRegex */
- String.format(
- "Key PACKAGE_NAME cannot be used with BooleanAtomicFormula"),
+ String.format("Key PACKAGE_NAME cannot be used with BooleanAtomicFormula"),
() -> new BooleanAtomicFormula(AtomicFormula.PACKAGE_NAME, true));
}
@Test
public void testIsSatisfiable_string_true() {
StringAtomicFormula stringAtomicFormula =
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
- "com.test.app", /* isHashedValue= */ false);
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("com.test.app").build();
@@ -105,8 +104,8 @@
@Test
public void testIsSatisfiable_string_false() {
StringAtomicFormula stringAtomicFormula =
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
- "com.test.app", /* isHashedValue= */ false);
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("com.foo.bar").build();
@@ -235,8 +234,9 @@
@Test
public void testParcelUnparcel_string() {
- StringAtomicFormula formula = new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "abc",
- /* isHashedValue= */ false);
+ StringAtomicFormula formula =
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, "abc", /* isHashedValue= */ false);
Parcel p = Parcel.obtain();
formula.writeToParcel(p, 0);
p.setDataPosition(0);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
similarity index 63%
rename from services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java
rename to core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
index b58ffd7..927e4db 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/model/OpenFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
-import static com.android.server.testutils.TestUtils.assertExpectException;
+import static android.content.integrity.TestUtils.assertExpectException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -32,21 +32,23 @@
import java.util.Collections;
@RunWith(JUnit4.class)
-public class OpenFormulaTest {
+public class CompoundFormulaTest {
private static final AtomicFormula ATOMIC_FORMULA_1 =
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "test1",
- /* isHashedValue= */ false);
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, "test1", /* isHashedValue= */ false);
private static final AtomicFormula ATOMIC_FORMULA_2 =
new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1);
@Test
- public void testValidOpenFormula() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ public void testValidCompoundFormula() {
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
- assertEquals(OpenFormula.AND, openFormula.getConnector());
- assertEquals(Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2), openFormula.getFormulas());
+ assertEquals(CompoundFormula.AND, compoundFormula.getConnector());
+ assertEquals(
+ Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2), compoundFormula.getFormulas());
}
@Test
@@ -56,8 +58,8 @@
/* expectedExceptionMessageRegex */
"Connector AND must have at least 2 formulas",
() ->
- new OpenFormula(
- OpenFormula.AND, Collections.singletonList(ATOMIC_FORMULA_1)));
+ new CompoundFormula(
+ CompoundFormula.AND, Collections.singletonList(ATOMIC_FORMULA_1)));
}
@Test
@@ -67,158 +69,169 @@
/* expectedExceptionMessageRegex */
"Connector NOT must have 1 formula only",
() ->
- new OpenFormula(
- OpenFormula.NOT,
+ new CompoundFormula(
+ CompoundFormula.NOT,
Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
}
@Test
public void testIsSatisfiable_notFalse_true() {
- OpenFormula openFormula = new OpenFormula(OpenFormula.NOT,
- Collections.singletonList(ATOMIC_FORMULA_1));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").build();
// validate assumptions about the metadata
assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertTrue(openFormula.isSatisfied(appInstallMetadata));
+ assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_notTrue_false() {
- OpenFormula openFormula = new OpenFormula(OpenFormula.NOT,
- Collections.singletonList(ATOMIC_FORMULA_1));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").build();
// validate assumptions about the metadata
assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertFalse(openFormula.isSatisfied(appInstallMetadata));
+ assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_trueAndTrue_true() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
// validate assumptions about the metadata
assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertTrue(openFormula.isSatisfied(appInstallMetadata));
+ assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_trueAndFalse_false() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
// validate assumptions about the metadata
assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertFalse(openFormula.isSatisfied(appInstallMetadata));
+ assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_falseAndTrue_false() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
// validate assumptions about the metadata
assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertFalse(openFormula.isSatisfied(appInstallMetadata));
+ assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_falseAndFalse_false() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
// validate assumptions about the metadata
assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertFalse(openFormula.isSatisfied(appInstallMetadata));
+ assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_trueOrTrue_true() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
// validate assumptions about the metadata
assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertTrue(openFormula.isSatisfied(appInstallMetadata));
+ assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_trueOrFalse_true() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
// validate assumptions about the metadata
assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertTrue(openFormula.isSatisfied(appInstallMetadata));
+ assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_falseOrTrue_true() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
// validate assumptions about the metadata
assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertTrue(openFormula.isSatisfied(appInstallMetadata));
+ assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testIsSatisfiable_falseOrFalse_false() {
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
// validate assumptions about the metadata
assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertFalse(openFormula.isSatisfied(appInstallMetadata));
+ assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
}
@Test
public void testParcelUnparcel() {
- OpenFormula formula =
- new OpenFormula(OpenFormula.AND, Arrays.asList(ATOMIC_FORMULA_2, ATOMIC_FORMULA_1));
+ CompoundFormula formula =
+ new CompoundFormula(
+ CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_2, ATOMIC_FORMULA_1));
Parcel p = Parcel.obtain();
formula.writeToParcel(p, 0);
p.setDataPosition(0);
- OpenFormula newFormula = OpenFormula.CREATOR.createFromParcel(p);
+ CompoundFormula newFormula = CompoundFormula.CREATOR.createFromParcel(p);
assertEquals(formula, newFormula);
}
@Test
- public void testInvalidOpenFormula_invalidConnector() {
+ public void testInvalidCompoundFormula_invalidConnector() {
assertExpectException(
IllegalArgumentException.class,
/* expectedExceptionMessageRegex */ "Unknown connector: -1",
- () -> new OpenFormula(/* connector= */ -1,
- Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+ () ->
+ new CompoundFormula(
+ /* connector= */ -1,
+ Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
}
/** Returns a builder with all fields filled with some dummy data. */
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java b/core/tests/coretests/src/android/content/integrity/RuleTest.java
similarity index 87%
rename from services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java
rename to core/tests/coretests/src/android/content/integrity/RuleTest.java
index cad3928..19e74e6 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/model/RuleTest.java
+++ b/core/tests/coretests/src/android/content/integrity/RuleTest.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.server.integrity.model;
+package android.content.integrity;
-import static com.android.server.testutils.TestUtils.assertExpectException;
+import static android.content.integrity.TestUtils.assertExpectException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -60,11 +60,11 @@
@Test
public void testToString() {
- OpenFormula openFormula =
- new OpenFormula(
- OpenFormula.AND,
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.AND,
Arrays.asList(PACKAGE_NAME_ATOMIC_FORMULA, APP_CERTIFICATE_ATOMIC_FORMULA));
- Rule rule = new Rule(openFormula, Rule.DENY);
+ Rule rule = new Rule(compoundFormula, Rule.DENY);
assertEquals(
String.format(
@@ -93,12 +93,12 @@
public void testParcelUnparcel() {
Rule rule =
new Rule(
- new OpenFormula(
- OpenFormula.AND,
+ new CompoundFormula(
+ CompoundFormula.AND,
Arrays.asList(
APP_CERTIFICATE_ATOMIC_FORMULA,
- new OpenFormula(
- OpenFormula.NOT,
+ new CompoundFormula(
+ CompoundFormula.NOT,
Arrays.asList(PACKAGE_NAME_ATOMIC_FORMULA)))),
Rule.DENY);
Parcel p = Parcel.obtain();
diff --git a/core/tests/coretests/src/android/content/integrity/TEST_MAPPING b/core/tests/coretests/src/android/content/integrity/TEST_MAPPING
new file mode 100644
index 0000000..2920716
--- /dev/null
+++ b/core/tests/coretests/src/android/content/integrity/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.content.integrity."
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/tests/coretests/src/android/content/integrity/TestUtils.java b/core/tests/coretests/src/android/content/integrity/TestUtils.java
new file mode 100644
index 0000000..af984cf
--- /dev/null
+++ b/core/tests/coretests/src/android/content/integrity/TestUtils.java
@@ -0,0 +1,51 @@
+/*
+ * 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 android.content.integrity;
+
+import android.test.MoreAsserts;
+
+import junit.framework.Assert;
+
+/** Helper methods used in tests. */
+class TestUtils {
+ private TestUtils() {}
+
+ public interface ExceptionRunnable {
+ void run() throws Exception;
+ }
+
+ public static void assertExpectException(
+ Class<? extends Throwable> expectedExceptionType,
+ String expectedExceptionMessageRegex,
+ ExceptionRunnable r) {
+ try {
+ r.run();
+ } catch (Throwable e) {
+ Assert.assertTrue(
+ "Expected exception type was "
+ + expectedExceptionType.getName()
+ + " but caught "
+ + e.getClass().getName(),
+ expectedExceptionType.isAssignableFrom(e.getClass()));
+ if (expectedExceptionMessageRegex != null) {
+ MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
+ }
+ return; // Pass.
+ }
+ Assert.fail(
+ "Expected exception type " + expectedExceptionType.getName() + " was not thrown");
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
index f0bb192..b8202b6 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
@@ -16,9 +16,10 @@
package com.android.server.integrity.engine;
-import com.android.server.integrity.model.AppInstallMetadata;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.Rule;
+
import com.android.server.integrity.model.IntegrityCheckResult;
-import com.android.server.integrity.model.Rule;
import java.util.ArrayList;
import java.util.List;
@@ -26,8 +27,8 @@
/**
* The engine used to evaluate rules against app installs.
*
- * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation
- * engine to allow/block that install.
+ * <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
+ * to allow/block that install.
*/
public final class RuleEvaluationEngine {
private static final String TAG = "RuleEvaluation";
@@ -36,9 +37,7 @@
// installs against rules.
private static RuleEvaluationEngine sRuleEvaluationEngine;
- /**
- * Provide a singleton instance of the rule evaluation engine.
- */
+ /** Provide a singleton instance of the rule evaluation engine. */
public static synchronized RuleEvaluationEngine getRuleEvaluationEngine() {
if (sRuleEvaluationEngine == null) {
return new RuleEvaluationEngine();
@@ -50,7 +49,7 @@
* Load, and match the list of rules against an app install metadata.
*
* @param appInstallMetadata Metadata of the app to be installed, and to evaluate the rules
- * against.
+ * against.
* @return result of the integrity check
*/
public IntegrityCheckResult evaluate(AppInstallMetadata appInstallMetadata) {
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
index 7deae46..ee51d4f 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
@@ -16,18 +16,18 @@
package com.android.server.integrity.engine;
-import static com.android.server.integrity.model.Rule.DENY;
-import static com.android.server.integrity.model.Rule.FORCE_ALLOW;
+import static android.content.integrity.Rule.DENY;
+import static android.content.integrity.Rule.FORCE_ALLOW;
import android.annotation.NonNull;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Formula;
+import android.content.integrity.Rule;
import android.util.Slog;
-import com.android.server.integrity.model.AppInstallMetadata;
-import com.android.server.integrity.model.AtomicFormula;
-import com.android.server.integrity.model.Formula;
import com.android.server.integrity.model.IntegrityCheckResult;
-import com.android.server.integrity.model.OpenFormula;
-import com.android.server.integrity.model.Rule;
import java.util.ArrayList;
import java.util.List;
@@ -89,17 +89,17 @@
if (isAtomicFormula(formula)) {
return true;
}
- OpenFormula openFormula = (OpenFormula) formula;
- return openFormula.getConnector() == OpenFormula.AND
- && openFormula.getFormulas().stream().allMatch(RuleEvaluator::isAtomicFormula);
+ CompoundFormula compoundFormula = (CompoundFormula) formula;
+ return compoundFormula.getConnector() == CompoundFormula.AND
+ && compoundFormula.getFormulas().stream().allMatch(RuleEvaluator::isAtomicFormula);
}
private static boolean isAtomicFormula(Formula formula) {
if (formula instanceof AtomicFormula) {
return true;
}
- OpenFormula openFormula = (OpenFormula) formula;
- return openFormula.getConnector() == OpenFormula.NOT
- && openFormula.getFormulas().get(0) instanceof AtomicFormula;
+ CompoundFormula compoundFormula = (CompoundFormula) formula;
+ return compoundFormula.getConnector() == CompoundFormula.NOT
+ && compoundFormula.getFormulas().get(0) instanceof AtomicFormula;
}
}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleLoader.java b/services/core/java/com/android/server/integrity/engine/RuleLoader.java
index af24d7a..4ba2bfb 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleLoader.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleLoader.java
@@ -16,7 +16,7 @@
package com.android.server.integrity.engine;
-import com.android.server.integrity.model.Rule;
+import android.content.integrity.Rule;
import java.util.ArrayList;
import java.util.List;
diff --git a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
index ef0751d..b3cb31a 100644
--- a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
+++ b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
@@ -17,6 +17,7 @@
package com.android.server.integrity.model;
import android.annotation.Nullable;
+import android.content.integrity.Rule;
/**
* A class encapsulating the result from the evaluation engine after evaluating rules against app
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 5ed282c..111b95a 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -16,7 +16,7 @@
package com.android.server.integrity.parser;
-import com.android.server.integrity.model.Rule;
+import android.content.integrity.Rule;
import java.io.InputStream;
import java.util.List;
diff --git a/services/core/java/com/android/server/integrity/parser/RuleParser.java b/services/core/java/com/android/server/integrity/parser/RuleParser.java
index 08e0a5d..4e1f914 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleParser.java
@@ -16,7 +16,7 @@
package com.android.server.integrity.parser;
-import com.android.server.integrity.model.Rule;
+import android.content.integrity.Rule;
import java.io.InputStream;
import java.util.List;
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 1508c27..1212a08 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
@@ -16,13 +16,12 @@
package com.android.server.integrity.parser;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Formula;
+import android.content.integrity.Rule;
import android.util.Xml;
-import com.android.server.integrity.model.AtomicFormula;
-import com.android.server.integrity.model.Formula;
-import com.android.server.integrity.model.OpenFormula;
-import com.android.server.integrity.model.Rule;
-
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -34,9 +33,7 @@
import java.util.List;
import java.util.Optional;
-/**
- * A helper class to parse rules into the {@link Rule} model from Xml representation.
- */
+/** A helper class to parse rules into the {@link Rule} model from Xml representation. */
public final class RuleXmlParser implements RuleParser {
public static final String TAG = "RuleXmlParser";
@@ -90,7 +87,8 @@
// corrupt in the XML, it will be skipped to the next rule.
if (!nodeName.equals(RULE_LIST_TAG)) {
throw new RuntimeException(
- String.format("Rules must start with RuleList <RL> tag. Found: %s at %s",
+ String.format(
+ "Rules must start with RuleList <RL> tag. Found: %s at %s",
nodeName, parser.getPositionDescription()));
}
@@ -141,8 +139,8 @@
private static Formula parseOpenFormula(XmlPullParser parser)
throws IOException, XmlPullParserException {
- int connector = Integer.parseInt(
- extractAttributeValue(parser, CONNECTOR_ATTRIBUTE).orElse("-1"));
+ int connector =
+ Integer.parseInt(extractAttributeValue(parser, CONNECTOR_ATTRIBUTE).orElse("-1"));
List<Formula> formulas = new ArrayList<>();
int eventType;
@@ -171,17 +169,17 @@
}
}
- return new OpenFormula(connector, formulas);
+ return new CompoundFormula(connector, formulas);
}
private static Formula parseAtomicFormula(XmlPullParser parser)
throws IOException, XmlPullParserException {
int key = Integer.parseInt(extractAttributeValue(parser, KEY_ATTRIBUTE).orElse("-1"));
- int operator = Integer.parseInt(
- extractAttributeValue(parser, OPERATOR_ATTRIBUTE).orElse("-1"));
+ int operator =
+ Integer.parseInt(extractAttributeValue(parser, OPERATOR_ATTRIBUTE).orElse("-1"));
String value = extractAttributeValue(parser, VALUE_ATTRIBUTE).orElse(null);
- String isHashedValue = extractAttributeValue(parser, IS_HASHED_VALUE_ATTRIBUTE).orElse(
- null);
+ String isHashedValue =
+ extractAttributeValue(parser, IS_HASHED_VALUE_ATTRIBUTE).orElse(null);
int eventType;
while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
@@ -192,15 +190,18 @@
return constructAtomicFormulaBasedOnKey(key, operator, value, isHashedValue);
}
- private static Formula constructAtomicFormulaBasedOnKey(@AtomicFormula.Key int key,
- @AtomicFormula.Operator int operator, String value, String isHashedValue) {
+ private static Formula constructAtomicFormulaBasedOnKey(
+ @AtomicFormula.Key int key,
+ @AtomicFormula.Operator int operator,
+ String value,
+ String isHashedValue) {
switch (key) {
case AtomicFormula.PACKAGE_NAME:
case AtomicFormula.INSTALLER_NAME:
case AtomicFormula.APP_CERTIFICATE:
case AtomicFormula.INSTALLER_CERTIFICATE:
- return new AtomicFormula.StringAtomicFormula(key, value,
- Boolean.parseBoolean(isHashedValue));
+ return new AtomicFormula.StringAtomicFormula(
+ key, value, Boolean.parseBoolean(isHashedValue));
case AtomicFormula.PRE_INSTALLED:
return new AtomicFormula.BooleanAtomicFormula(key, Boolean.parseBoolean(value));
case AtomicFormula.VERSION_CODE:
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 ee95d2b..ace15bd 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -16,7 +16,7 @@
package com.android.server.integrity.serializer;
-import com.android.server.integrity.model.Rule;
+import android.content.integrity.Rule;
import java.io.OutputStream;
import java.util.List;
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
index 5c99c5a..c45f6be 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
@@ -16,7 +16,7 @@
package com.android.server.integrity.serializer;
-import com.android.server.integrity.model.Rule;
+import android.content.integrity.Rule;
import java.io.OutputStream;
import java.util.List;
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index f2ba756..5dd7891 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -16,13 +16,12 @@
package com.android.server.integrity.serializer;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Formula;
+import android.content.integrity.Rule;
import android.util.Xml;
-import com.android.server.integrity.model.AtomicFormula;
-import com.android.server.integrity.model.Formula;
-import com.android.server.integrity.model.OpenFormula;
-import com.android.server.integrity.model.Rule;
-
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
@@ -31,9 +30,7 @@
import java.nio.charset.StandardCharsets;
import java.util.List;
-/**
- * A helper class to serialize rules from the {@link Rule} model to Xml representation.
- */
+/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
public class RuleXmlSerializer implements RuleSerializer {
public static final String TAG = "RuleXmlSerializer";
@@ -97,23 +94,23 @@
private void serializeFormula(Formula formula, XmlSerializer xmlSerializer) throws IOException {
if (formula instanceof AtomicFormula) {
serializeAtomicFormula((AtomicFormula) formula, xmlSerializer);
- } else if (formula instanceof OpenFormula) {
- serializeOpenFormula((OpenFormula) formula, xmlSerializer);
+ } else if (formula instanceof CompoundFormula) {
+ serializeOpenFormula((CompoundFormula) formula, xmlSerializer);
} else {
throw new IllegalArgumentException(
String.format("Invalid formula type: %s", formula.getClass()));
}
}
- private void serializeOpenFormula(OpenFormula openFormula, XmlSerializer xmlSerializer)
+ private void serializeOpenFormula(CompoundFormula compoundFormula, XmlSerializer xmlSerializer)
throws IOException {
- if (openFormula == null) {
+ if (compoundFormula == null) {
return;
}
xmlSerializer.startTag(NAMESPACE, OPEN_FORMULA_TAG);
- serializeAttributeValue(CONNECTOR_ATTRIBUTE, String.valueOf(openFormula.getConnector()),
+ serializeAttributeValue(CONNECTOR_ATTRIBUTE, String.valueOf(compoundFormula.getConnector()),
xmlSerializer);
- for (Formula formula : openFormula.getFormulas()) {
+ for (Formula formula : compoundFormula.getFormulas()) {
serializeFormula(formula, xmlSerializer);
}
xmlSerializer.endTag(NAMESPACE, OPEN_FORMULA_TAG);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
index d6773d4..7a070ee 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
@@ -21,12 +21,13 @@
import static org.junit.Assert.assertEquals;
-import com.android.server.integrity.model.AppInstallMetadata;
-import com.android.server.integrity.model.AtomicFormula;
-import com.android.server.integrity.model.AtomicFormula.StringAtomicFormula;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Rule;
+
import com.android.server.integrity.model.IntegrityCheckResult;
-import com.android.server.integrity.model.OpenFormula;
-import com.android.server.integrity.model.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -63,7 +64,9 @@
public void testEvaluateRules_noMatchedRules_allow() {
Rule rule1 =
new Rule(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_2,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_2,
/* isHashedValue= */ false),
Rule.DENY);
@@ -77,12 +80,16 @@
public void testEvaluateRules_oneMatch_deny() {
Rule rule1 =
new Rule(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_1,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_1,
/* isHashedValue= */ false),
Rule.DENY);
Rule rule2 =
new Rule(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_2,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_2,
/* isHashedValue= */ false),
Rule.DENY);
@@ -97,19 +104,24 @@
public void testEvaluateRules_multipleMatches_deny() {
Rule rule1 =
new Rule(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_1,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_1,
/* isHashedValue= */ false),
Rule.DENY);
- OpenFormula openFormula2 =
- new OpenFormula(
- OpenFormula.AND,
+ CompoundFormula compoundFormula2 =
+ new CompoundFormula(
+ CompoundFormula.AND,
Arrays.asList(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_1,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_1,
/* isHashedValue= */ false),
new StringAtomicFormula(
- AtomicFormula.APP_CERTIFICATE, APP_CERTIFICATE,
+ AtomicFormula.APP_CERTIFICATE,
+ APP_CERTIFICATE,
/* isHashedValue= */ false)));
- Rule rule2 = new Rule(openFormula2, Rule.DENY);
+ Rule rule2 = new Rule(compoundFormula2, Rule.DENY);
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
@@ -120,14 +132,15 @@
@Test
public void testEvaluateRules_ruleWithNot_deny() {
- OpenFormula openFormula =
- new OpenFormula(
- OpenFormula.NOT,
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.NOT,
Collections.singletonList(
new StringAtomicFormula(
AtomicFormula.PACKAGE_NAME,
- PACKAGE_NAME_2, /* isHashedValue= */ false)));
- Rule rule = new Rule(openFormula, Rule.DENY);
+ PACKAGE_NAME_2,
+ /* isHashedValue= */ false)));
+ Rule rule = new Rule(compoundFormula, Rule.DENY);
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
@@ -153,16 +166,19 @@
@Test
public void testEvaluateRules_validForm_deny() {
- OpenFormula openFormula =
- new OpenFormula(
- OpenFormula.AND,
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.AND,
Arrays.asList(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_1,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_1,
/* isHashedValue= */ false),
new StringAtomicFormula(
- AtomicFormula.APP_CERTIFICATE, APP_CERTIFICATE,
+ AtomicFormula.APP_CERTIFICATE,
+ APP_CERTIFICATE,
/* isHashedValue= */ false)));
- Rule rule = new Rule(openFormula, Rule.DENY);
+ Rule rule = new Rule(compoundFormula, Rule.DENY);
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
@@ -173,16 +189,19 @@
@Test
public void testEvaluateRules_ruleNotInDNF_ignoreAndAllow() {
- OpenFormula openFormula =
- new OpenFormula(
- OpenFormula.OR,
+ CompoundFormula compoundFormula =
+ new CompoundFormula(
+ CompoundFormula.OR,
Arrays.asList(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_1,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_1,
/* isHashedValue= */ false),
new StringAtomicFormula(
- AtomicFormula.APP_CERTIFICATE, APP_CERTIFICATE,
+ AtomicFormula.APP_CERTIFICATE,
+ APP_CERTIFICATE,
/* isHashedValue= */ false)));
- Rule rule = new Rule(openFormula, Rule.DENY);
+ Rule rule = new Rule(compoundFormula, Rule.DENY);
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
@@ -191,19 +210,22 @@
}
@Test
- public void testEvaluateRules_openFormulaWithNot_allow() {
- OpenFormula openSubFormula =
- new OpenFormula(
- OpenFormula.AND,
+ public void testEvaluateRules_compoundFormulaWithNot_allow() {
+ CompoundFormula openSubFormula =
+ new CompoundFormula(
+ CompoundFormula.AND,
Arrays.asList(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_2,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_2,
/* isHashedValue= */ false),
new StringAtomicFormula(
- AtomicFormula.APP_CERTIFICATE, APP_CERTIFICATE,
+ AtomicFormula.APP_CERTIFICATE,
+ APP_CERTIFICATE,
/* isHashedValue= */ false)));
- OpenFormula openFormula =
- new OpenFormula(OpenFormula.NOT, Collections.singletonList(openSubFormula));
- Rule rule = new Rule(openFormula, Rule.DENY);
+ CompoundFormula compoundFormula =
+ new CompoundFormula(CompoundFormula.NOT, Collections.singletonList(openSubFormula));
+ Rule rule = new Rule(compoundFormula, Rule.DENY);
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
@@ -215,19 +237,24 @@
public void testEvaluateRules_forceAllow() {
Rule rule1 =
new Rule(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_1,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_1,
/* isHashedValue= */ false),
Rule.FORCE_ALLOW);
- OpenFormula openFormula2 =
- new OpenFormula(
- OpenFormula.AND,
+ CompoundFormula compoundFormula2 =
+ new CompoundFormula(
+ CompoundFormula.AND,
Arrays.asList(
- new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME_1,
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME_1,
/* isHashedValue= */ false),
new StringAtomicFormula(
- AtomicFormula.APP_CERTIFICATE, APP_CERTIFICATE,
+ AtomicFormula.APP_CERTIFICATE,
+ APP_CERTIFICATE,
/* isHashedValue= */ false)));
- Rule rule2 = new Rule(openFormula2, Rule.DENY);
+ Rule rule2 = new Rule(compoundFormula2, Rule.DENY);
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
index 7d71cd4c..495923d 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
@@ -20,9 +20,9 @@
import static com.google.common.truth.Truth.assertThat;
-import com.android.server.integrity.model.AtomicFormula;
-import com.android.server.integrity.model.OpenFormula;
-import com.android.server.integrity.model.Rule;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.CompoundFormula;
+import android.content.integrity.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,27 +40,37 @@
public class RuleXmlParserTest {
@Test
- public void testXmlStream_validOpenFormula() throws Exception {
+ public void testXmlStream_validCompoundFormula() throws Exception {
Map<String, String> atomicFormulaAttrs = new HashMap<>();
atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
atomicFormulaAttrs.put("V", "com.app.test");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- InputStream inputStream = new ByteArrayInputStream(ruleXmlOpenFormula.getBytes());
- Rule expectedRule = new Rule(new OpenFormula(OpenFormula.NOT, Collections.singletonList(
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
- /* isHashedValue= */ false))),
- Rule.DENY);
+ InputStream inputStream = new ByteArrayInputStream(ruleXmlCompoundFormula.getBytes());
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.NOT,
+ Collections.singletonList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "com.app.test",
+ /* isHashedValue= */ false))),
+ Rule.DENY);
List<Rule> rules = xmlParser.parse(inputStream);
@@ -68,127 +78,172 @@
}
@Test
- public void testXmlString_validOpenFormula_notConnector() throws Exception {
+ public void testXmlString_validCompoundFormula_notConnector() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(new OpenFormula(OpenFormula.NOT, Collections.singletonList(
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
- /* isHashedValue= */ false))),
- Rule.DENY);
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.NOT,
+ Collections.singletonList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "com.app.test",
+ /* isHashedValue= */ false))),
+ Rule.DENY);
- List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
+ List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
- public void testXmlString_validOpenFormula_andConnector() throws Exception {
+ public void testXmlString_validCompoundFormula_andConnector() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
Map<String, String> appCertificateAttrs = new HashMap<>();
appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
appCertificateAttrs.put("V", "test_cert");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.AND)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(new OpenFormula(OpenFormula.AND, Arrays.asList(
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
- /* isHashedValue= */ false),
- new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert",
- /* isHashedValue= */ false))),
- Rule.DENY);
-
- List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "com.app.test",
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ "test_cert",
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
- public void testXmlString_validOpenFormula_orConnector() throws Exception {
+ public void testXmlString_validCompoundFormula_orConnector() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
Map<String, String> appCertificateAttrs = new HashMap<>();
appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
appCertificateAttrs.put("V", "test_cert");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.OR)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.OR)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(new OpenFormula(OpenFormula.OR, Arrays.asList(
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
- /* isHashedValue= */ false),
- new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert",
- /* isHashedValue= */ false))),
- Rule.DENY);
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.OR,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "com.app.test",
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ "test_cert",
+ /* isHashedValue= */ false))),
+ Rule.DENY);
- List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
+ List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
- public void testXmlString_validOpenFormula_differentTagOrder() throws Exception {
+ public void testXmlString_validCompoundFormula_differentTagOrder() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(new OpenFormula(OpenFormula.NOT, Collections.singletonList(
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
- /* isHashedValue= */ false))),
- Rule.DENY);
+ Rule expectedRule =
+ new Rule(
+ new CompoundFormula(
+ CompoundFormula.NOT,
+ Collections.singletonList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "com.app.test",
+ /* isHashedValue= */ false))),
+ Rule.DENY);
- List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
+ List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
}
@Test
- public void testXmlString_invalidOpenFormula_invalidNumberOfFormulas() throws Exception {
+ public void testXmlString_invalidCompoundFormula_invalidNumberOfFormulas() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
@@ -196,98 +251,116 @@
versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE));
versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ));
versionCodeAttrs.put("V", "1");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "Connector NOT must have 1 formula only",
- () -> xmlParser.parse(ruleXmlOpenFormula));
+ () -> xmlParser.parse(ruleXmlCompoundFormula));
}
@Test
- public void testXmlString_invalidOpenFormula_invalidOperator() throws Exception {
+ public void testXmlString_invalidCompoundFormula_invalidOperator() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("O", "INVALID_OPERATOR");
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "For input string: \"INVALID_OPERATOR\"",
- () -> xmlParser.parse(ruleXmlOpenFormula));
+ () -> xmlParser.parse(ruleXmlCompoundFormula));
}
@Test
- public void testXmlString_invalidOpenFormula_invalidEffect() throws Exception {
+ public void testXmlString_invalidCompoundFormula_invalidEffect() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", "INVALID_EFFECT"),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", "INVALID_EFFECT"),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "For input string: \"INVALID_EFFECT\"",
- () -> xmlParser.parse(ruleXmlOpenFormula));
+ () -> xmlParser.parse(ruleXmlCompoundFormula));
}
@Test
- public void testXmlString_invalidOpenFormula_invalidTags() throws Exception {
+ public void testXmlString_invalidCompoundFormula_invalidTags() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "InvalidAtomicFormula",
- packageNameAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "InvalidAtomicFormula",
+ packageNameAttrs,
+ /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "Found unexpected tag: InvalidAtomicFormula",
- () -> xmlParser.parse(ruleXmlOpenFormula));
+ () -> xmlParser.parse(ruleXmlCompoundFormula));
}
@Test
@@ -295,18 +368,24 @@
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlAtomicFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ String ruleXmlAtomicFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
- /* isHashedValue= */ false),
- Rule.DENY);
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "com.app.test",
+ /* isHashedValue= */ false),
+ Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
@@ -319,17 +398,22 @@
versionCodeAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE));
versionCodeAttrs.put("O", String.valueOf(AtomicFormula.EQ));
versionCodeAttrs.put("V", "1");
- String ruleXmlAtomicFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ String ruleXmlAtomicFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(
- new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
- Rule.DENY);
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.IntAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
+ Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
@@ -341,17 +425,21 @@
Map<String, String> preInstalledAttrs = new HashMap<>();
preInstalledAttrs.put("K", String.valueOf(AtomicFormula.PRE_INSTALLED));
preInstalledAttrs.put("V", "true");
- String ruleXmlAtomicFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ String ruleXmlAtomicFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
- Rule.DENY);
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
@@ -363,18 +451,24 @@
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlAtomicFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ String ruleXmlAtomicFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
- Rule expectedRule = new Rule(
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
- /* isHashedValue= */ false),
- Rule.DENY);
+ Rule expectedRule =
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ "com.app.test",
+ /* isHashedValue= */ false),
+ Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula);
@@ -386,13 +480,16 @@
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("BadKey", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlAtomicFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ String ruleXmlAtomicFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
@@ -406,13 +503,16 @@
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlAtomicFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("BadEffect", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ String ruleXmlAtomicFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("BadEffect", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
@@ -421,26 +521,31 @@
}
@Test
- public void testXmlString_invalidOpenFormula_invalidAttribute() throws Exception {
+ public void testXmlString_invalidCompoundFormula_invalidAttribute() throws Exception {
Map<String, String> packageNameAttrs = new HashMap<>();
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlOpenFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("BadConnector", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>"
- + "</RL>";
+ String ruleXmlCompoundFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap(
+ "BadConnector", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
RuleParseException.class,
/* expectedExceptionMessageRegex */ "Unknown connector: -1",
- () -> xmlParser.parse(ruleXmlOpenFormula));
+ () -> xmlParser.parse(ruleXmlCompoundFormula));
}
@Test
@@ -449,13 +554,16 @@
packageNameAttrs.put("K", String.valueOf(AtomicFormula.VERSION_CODE));
packageNameAttrs.put("O", String.valueOf(AtomicFormula.EQ));
packageNameAttrs.put("V", "com.app.test");
- String ruleXmlAtomicFormula = "<RL>"
- + generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ String ruleXmlAtomicFormula =
+ "<RL>"
+ + generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + "</R>"
+ + "</RL>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
@@ -469,15 +577,19 @@
Map<String, String> atomicFormulaAttrs = new HashMap<>();
atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
atomicFormulaAttrs.put("V", "com.app.test");
- String ruleXmlWithNoRuleList = generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>";
+ String ruleXmlWithNoRuleList =
+ generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
RuleParser xmlParser = new RuleXmlParser();
assertExpectException(
@@ -491,15 +603,19 @@
Map<String, String> atomicFormulaAttrs = new HashMap<>();
atomicFormulaAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
atomicFormulaAttrs.put("V", "com.app.test");
- String ruleXmlWithNoRuleList = generateTagWithAttribute(/* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
- /* closed= */ false)
- + generateTagWithAttribute(/* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
- + "</OF>"
- + "</R>";
+ String ruleXmlWithNoRuleList =
+ generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
InputStream inputStream = new ByteArrayInputStream(ruleXmlWithNoRuleList.getBytes());
RuleParser xmlParser = new RuleXmlParser();
@@ -509,8 +625,8 @@
() -> xmlParser.parse(inputStream));
}
- private String generateTagWithAttribute(String tag, Map<String, String> attributeValues,
- boolean closed) {
+ private String generateTagWithAttribute(
+ String tag, Map<String, String> attributeValues, boolean closed) {
StringBuilder res = new StringBuilder("<");
res.append(tag);
for (String attribute : attributeValues.keySet()) {
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index 7eac0b9..40e89ba 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -20,13 +20,13 @@
import static org.junit.Assert.assertEquals;
-import androidx.annotation.NonNull;
+import android.content.integrity.AppInstallMetadata;
+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.AppInstallMetadata;
-import com.android.server.integrity.model.AtomicFormula;
-import com.android.server.integrity.model.Formula;
-import com.android.server.integrity.model.OpenFormula;
-import com.android.server.integrity.model.Rule;
+import androidx.annotation.NonNull;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -80,7 +80,7 @@
@Test
public void testXmlStream_serializeValidOpenFormula() throws Exception {
- Rule rule = new Rule(new OpenFormula(OpenFormula.NOT,
+ Rule rule = new Rule(new CompoundFormula(CompoundFormula.NOT,
Collections.singletonList(
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
"com.app.test", /* isHashedValue= */ false))), Rule.DENY);
@@ -95,7 +95,7 @@
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
@@ -110,7 +110,7 @@
@Test
public void testXmlString_serializeValidOpenFormula_notConnector() throws Exception {
- Rule rule = new Rule(new OpenFormula(OpenFormula.NOT,
+ Rule rule = new Rule(new CompoundFormula(CompoundFormula.NOT,
Collections.singletonList(
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
"com.app.test", /* isHashedValue= */ false))), Rule.DENY);
@@ -124,7 +124,7 @@
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
@@ -138,7 +138,7 @@
@Test
public void testXmlString_serializeValidOpenFormula_andConnector() throws Exception {
- Rule rule = new Rule(new OpenFormula(OpenFormula.AND,
+ Rule rule = new Rule(new CompoundFormula(CompoundFormula.AND,
Arrays.asList(new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
"com.app.test", /* isHashedValue= */ false),
new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE,
@@ -157,7 +157,7 @@
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.AND)),
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
@@ -172,7 +172,7 @@
@Test
public void testXmlString_serializeValidOpenFormula_orConnector() throws Exception {
- Rule rule = new Rule(new OpenFormula(OpenFormula.OR,
+ Rule rule = new Rule(new CompoundFormula(CompoundFormula.OR,
Arrays.asList(new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
"com.app.test", /* isHashedValue= */ false),
new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE,
@@ -191,7 +191,7 @@
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(OpenFormula.OR)),
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.OR)),
/* closed= */ false)
+ generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)