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

Commit 262d2db5 authored by Elis Elliott's avatar Elis Elliott Committed by Android (Google) Code Review
Browse files

Merge "Add method to return an EnforcingAdmin after checking the caller's permissions."

parents ce7b8f0a 7b649b92
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -7708,7 +7708,7 @@ package android.app.admin {
    method @RequiresPermission(value=android.Manifest.permission.READ_NEARBY_STREAMING_POLICY, conditional=true) public int getNearbyAppStreamingPolicy();
    method @RequiresPermission(value=android.Manifest.permission.READ_NEARBY_STREAMING_POLICY, conditional=true) public int getNearbyNotificationStreamingPolicy();
    method @Deprecated @ColorInt public int getOrganizationColor(@NonNull android.content.ComponentName);
    method @Nullable public CharSequence getOrganizationName(@NonNull android.content.ComponentName);
    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY) public CharSequence getOrganizationName(@Nullable android.content.ComponentName);
    method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(@NonNull android.content.ComponentName);
    method @NonNull public android.app.admin.DevicePolicyManager getParentProfileInstance(@NonNull android.content.ComponentName);
    method @RequiresPermission(android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY) public int getPasswordComplexity();
@@ -7863,7 +7863,7 @@ package android.app.admin {
    method public void setNetworkLoggingEnabled(@Nullable android.content.ComponentName, boolean);
    method @Deprecated public void setOrganizationColor(@NonNull android.content.ComponentName, int);
    method public void setOrganizationId(@NonNull String);
    method public void setOrganizationName(@NonNull android.content.ComponentName, @Nullable CharSequence);
    method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY) public void setOrganizationName(@Nullable android.content.ComponentName, @Nullable CharSequence);
    method public void setOverrideApnsEnabled(@NonNull android.content.ComponentName, boolean);
    method @NonNull public String[] setPackagesSuspended(@NonNull android.content.ComponentName, @NonNull String[], boolean);
    method public void setPasswordExpirationTimeout(@NonNull android.content.ComponentName, long);
