Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +56 −16 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.app.admin.PolicyUpdateResult.RESULT_SUCCESS; import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_TARGET_USER_ID; import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY; import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT; import static android.provider.DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER; import android.Manifest; import android.annotation.NonNull; Loading @@ -42,6 +43,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; import android.util.AtomicFile; import android.util.Log; import android.util.SparseArray; Loading Loading @@ -74,6 +76,9 @@ import java.util.Set; final class DevicePolicyEngine { static final String TAG = "DevicePolicyEngine"; private static final String ENABLE_COEXISTENCE_FLAG = "enable_coexistence"; private static final boolean DEFAULT_ENABLE_COEXISTENCE_FLAG = true; private final Context mContext; private final UserManager mUserManager; Loading Loading @@ -820,7 +825,7 @@ final class DevicePolicyEngine { * each admin. Global policies are returned under {@link UserHandle#ALL}. */ @NonNull DevicePolicyState getParcelablePoliciesStateMap() { DevicePolicyState getDevicePolicyState() { Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies = new HashMap<>(); for (int i = 0; i < mLocalPolicies.size(); i++) { Loading Loading @@ -869,11 +874,6 @@ final class DevicePolicyEngine { private void updateDeviceAdminServiceOnPolicyAddLocked(@NonNull EnforcingAdmin enforcingAdmin) { int userId = enforcingAdmin.getUserId(); // A connection is established with DPCs as soon as they are provisioned, so no need to // connect when a policy is set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } if (mEnforcingAdmins.contains(userId) && mEnforcingAdmins.get(userId).contains(enforcingAdmin)) { return; Loading @@ -884,6 +884,11 @@ final class DevicePolicyEngine { } mEnforcingAdmins.get(enforcingAdmin.getUserId()).add(enforcingAdmin); // A connection is established with DPCs as soon as they are provisioned, so no need to // connect when a policy is set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } mDeviceAdminServiceController.startServiceForAdmin( enforcingAdmin.getPackageName(), userId, Loading @@ -896,18 +901,10 @@ final class DevicePolicyEngine { */ private void updateDeviceAdminServiceOnPolicyRemoveLocked( @NonNull EnforcingAdmin enforcingAdmin) { // TODO(b/263364434): centralise handling in one place. // DPCs rely on a constant connection being established as soon as they are provisioned, // so we shouldn't disconnect it even if they no longer have policies set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } if (doesAdminHavePolicies(enforcingAdmin)) { return; } int userId = enforcingAdmin.getUserId(); if (mEnforcingAdmins.contains(userId)) { mEnforcingAdmins.get(userId).remove(enforcingAdmin); if (mEnforcingAdmins.get(userId).isEmpty()) { Loading @@ -915,6 +912,12 @@ final class DevicePolicyEngine { } } // TODO(b/263364434): centralise handling in one place. // DPCs rely on a constant connection being established as soon as they are provisioned, // so we shouldn't disconnect it even if they no longer have policies set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } mDeviceAdminServiceController.stopServiceForAdmin( enforcingAdmin.getPackageName(), userId, Loading Loading @@ -968,14 +971,51 @@ final class DevicePolicyEngine { } } // TODO: we need to listen for user removal and package removal and update out internal policy // map and enforcing admins for this is be accurate. boolean hasActivePolicies() { return mEnforcingAdmins.size() > 0; } /** * Returns {@code true} if the coexistence flag is enabled or: * <ul> * <li>If the provided package is an admin with existing policies * <li>A new admin and no other admin have policies set * <li>More than one admin have policies set */ boolean canAdminAddPolicies(String packageName, int userId) { if (isCoexistenceFlagEnabled()) { return true; } if (mEnforcingAdmins.contains(userId) && mEnforcingAdmins.get(userId).stream().anyMatch(admin -> admin.getPackageName().equals(packageName))) { return true; } int numOfEnforcingAdmins = 0; for (int i = 0; i < mEnforcingAdmins.size(); i++) { numOfEnforcingAdmins += mEnforcingAdmins.get(i).size(); } return numOfEnforcingAdmins == 0 || numOfEnforcingAdmins > 1; } private boolean isCoexistenceFlagEnabled() { return DeviceConfig.getBoolean( NAMESPACE_DEVICE_POLICY_MANAGER, ENABLE_COEXISTENCE_FLAG, DEFAULT_ENABLE_COEXISTENCE_FLAG); } private class DevicePoliciesReaderWriter { private static final String DEVICE_POLICIES_XML = "device_policies.xml"; private static final String DEVICE_POLICIES_XML = "device_policy_state.xml"; private static final String TAG_LOCAL_POLICY_ENTRY = "local-policy-entry"; private static final String TAG_GLOBAL_POLICY_ENTRY = "global-policy-entry"; private static final String TAG_ADMINS_POLICY_ENTRY = "admins-policy-entry"; private static final String TAG_ENFORCING_ADMINS_ENTRY = "enforcing-admins-entry"; private static final String ATTR_USER_ID = "user-id"; private static final String ATTR_POLICY_ID = "policy-id"; private final File mFile; Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +166 −40 Original line number Diff line number Diff line Loading @@ -745,11 +745,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + "management app's authentication policy"; private static final String NOT_SYSTEM_CALLER_MSG = "Only the system can %s"; // ENABLE_DEVICE_POLICY_ENGINE_FLAG must be enabled before this could be enabled. private static final String PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG = "enable_permission_based_access"; private static final String ENABLE_COEXISTENCE_FLAG = "enable_coexistence"; private static final boolean DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG = false; private static final boolean DEFAULT_ENABLE_COEXISTENCE_FLAG = false; // This must be enabled before PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG is enabled, the reason // we're not just relying on PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG to enable the policy engine // is that we might want to enable it before the permission changes are ready if we want to test // it on DPCs. // Once this is enabled, it can no longer be disabled in production private static final String ENABLE_DEVICE_POLICY_ENGINE_FLAG = "enable_device_policy_engine"; private static final boolean DEFAULT_ENABLE_DEVICE_POLICY_ENGINE_FLAG = false; // TODO(b/258425381) remove the flag after rollout. private static final String KEEP_PROFILES_RUNNING_FLAG = "enable_keep_profiles_running"; Loading Loading @@ -1309,10 +1316,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { && (owner.getPackageName().equals(packageName))) { startOwnerService(userHandle, "package-broadcast"); } if (isCoexistenceFlagEnabled()) { if (shouldMigrateToDevicePolicyEngine()) { migratePoliciesToDevicePolicyEngine(); } if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handlePackageChanged(packageName, userHandle); } // Persist updates if the removed package was an admin or delegate. if (removedAdmin || removedDelegate) { saveSettingsLocked(policy.mUserId); Loading Loading @@ -2002,7 +2011,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener()); mDeviceManagementResourcesProvider.load(); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.load(); } Loading Loading @@ -3133,6 +3142,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (getLockObject()) { migrateToProfileOnOrganizationOwnedDeviceIfCompLocked(); applyProfileRestrictionsIfDeviceOwnerLocked(); // TODO: Is this the right place to trigger the migration? if (shouldMigrateToDevicePolicyEngine()) { migratePoliciesToDevicePolicyEngine(); } } maybeStartSecurityLogMonitorOnActivityManagerReady(); break; Loading Loading @@ -3341,7 +3355,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { updateNetworkPreferenceForUser(userId, preferentialNetworkServiceConfigs); startOwnerService(userId, "start-user"); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleStartUser(userId); } } Loading @@ -3366,7 +3380,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { void handleUnlockUser(int userId) { startOwnerService(userId, "unlock-user"); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleUnlockUser(userId); } } Loading @@ -3378,7 +3392,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { void handleStopUser(int userId) { updateNetworkPreferenceForUser(userId, List.of(PreferentialNetworkServiceConfig.DEFAULT)); mDeviceAdminServiceController.stopServicesForUser(userId, /* actionForLog= */ "stop-user"); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleStopUser(userId); } } Loading Loading @@ -3486,7 +3500,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * @param refreshing true = update an active admin, no error */ @Override public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) { public void setActiveAdmin( ComponentName adminReceiver, boolean refreshing, int userHandle) { if (!mHasFeature) { return; } Loading @@ -3503,6 +3518,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (getLockObject()) { checkActiveAdminPrecondition(adminReceiver, info, policy); mInjector.binderWithCleanCallingIdentity(() -> { if (!canAddActiveAdminIfPolicyEngineEnabled( adminReceiver.getPackageName(), userHandle)) { throw new IllegalStateException("Can't add non-coexistable admin."); } final ActiveAdmin existingAdmin = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (!refreshing && existingAdmin != null) { Loading Loading @@ -8246,7 +8266,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { caller)); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { mDevicePolicyEngine.setGlobalPolicy( PolicyDefinition.AUTO_TIMEZONE, // TODO(b/260573124): add correct enforcing admin when permission changes are Loading Loading @@ -10356,7 +10376,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller)); final int userHandle = caller.getUserId(); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { mDevicePolicyEngine.setLocalPolicy( PolicyDefinition.PERSISTENT_PREFERRED_ACTIVITY(filter), EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle), Loading Loading @@ -10394,7 +10414,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int userHandle = caller.getUserId(); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { clearPackagePersistentPreferredActivitiesFromPolicyEngine( EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle), packageName, Loading Loading @@ -11348,7 +11368,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int userId = user.id; if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleUserCreated(user); } Loading Loading @@ -12378,7 +12398,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { || isFinancedDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_BLOCK_UNINSTALL))); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, DELEGATION_BLOCK_UNINSTALL)) { // 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. Loading Loading @@ -12942,7 +12962,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_PACKAGES); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin( who, caller.getUserId()); if (packages.length == 0) { Loading Loading @@ -12996,7 +13016,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCanCallLockTaskLocked(caller); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.LOCK_TASK, userHandle); if (policy == null) { Loading Loading @@ -13024,9 +13044,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } final int userId = mInjector.userHandleGetCallingUserId(); // 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()) { // Is it ok to just check that no active policies exist currently? if (mDevicePolicyEngine.hasActivePolicies()) { LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.LOCK_TASK, userId); if (policy == null) { Loading Loading @@ -13060,7 +13079,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCanSetLockTaskFeaturesOnFinancedDevice(caller, flags); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle); LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicySetByAdmin( PolicyDefinition.LOCK_TASK, Loading Loading @@ -13101,7 +13120,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCanCallLockTaskLocked(caller); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.LOCK_TASK, userHandle); if (policy == null) { Loading Loading @@ -14773,7 +14792,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforcePermissionGrantStateOnFinancedDevice(packageName, permission); } } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, DELEGATION_PERMISSION_GRANT)) { mDevicePolicyEngine.setLocalPolicy( PolicyDefinition.PERMISSION_GRANT(packageName, permission), // TODO(b/260573124): Add correct enforcing admin when permission changes are Loading Loading @@ -16183,6 +16202,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // The removed admin might have disabled camera, so update user // restrictions. pushUserRestrictions(userHandle); // The removed admin might've been stopping the migration if it was targeting pre Android U if (shouldMigrateToDevicePolicyEngine()) { migratePoliciesToDevicePolicyEngine(); } } @Override Loading Loading @@ -18076,7 +18100,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { checkCanExecuteOrThrowUnsafe( DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { Binder.withCleanCallingIdentity(() -> { if (packages.isEmpty()) { removeUserControlDisabledPackages(caller); Loading Loading @@ -18156,7 +18180,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller) || isFinancedDeviceOwner(caller)); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { // This retrieves the policy for the calling user only, DOs for example can't know // what's enforced globally or on another user. Set<String> packages = mDevicePolicyEngine.getResolvedPolicy( Loading Loading @@ -20360,20 +20384,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG); } // 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); } private static boolean isKeepProfilesRunningFlagEnabled() { return DeviceConfig.getBoolean( NAMESPACE_DEVICE_POLICY_MANAGER, Loading Loading @@ -20622,7 +20632,123 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public DevicePolicyState getDevicePolicyState() { Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); return mInjector.binderWithCleanCallingIdentity(() -> mDevicePolicyEngine.getParcelablePoliciesStateMap()); return mInjector.binderWithCleanCallingIdentity(mDevicePolicyEngine::getDevicePolicyState); } // TODO(b/266808047): handle DeviceAdmin migration when there is no DPCs on the device private boolean shouldMigrateToDevicePolicyEngine() { return mInjector.binderWithCleanCallingIdentity(() -> { if (!isDevicePolicyEngineFlagEnabled()) { return false; } if (mOwners.isMigratedToPolicyEngine()) { return false; } // We're only checking if existing DPCs are not targeting U, regardless of what // DeviceAdmins are targeting, as they can access very limited APIs, and we'll ensure // that these APIs maintain the current behaviour of strictest applies. boolean hasDPCs = false; for (UserInfo userInfo : mUserManager.getUsers()) { List<ComponentName> activeAdmins = getActiveAdmins(userInfo.id); if (activeAdmins == null) { continue; } for (ComponentName admin : activeAdmins) { if ((isProfileOwner(admin, userInfo.id) || isDeviceOwner(admin, userInfo.id))) { if (!mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, admin.getPackageName(), userInfo.id)) { return false; } hasDPCs = true; } } } return hasDPCs; }); } private void migratePoliciesToDevicePolicyEngine() { // TODO(b/258811766): add migration logic for each policy mOwners.markMigrationToPolicyEngine(); } // TODO: This can actually accept an EnforcingAdmin that gets created in the permission check // method. private boolean useDevicePolicyEngine(CallerIdentity caller, @Nullable String delegateScope) { if (!isCallerActiveAdminOrDelegate(caller, delegateScope)) { if (!isDevicePolicyEngineFlagEnabled()) { throw new IllegalStateException("Non DPC caller can't set device policies."); } if (hasDPCsNotSupportingCoexistence()) { throw new IllegalStateException("Non DPC caller can't set device policies with " + "existing legacy admins on the device."); } return true; } else { return isDevicePolicyEngineFlagEnabled() && !hasDPCsNotSupportingCoexistence(); } } private boolean isDevicePolicyEngineFlagEnabled() { return DeviceConfig.getBoolean( NAMESPACE_DEVICE_POLICY_MANAGER, ENABLE_DEVICE_POLICY_ENGINE_FLAG, DEFAULT_ENABLE_DEVICE_POLICY_ENGINE_FLAG); } private boolean hasDPCsNotSupportingCoexistence() { return mInjector.binderWithCleanCallingIdentity(() -> { for (UserInfo userInfo : mUserManager.getUsers()) { List<ComponentName> activeAdmins = getActiveAdmins(userInfo.id); if (activeAdmins == null) { continue; } for (ComponentName admin : activeAdmins) { if ((isProfileOwner(admin, userInfo.id) || isDeviceOwner(admin, userInfo.id)) && !mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, admin.getPackageName(), userInfo.id)) { return true; } } } return false; }); } // TODO: this can actually accept an EnforcingAdmin that gets created in the permission // check method. private boolean isCallerActiveAdminOrDelegate( CallerIdentity caller, @Nullable String delegateScope) { return mInjector.binderWithCleanCallingIdentity(() -> { List<ComponentName> activeAdmins = getActiveAdmins(caller.getUserId()); if (activeAdmins != null) { for (ComponentName admin : activeAdmins) { if (admin.getPackageName().equals(caller.getPackageName())) { return true; } } } return delegateScope != null && isCallerDelegate(caller, delegateScope); }); } // TODO(b/266808047): This will return false for DeviceAdmins not targetting U, which is // inconsistent with the migration logic that allows migration with old DeviceAdmins. private boolean canAddActiveAdminIfPolicyEngineEnabled(String packageName, int userId) { if (!isDevicePolicyEngineFlagEnabled()) { return true; } if (hasDPCsNotSupportingCoexistence()) { return true; } if (mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, packageName, userId)) { // This will always return true unless we turn off coexistence, in which case it will // return true if no current admins exist, or more than one admin exist return mDevicePolicyEngine.canAdminAddPolicies(packageName, userId); } // Is it ok to just check that no active policies exist currently, or should we return false // if the policy engine was ever used? return !mDevicePolicyEngine.hasActivePolicies(); } } services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +13 −0 Original line number Diff line number Diff line Loading @@ -579,6 +579,19 @@ class Owners { } } void markMigrationToPolicyEngine() { synchronized (mData) { mData.mMigratedToPolicyEngine = true; mData.writeDeviceOwner(); } } boolean isMigratedToPolicyEngine() { synchronized (mData) { return mData.mMigratedToPolicyEngine; } } @GuardedBy("mData") void pushToAppOpsLocked() { if (!mSystemReady) { Loading services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java +13 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ class OwnersData { private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type"; private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES = "device-owner-protected-packages"; private static final String TAG_POLICY_ENGINE_MIGRATION = "policy-engine-migration"; private static final String ATTR_NAME = "name"; private static final String ATTR_PACKAGE = "package"; Loading @@ -84,6 +85,8 @@ class OwnersData { "isPoOrganizationOwnedDevice"; private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value"; private static final String ATTR_MIGRATED_TO_POLICY_ENGINE = "migratedToPolicyEngine"; // Internal state for the device owner package. OwnerInfo mDeviceOwner; int mDeviceOwnerUserId = UserHandle.USER_NULL; Loading @@ -109,6 +112,8 @@ class OwnersData { SystemUpdateInfo mSystemUpdateInfo; private final PolicyPathProvider mPathProvider; boolean mMigratedToPolicyEngine = false; OwnersData(PolicyPathProvider pathProvider) { mPathProvider = pathProvider; } Loading Loading @@ -389,6 +394,11 @@ class OwnersData { } out.endTag(null, TAG_FREEZE_PERIOD_RECORD); } out.startTag(null, TAG_POLICY_ENGINE_MIGRATION); out.attributeBoolean(null, ATTR_MIGRATED_TO_POLICY_ENGINE, mMigratedToPolicyEngine); out.endTag(null, TAG_POLICY_ENGINE_MIGRATION); } @Override Loading Loading @@ -444,6 +454,9 @@ class OwnersData { } mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); break; case TAG_POLICY_ENGINE_MIGRATION: mMigratedToPolicyEngine = parser.getAttributeBoolean( null, ATTR_MIGRATED_TO_POLICY_ENGINE, false); default: Slog.e(TAG, "Unexpected tag: " + tag); return false; Loading Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java +56 −16 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.app.admin.PolicyUpdateResult.RESULT_SUCCESS; import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_TARGET_USER_ID; import static android.app.admin.PolicyUpdatesReceiver.EXTRA_POLICY_UPDATE_RESULT_KEY; import static android.content.pm.UserProperties.INHERIT_DEVICE_POLICY_FROM_PARENT; import static android.provider.DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER; import android.Manifest; import android.annotation.NonNull; Loading @@ -42,6 +43,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.UserHandle; import android.os.UserManager; import android.provider.DeviceConfig; import android.util.AtomicFile; import android.util.Log; import android.util.SparseArray; Loading Loading @@ -74,6 +76,9 @@ import java.util.Set; final class DevicePolicyEngine { static final String TAG = "DevicePolicyEngine"; private static final String ENABLE_COEXISTENCE_FLAG = "enable_coexistence"; private static final boolean DEFAULT_ENABLE_COEXISTENCE_FLAG = true; private final Context mContext; private final UserManager mUserManager; Loading Loading @@ -820,7 +825,7 @@ final class DevicePolicyEngine { * each admin. Global policies are returned under {@link UserHandle#ALL}. */ @NonNull DevicePolicyState getParcelablePoliciesStateMap() { DevicePolicyState getDevicePolicyState() { Map<UserHandle, Map<PolicyKey, android.app.admin.PolicyState<?>>> policies = new HashMap<>(); for (int i = 0; i < mLocalPolicies.size(); i++) { Loading Loading @@ -869,11 +874,6 @@ final class DevicePolicyEngine { private void updateDeviceAdminServiceOnPolicyAddLocked(@NonNull EnforcingAdmin enforcingAdmin) { int userId = enforcingAdmin.getUserId(); // A connection is established with DPCs as soon as they are provisioned, so no need to // connect when a policy is set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } if (mEnforcingAdmins.contains(userId) && mEnforcingAdmins.get(userId).contains(enforcingAdmin)) { return; Loading @@ -884,6 +884,11 @@ final class DevicePolicyEngine { } mEnforcingAdmins.get(enforcingAdmin.getUserId()).add(enforcingAdmin); // A connection is established with DPCs as soon as they are provisioned, so no need to // connect when a policy is set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } mDeviceAdminServiceController.startServiceForAdmin( enforcingAdmin.getPackageName(), userId, Loading @@ -896,18 +901,10 @@ final class DevicePolicyEngine { */ private void updateDeviceAdminServiceOnPolicyRemoveLocked( @NonNull EnforcingAdmin enforcingAdmin) { // TODO(b/263364434): centralise handling in one place. // DPCs rely on a constant connection being established as soon as they are provisioned, // so we shouldn't disconnect it even if they no longer have policies set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } if (doesAdminHavePolicies(enforcingAdmin)) { return; } int userId = enforcingAdmin.getUserId(); if (mEnforcingAdmins.contains(userId)) { mEnforcingAdmins.get(userId).remove(enforcingAdmin); if (mEnforcingAdmins.get(userId).isEmpty()) { Loading @@ -915,6 +912,12 @@ final class DevicePolicyEngine { } } // TODO(b/263364434): centralise handling in one place. // DPCs rely on a constant connection being established as soon as they are provisioned, // so we shouldn't disconnect it even if they no longer have policies set. if (enforcingAdmin.hasAuthority(EnforcingAdmin.DPC_AUTHORITY)) { return; } mDeviceAdminServiceController.stopServiceForAdmin( enforcingAdmin.getPackageName(), userId, Loading Loading @@ -968,14 +971,51 @@ final class DevicePolicyEngine { } } // TODO: we need to listen for user removal and package removal and update out internal policy // map and enforcing admins for this is be accurate. boolean hasActivePolicies() { return mEnforcingAdmins.size() > 0; } /** * Returns {@code true} if the coexistence flag is enabled or: * <ul> * <li>If the provided package is an admin with existing policies * <li>A new admin and no other admin have policies set * <li>More than one admin have policies set */ boolean canAdminAddPolicies(String packageName, int userId) { if (isCoexistenceFlagEnabled()) { return true; } if (mEnforcingAdmins.contains(userId) && mEnforcingAdmins.get(userId).stream().anyMatch(admin -> admin.getPackageName().equals(packageName))) { return true; } int numOfEnforcingAdmins = 0; for (int i = 0; i < mEnforcingAdmins.size(); i++) { numOfEnforcingAdmins += mEnforcingAdmins.get(i).size(); } return numOfEnforcingAdmins == 0 || numOfEnforcingAdmins > 1; } private boolean isCoexistenceFlagEnabled() { return DeviceConfig.getBoolean( NAMESPACE_DEVICE_POLICY_MANAGER, ENABLE_COEXISTENCE_FLAG, DEFAULT_ENABLE_COEXISTENCE_FLAG); } private class DevicePoliciesReaderWriter { private static final String DEVICE_POLICIES_XML = "device_policies.xml"; private static final String DEVICE_POLICIES_XML = "device_policy_state.xml"; private static final String TAG_LOCAL_POLICY_ENTRY = "local-policy-entry"; private static final String TAG_GLOBAL_POLICY_ENTRY = "global-policy-entry"; private static final String TAG_ADMINS_POLICY_ENTRY = "admins-policy-entry"; private static final String TAG_ENFORCING_ADMINS_ENTRY = "enforcing-admins-entry"; private static final String ATTR_USER_ID = "user-id"; private static final String ATTR_POLICY_ID = "policy-id"; private final File mFile; Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +166 −40 Original line number Diff line number Diff line Loading @@ -745,11 +745,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + "management app's authentication policy"; private static final String NOT_SYSTEM_CALLER_MSG = "Only the system can %s"; // ENABLE_DEVICE_POLICY_ENGINE_FLAG must be enabled before this could be enabled. private static final String PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG = "enable_permission_based_access"; private static final String ENABLE_COEXISTENCE_FLAG = "enable_coexistence"; private static final boolean DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG = false; private static final boolean DEFAULT_ENABLE_COEXISTENCE_FLAG = false; // This must be enabled before PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG is enabled, the reason // we're not just relying on PERMISSION_BASED_ACCESS_EXPERIMENT_FLAG to enable the policy engine // is that we might want to enable it before the permission changes are ready if we want to test // it on DPCs. // Once this is enabled, it can no longer be disabled in production private static final String ENABLE_DEVICE_POLICY_ENGINE_FLAG = "enable_device_policy_engine"; private static final boolean DEFAULT_ENABLE_DEVICE_POLICY_ENGINE_FLAG = false; // TODO(b/258425381) remove the flag after rollout. private static final String KEEP_PROFILES_RUNNING_FLAG = "enable_keep_profiles_running"; Loading Loading @@ -1309,10 +1316,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { && (owner.getPackageName().equals(packageName))) { startOwnerService(userHandle, "package-broadcast"); } if (isCoexistenceFlagEnabled()) { if (shouldMigrateToDevicePolicyEngine()) { migratePoliciesToDevicePolicyEngine(); } if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handlePackageChanged(packageName, userHandle); } // Persist updates if the removed package was an admin or delegate. if (removedAdmin || removedDelegate) { saveSettingsLocked(policy.mUserId); Loading Loading @@ -2002,7 +2011,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener()); mDeviceManagementResourcesProvider.load(); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.load(); } Loading Loading @@ -3133,6 +3142,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (getLockObject()) { migrateToProfileOnOrganizationOwnedDeviceIfCompLocked(); applyProfileRestrictionsIfDeviceOwnerLocked(); // TODO: Is this the right place to trigger the migration? if (shouldMigrateToDevicePolicyEngine()) { migratePoliciesToDevicePolicyEngine(); } } maybeStartSecurityLogMonitorOnActivityManagerReady(); break; Loading Loading @@ -3341,7 +3355,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { updateNetworkPreferenceForUser(userId, preferentialNetworkServiceConfigs); startOwnerService(userId, "start-user"); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleStartUser(userId); } } Loading @@ -3366,7 +3380,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { void handleUnlockUser(int userId) { startOwnerService(userId, "unlock-user"); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleUnlockUser(userId); } } Loading @@ -3378,7 +3392,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { void handleStopUser(int userId) { updateNetworkPreferenceForUser(userId, List.of(PreferentialNetworkServiceConfig.DEFAULT)); mDeviceAdminServiceController.stopServicesForUser(userId, /* actionForLog= */ "stop-user"); if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleStopUser(userId); } } Loading Loading @@ -3486,7 +3500,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * @param refreshing true = update an active admin, no error */ @Override public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) { public void setActiveAdmin( ComponentName adminReceiver, boolean refreshing, int userHandle) { if (!mHasFeature) { return; } Loading @@ -3503,6 +3518,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (getLockObject()) { checkActiveAdminPrecondition(adminReceiver, info, policy); mInjector.binderWithCleanCallingIdentity(() -> { if (!canAddActiveAdminIfPolicyEngineEnabled( adminReceiver.getPackageName(), userHandle)) { throw new IllegalStateException("Can't add non-coexistable admin."); } final ActiveAdmin existingAdmin = getActiveAdminUncheckedLocked(adminReceiver, userHandle); if (!refreshing && existingAdmin != null) { Loading Loading @@ -8246,7 +8266,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { caller)); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { mDevicePolicyEngine.setGlobalPolicy( PolicyDefinition.AUTO_TIMEZONE, // TODO(b/260573124): add correct enforcing admin when permission changes are Loading Loading @@ -10356,7 +10376,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller)); final int userHandle = caller.getUserId(); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { mDevicePolicyEngine.setLocalPolicy( PolicyDefinition.PERSISTENT_PREFERRED_ACTIVITY(filter), EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle), Loading Loading @@ -10394,7 +10414,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int userHandle = caller.getUserId(); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { clearPackagePersistentPreferredActivitiesFromPolicyEngine( EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle), packageName, Loading Loading @@ -11348,7 +11368,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final int userId = user.id; if (isCoexistenceFlagEnabled()) { if (isDevicePolicyEngineFlagEnabled()) { mDevicePolicyEngine.handleUserCreated(user); } Loading Loading @@ -12378,7 +12398,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { || isFinancedDeviceOwner(caller))) || (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_BLOCK_UNINSTALL))); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, DELEGATION_BLOCK_UNINSTALL)) { // 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. Loading Loading @@ -12942,7 +12962,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_PACKAGES); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin( who, caller.getUserId()); if (packages.length == 0) { Loading Loading @@ -12996,7 +13016,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCanCallLockTaskLocked(caller); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.LOCK_TASK, userHandle); if (policy == null) { Loading Loading @@ -13024,9 +13044,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } final int userId = mInjector.userHandleGetCallingUserId(); // 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()) { // Is it ok to just check that no active policies exist currently? if (mDevicePolicyEngine.hasActivePolicies()) { LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.LOCK_TASK, userId); if (policy == null) { Loading Loading @@ -13060,7 +13079,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCanSetLockTaskFeaturesOnFinancedDevice(caller, flags); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { EnforcingAdmin admin = EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userHandle); LockTaskPolicy currentPolicy = mDevicePolicyEngine.getLocalPolicySetByAdmin( PolicyDefinition.LOCK_TASK, Loading Loading @@ -13101,7 +13120,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforceCanCallLockTaskLocked(caller); } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy( PolicyDefinition.LOCK_TASK, userHandle); if (policy == null) { Loading Loading @@ -14773,7 +14792,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { enforcePermissionGrantStateOnFinancedDevice(packageName, permission); } } if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, DELEGATION_PERMISSION_GRANT)) { mDevicePolicyEngine.setLocalPolicy( PolicyDefinition.PERMISSION_GRANT(packageName, permission), // TODO(b/260573124): Add correct enforcing admin when permission changes are Loading Loading @@ -16183,6 +16202,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // The removed admin might have disabled camera, so update user // restrictions. pushUserRestrictions(userHandle); // The removed admin might've been stopping the migration if it was targeting pre Android U if (shouldMigrateToDevicePolicyEngine()) { migratePoliciesToDevicePolicyEngine(); } } @Override Loading Loading @@ -18076,7 +18100,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { checkCanExecuteOrThrowUnsafe( DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { Binder.withCleanCallingIdentity(() -> { if (packages.isEmpty()) { removeUserControlDisabledPackages(caller); Loading Loading @@ -18156,7 +18180,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller) || isFinancedDeviceOwner(caller)); if (isCoexistenceEnabled(caller)) { if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) { // This retrieves the policy for the calling user only, DOs for example can't know // what's enforced globally or on another user. Set<String> packages = mDevicePolicyEngine.getResolvedPolicy( Loading Loading @@ -20360,20 +20384,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG); } // 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); } private static boolean isKeepProfilesRunningFlagEnabled() { return DeviceConfig.getBoolean( NAMESPACE_DEVICE_POLICY_MANAGER, Loading Loading @@ -20622,7 +20632,123 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public DevicePolicyState getDevicePolicyState() { Preconditions.checkCallAuthorization( hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); return mInjector.binderWithCleanCallingIdentity(() -> mDevicePolicyEngine.getParcelablePoliciesStateMap()); return mInjector.binderWithCleanCallingIdentity(mDevicePolicyEngine::getDevicePolicyState); } // TODO(b/266808047): handle DeviceAdmin migration when there is no DPCs on the device private boolean shouldMigrateToDevicePolicyEngine() { return mInjector.binderWithCleanCallingIdentity(() -> { if (!isDevicePolicyEngineFlagEnabled()) { return false; } if (mOwners.isMigratedToPolicyEngine()) { return false; } // We're only checking if existing DPCs are not targeting U, regardless of what // DeviceAdmins are targeting, as they can access very limited APIs, and we'll ensure // that these APIs maintain the current behaviour of strictest applies. boolean hasDPCs = false; for (UserInfo userInfo : mUserManager.getUsers()) { List<ComponentName> activeAdmins = getActiveAdmins(userInfo.id); if (activeAdmins == null) { continue; } for (ComponentName admin : activeAdmins) { if ((isProfileOwner(admin, userInfo.id) || isDeviceOwner(admin, userInfo.id))) { if (!mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, admin.getPackageName(), userInfo.id)) { return false; } hasDPCs = true; } } } return hasDPCs; }); } private void migratePoliciesToDevicePolicyEngine() { // TODO(b/258811766): add migration logic for each policy mOwners.markMigrationToPolicyEngine(); } // TODO: This can actually accept an EnforcingAdmin that gets created in the permission check // method. private boolean useDevicePolicyEngine(CallerIdentity caller, @Nullable String delegateScope) { if (!isCallerActiveAdminOrDelegate(caller, delegateScope)) { if (!isDevicePolicyEngineFlagEnabled()) { throw new IllegalStateException("Non DPC caller can't set device policies."); } if (hasDPCsNotSupportingCoexistence()) { throw new IllegalStateException("Non DPC caller can't set device policies with " + "existing legacy admins on the device."); } return true; } else { return isDevicePolicyEngineFlagEnabled() && !hasDPCsNotSupportingCoexistence(); } } private boolean isDevicePolicyEngineFlagEnabled() { return DeviceConfig.getBoolean( NAMESPACE_DEVICE_POLICY_MANAGER, ENABLE_DEVICE_POLICY_ENGINE_FLAG, DEFAULT_ENABLE_DEVICE_POLICY_ENGINE_FLAG); } private boolean hasDPCsNotSupportingCoexistence() { return mInjector.binderWithCleanCallingIdentity(() -> { for (UserInfo userInfo : mUserManager.getUsers()) { List<ComponentName> activeAdmins = getActiveAdmins(userInfo.id); if (activeAdmins == null) { continue; } for (ComponentName admin : activeAdmins) { if ((isProfileOwner(admin, userInfo.id) || isDeviceOwner(admin, userInfo.id)) && !mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, admin.getPackageName(), userInfo.id)) { return true; } } } return false; }); } // TODO: this can actually accept an EnforcingAdmin that gets created in the permission // check method. private boolean isCallerActiveAdminOrDelegate( CallerIdentity caller, @Nullable String delegateScope) { return mInjector.binderWithCleanCallingIdentity(() -> { List<ComponentName> activeAdmins = getActiveAdmins(caller.getUserId()); if (activeAdmins != null) { for (ComponentName admin : activeAdmins) { if (admin.getPackageName().equals(caller.getPackageName())) { return true; } } } return delegateScope != null && isCallerDelegate(caller, delegateScope); }); } // TODO(b/266808047): This will return false for DeviceAdmins not targetting U, which is // inconsistent with the migration logic that allows migration with old DeviceAdmins. private boolean canAddActiveAdminIfPolicyEngineEnabled(String packageName, int userId) { if (!isDevicePolicyEngineFlagEnabled()) { return true; } if (hasDPCsNotSupportingCoexistence()) { return true; } if (mInjector.isChangeEnabled(ENABLE_COEXISTENCE_CHANGE, packageName, userId)) { // This will always return true unless we turn off coexistence, in which case it will // return true if no current admins exist, or more than one admin exist return mDevicePolicyEngine.canAdminAddPolicies(packageName, userId); } // Is it ok to just check that no active policies exist currently, or should we return false // if the policy engine was ever used? return !mDevicePolicyEngine.hasActivePolicies(); } }
services/devicepolicy/java/com/android/server/devicepolicy/Owners.java +13 −0 Original line number Diff line number Diff line Loading @@ -579,6 +579,19 @@ class Owners { } } void markMigrationToPolicyEngine() { synchronized (mData) { mData.mMigratedToPolicyEngine = true; mData.writeDeviceOwner(); } } boolean isMigratedToPolicyEngine() { synchronized (mData) { return mData.mMigratedToPolicyEngine; } } @GuardedBy("mData") void pushToAppOpsLocked() { if (!mSystemReady) { Loading
services/devicepolicy/java/com/android/server/devicepolicy/OwnersData.java +13 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ class OwnersData { private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type"; private static final String TAG_DEVICE_OWNER_PROTECTED_PACKAGES = "device-owner-protected-packages"; private static final String TAG_POLICY_ENGINE_MIGRATION = "policy-engine-migration"; private static final String ATTR_NAME = "name"; private static final String ATTR_PACKAGE = "package"; Loading @@ -84,6 +85,8 @@ class OwnersData { "isPoOrganizationOwnedDevice"; private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value"; private static final String ATTR_MIGRATED_TO_POLICY_ENGINE = "migratedToPolicyEngine"; // Internal state for the device owner package. OwnerInfo mDeviceOwner; int mDeviceOwnerUserId = UserHandle.USER_NULL; Loading @@ -109,6 +112,8 @@ class OwnersData { SystemUpdateInfo mSystemUpdateInfo; private final PolicyPathProvider mPathProvider; boolean mMigratedToPolicyEngine = false; OwnersData(PolicyPathProvider pathProvider) { mPathProvider = pathProvider; } Loading Loading @@ -389,6 +394,11 @@ class OwnersData { } out.endTag(null, TAG_FREEZE_PERIOD_RECORD); } out.startTag(null, TAG_POLICY_ENGINE_MIGRATION); out.attributeBoolean(null, ATTR_MIGRATED_TO_POLICY_ENGINE, mMigratedToPolicyEngine); out.endTag(null, TAG_POLICY_ENGINE_MIGRATION); } @Override Loading Loading @@ -444,6 +454,9 @@ class OwnersData { } mDeviceOwnerProtectedPackages.put(packageName, protectedPackages); break; case TAG_POLICY_ENGINE_MIGRATION: mMigratedToPolicyEngine = parser.getAttributeBoolean( null, ATTR_MIGRATED_TO_POLICY_ENGINE, false); default: Slog.e(TAG, "Unexpected tag: " + tag); return false; Loading