Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 864d7e56 authored by Pavel Grafov's avatar Pavel Grafov Committed by Android (Google) Code Review
Browse files

Merge "Migrate COMP to PO on corp owned device on boot."

parents d77145bd 72451325
Loading
Loading
Loading
Loading
+164 −26
Original line number Diff line number Diff line
@@ -1095,7 +1095,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        String globalProxySpec = null;
        String globalProxyExclusionList = null;
        ArrayMap<String, TrustAgentInfo> trustAgentInfos = new ArrayMap<>();
        @NonNull ArrayMap<String, TrustAgentInfo> trustAgentInfos = new ArrayMap<>();
        List<String> crossProfileWidgetProviders;
@@ -1650,6 +1650,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            }
        }
        @NonNull
        private ArrayMap<String, TrustAgentInfo> getAllTrustAgentInfos(
                XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
            int outerDepthDAM = parser.getDepth();
@@ -2434,11 +2435,133 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            migrateUserRestrictionsIfNecessaryLocked();
            // TODO PO may not have a class name either due to b/17652534.  Address that too.
            updateDeviceOwnerLocked();
        }
    }
    /**
     * Checks if the device is in COMP mode, and if so migrates it to managed profile on a
     * corporate owned device.
     */
    @GuardedBy("getLockObject()")
    private void maybeMigrateToProfileOnOrganizationOwnedDeviceLocked() {
        logIfVerbose("Checking whether we need to migrate COMP ");
        final int doUserId = mOwners.getDeviceOwnerUserId();
        if (doUserId == UserHandle.USER_NULL) {
            logIfVerbose("No DO found, skipping migration.");
            return;
        }
        final List<UserInfo> profiles = mUserManager.getProfiles(doUserId);
        if (profiles.size() != 2) {
            if (profiles.size() == 1) {
                logIfVerbose("Profile not found, skipping migration.");
            } else {
                Slog.wtf(LOG_TAG, "Found " + profiles.size() + " profiles, skipping migration");
            }
            return;
        }
        final int poUserId = getManagedUserId(doUserId);
        if (poUserId < 0) {
            Slog.wtf(LOG_TAG, "Found DO and a profile, but it is not managed, skipping migration");
            return;
        }
        final ActiveAdmin doAdmin = getDeviceOwnerAdminLocked();
        final ActiveAdmin poAdmin = getProfileOwnerAdminLocked(poUserId);
        if (doAdmin == null || poAdmin == null) {
            Slog.wtf(LOG_TAG, "Failed to get either PO or DO admin, aborting migration.");
            return;
        }
        final ComponentName doAdminComponent = mOwners.getDeviceOwnerComponent();
        final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(poUserId);
        if (doAdminComponent == null || poAdminComponent == null) {
            Slog.wtf(LOG_TAG, "Cannot find PO or DO component name, aborting migration.");
            return;
        }
        if (!doAdminComponent.getPackageName().equals(poAdminComponent.getPackageName())) {
            Slog.e(LOG_TAG, "DO and PO are different packages, aborting migration.");
            return;
        }
        Slog.i(LOG_TAG, String.format(
                "Migrating COMP to PO on a corp owned device; primary user: %d; profile: %d",
                doUserId, poUserId));
        Slog.i(LOG_TAG, "Giving the PO additional power...");
        markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(poAdminComponent, poUserId);
        Slog.i(LOG_TAG, "Migrating DO policies to PO...");
        moveDoPoliciesToProfileParentAdmin(doAdmin, poAdmin.getParentActiveAdmin());
        saveSettingsLocked(poUserId);
        Slog.i(LOG_TAG, "Clearing the DO...");
        final ComponentName doAdminReceiver = doAdmin.info.getComponent();
        clearDeviceOwnerLocked(doAdmin, doUserId);
        // TODO(b/143516163): If we have a power cut here, we might leave active admin. Consider if
        // it is worth the complexity to make it more robust.
        Slog.i(LOG_TAG, "Removing admin artifacts...");
        // TODO(b/143516163): Clean up application restrictions in UserManager.
        removeAdminArtifacts(doAdminReceiver, doUserId);
        Slog.i(LOG_TAG, "Migration complete.");
        // Note: KeyChain keys are not removed and will remain accessible for the apps that have
        // been given grants to use them.
    }
    private void moveDoPoliciesToProfileParentAdmin(ActiveAdmin doAdmin, ActiveAdmin parentAdmin) {
        // The following policies can be already controlled via parent instance, skip if so.
        if (parentAdmin.mPasswordPolicy.quality == PASSWORD_QUALITY_UNSPECIFIED) {
            parentAdmin.mPasswordPolicy = doAdmin.mPasswordPolicy;
        }
        if (parentAdmin.passwordHistoryLength == ActiveAdmin.DEF_PASSWORD_HISTORY_LENGTH) {
            parentAdmin.passwordHistoryLength = doAdmin.passwordHistoryLength;
        }
        if (parentAdmin.passwordExpirationTimeout == ActiveAdmin.DEF_PASSWORD_HISTORY_LENGTH) {
            parentAdmin.passwordExpirationTimeout = doAdmin.passwordExpirationTimeout;
        }
        if (parentAdmin.maximumFailedPasswordsForWipe
                == ActiveAdmin.DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
            parentAdmin.maximumFailedPasswordsForWipe = doAdmin.maximumFailedPasswordsForWipe;
        }
        if (parentAdmin.maximumTimeToUnlock == ActiveAdmin.DEF_MAXIMUM_TIME_TO_UNLOCK) {
            parentAdmin.maximumTimeToUnlock = doAdmin.maximumTimeToUnlock;
        }
        if (parentAdmin.strongAuthUnlockTimeout
                == DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
            parentAdmin.strongAuthUnlockTimeout = doAdmin.strongAuthUnlockTimeout;
        }
        parentAdmin.disabledKeyguardFeatures |=
                doAdmin.disabledKeyguardFeatures & PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
        parentAdmin.trustAgentInfos.putAll(doAdmin.trustAgentInfos);
        // The following policies weren't available to PO, but will be available after migration.
        parentAdmin.disableCamera = doAdmin.disableCamera;
        // TODO(b/143516163): Uncomment once corresponding APIs are available via parent instance.
        // parentAdmin.disableScreenCapture = doAdmin.disableScreenCapture;
        // parentAdmin.accountTypesWithManagementDisabled.addAll(
        //         doAdmin.accountTypesWithManagementDisabled);
        moveDoUserRestrictionsToCopeParent(doAdmin, parentAdmin);
        // TODO(b/143516163): migrate network and security logging state, currently they are
        // turned off when DO is removed.
    }
    private void moveDoUserRestrictionsToCopeParent(ActiveAdmin doAdmin, ActiveAdmin parentAdmin) {
        if (doAdmin.userRestrictions == null) {
            return;
        }
        for (final String restriction : doAdmin.userRestrictions.keySet()) {
            if (UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(restriction)) {
                parentAdmin.userRestrictions.putBoolean(
                        restriction, doAdmin.userRestrictions.getBoolean(restriction));
            }
        }
    }
    /** Apply default restrictions that haven't been applied to profile owners yet. */
    private void maybeSetDefaultProfileOwnerUserRestrictions() {
        synchronized (getLockObject()) {
@@ -3625,6 +3748,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                break;
            case SystemService.PHASE_ACTIVITY_MANAGER_READY:
                maybeStartSecurityLogMonitorOnActivityManagerReady();
                synchronized (getLockObject()) {
                    maybeMigrateToProfileOnOrganizationOwnedDeviceLocked();
                }
                break;
            case SystemService.PHASE_BOOT_COMPLETED:
                ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this.
@@ -12919,6 +13045,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        // Grant access under lock.
        synchronized (getLockObject()) {
            markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(who, userId);
        }
    }
    @GuardedBy("getLockObject()")
    private void markProfileOwnerOnOrganizationOwnedDeviceUncheckedLocked(
            ComponentName who, int userId) {
        // Sanity check: Make sure that the user has a profile owner and that the specified
        // component is the profile owner of that user.
        if (!isProfileOwner(who, userId)) {
@@ -12934,7 +13067,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        // First, set restriction on removing the profile.
        mInjector.binderWithCleanCallingIdentity(() -> {
            // Clear restriction as user.
                UserHandle parentUser = mUserManager.getProfileParent(UserHandle.of(userId));
            final UserHandle parentUser = mUserManager.getProfileParent(UserHandle.of(userId));
            if (!parentUser.isSystem()) {
                throw new IllegalStateException(
                        String.format("Only the profile owner of a managed profile on the"
@@ -12950,7 +13083,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        // data, no need to do it manually.
        mOwners.markProfileOwnerOfOrganizationOwnedDevice(userId);
    }
    }
    private void pushMeteredDisabledPackagesLocked(int userId) {
        mInjector.getNetworkPolicyManagerInternal().setMeteredRestrictedPackages(
@@ -14913,4 +15045,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            return packages == null ? Collections.EMPTY_LIST : packages;
        }
    }
    private void logIfVerbose(String message) {
        if (VERBOSE_LOG) {
            Slog.d(LOG_TAG, message);
        }
    }
}
+8 −0
Original line number Diff line number Diff line
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<root>
    <device-owner package="com.android.frameworks.servicestests"
        name=""
        component="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1"
        userRestrictionsMigrated="true" />
    <device-owner-context userId="0" />
</root>
+7 −0
Original line number Diff line number Diff line
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<policies setup-complete="true" provisioning-state="3">
    <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
        <policies flags="991"/>
        <password-history-length value="33" />
    </admin>
</policies>
+6 −0
Original line number Diff line number Diff line
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<policies setup-complete="true" provisioning-state="3">
    <admin name="com.another.package.name/whatever.random.class">
        <policies flags="991"/>
    </admin>
</policies>
+6 −0
Original line number Diff line number Diff line
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<policies setup-complete="true" provisioning-state="3">
    <admin name="com.android.frameworks.servicestests/com.android.server.devicepolicy.DummyDeviceAdmins$Admin1">
        <policies flags="991"/>
    </admin>
</policies>
Loading