+27 −13
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.app.admin;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
import static android.Manifest.permission.SET_TIME_ZONE;
@@ -13485,18 +13486,24 @@ public class DevicePolicyManager {
    }
    /**
     * Called by the device owner (since API 26) or profile owner (since API 24) to set the name of
     * the organization under management.
     * Called by the device owner (since API 26) or profile owner (since API 24) or, starting from
     * Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
     * holders of the permission
     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY} to set the
     * name of the organization under management.
     *
     * <p>If the organization name needs to be localized, it is the responsibility of the {@link
     * DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast and set
     * a new version of this string accordingly.
     * <p>If the organization name needs to be localized, it is the responsibility of the caller
     * to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast and set a new version of this
     * string accordingly.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or can be
     * {@code null} if accessing with a permission without association with a DeviceAdminReceiver.
     * @param title The organization name or {@code null} to clear a previously set name.
     * @throws SecurityException if {@code admin} is not a device or profile owner.
     * @throws SecurityException if {@code admin} is not a device or profile owner or holder of the
     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY}.
     */
    public void setOrganizationName(@NonNull ComponentName admin, @Nullable CharSequence title) {
    @RequiresPermission(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY)
    public void setOrganizationName(@Nullable ComponentName admin, @Nullable CharSequence title) {
        throwIfParentInstance("setOrganizationName");
        try {
            mService.setOrganizationName(admin, title);
@@ -13506,14 +13513,21 @@ public class DevicePolicyManager {
    }
    /**
     * Called by a profile owner of a managed profile to retrieve the name of the organization under
     * management.
     * Called by the device owner (since API 26) or profile owner (since API 24) or, starting from
     * Android {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
     * holders of the permission
     * {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY
     * to retrieve the name of the organization under management.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or can be
     * {@code null} if accessing with a permission without association with a DeviceAdminReceiver.
     * @return The organization name or {@code null} if none is set.
     * @throws SecurityException if {@code admin} is not a profile owner.
     * @throws SecurityException if {@code admin} if {@code admin} is not a device or profile
     * owner or holder of the
     * permission {@link android.Manifest.permission#MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY}.
     */
    public @Nullable CharSequence getOrganizationName(@NonNull ComponentName admin) {
    @RequiresPermission(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY)
    public @Nullable CharSequence getOrganizationName(@Nullable ComponentName admin) {
        throwIfParentInstance("getOrganizationName");
        try {
            return mService.getOrganizationName(admin);
+111 −24
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
@@ -15436,16 +15437,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    @Override
    public void setOrganizationName(@NonNull ComponentName who, CharSequence text) {
    public void setOrganizationName(@Nullable ComponentName who, CharSequence text) {
        if (!mHasFeature) {
            return;
        }
        Objects.requireNonNull(who, "ComponentName is null");
        final CallerIdentity caller = getCallerIdentity(who);
        CallerIdentity caller = getCallerIdentity(who);
        ActiveAdmin admin = null;
        if (isPermissionCheckFlagEnabled()) {
            EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                    who,
                    MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
                    caller.getUserId());
            admin = enforcingAdmin.getActiveAdmin();
        } else {
            Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
        }
        synchronized (getLockObject()) {
            ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            if (!isPermissionCheckFlagEnabled()) {
                admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            }
            if (!TextUtils.equals(admin.organizationName, text)) {
                admin.organizationName = (text == null || text.length() == 0)
                        ? null : text.toString();
@@ -15455,20 +15467,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    @Override
    public CharSequence getOrganizationName(@NonNull ComponentName who) {
    public CharSequence getOrganizationName(@Nullable ComponentName who) {
        if (!mHasFeature) {
            return null;
        }
        Objects.requireNonNull(who, "ComponentName is null");
        CallerIdentity caller = getCallerIdentity(who);
        ActiveAdmin admin = null;
        final CallerIdentity caller = getCallerIdentity(who);
        if (isPermissionCheckFlagEnabled()) {
            EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
                    who,
                    MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
                    caller.getUserId());
            admin = enforcingAdmin.getActiveAdmin();
        } else {
            Preconditions.checkCallingUser(isManagedProfile(caller.getUserId()));
            Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
            synchronized (getLockObject()) {
            ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            return admin.organizationName;
                admin = getProfileOwnerOrDeviceOwnerLocked(caller.getUserId());
            }
        }
        return admin.organizationName;
    }
    /**
@@ -20092,22 +20113,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            MANAGE_DEVICE_POLICY_ACROSS_USERS,
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
            SET_TIME,
            SET_TIME_ZONE);
            SET_TIME_ZONE,
            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    private static final List<String> FINANCED_DEVICE_OWNER_PERMISSIONS = List.of(
            MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL,
            MANAGE_DEVICE_POLICY_ACROSS_USERS,
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL);
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    private static final List<String> PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE_PERMISSIONS =
            List.of(
                MANAGE_DEVICE_POLICY_ACROSS_USERS,
                MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
                SET_TIME,
                SET_TIME_ZONE);
                SET_TIME_ZONE,
                MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    private static final List<String> PROFILE_OWNER_ON_USER_0_PERMISSIONS  = List.of(
            SET_TIME,
            SET_TIME_ZONE);
    private static final List<String> PROFILE_OWNER_PERMISSIONS  = List.of(
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL);
            MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL,
            MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY);
    private static final HashMap<Integer, List<String>> DPC_PERMISSIONS = new HashMap<>();
    {
@@ -20125,9 +20150,48 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    private static final HashMap<String, String> CROSS_USER_PERMISSIONS =
            new HashMap<>();
    {
        // Auto time is intrinsically global so there is no cross-user permission.
        // Time and Timezone is intrinsically global so there is no cross-user permission.
        CROSS_USER_PERMISSIONS.put(SET_TIME, null);
        CROSS_USER_PERMISSIONS.put(SET_TIME_ZONE, null);
        // Organisation identity policy will involve data of other organisations on the device and
        // therefore the FULL cross-user permission is required.
        CROSS_USER_PERMISSIONS.put(MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
                MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL);
    }
    /**
     * Checks if the calling process has been granted permission to apply a device policy on a
     * specific user.
     * The given permission will be checked along with its associated cross-user permission if it
     * exists and the target user is different to the calling user.
     * Returns the {@link ActiveAdmin} of the caller.
     *
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associated cross-user permission if the caller's user is different to the target user.
     */
    private EnforcingAdmin enforcePermissionAndGetEnforcingAdmin(@Nullable ComponentName admin,
            String permission, int targetUserId) {
        enforcePermission(permission, targetUserId);
        return getEnforcingAdminForCaller(admin, getCallerIdentity());
    }
    /**
     * Checks whether the calling process has been granted permission to query a device policy on
     * a specific user.
     * The given permission will be checked along with its associated cross-user permission if it
     * exists and the target user is different to the calling user.
     *
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associated cross-user permission if the caller's user is different to the target user.
     */
    private EnforcingAdmin enforceCanQueryAndGetEnforcingAdmin(@Nullable ComponentName admin,
            String permission, int targetUserId) {
        enforceCanQuery(permission, targetUserId);
        return getEnforcingAdminForCaller(admin, getCallerIdentity());
    }
    /**
@@ -20139,7 +20203,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associtated cross-user permission if the caller's user is different to the target user.
     * the associated cross-user permission if the caller's user is different to the target user.
     */
    private void enforcePermission(String permission, int targetUserId)
            throws SecurityException {
@@ -20154,13 +20218,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }
    /**
     * Return whether the calling process has been granted permission to query a device policy on
     * Checks whether the calling process has been granted permission to query a device policy on
     * a specific user.
     * The given permission will be checked along with its associated cross-user permission if it
     * exists and the target user is different to the calling user.
     *
     * @param permission The name of the permission being checked.
     * @param targetUserId The userId of the user which the caller needs permission to act on.
     * @throws SecurityException if the caller has not been granted the given permission,
     * the associatated cross-user permission if the caller's user is different to the target user
     * the associated cross-user permission if the caller's user is different to the target user
     * and if the user has not been granted {@link QUERY_ADMIN_POLICY}.
     */
    private void enforceCanQuery(String permission, int targetUserId) throws SecurityException {
@@ -20225,10 +20291,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        // Check if the caller is an active admin that uses a certain policy.
        if (ACTIVE_ADMIN_POLICIES.containsKey(permission)) {
            try {
                return getActiveAdminForCallerLocked(
                        null, ACTIVE_ADMIN_POLICIES.get(permission), false) != null;
            } catch (SecurityException e) {
                // A security exception means there is not an active admin with permission and
                // therefore
                return false;
            }
        }
        return false;
    }
@@ -20258,6 +20329,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        return false;
    }
    private EnforcingAdmin getEnforcingAdminForCaller(@Nullable ComponentName who,
            CallerIdentity caller) {
        int userId = caller.getUserId();
        ActiveAdmin admin = null;
        synchronized (getLockObject()) {
            admin = getActiveAdminUncheckedLocked(who, userId);
        }
        if (isDeviceOwner(caller) || isProfileOwner(caller)) {
            return EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId, admin);
        }
        if (getActiveAdminUncheckedLocked(who, userId) != null) {
            return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
        }
        return  EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId);
    }
    private boolean isPermissionCheckFlagEnabled() {
        return DeviceConfig.getBoolean(
                NAMESPACE_DEVICE_POLICY_MANAGER,
+30 −4
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ final class EnforcingAdmin {
    private Set<String> mAuthorities;
    private final int mUserId;
    private final boolean mIsRoleAuthority;
    private final ActiveAdmin mActiveAdmin;

    static EnforcingAdmin createEnforcingAdmin(@NonNull String packageName, int userId) {
        Objects.requireNonNull(packageName);
@@ -73,14 +74,31 @@ final class EnforcingAdmin {
            @NonNull ComponentName componentName, int userId) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId);
                componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId,
                /* activeAdmin=*/ null);
    }

    static EnforcingAdmin createEnterpriseEnforcingAdmin(
            @NonNull ComponentName componentName, int userId, ActiveAdmin activeAdmin) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DPC_AUTHORITY), userId,
                activeAdmin);
    }

    static EnforcingAdmin createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DEVICE_ADMIN_AUTHORITY),
                userId);
                userId, /* activeAdmin=*/ null);
    }

    static EnforcingAdmin createDeviceAdminEnforcingAdmin(ComponentName componentName, int userId,
            ActiveAdmin activeAdmin) {
        Objects.requireNonNull(componentName);
        return new EnforcingAdmin(
                componentName.getPackageName(), componentName, Set.of(DEVICE_ADMIN_AUTHORITY),
                userId, activeAdmin);
    }

    static String getRoleAuthorityOf(String roleName) {
@@ -88,7 +106,8 @@ final class EnforcingAdmin {
    }

    private EnforcingAdmin(
            String packageName, ComponentName componentName, Set<String> authorities, int userId) {
            String packageName, ComponentName componentName, Set<String> authorities, int userId,
            ActiveAdmin activeAdmin) {
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(componentName);
        Objects.requireNonNull(authorities);
@@ -99,6 +118,7 @@ final class EnforcingAdmin {
        mComponentName = componentName;
        mAuthorities = new HashSet<>(authorities);
        mUserId = userId;
        mActiveAdmin = activeAdmin;
    }

    private EnforcingAdmin(String packageName, int userId) {
@@ -111,6 +131,7 @@ final class EnforcingAdmin {
        mComponentName = null;
        // authorities will be loaded when needed
        mAuthorities = null;
        mActiveAdmin = null;
    }

    private static Set<String> getRoleAuthoritiesOrDefault(String packageName, int userId) {
@@ -156,6 +177,11 @@ final class EnforcingAdmin {
        return mUserId;
    }

    @Nullable
    public ActiveAdmin getActiveAdmin() {
        return mActiveAdmin;
    }

    /**
     * For two EnforcingAdmins to be equal they must:
     *
@@ -224,7 +250,7 @@ final class EnforcingAdmin {
            String className = parser.getAttributeValue(/* namespace= */ null, ATTR_CLASS_NAME);
            ComponentName componentName = new ComponentName(packageName, className);
            Set<String> authorities = Set.of(authoritiesStr.split(ATTR_AUTHORITIES_SEPARATOR));
            return new EnforcingAdmin(packageName, componentName, authorities, userId);
            return new EnforcingAdmin(packageName, componentName, authorities, userId, null);
        }
    }