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

Commit 3001af92 authored by Anthony Alridge's avatar Anthony Alridge
Browse files

User restriction to block adding SIMs

Adds a flag for the eSIM project, and define user restriction
that will block addition of new SIMs to the device.

Next steps:
- Settings policy transparency
- Programatically disable physical SIMs when the restriction is set

Test: TestDPC, set restriction, observe actions blocked in settings

Change-Id: Id89a3c19a0c8795da729082171977c5170167f9f
Bug: 316325560
parent 931043d1
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -33709,6 +33709,7 @@ package android.os {
    field public static final String DISALLOW_SHARE_INTO_MANAGED_PROFILE = "no_sharing_into_profile";
    field public static final String DISALLOW_SHARE_INTO_MANAGED_PROFILE = "no_sharing_into_profile";
    field public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
    field public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
    field public static final String DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI = "no_sharing_admin_configured_wifi";
    field public static final String DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI = "no_sharing_admin_configured_wifi";
    field @FlaggedApi("android.app.admin.flags.esim_management_enabled") public static final String DISALLOW_SIM_GLOBALLY = "no_sim_globally";
    field public static final String DISALLOW_SMS = "no_sms";
    field public static final String DISALLOW_SMS = "no_sms";
    field public static final String DISALLOW_SYSTEM_ERROR_DIALOGS = "no_system_error_dialogs";
    field public static final String DISALLOW_SYSTEM_ERROR_DIALOGS = "no_system_error_dialogs";
    field @FlaggedApi("com.android.net.thread.flags.thread_user_restriction_enabled") public static final String DISALLOW_THREAD_NETWORK = "no_thread_network";
    field @FlaggedApi("com.android.net.thread.flags.thread_user_restriction_enabled") public static final String DISALLOW_THREAD_NETWORK = "no_thread_network";
+7 −0
Original line number Original line Diff line number Diff line
@@ -69,3 +69,10 @@ flag {
  description: "Emit a security log event when DPM.setBackupServiceEnabled is called"
  description: "Emit a security log event when DPM.setBackupServiceEnabled is called"
  bug: "304999634"
  bug: "304999634"
}
}

