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

Commit 75f28f8e authored by Jonathan Scott's avatar Jonathan Scott
Browse files

Return STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED if the DO doesn't

specify the correct metadata.

Test: btest android.devicepolicy.cts.ProvisioningTest
Bug: 241553133
Change-Id: Icd725ca38c21134f40753330554ace3e70a310e1
parent cefe8382
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -7408,6 +7408,7 @@ package android.app.admin {
    method public void dump(android.util.Printer, String);
    method public android.content.pm.ActivityInfo getActivityInfo();
    method @NonNull public android.content.ComponentName getComponent();
    method public int getHeadlessDeviceOwnerMode();
    method public String getPackageName();
    method public String getReceiverName();
    method public String getTagForPolicy(int);
@@ -7419,6 +7420,8 @@ package android.app.admin {
    method public boolean usesPolicy(int);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.DeviceAdminInfo> CREATOR;
    field public static final int HEADLESS_DEVICE_OWNER_MODE_AFFILIATED = 1; // 0x1
    field public static final int HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED = 0; // 0x0
    field public static final int USES_ENCRYPTED_STORAGE = 7; // 0x7
    field public static final int USES_POLICY_DISABLE_CAMERA = 8; // 0x8
    field public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9; // 0x9
+1 −0
Original line number Diff line number Diff line
@@ -1272,6 +1272,7 @@ package android.app.admin {
    field public static final int STATUS_DEVICE_ADMIN_NOT_SUPPORTED = 13; // 0xd
    field public static final int STATUS_HAS_DEVICE_OWNER = 1; // 0x1
    field public static final int STATUS_HAS_PAIRED = 8; // 0x8
    field public static final int STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED = 16; // 0x10
    field public static final int STATUS_MANAGED_USERS_NOT_SUPPORTED = 9; // 0x9
    field public static final int STATUS_NONSYSTEM_USER_EXISTS = 5; // 0x5
    field public static final int STATUS_NOT_SYSTEM_USER = 7; // 0x7
+42 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app.admin;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -158,6 +159,24 @@ public final class DeviceAdminInfo implements Parcelable {
     */
    public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;


    /**
     * Value for {@link #getHeadlessDeviceOwnerMode} which indicates that this DPC should not
     * be provisioned into Device Owner mode on a Headless System User Mode device.
     */
    public static final int HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED = 0;

    /**
     * Value for {@link #getHeadlessDeviceOwnerMode} which indicates that this DPC should be
     * provisioned into "affiliated" mode when on a Headless System User Mode device.
     *
     * <p>This mode adds a Profile Owner to all users other than the user the Device Owner is on.
     */
    public static final int HEADLESS_DEVICE_OWNER_MODE_AFFILIATED = 1;

    @IntDef({HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED, HEADLESS_DEVICE_OWNER_MODE_AFFILIATED})
    private @interface HeadlessDeviceOwnerMode {}

    /** @hide */
    public static class PolicyInfo {
        public final int ident;
@@ -255,6 +274,8 @@ public final class DeviceAdminInfo implements Parcelable {
     */
    boolean mSupportsTransferOwnership;

    @HeadlessDeviceOwnerMode int mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;

    /**
     * Constructor.
     *
@@ -341,6 +362,17 @@ public final class DeviceAdminInfo implements Parcelable {
                                "support-transfer-ownership tag must be empty.");
                    }
                    mSupportsTransferOwnership = true;
                } else if (tagName.equals("headless-system-user")) {
                    String deviceOwnerModeStringValue =
                            parser.getAttributeValue(null, "device-owner-mode");

                    if (deviceOwnerModeStringValue.equalsIgnoreCase("unsupported")) {
                        mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_UNSUPPORTED;
                    } else if (deviceOwnerModeStringValue.equalsIgnoreCase("affiliated")) {
                        mHeadlessDeviceOwnerMode = HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
                    } else {
                        throw new XmlPullParserException("headless-system-user mode must be valid");
                    }
                }
            }
        } catch (NameNotFoundException e) {
@@ -355,6 +387,7 @@ public final class DeviceAdminInfo implements Parcelable {
        mActivityInfo = ActivityInfo.CREATOR.createFromParcel(source);
        mUsesPolicies = source.readInt();
        mSupportsTransferOwnership = source.readBoolean();
        mHeadlessDeviceOwnerMode = source.readInt();
    }

    /**
@@ -460,6 +493,14 @@ public final class DeviceAdminInfo implements Parcelable {
        return mSupportsTransferOwnership;
    }

    /**
     * Returns the mode this DeviceAdmin wishes to use if provisioned as a Device Owner on a
     * headless system user mode device.
     */
    public @HeadlessDeviceOwnerMode int getHeadlessDeviceOwnerMode() {
        return mHeadlessDeviceOwnerMode;
    }

    /** @hide */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public ArrayList<PolicyInfo> getUsedPolicies() {
@@ -505,6 +546,7 @@ public final class DeviceAdminInfo implements Parcelable {
        mActivityInfo.writeToParcel(dest, flags);
        dest.writeInt(mUsesPolicies);
        dest.writeBoolean(mSupportsTransferOwnership);
        dest.writeInt(mHeadlessDeviceOwnerMode);
    }

    /**
+14 −2
Original line number Diff line number Diff line
@@ -16,10 +16,10 @@
package android.app.admin;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
@@ -2811,6 +2811,17 @@ public class DevicePolicyManager {
    @SystemApi
    public static final int STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS = 15;
    /**
     * Result code for {@link #checkProvisioningPrecondition}.
     *
     * <p>Returned for {@link #ACTION_PROVISION_MANAGED_DEVICE} when provisioning a DPC which does
     * not support headless system user mode on a headless system user mode device.
     *
     * @hide
     */
    @SystemApi
    public static final int STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED = 16;
    /**
     * Result codes for {@link #checkProvisioningPrecondition} indicating all the provisioning pre
     * conditions.
@@ -2824,7 +2835,8 @@ public class DevicePolicyManager {
            STATUS_HAS_PAIRED, STATUS_MANAGED_USERS_NOT_SUPPORTED, STATUS_SYSTEM_USER,
            STATUS_CANNOT_ADD_MANAGED_PROFILE, STATUS_DEVICE_ADMIN_NOT_SUPPORTED,
            STATUS_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER,
            STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS
            STATUS_PROVISIONING_NOT_ALLOWED_FOR_NON_DEVELOPER_USERS,
            STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED
    })
    public @interface ProvisioningPrecondition {}
+34 −11
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_APP_STANDBY;
import static android.app.admin.DeviceAdminInfo.HEADLESS_DEVICE_OWNER_MODE_AFFILIATED;
import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
@@ -105,6 +106,7 @@ import static android.app.admin.DevicePolicyManager.STATUS_CANNOT_ADD_MANAGED_PR
import static android.app.admin.DevicePolicyManager.STATUS_DEVICE_ADMIN_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.STATUS_HAS_DEVICE_OWNER;
import static android.app.admin.DevicePolicyManager.STATUS_HAS_PAIRED;
import static android.app.admin.DevicePolicyManager.STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.STATUS_MANAGED_USERS_NOT_SUPPORTED;
import static android.app.admin.DevicePolicyManager.STATUS_NONSYSTEM_USER_EXISTS;
import static android.app.admin.DevicePolicyManager.STATUS_NOT_SYSTEM_USER;
@@ -140,6 +142,7 @@ import static android.app.admin.ProvisioningException.ERROR_SETTING_PROFILE_OWNE
import static android.app.admin.ProvisioningException.ERROR_SET_DEVICE_OWNER_FAILED;
import static android.app.admin.ProvisioningException.ERROR_STARTING_PROFILE_FAILED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.PackageManager.GET_META_DATA;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
@@ -2929,7 +2932,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        final ActivityInfo ai = mInjector.binderWithCleanCallingIdentity(() -> {
            try {
                return mIPackageManager.getReceiverInfo(adminName,
                        PackageManager.GET_META_DATA
                        GET_META_DATA
                        | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
                        | PackageManager.MATCH_DIRECT_BOOT_AWARE
                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
@@ -14670,7 +14673,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Preconditions.checkCallAuthorization(
                hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
        return checkProvisioningPreconditionSkipPermission(action, packageName, caller.getUserId());
        long originalId = mInjector.binderClearCallingIdentity();
        try {
            return checkProvisioningPreconditionSkipPermission(
                    action, packageName, caller.getUserId());
        } finally {
            mInjector.binderRestoreCallingIdentity(originalId);
        }
    }
    private int checkProvisioningPreconditionSkipPermission(String action,
            String packageName, int userId) {
@@ -14736,22 +14746,31 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            return STATUS_USER_HAS_PROFILE_OWNER;
        }
        boolean isHeadlessSystemUserMode = mInjector.userManagerIsHeadlessSystemUserMode();
        // System user is always running in headless system user mode.
        if (!isHeadlessSystemUserMode
                && !mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
        if (!mUserManager.isUserRunning(new UserHandle(deviceOwnerUserId))) {
            return STATUS_USER_NOT_RUNNING;
        }
        if (mIsWatch && hasPaired(UserHandle.USER_SYSTEM)) {
            return STATUS_HAS_PAIRED;
        }
        boolean isHeadlessSystemUserMode = mInjector.userManagerIsHeadlessSystemUserMode();
        if (isHeadlessSystemUserMode) {
            if (deviceOwnerUserId != UserHandle.USER_SYSTEM) {
                Slogf.e(LOG_TAG, "In headless system user mode, "
                        + "device owner can only be set on headless system user.");
                return STATUS_NOT_SYSTEM_USER;
            }
            if (owner != null) {
                DeviceAdminInfo adminInfo = findAdmin(
                        owner, deviceOwnerUserId, /* throwForMissingPermission= */ false);
                if (adminInfo.getHeadlessDeviceOwnerMode()
                        != HEADLESS_DEVICE_OWNER_MODE_AFFILIATED) {
                    return STATUS_HEADLESS_SYSTEM_USER_MODE_NOT_SUPPORTED;
                }
            }
        }
        if (isAdb) {
@@ -18883,11 +18902,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                        "Provisioning preconditions failed with result: " + result);
            }
            onProvisionFullyManagedDeviceStarted(provisioningParams);
            // These properties are global so will apply on all users
            setTimeAndTimezone(provisioningParams.getTimeZone(), provisioningParams.getLocalTime());
            setLocale(provisioningParams.getLocale());
            final int deviceOwnerUserId = mInjector.userManagerIsHeadlessSystemUserMode()
                    ? UserHandle.USER_SYSTEM : caller.getUserId();
            int deviceOwnerUserId = UserHandle.USER_SYSTEM;
            if (!removeNonRequiredAppsForManagedDevice(
                    deviceOwnerUserId,
                    provisioningParams.isLeaveAllSystemAppsEnabled(),
@@ -19013,10 +19033,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    private void disallowAddUser() {
        if (!isHeadlessFlagEnabled() || mIsAutomotive) {
            // Auto still enables adding users due to the communal nature of those devices
            if (mInjector.userManagerIsHeadlessSystemUserMode()) {
                Slogf.i(LOG_TAG, "Not setting DISALLOW_ADD_USER on headless system user mode.");
                return;
            }
        }
        for (UserInfo userInfo : mUserManager.getUsers()) {
            UserHandle userHandle = userInfo.getUserHandle();
            if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER, userHandle)) {
Loading