Merge "Add public API and stub implementations for app integrity manager (service)."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ca4f0580fe
@@ -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 {
|
||||
|
||||
@@ -4908,6 +4908,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.
|
||||
|
||||
@@ -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()).
|
||||
|
||||
@@ -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;
|
||||
103
core/java/android/content/integrity/AppIntegrityManager.java
Normal file
103
core/java/android/content/integrity/AppIntegrityManager.java
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
@@ -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();
|
||||
}
|
||||
19
core/java/android/content/integrity/Rule.aidl
Normal file
19
core/java/android/content/integrity/Rule.aidl
Normal file
@@ -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;
|
||||
@@ -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;
|
||||
92
core/java/android/content/integrity/RuleSet.java
Normal file
92
core/java/android/content/integrity/RuleSet.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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" />
|
||||
|
||||
@@ -4173,4 +4173,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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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. */
|
||||
@@ -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();
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "FrameworksCoreTests",
|
||||
"options": [
|
||||
{
|
||||
"include-filter": "android.content.integrity."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
Rule expectedRule =
|
||||
new Rule(
|
||||
new CompoundFormula(
|
||||
CompoundFormula.NOT,
|
||||
Collections.singletonList(
|
||||
new AtomicFormula.StringAtomicFormula(
|
||||
AtomicFormula.PACKAGE_NAME,
|
||||
"com.app.test",
|
||||
/* isHashedValue= */ false))),
|
||||
Rule.DENY);
|
||||
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
|
||||
|
||||
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXmlString_validOpenFormula_andConnector() throws Exception {
|
||||
public void testXmlString_validCompoundFormula_andConnector() throws Exception {
|
||||
Map<String, String> packageNameAttrs = new HashMap<>();
|
||||
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
|
||||
packageNameAttrs.put("V", "com.app.test");
|
||||
Map<String, String> appCertificateAttrs = new HashMap<>();
|
||||
appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
|
||||
appCertificateAttrs.put("V", "test_cert");
|
||||
String ruleXmlOpenFormula = "<RL>"
|
||||
+ generateTagWithAttribute(/* tag= */ "R",
|
||||
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(/* tag= */ "OF",
|
||||
Collections.singletonMap("C", String.valueOf(OpenFormula.AND)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
|
||||
+ generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
|
||||
+ "</OF>"
|
||||
+ "</R>"
|
||||
+ "</RL>";
|
||||
String ruleXmlCompoundFormula =
|
||||
"<RL>"
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "R",
|
||||
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "OF",
|
||||
Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
|
||||
+ "</OF>"
|
||||
+ "</R>"
|
||||
+ "</RL>";
|
||||
RuleParser xmlParser = new RuleXmlParser();
|
||||
Rule expectedRule = new Rule(new OpenFormula(OpenFormula.AND, Arrays.asList(
|
||||
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
|
||||
/* isHashedValue= */ false),
|
||||
new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert",
|
||||
/* isHashedValue= */ false))),
|
||||
Rule.DENY);
|
||||
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
|
||||
Rule expectedRule =
|
||||
new Rule(
|
||||
new CompoundFormula(
|
||||
CompoundFormula.AND,
|
||||
Arrays.asList(
|
||||
new AtomicFormula.StringAtomicFormula(
|
||||
AtomicFormula.PACKAGE_NAME,
|
||||
"com.app.test",
|
||||
/* isHashedValue= */ false),
|
||||
new AtomicFormula.StringAtomicFormula(
|
||||
AtomicFormula.APP_CERTIFICATE,
|
||||
"test_cert",
|
||||
/* isHashedValue= */ false))),
|
||||
Rule.DENY);
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
|
||||
|
||||
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXmlString_validOpenFormula_orConnector() throws Exception {
|
||||
public void testXmlString_validCompoundFormula_orConnector() throws Exception {
|
||||
Map<String, String> packageNameAttrs = new HashMap<>();
|
||||
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
|
||||
packageNameAttrs.put("V", "com.app.test");
|
||||
Map<String, String> appCertificateAttrs = new HashMap<>();
|
||||
appCertificateAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
|
||||
appCertificateAttrs.put("V", "test_cert");
|
||||
String ruleXmlOpenFormula = "<RL>"
|
||||
+ generateTagWithAttribute(/* tag= */ "R",
|
||||
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(/* tag= */ "OF",
|
||||
Collections.singletonMap("C", String.valueOf(OpenFormula.OR)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
|
||||
+ generateTagWithAttribute(/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
|
||||
+ "</OF>"
|
||||
+ "</R>"
|
||||
+ "</RL>";
|
||||
String ruleXmlCompoundFormula =
|
||||
"<RL>"
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "R",
|
||||
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "OF",
|
||||
Collections.singletonMap("C", String.valueOf(CompoundFormula.OR)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
|
||||
+ "</OF>"
|
||||
+ "</R>"
|
||||
+ "</RL>";
|
||||
RuleParser xmlParser = new RuleXmlParser();
|
||||
Rule expectedRule = new Rule(new OpenFormula(OpenFormula.OR, Arrays.asList(
|
||||
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
|
||||
/* isHashedValue= */ false),
|
||||
new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, "test_cert",
|
||||
/* isHashedValue= */ false))),
|
||||
Rule.DENY);
|
||||
Rule expectedRule =
|
||||
new Rule(
|
||||
new CompoundFormula(
|
||||
CompoundFormula.OR,
|
||||
Arrays.asList(
|
||||
new AtomicFormula.StringAtomicFormula(
|
||||
AtomicFormula.PACKAGE_NAME,
|
||||
"com.app.test",
|
||||
/* isHashedValue= */ false),
|
||||
new AtomicFormula.StringAtomicFormula(
|
||||
AtomicFormula.APP_CERTIFICATE,
|
||||
"test_cert",
|
||||
/* isHashedValue= */ false))),
|
||||
Rule.DENY);
|
||||
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
|
||||
|
||||
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXmlString_validOpenFormula_differentTagOrder() throws Exception {
|
||||
public void testXmlString_validCompoundFormula_differentTagOrder() throws Exception {
|
||||
Map<String, String> packageNameAttrs = new HashMap<>();
|
||||
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
|
||||
packageNameAttrs.put("V", "com.app.test");
|
||||
String ruleXmlOpenFormula = "<RL>"
|
||||
+ generateTagWithAttribute(/* tag= */ "R",
|
||||
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(/* tag= */ "OF",
|
||||
Collections.singletonMap("C", String.valueOf(OpenFormula.NOT)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
|
||||
+ "</OF>"
|
||||
+ "</R>"
|
||||
+ "</RL>";
|
||||
String ruleXmlCompoundFormula =
|
||||
"<RL>"
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "R",
|
||||
Collections.singletonMap("E", String.valueOf(Rule.DENY)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "OF",
|
||||
Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
|
||||
/* closed= */ false)
|
||||
+ generateTagWithAttribute(
|
||||
/* tag= */ "AF", packageNameAttrs, /* closed= */ true)
|
||||
+ "</OF>"
|
||||
+ "</R>"
|
||||
+ "</RL>";
|
||||
RuleParser xmlParser = new RuleXmlParser();
|
||||
Rule expectedRule = new Rule(new OpenFormula(OpenFormula.NOT, Collections.singletonList(
|
||||
new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, "com.app.test",
|
||||
/* isHashedValue= */ false))),
|
||||
Rule.DENY);
|
||||
Rule expectedRule =
|
||||
new Rule(
|
||||
new CompoundFormula(
|
||||
CompoundFormula.NOT,
|
||||
Collections.singletonList(
|
||||
new AtomicFormula.StringAtomicFormula(
|
||||
AtomicFormula.PACKAGE_NAME,
|
||||
"com.app.test",
|
||||
/* isHashedValue= */ false))),
|
||||
Rule.DENY);
|
||||
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlOpenFormula);
|
||||
List<Rule> rules = xmlParser.parse(ruleXmlCompoundFormula);
|
||||
|
||||
assertThat(rules).isEqualTo(Collections.singletonList(expectedRule));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testXmlString_invalidOpenFormula_invalidNumberOfFormulas() throws Exception {
|
||||
public void testXmlString_invalidCompoundFormula_invalidNumberOfFormulas() throws Exception {
|
||||
Map<String, String> packageNameAttrs = new HashMap<>();
|
||||
packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
|
||||
packageNameAttrs.put("V", "com.app.test");
|
||||
@@ -196,98 +251,116 @@ 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()) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user