Merge changes Idb1d2d27,I60837e40

* changes:
  Migrate lock task policy APIs to coexistence
  Call device policy engine from DPMS
This commit is contained in:
Kholoud Mohamed
2022-11-30 10:41:12 +00:00
committed by Android (Google) Code Review
8 changed files with 292 additions and 80 deletions

View File

@@ -16,24 +16,35 @@
package com.android.server.devicepolicy;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.Objects;
final class BooleanPolicySerializer extends PolicySerializer<Boolean> {
@Override
void saveToXml(TypedXmlSerializer serializer, String attributeName, Boolean value)
void saveToXml(TypedXmlSerializer serializer, String attributeName, @NonNull Boolean value)
throws IOException {
Objects.requireNonNull(value);
serializer.attributeBoolean(/* namespace= */ null, attributeName, value);
}
@Nullable
@Override
Boolean readFromXml(TypedXmlPullParser parser, String attributeName)
throws XmlPullParserException {
return parser.getAttributeBoolean(/* namespace= */ null, attributeName);
Boolean readFromXml(TypedXmlPullParser parser, String attributeName) {
try {
return parser.getAttributeBoolean(/* namespace= */ null, attributeName);
} catch (XmlPullParserException e) {
Log.e(DevicePolicyEngine.TAG, "Error parsing Boolean policy value", e);
return null;
}
}
}

View File

@@ -81,6 +81,7 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.app.admin.DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED;
import static android.app.admin.DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY;
import static android.app.admin.DevicePolicyManager.PERSONAL_APPS_SUSPENDED_PROFILE_TIMEOUT;
@@ -140,6 +141,7 @@ import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.provider.DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Settings.Secure.MANAGED_PROVISIONING_DPC_DOWNLOADED;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
@@ -309,6 +311,7 @@ import android.permission.PermissionControllerManager;
import android.provider.CalendarContract;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsInternal;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.provider.Telephony;
@@ -712,6 +715,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
+ "management app's authentication policy";
private static final String NOT_SYSTEM_CALLER_MSG = "Only the system can %s";
private static final String ENABLE_COEXISTENCE_FLAG = "enable_coexistence";
private static final boolean DEFAULT_ENABLE_COEXISTENCE_FLAG = false;
/**
* For apps targeting U+
* Enable multiple admins to coexist on the same device.
*/
@ChangeId
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
static final long ENABLE_COEXISTENCE_CHANGE = 260560985L;
final Context mContext;
final Injector mInjector;
final PolicyPathProvider mPathProvider;
@@ -795,6 +809,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private final DeviceManagementResourcesProvider mDeviceManagementResourcesProvider;
private final DevicePolicyManagementRoleObserver mDevicePolicyManagementRoleObserver;
private final DevicePolicyEngine mDevicePolicyEngine;
private static final boolean ENABLE_LOCK_GUARD = true;
/**
@@ -1864,6 +1880,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mUserData = new SparseArray<>();
mOwners = makeOwners(injector, pathProvider);
mDevicePolicyEngine = new DevicePolicyEngine(mContext);
if (!mHasFeature) {
// Skip the rest of the initialization
mSetupContentObserver = null;
@@ -1908,6 +1926,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener());
mDeviceManagementResourcesProvider.load();
if (isCoexistenceFlagEnabled()) {
mDevicePolicyEngine.load();
}
// The binder caches are not enabled until the first invalidation.
invalidateBinderCaches();
@@ -7951,8 +7972,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
mInjector.binderWithCleanCallingIdentity(() ->
mInjector.settingsGlobalPutInt(Global.AUTO_TIME_ZONE, enabled ? 1 : 0));
if (isCoexistenceEnabled(caller)) {
mDevicePolicyEngine.setGlobalPolicy(
PolicyDefinition.AUTO_TIMEZONE,
// TODO(b/260573124): add correct enforcing admin when permission changes are
// merged.
EnforcingAdmin.createEnterpriseEnforcingAdmin(caller.getComponentName()),
enabled);
} else {
mInjector.binderWithCleanCallingIdentity(() ->
mInjector.settingsGlobalPutInt(Global.AUTO_TIME_ZONE, enabled ? 1 : 0));
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_AUTO_TIME_ZONE)
@@ -12245,8 +12275,38 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(caller);
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_PACKAGES);
final int userHandle = caller.getUserId();
setLockTaskPackagesLocked(userHandle, new ArrayList<>(Arrays.asList(packages)));
}
if (isCoexistenceEnabled(caller)) {
EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(who);
if (packages.length == 0) {
mDevicePolicyEngine.removeLocalPolicy(
PolicyDefinition.LOCK_TASK,
admin,
caller.getUserId());
} else {
LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicy(
PolicyDefinition.LOCK_TASK,
caller.getUserId()).getPoliciesSetByAdmins().get(admin);
LockTaskPolicy policy;
if (currentPolicy == null) {
policy = new LockTaskPolicy(Set.of(packages));
} else {
policy = currentPolicy.clone();
policy.setPackages(Set.of(packages));
}
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.LOCK_TASK,
EnforcingAdmin.createEnterpriseEnforcingAdmin(who),
policy,
caller.getUserId());
}
} else {
synchronized (getLockObject()) {
final int userHandle = caller.getUserId();
setLockTaskPackagesLocked(userHandle, new ArrayList<>(Arrays.asList(packages)));
}
}
}
@@ -12267,8 +12327,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(caller);
final List<String> packages = getUserData(userHandle).mLockTaskPackages;
return packages.toArray(new String[packages.size()]);
}
if (isCoexistenceEnabled(caller)) {
LockTaskPolicy policy = mDevicePolicyEngine.getLocalPolicy(
PolicyDefinition.LOCK_TASK, userHandle).getCurrentResolvedPolicy();
if (policy == null) {
return new String[0];
} else {
return policy.getPackages().toArray(new String[policy.getPackages().size()]);
}
} else {
synchronized (getLockObject()) {
final List<String> packages = getUserData(userHandle).mLockTaskPackages;
return packages.toArray(new String[packages.size()]);
}
}
}
@@ -12284,8 +12357,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final int userId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
return getUserData(userId).mLockTaskPackages.contains(pkg);
// TODO(b/260560985): This is not the right check, as the flag could be enabled but there
// could be an admin that hasn't targeted U.
if (isCoexistenceFlagEnabled()) {
LockTaskPolicy policy = mDevicePolicyEngine.getLocalPolicy(
PolicyDefinition.LOCK_TASK, userId).getCurrentResolvedPolicy();
if (policy == null) {
return false;
}
return policy.getPackages().contains(pkg);
} else {
synchronized (getLockObject()) {
return getUserData(userId).mLockTaskPackages.contains(pkg);
}
}
}
@@ -12308,7 +12392,28 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceCanCallLockTaskLocked(caller);
enforceCanSetLockTaskFeaturesOnFinancedDevice(caller, flags);
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES);
setLockTaskFeaturesLocked(userHandle, flags);
}
if (isCoexistenceEnabled(caller)) {
EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(who);
LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicy(
PolicyDefinition.LOCK_TASK,
caller.getUserId()).getPoliciesSetByAdmins().get(admin);
if (currentPolicy == null) {
throw new IllegalArgumentException("Can't set a lock task flags without setting "
+ "lock task packages first.");
}
LockTaskPolicy policy = currentPolicy.clone();
policy.setFlags(flags);
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.LOCK_TASK,
EnforcingAdmin.createEnterpriseEnforcingAdmin(who),
policy,
caller.getUserId());
} else {
synchronized (getLockObject()) {
setLockTaskFeaturesLocked(userHandle, flags);
}
}
}
@@ -12326,7 +12431,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int userHandle = caller.getUserId();
synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(caller);
return getUserData(userHandle).mLockTaskFeatures;
}
if (isCoexistenceEnabled(caller)) {
LockTaskPolicy policy = mDevicePolicyEngine.getLocalPolicy(
PolicyDefinition.LOCK_TASK, userHandle).getCurrentResolvedPolicy();
if (policy == null) {
// We default on the power button menu, in order to be consistent with pre-P
// behaviour.
return DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
}
return policy.getFlags();
} else {
synchronized (getLockObject()) {
return getUserData(userHandle).mLockTaskFeatures;
}
}
}
@@ -13905,6 +14024,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (isFinancedDeviceOwner(caller)) {
enforcePermissionGrantStateOnFinancedDevice(packageName, permission);
}
}
if (isCoexistenceEnabled(caller)) {
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.PERMISSION_GRANT(packageName, permission),
// TODO(b/260573124): Add correct enforcing admin when permission changes are
// merged, and don't forget to handle delegates! Enterprise admins assume
// component name isn't null.
EnforcingAdmin.createEnterpriseEnforcingAdmin(caller.getComponentName()),
grantState,
caller.getUserId());
// TODO: update javadoc to reflect that callback no longer return success/failure
callback.sendResult(Bundle.EMPTY);
} else {
synchronized (getLockObject()) {
long ident = mInjector.binderClearCallingIdentity();
try {
boolean isPostQAdmin = getTargetSdk(caller.getPackageName(), caller.getUserId())
@@ -13921,14 +14054,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
callback.sendResult(null);
return;
}
if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
if (grantState == PERMISSION_GRANT_STATE_GRANTED
|| grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
|| grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT) {
AdminPermissionControlParams permissionParams =
new AdminPermissionControlParams(packageName, permission, grantState,
new AdminPermissionControlParams(packageName, permission,
grantState,
canAdminGrantSensorsPermissionsForUser(caller.getUserId()));
mInjector.getPermissionControllerManager(caller.getUserHandle())
.setRuntimePermissionGrantStateByDeviceAdmin(caller.getPackageName(),
.setRuntimePermissionGrantStateByDeviceAdmin(
caller.getPackageName(),
permissionParams, mContext.getMainExecutor(),
(permissionWasSet) -> {
if (isPostQAdmin && !permissionWasSet) {
@@ -13947,13 +14082,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
callback.sendResult(Bundle.EMPTY);
});
}
} catch (SecurityException e) {
Slogf.e(LOG_TAG, "Could not set permission grant state", e);
}
} catch (SecurityException e) {
Slogf.e(LOG_TAG, "Could not set permission grant state", e);
callback.sendResult(null);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
callback.sendResult(null);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
}
}
}
@@ -19017,4 +19153,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return result;
});
}
// TODO(b/260560985): properly gate coexistence changes
private boolean isCoexistenceEnabled(CallerIdentity caller) {
return isCoexistenceFlagEnabled()
&& mInjector.isChangeEnabled(
ENABLE_COEXISTENCE_CHANGE, caller.getPackageName(), caller.getUserId());
}
private boolean isCoexistenceFlagEnabled() {
return DeviceConfig.getBoolean(
NAMESPACE_DEVICE_POLICY_MANAGER,
ENABLE_COEXISTENCE_FLAG,
DEFAULT_ENABLE_COEXISTENCE_FLAG);
}
}

View File

@@ -16,24 +16,35 @@
package com.android.server.devicepolicy;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.Objects;
final class IntegerPolicySerializer extends PolicySerializer<Integer> {
@Override
void saveToXml(TypedXmlSerializer serializer, String attributeName, Integer value)
void saveToXml(TypedXmlSerializer serializer, String attributeName, @NonNull Integer value)
throws IOException {
Objects.requireNonNull(value);
serializer.attributeInt(/* namespace= */ null, attributeName, value);
}
@Nullable
@Override
Integer readFromXml(TypedXmlPullParser parser, String attributeName)
throws XmlPullParserException {
return parser.getAttributeInt(/* namespace= */ null, attributeName);
Integer readFromXml(TypedXmlPullParser parser, String attributeName) {
try {
return parser.getAttributeInt(/* namespace= */ null, attributeName);
} catch (XmlPullParserException e) {
Log.e(DevicePolicyEngine.TAG, "Error parsing Integer policy value", e);
return null;
}
}
}