flag {
  name: "esim_management_enabled"
  namespace: "enterprise"
  description: "Enable APIs to provision and manage eSIMs"
  bug: "295301164"
}
+31 −0
Original line number Original line Diff line number Diff line
@@ -1921,6 +1921,36 @@ public class UserManager {
    @FlaggedApi("com.android.net.thread.flags.thread_user_restriction_enabled")
    @FlaggedApi("com.android.net.thread.flags.thread_user_restriction_enabled")
    public static final String DISALLOW_THREAD_NETWORK = "no_thread_network";
    public static final String DISALLOW_THREAD_NETWORK = "no_thread_network";


    /**
     * This user restriction specifies if the user is able to add SIMs to the device.
     *
     * <p>
     * This restriction blocks the download of embedded SIMs, and disables any physical SIMs.
     * If any embedded SIMs are already on the device, then they are removed. This restriction
     * does not affect SIMs provisioned to the device by device owners or profile owners.
     *
     * <p>
     * This restriction can only be set by a device owner or a profile owner of an
     * organization-owned managed profile.
     * In both cases, the restriction applies globally on the device.
     *
     * <p>
     * Holders of the permission
     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_MOBILE_NETWORK}
     * can set this restriction using the DevicePolicyManager APIs mentioned below.
     *
     * <p>Default is <code>false</code>.
     *
     * <p>Key for user restrictions.
     * <p>Type: Boolean
     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
     * @see #getUserRestrictions()
     */
    @FlaggedApi(android.app.admin.flags.Flags.FLAG_ESIM_MANAGEMENT_ENABLED)
    public static final String DISALLOW_SIM_GLOBALLY =
            "no_sim_globally";

    /**
    /**
     * List of key values that can be passed into the various user restriction related methods
     * List of key values that can be passed into the various user restriction related methods
     * in {@link UserManager} & {@link DevicePolicyManager}.
     * in {@link UserManager} & {@link DevicePolicyManager}.
@@ -2008,6 +2038,7 @@ public class UserManager {
            DISALLOW_GRANT_ADMIN,
            DISALLOW_GRANT_ADMIN,
            DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO,
            DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO,
            DISALLOW_THREAD_NETWORK,
            DISALLOW_THREAD_NETWORK,
            DISALLOW_SIM_GLOBALLY,
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    public @interface UserRestrictionKey {}
    public @interface UserRestrictionKey {}
+66 −12
Original line number Original line Diff line number Diff line
@@ -153,7 +153,8 @@ public class UserRestrictionsUtils {
            UserManager.DISALLOW_CELLULAR_2G,
            UserManager.DISALLOW_CELLULAR_2G,
            UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO,
            UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO,
            UserManager.DISALLOW_CONFIG_DEFAULT_APPS,
            UserManager.DISALLOW_CONFIG_DEFAULT_APPS,
            UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO
            UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO,
            UserManager.DISALLOW_SIM_GLOBALLY
    });
    });


    public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet(
    public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet(
@@ -236,7 +237,7 @@ public class UserRestrictionsUtils {
     * Special user restrictions that profile owner of an organization-owned managed profile can
     * Special user restrictions that profile owner of an organization-owned managed profile can
     * set on the parent profile instance to apply them globally.
     * set on the parent profile instance to apply them globally.
     */
     */
    private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS =
    private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_PARENT_GLOBAL_RESTRICTIONS =
            Sets.newArraySet(
            Sets.newArraySet(
                    UserManager.DISALLOW_AIRPLANE_MODE,
                    UserManager.DISALLOW_AIRPLANE_MODE,
                    UserManager.DISALLOW_CONFIG_DATE_TIME,
                    UserManager.DISALLOW_CONFIG_DATE_TIME,
@@ -251,6 +252,15 @@ public class UserRestrictionsUtils {
                    UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO
                    UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO
            );
            );


    /**
     * Special user restrictions that profile owner of an organization-owned managed profile can
     * set on the profile, which regular profile owners cannot set.
     */
    private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_PROFILE_RESTRICTIONS =
            Sets.newArraySet(
                    UserManager.DISALLOW_SIM_GLOBALLY
            );

    /**
    /**
     * Special user restrictions that profile owner of an organization-owned managed profile can
     * Special user restrictions that profile owner of an organization-owned managed profile can
     * set on the parent profile instance to apply them on the personal profile.
     * set on the parent profile instance to apply them on the personal profile.
@@ -296,7 +306,8 @@ public class UserRestrictionsUtils {
    private static final Set<String> PROFILE_GLOBAL_RESTRICTIONS = Sets.newArraySet(
    private static final Set<String> PROFILE_GLOBAL_RESTRICTIONS = Sets.newArraySet(
            UserManager.ENSURE_VERIFY_APPS,
            UserManager.ENSURE_VERIFY_APPS,
            UserManager.DISALLOW_AIRPLANE_MODE,
            UserManager.DISALLOW_AIRPLANE_MODE,
            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY
            UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
            UserManager.DISALLOW_SIM_GLOBALLY
    );
    );


    /**
    /**
@@ -460,21 +471,64 @@ public class UserRestrictionsUtils {
    }
    }


    /**
    /**
     * @return true if a restriction is settable by profile owner.  Note it takes a boolean to say
     * Checks whether a restriction is settable by a profile owner
     * if the relevant user is the {@link UserManager#isMainUser() MainUser}, because some
     *
     * restrictions can be changed by PO only when it's running on the main user.
     * <p> Whether a restriction is settable by a profile owner is a property of the restriction and
     * defined statically by the restriction. It may depend on other context information, such
     * as whether the relevant user is the {@link UserManager#isMainUser() MainUser}.
     *
     * @param restriction the restrictions to check
     * @param isMainUser true if the relevant user is the {@link UserManager#isMainUser() MainUser}.
     *                   Some restrictions can be changed by PO only when it's running on the main
     *                   user.
     * @param isProfileOwnerOnOrgOwnedDevice true if the relevant user is the profile owner of an
     *                                       organization owned device. Some restrictions can only
     *                                       be set by PO when it's running as the profile owner
     *                                       on an organization owned device.
     * @return true if a restriction is settable by a profile owner
     */
     */
    public static boolean canProfileOwnerChange(String restriction, boolean isMainUser) {
    public static boolean canProfileOwnerChange(
            String restriction,
            boolean isMainUser,
            boolean isProfileOwnerOnOrgOwnedDevice) {
        if (android.app.admin.flags.Flags.esimManagementEnabled()) {
            if (IMMUTABLE_BY_OWNERS.contains(restriction)) {
                return false;
            }
            if (DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction)) {
                return false;
            }
            if (!isMainUser && MAIN_USER_ONLY_RESTRICTIONS.contains(restriction)) {
                return false;
            }
            if (!isProfileOwnerOnOrgOwnedDevice
                    && PROFILE_OWNER_ORGANIZATION_OWNED_PROFILE_RESTRICTIONS.contains(
                            restriction)) {
                return false;
            }
            return true;
        }
        return !IMMUTABLE_BY_OWNERS.contains(restriction)
        return !IMMUTABLE_BY_OWNERS.contains(restriction)
                && !DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction)
                && !DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction)
                && !(!isMainUser && MAIN_USER_ONLY_RESTRICTIONS.contains(restriction));
                && !(!isMainUser && MAIN_USER_ONLY_RESTRICTIONS.contains(restriction));
    }
    }


    /**
    /**
     * @return true if a restriction is settable by profile owner of an organization owned device.
     * Checks whether a restriction is settable by a profile owner on the parent instance
     * of an organization owned device.
     *
     * <p> Whether a restriction is settable by a profile owner is a property of the restriction and
     * defined statically by the restriction.
     *
     * <p> Note: This is used to check whether a restriction can be set by a profile owner
     *     on the parent instance.
     *
     * @param restriction the restrictions to check
     * @return true if a restriction is settable by a profile owner on the parent instance
     */
     */
    public static boolean canProfileOwnerOfOrganizationOwnedDeviceChange(String restriction) {
    public static boolean canParentOfProfileOwnerOfOrganizationOwnedDeviceChange(
        return PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(restriction)
            String restriction) {
        return PROFILE_OWNER_ORGANIZATION_OWNED_PARENT_GLOBAL_RESTRICTIONS.contains(restriction)
                || PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS.contains(restriction);
                || PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS.contains(restriction);
    }
    }


