diff options
33 files changed, 1118 insertions, 482 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index adfda2fe527a..83c03a363482 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1453,6 +1453,7 @@ package android.content { 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 @@ package android.content { 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 { } +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 0fdb51359cf9..0c6fdc079321 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4917,6 +4917,14 @@ public abstract class Context { 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 ca374f938f1e..40aca0ef2033 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -4417,6 +4417,22 @@ public class Intent implements Parcelable, Cloneable { @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 index dfc373bb97dc..c9634758f63f 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 000000000000..e53ef66020f1 --- /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 index a16f6b9b5970..c8e164f1f232 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 index f7ea9208f7fe..53a99534906c 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.List; 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 @@ import java.util.Objects; */ @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 @@ public final class OpenFormula implements Formula, Parcelable { 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 @@ public final class OpenFormula implements Formula, Parcelable { * @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 @@ public final class OpenFormula implements Formula, Parcelable { @Override public int getTag() { - return Formula.OPEN_FORMULA_TAG; + return Formula.COMPOUND_FORMULA_TAG; } @Override @@ -160,7 +161,7 @@ public final class OpenFormula implements Formula, Parcelable { 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 @@ public final class OpenFormula implements Formula, Parcelable { } 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 index 67698277800f..030ff6b66e1f 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 @@ import java.lang.annotation.RetentionPolicy; 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 @@ public interface Formula { @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 @@ public interface Formula { 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 000000000000..6b73fd70bb99 --- /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 000000000000..a6634ee67905 --- /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 index 3ad876292ab4..914f1479edf3 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 000000000000..a78f8c97d553 --- /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 220fdd2e889d..c3f4384b46d3 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 74bb2cf6658d..2ede8d1de983 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 1d5133901064..15de2f463430 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 index 988e18b8e194..e48f1c3a89c7 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 @@ public class AtomicFormulaTest { @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 @@ public class AtomicFormulaTest { 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 @@ public class AtomicFormulaTest { 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 @@ public class AtomicFormulaTest { 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 @@ public class AtomicFormulaTest { @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 @@ public class AtomicFormulaTest { @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 index b58ffd7dd6c6..927e4dbb5200 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.Arrays; 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 @@ public class OpenFormulaTest { /* 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 @@ public class OpenFormulaTest { /* 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 index cad392826d42..19e74e6b93cc 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 @@ public class RuleTest { @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 class RuleTest { 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 000000000000..2920716f5d5d --- /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 000000000000..af984cf318f5 --- /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 f0bb192e3b61..b8202b6c0dc6 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 @@ import java.util.List; /** * 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 @@ public final class RuleEvaluationEngine { // 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 @@ public final class RuleEvaluationEngine { * 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 7deae466ac3f..ee51d4f87848 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 @@ final class RuleEvaluator { 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 af24d7a21dc8..4ba2bfb00d05 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 ef0751d329d0..b3cb31ac8cb1 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 5ed282cd8b1f..111b95a05d24 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 08e0a5db8c20..4e1f9141c8ed 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 1508c273f553..1212a083bfaa 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.ArrayList; 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 @@ public final class RuleXmlParser implements RuleParser { // 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 @@ public final class RuleXmlParser implements RuleParser { 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 @@ public final class RuleXmlParser implements RuleParser { } } - 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 @@ public final class RuleXmlParser implements RuleParser { 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 ee95d2bb4d69..ace15bdfb028 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 5c99c5a4c2da..c45f6beeffe1 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 f2ba756ee0d1..5dd7891d15f9 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.io.StringWriter; 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 @@ public class RuleXmlSerializer implements RuleSerializer { 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 d6773d45c5ed..7a070ee72b5d 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 com.android.server.integrity.model.IntegrityCheckResult.Effect.DEN 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 class RuleEvaluatorTest { 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 class RuleEvaluatorTest { 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 class RuleEvaluatorTest { 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 @@ public class RuleEvaluatorTest { @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 @@ public class RuleEvaluatorTest { @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 @@ public class RuleEvaluatorTest { @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 @@ public class RuleEvaluatorTest { } @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 class RuleEvaluatorTest { 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 7d71cd4c1b7f..495923d9ccf9 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.android.server.testutils.TestUtils.assertExpectException; 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 @@ import java.util.Map; 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 @@ public class RuleXmlParserTest { } @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); - - List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula); + 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(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); - - List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula); + 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(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); - - List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula); + 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(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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { } @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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { 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 @@ public class RuleXmlParserTest { () -> 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 7eac0b912bf8..40e89ba1e9c7 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 com.android.server.testutils.TestUtils.assertExpectException; 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 @@ public class RuleXmlSerializerTest { @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 @@ public class RuleXmlSerializerTest { 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 @@ public class RuleXmlSerializerTest { @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 @@ public class RuleXmlSerializerTest { 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 @@ public class RuleXmlSerializerTest { @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 @@ public class RuleXmlSerializerTest { 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 @@ public class RuleXmlSerializerTest { @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 @@ public class RuleXmlSerializerTest { 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) |