View File

@@ -16,7 +16,10 @@
package com.android.server.devicepolicy;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
import android.util.Log;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -24,19 +27,16 @@ import com.android.modules.utils.TypedXmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
final class LockTaskPolicy {
private Set<String> mPackages;
private int mFlags;
static final int DEFAULT_LOCK_TASK_FLAG = DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
private Set<String> mPackages = new HashSet<>();
private int mFlags = DEFAULT_LOCK_TASK_FLAG;
LockTaskPolicy(@Nullable Set<String> packages, int flags) {
mPackages = packages;
mFlags = flags;
}
@Nullable
@NonNull
Set<String> getPackages() {
return mPackages;
}
@@ -45,14 +45,33 @@ final class LockTaskPolicy {
return mFlags;
}
void setPackages(Set<String> packages) {
mPackages = packages;
LockTaskPolicy(Set<String> packages) {
Objects.requireNonNull(packages);
mPackages.addAll(packages);
}
private LockTaskPolicy(Set<String> packages, int flags) {
Objects.requireNonNull(packages);
mPackages = new HashSet<>(packages);
mFlags = flags;
}
void setPackages(@NonNull Set<String> packages) {
Objects.requireNonNull(packages);
mPackages = new HashSet<>(packages);
}
void setFlags(int flags) {
mFlags = flags;
}
@Override
public LockTaskPolicy clone() {
LockTaskPolicy policy = new LockTaskPolicy(mPackages);
policy.setFlags(mFlags);
return policy;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
@@ -67,6 +86,11 @@ final class LockTaskPolicy {
return Objects.hash(mPackages, mFlags);
}
@Override
public String toString() {
return "mPackages= " + String.join(", ", mPackages) + "; mFlags= " + mFlags;
}
static final class LockTaskPolicySerializer extends PolicySerializer<LockTaskPolicy> {
private static final String ATTR_PACKAGES = ":packages";
@@ -74,15 +98,17 @@ final class LockTaskPolicy {
private static final String ATTR_FLAGS = ":flags";
@Override
void saveToXml(
TypedXmlSerializer serializer, String attributeNamePrefix, LockTaskPolicy value)
throws IOException {
if (value.mPackages != null) {
serializer.attribute(
/* namespace= */ null,
attributeNamePrefix + ATTR_PACKAGES,
String.join(ATTR_PACKAGES_SEPARATOR, value.mPackages));
void saveToXml(TypedXmlSerializer serializer, String attributeNamePrefix,
@NonNull LockTaskPolicy value) throws IOException {
Objects.requireNonNull(value);
if (value.mPackages == null || value.mPackages.isEmpty()) {
throw new IllegalArgumentException("Error saving LockTaskPolicy to file, lock task "
+ "packages must be present");
}
serializer.attribute(
/* namespace= */ null,
attributeNamePrefix + ATTR_PACKAGES,
String.join(ATTR_PACKAGES_SEPARATOR, value.mPackages));
serializer.attributeInt(
/* namespace= */ null,
attributeNamePrefix + ATTR_FLAGS,
@@ -90,18 +116,24 @@ final class LockTaskPolicy {
}
@Override
LockTaskPolicy readFromXml(TypedXmlPullParser parser, String attributeNamePrefix)
throws XmlPullParserException {
LockTaskPolicy readFromXml(TypedXmlPullParser parser, String attributeNamePrefix) {
String packagesStr = parser.getAttributeValue(
/* namespace= */ null,
attributeNamePrefix + ATTR_PACKAGES);
Set<String> packages = packagesStr == null
? null
: Set.of(packagesStr.split(ATTR_PACKAGES_SEPARATOR));
int flags = parser.getAttributeInt(
/* namespace= */ null,
attributeNamePrefix + ATTR_FLAGS);
return new LockTaskPolicy(packages, flags);
if (packagesStr == null) {
Log.e(DevicePolicyEngine.TAG, "Error parsing LockTask policy value.");
return null;
}
Set<String> packages = Set.of(packagesStr.split(ATTR_PACKAGES_SEPARATOR));
try {
int flags = parser.getAttributeInt(
/* namespace= */ null,
attributeNamePrefix + ATTR_FLAGS);
return new LockTaskPolicy(packages, flags);
} catch (XmlPullParserException e) {
Log.e(DevicePolicyEngine.TAG, "Error parsing LockTask policy value", e);
return null;
}
}
}
}

View File

@@ -25,8 +25,6 @@ import com.android.internal.util.function.QuadFunction;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
@@ -225,8 +223,8 @@ final class PolicyDefinition<V> {
mPolicySerializer.saveToXml(serializer, attributeName, value);
}
V readPolicyValueFromXml(TypedXmlPullParser parser, String attributeName)
throws XmlPullParserException {
@Nullable
V readPolicyValueFromXml(TypedXmlPullParser parser, String attributeName) {
return mPolicySerializer.readFromXml(parser, attributeName);
}
}

View File

@@ -29,6 +29,7 @@ import android.provider.Settings;
import com.android.server.utils.Slogf;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
@@ -53,7 +54,7 @@ final class PolicyEnforcerCallbacks {
static boolean setPermissionGrantState(
@Nullable Integer grantState, @NonNull Context context, int userId,
@NonNull String[] args) {
Binder.withCleanCallingIdentity(() -> {
return Boolean.TRUE.equals(Binder.withCleanCallingIdentity(() -> {
if (args == null || args.length < 2) {
throw new IllegalArgumentException("Package name and permission name must be "
+ "provided as arguments");
@@ -84,8 +85,7 @@ final class PolicyEnforcerCallbacks {
// TODO: add logging
return false;
}
});
return true;
}));
}
@NonNull
@@ -106,9 +106,14 @@ final class PolicyEnforcerCallbacks {
static boolean setLockTask(
@Nullable LockTaskPolicy policy, @NonNull Context context, int userId) {
DevicePolicyManagerService.updateLockTaskPackagesLocked(
context, List.copyOf(policy.getPackages()), userId);
DevicePolicyManagerService.updateLockTaskFeaturesLocked(policy.getFlags(), userId);
List<String> packages = Collections.emptyList();
int flags = LockTaskPolicy.DEFAULT_LOCK_TASK_FLAG;
if (policy != null) {
packages = List.copyOf(policy.getPackages());
flags = policy.getFlags();
}
DevicePolicyManagerService.updateLockTaskPackagesLocked(context, packages, userId);
DevicePolicyManagerService.updateLockTaskFeaturesLocked(flags, userId);
return true;
}

View File

@@ -16,16 +16,15 @@
package com.android.server.devicepolicy;
import android.annotation.NonNull;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
abstract class PolicySerializer<V> {
abstract void saveToXml(TypedXmlSerializer serializer, String attributeName, V value)
abstract void saveToXml(TypedXmlSerializer serializer, String attributeName, @NonNull V value)
throws IOException;
abstract V readFromXml(TypedXmlPullParser parser, String attributeName)
throws XmlPullParserException;
abstract V readFromXml(TypedXmlPullParser parser, String attributeName);
}

View File

@@ -40,7 +40,7 @@ final class PolicyState<V> {
private static final String ATTR_RESOLVED_POLICY = "resolved-policy";
private final PolicyDefinition<V> mPolicyDefinition;
private final LinkedHashMap<EnforcingAdmin, V> mAdminsPolicy = new LinkedHashMap<>();
private final LinkedHashMap<EnforcingAdmin, V> mPoliciesSetByAdmins = new LinkedHashMap<>();
private V mCurrentResolvedPolicy;
PolicyState(@NonNull PolicyDefinition<V> policyDefinition) {
@@ -49,13 +49,13 @@ final class PolicyState<V> {
private PolicyState(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull LinkedHashMap<EnforcingAdmin, V> adminsPolicy,
@NonNull LinkedHashMap<EnforcingAdmin, V> policiesSetByAdmins,
V currentEnforcedPolicy) {
Objects.requireNonNull(policyDefinition);
Objects.requireNonNull(adminsPolicy);
Objects.requireNonNull(policiesSetByAdmins);
mPolicyDefinition = policyDefinition;
mAdminsPolicy.putAll(adminsPolicy);
mPoliciesSetByAdmins.putAll(policiesSetByAdmins);
mCurrentResolvedPolicy = currentEnforcedPolicy;
}
@@ -63,7 +63,7 @@ final class PolicyState<V> {
* Returns {@code true} if the resolved policy has changed, {@code false} otherwise.
*/
boolean setPolicy(@NonNull EnforcingAdmin admin, @NonNull V value) {
mAdminsPolicy.put(Objects.requireNonNull(admin), Objects.requireNonNull(value));
mPoliciesSetByAdmins.put(Objects.requireNonNull(admin), Objects.requireNonNull(value));
return resolvePolicy();
}
@@ -71,15 +71,19 @@ final class PolicyState<V> {
boolean removePolicy(@NonNull EnforcingAdmin admin) {
Objects.requireNonNull(admin);
if (mAdminsPolicy.remove(admin) == null) {
if (mPoliciesSetByAdmins.remove(admin) == null) {
return false;
}
return resolvePolicy();
}
LinkedHashMap<EnforcingAdmin, V> getPoliciesSetByAdmins() {
return mPoliciesSetByAdmins;
}
private boolean resolvePolicy() {
V resolvedPolicy = mPolicyDefinition.resolvePolicy(mAdminsPolicy);
V resolvedPolicy = mPolicyDefinition.resolvePolicy(mPoliciesSetByAdmins);
boolean policyChanged = !Objects.equals(resolvedPolicy, mCurrentResolvedPolicy);
mCurrentResolvedPolicy = resolvedPolicy;
@@ -94,14 +98,16 @@ final class PolicyState<V> {
void saveToXml(TypedXmlSerializer serializer) throws IOException {
mPolicyDefinition.saveToXml(serializer);
mPolicyDefinition.savePolicyValueToXml(
serializer, ATTR_RESOLVED_POLICY, mCurrentResolvedPolicy);
if (mCurrentResolvedPolicy != null) {
mPolicyDefinition.savePolicyValueToXml(
serializer, ATTR_RESOLVED_POLICY, mCurrentResolvedPolicy);
}
for (EnforcingAdmin admin : mAdminsPolicy.keySet()) {
for (EnforcingAdmin admin : mPoliciesSetByAdmins.keySet()) {
serializer.startTag(/* namespace= */ null, TAG_ADMIN_POLICY_ENTRY);
mPolicyDefinition.savePolicyValueToXml(
serializer, ATTR_POLICY_VALUE, mAdminsPolicy.get(admin));
serializer, ATTR_POLICY_VALUE, mPoliciesSetByAdmins.get(admin));
serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMIN_ENTRY);
admin.saveToXml(serializer);