@@ -503,7 +557,7 @@ public class UserRestrictionsUtils {
                MAIN_USER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)))
                MAIN_USER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)))
                || ((restrictionOwnerType
                || ((restrictionOwnerType
                == UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)
                == UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)
                && PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(key))
                && (PROFILE_OWNER_ORGANIZATION_OWNED_PARENT_GLOBAL_RESTRICTIONS.contains(key)))
                || PROFILE_GLOBAL_RESTRICTIONS.contains(key)
                || PROFILE_GLOBAL_RESTRICTIONS.contains(key)
                || DEVICE_OWNER_ONLY_RESTRICTIONS.contains(key);
                || DEVICE_OWNER_ONLY_RESTRICTIONS.contains(key);
    }
    }
+14 −6
Original line number Original line Diff line number Diff line
@@ -2581,7 +2581,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            return;
            return;
        }
        }
        for (final String restriction : doAdmin.userRestrictions.keySet()) {
        for (final String restriction : doAdmin.userRestrictions.keySet()) {
            if (UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(restriction)) {
            if (UserRestrictionsUtils.canParentOfProfileOwnerOfOrganizationOwnedDeviceChange(
                    restriction)) {
                parentAdmin.ensureUserRestrictions().putBoolean(
                parentAdmin.ensureUserRestrictions().putBoolean(
                        restriction, doAdmin.userRestrictions.getBoolean(restriction));
                        restriction, doAdmin.userRestrictions.getBoolean(restriction));
            }
            }
@@ -13047,9 +13048,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    }
    private void checkAdminCanSetRestriction(CallerIdentity caller, boolean parent, String key) {
    private void checkAdminCanSetRestriction(CallerIdentity caller, boolean parent, String key) {
        boolean isProfileOwnerOfOrganizationOwnedDevice =
                isProfileOwnerOfOrganizationOwnedDevice(caller);
        if (parent) {
        if (parent) {
            Preconditions.checkCallAuthorization(
            Preconditions.checkCallAuthorization(
                    isProfileOwnerOfOrganizationOwnedDevice(caller));
                    isProfileOwnerOfOrganizationOwnedDevice);
        } else {
        } else {
            Preconditions.checkCallAuthorization(
            Preconditions.checkCallAuthorization(
                    isDeviceOwner(caller) || isProfileOwner(caller));
                    isDeviceOwner(caller) || isProfileOwner(caller));
@@ -13073,11 +13076,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            } else {
            } else {
                boolean profileOwnerCanChangeOnItself = !parent
                boolean profileOwnerCanChangeOnItself = !parent
                        && UserRestrictionsUtils.canProfileOwnerChange(
                        && UserRestrictionsUtils.canProfileOwnerChange(
                        key, caller.getUserId() == getMainUserId());
                            key,
                            caller.getUserId() == getMainUserId(),
                            isProfileOwnerOfOrganizationOwnedDevice);
                boolean orgOwnedProfileOwnerCanChangeGlobally = parent
                boolean orgOwnedProfileOwnerCanChangeGlobally = parent
                        && isProfileOwnerOfOrganizationOwnedDevice(caller)
                        && isProfileOwnerOfOrganizationOwnedDevice
                        && UserRestrictionsUtils.canProfileOwnerOfOrganizationOwnedDeviceChange(
                        && UserRestrictionsUtils
                        key);
                            .canParentOfProfileOwnerOfOrganizationOwnedDeviceChange(key);
                if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) {
                if (!profileOwnerCanChangeOnItself && !orgOwnedProfileOwnerCanChangeGlobally) {
                    throw new SecurityException("Profile owner cannot set user restriction "
                    throw new SecurityException("Profile owner cannot set user restriction "
@@ -13370,6 +13375,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                UserManager.DISALLOW_WIFI_TETHERING, new String[]{MANAGE_DEVICE_POLICY_WIFI});
                UserManager.DISALLOW_WIFI_TETHERING, new String[]{MANAGE_DEVICE_POLICY_WIFI});
        USER_RESTRICTION_PERMISSIONS.put(
        USER_RESTRICTION_PERMISSIONS.put(
                UserManager.ENSURE_VERIFY_APPS, new String[]{MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES});
                UserManager.ENSURE_VERIFY_APPS, new String[]{MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES});
        USER_RESTRICTION_PERMISSIONS.put(
                UserManager.DISALLOW_SIM_GLOBALLY,
                new String[]{MANAGE_DEVICE_POLICY_MOBILE_NETWORK});
        // Restrictions not allowed to be set by admins.
        // Restrictions not allowed to be set by admins.
        USER_RESTRICTION_PERMISSIONS.put(
        USER_RESTRICTION_PERMISSIONS.put(
Loading