diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java index 8a8485ad5771f..9cb7533e43ac5 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BooleanPolicySerializer.java @@ -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 { @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; + } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 61d93c7ce655d..775e3d8334039 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -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 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 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); + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java index 3152f0ba1f262..d5949dda8b300 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/IntegerPolicySerializer.java @@ -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 { @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; + } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicy.java b/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicy.java index 9360fd790ab10..d3e8de488e0b1 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicy.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/LockTaskPolicy.java @@ -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 mPackages; - private int mFlags; + static final int DEFAULT_LOCK_TASK_FLAG = DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS; + private Set mPackages = new HashSet<>(); + private int mFlags = DEFAULT_LOCK_TASK_FLAG; - LockTaskPolicy(@Nullable Set packages, int flags) { - mPackages = packages; - mFlags = flags; - } - - @Nullable + @NonNull Set getPackages() { return mPackages; } @@ -45,14 +45,33 @@ final class LockTaskPolicy { return mFlags; } - void setPackages(Set packages) { - mPackages = packages; + LockTaskPolicy(Set packages) { + Objects.requireNonNull(packages); + mPackages.addAll(packages); + } + + private LockTaskPolicy(Set packages, int flags) { + Objects.requireNonNull(packages); + mPackages = new HashSet<>(packages); + mFlags = flags; + } + + void setPackages(@NonNull Set 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 { 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 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 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; + } } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java index 3a18cb9c244fd..a787a0b3943bc 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java @@ -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 { 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); } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java index b645b979ef0c5..74b6f9ea114f6 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java @@ -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 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; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java index b3259d34bd3f4..528d3b0c8055e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicySerializer.java @@ -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 { - 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); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java index 5fc3cb00e57f9..d3dee98cf7ba9 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java @@ -40,7 +40,7 @@ final class PolicyState { private static final String ATTR_RESOLVED_POLICY = "resolved-policy"; private final PolicyDefinition mPolicyDefinition; - private final LinkedHashMap mAdminsPolicy = new LinkedHashMap<>(); + private final LinkedHashMap mPoliciesSetByAdmins = new LinkedHashMap<>(); private V mCurrentResolvedPolicy; PolicyState(@NonNull PolicyDefinition policyDefinition) { @@ -49,13 +49,13 @@ final class PolicyState { private PolicyState( @NonNull PolicyDefinition policyDefinition, - @NonNull LinkedHashMap adminsPolicy, + @NonNull LinkedHashMap 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 { * 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 { boolean removePolicy(@NonNull EnforcingAdmin admin) { Objects.requireNonNull(admin); - if (mAdminsPolicy.remove(admin) == null) { + if (mPoliciesSetByAdmins.remove(admin) == null) { return false; } return resolvePolicy(); } + LinkedHashMap 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 { 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);