Merge "Add public API and stub implementations for app integrity manager (service)."

This commit is contained in:
TreeHugger Robot
2019-11-26 20:31:33 +00:00
committed by Android (Google) Code Review
33 changed files with 1115 additions and 479 deletions

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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()).

View File

@@ -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;

View 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();
}
}
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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:

View File

@@ -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();
}

View 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;

View File

@@ -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;

View 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);
}
}
}

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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);

View File

@@ -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. */

View File

@@ -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();

View File

@@ -0,0 +1,12 @@
{
"presubmit": [
{
"name": "FrameworksCoreTests",
"options": [
{
"include-filter": "android.content.integrity."
}
]
}
]
}

View File

@@ -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");
}
}

View File

@@ -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) {

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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:

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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()) {

View File

@@ -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)