Loading core/java/android/app/admin/DevicePolicyManager.java +28 −1 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ import android.service.restrictions.RestrictionsReceiver; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.util.ArraySet; import android.util.DebugUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -2453,19 +2454,45 @@ public class DevicePolicyManager { @Retention(RetentionPolicy.SOURCE) public @interface PersonalAppsSuspensionReason {} // TODO(b/172376923) - make all (or none) @TestApi /** @hide */ @TestApi public static final int OPERATION_LOCK_NOW = 1; /** @hide */ public static final int OPERATION_SWITCH_USER = 2; /** @hide */ public static final int OPERATION_START_USER_IN_BACKGROUND = 3; /** @hide */ public static final int OPERATION_STOP_USER = 4; /** @hide */ public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; /** @hide */ public static final int OPERATION_REMOVE_USER = 6; private static final String PREFIX_OPERATION = "OPERATION_"; // TODO(b/172376923) - add all operations /** @hide */ @IntDef(prefix = "OPERATION_", value = { @IntDef(prefix = PREFIX_OPERATION, value = { OPERATION_LOCK_NOW, OPERATION_SWITCH_USER, OPERATION_START_USER_IN_BACKGROUND, OPERATION_STOP_USER, OPERATION_CREATE_AND_MANAGE_USER, OPERATION_REMOVE_USER }) @Retention(RetentionPolicy.SOURCE) public static @interface DevicePolicyOperation { } /** @hide */ public static String operationToString(@DevicePolicyOperation int operation) { return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); } /** * Return true if the given administrator component is currently active (enabled) in the system. * Loading core/java/android/util/DebugUtils.java +20 −0 Original line number Diff line number Diff line Loading @@ -271,6 +271,26 @@ public class DebugUtils { return res.toString(); } /** * Gets human-readable representation of constants (static final values). * * @hide */ public static String constantToString(Class<?> clazz, String prefix, int value) { for (Field field : clazz.getDeclaredFields()) { final int modifiers = field.getModifiers(); try { if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) && field.getType().equals(int.class) && field.getName().startsWith(prefix) && field.getInt(null) == value) { return constNameWithoutPrefix(prefix, field); } } catch (IllegalAccessException ignored) { } } return prefix + Integer.toString(value); } private static String constNameWithoutPrefix(String prefix, Field field) { return field.getName().substring(prefix.length()); } Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +18 −23 Original line number Diff line number Diff line Loading @@ -987,29 +987,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } /** * Checks if the feature is supported and it's safe to execute the given {@code operation}. * * <p>Typically called at the beginning of each API method as: * * <pre><code> * * if (!canExecute(operation, permission)) return; * * </code></pre> * * @return {@code true} when it's safe to execute, {@code false} when the feature is not * supported or the caller does not have the given {@code requiredPermission}. * Checks if it's safe to execute the given {@code operation}. * * @throws UnsafeStateException if it's not safe to execute the operation. */ boolean canExecute(@DevicePolicyOperation int operation, @NonNull String requiredPermission) { if (!mHasFeature && !hasCallingPermission(requiredPermission)) { return false; private void checkCanExecuteOrThrowUnsafe(@DevicePolicyOperation int operation) { if (!canExecute(operation)) { throw mSafetyChecker.newUnsafeStateException(operation); } if (mSafetyChecker == null || mSafetyChecker.isDevicePolicyOperationSafe(operation)) { return true; } throw mSafetyChecker.newUnsafeStateException(operation); /** * Returns whether it's safe to execute the given {@code operation}. */ boolean canExecute(@DevicePolicyOperation int operation) { return mSafetyChecker == null || mSafetyChecker.isDevicePolicyOperationSafe(operation); } /** Loading Loading @@ -4845,10 +4837,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void lockNow(int flags, boolean parent) { if (!canExecute(DevicePolicyManager.OPERATION_LOCK_NOW, permission.LOCK_DEVICE)) { return; } final CallerIdentity caller = getCallerIdentity(); final int callingUserId = caller.getUserId(); Loading @@ -4861,6 +4849,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent, android.Manifest.permission.LOCK_DEVICE); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_LOCK_NOW); final long ident = mInjector.binderClearCallingIdentity(); try { adminComponent = admin == null ? null : admin.info.getComponent(); Loading Loading @@ -9398,6 +9387,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkCallAuthorization(caller.getUserHandle().isSystem(), "createAndManageUser was called from non-system user"); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_CREATE_AND_MANAGE_USER); final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0; final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0 && UserManager.isDeviceInDemoMode(mContext); Loading Loading @@ -9526,6 +9517,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(userHandle, "UserHandle is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_USER); return mInjector.binderWithCleanCallingIdentity(() -> { String restriction = isManagedProfile(userHandle.getIdentifier()) Loading Loading @@ -9559,6 +9551,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SWITCH_USER); synchronized (getLockObject()) { long id = mInjector.binderClearCallingIdentity(); Loading @@ -9583,6 +9576,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(userHandle, "UserHandle is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_START_USER_IN_BACKGROUND); final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { Loading Loading @@ -9616,6 +9610,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(userHandle, "UserHandle is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_STOP_USER); final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +28 −1 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ import android.service.restrictions.RestrictionsReceiver; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.util.ArraySet; import android.util.DebugUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -2453,19 +2454,45 @@ public class DevicePolicyManager { @Retention(RetentionPolicy.SOURCE) public @interface PersonalAppsSuspensionReason {} // TODO(b/172376923) - make all (or none) @TestApi /** @hide */ @TestApi public static final int OPERATION_LOCK_NOW = 1; /** @hide */ public static final int OPERATION_SWITCH_USER = 2; /** @hide */ public static final int OPERATION_START_USER_IN_BACKGROUND = 3; /** @hide */ public static final int OPERATION_STOP_USER = 4; /** @hide */ public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; /** @hide */ public static final int OPERATION_REMOVE_USER = 6; private static final String PREFIX_OPERATION = "OPERATION_"; // TODO(b/172376923) - add all operations /** @hide */ @IntDef(prefix = "OPERATION_", value = { @IntDef(prefix = PREFIX_OPERATION, value = { OPERATION_LOCK_NOW, OPERATION_SWITCH_USER, OPERATION_START_USER_IN_BACKGROUND, OPERATION_STOP_USER, OPERATION_CREATE_AND_MANAGE_USER, OPERATION_REMOVE_USER }) @Retention(RetentionPolicy.SOURCE) public static @interface DevicePolicyOperation { } /** @hide */ public static String operationToString(@DevicePolicyOperation int operation) { return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); } /** * Return true if the given administrator component is currently active (enabled) in the system. * Loading
core/java/android/util/DebugUtils.java +20 −0 Original line number Diff line number Diff line Loading @@ -271,6 +271,26 @@ public class DebugUtils { return res.toString(); } /** * Gets human-readable representation of constants (static final values). * * @hide */ public static String constantToString(Class<?> clazz, String prefix, int value) { for (Field field : clazz.getDeclaredFields()) { final int modifiers = field.getModifiers(); try { if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers) && field.getType().equals(int.class) && field.getName().startsWith(prefix) && field.getInt(null) == value) { return constNameWithoutPrefix(prefix, field); } } catch (IllegalAccessException ignored) { } } return prefix + Integer.toString(value); } private static String constNameWithoutPrefix(String prefix, Field field) { return field.getName().substring(prefix.length()); } Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +18 −23 Original line number Diff line number Diff line Loading @@ -987,29 +987,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } /** * Checks if the feature is supported and it's safe to execute the given {@code operation}. * * <p>Typically called at the beginning of each API method as: * * <pre><code> * * if (!canExecute(operation, permission)) return; * * </code></pre> * * @return {@code true} when it's safe to execute, {@code false} when the feature is not * supported or the caller does not have the given {@code requiredPermission}. * Checks if it's safe to execute the given {@code operation}. * * @throws UnsafeStateException if it's not safe to execute the operation. */ boolean canExecute(@DevicePolicyOperation int operation, @NonNull String requiredPermission) { if (!mHasFeature && !hasCallingPermission(requiredPermission)) { return false; private void checkCanExecuteOrThrowUnsafe(@DevicePolicyOperation int operation) { if (!canExecute(operation)) { throw mSafetyChecker.newUnsafeStateException(operation); } if (mSafetyChecker == null || mSafetyChecker.isDevicePolicyOperationSafe(operation)) { return true; } throw mSafetyChecker.newUnsafeStateException(operation); /** * Returns whether it's safe to execute the given {@code operation}. */ boolean canExecute(@DevicePolicyOperation int operation) { return mSafetyChecker == null || mSafetyChecker.isDevicePolicyOperationSafe(operation); } /** Loading Loading @@ -4845,10 +4837,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void lockNow(int flags, boolean parent) { if (!canExecute(DevicePolicyManager.OPERATION_LOCK_NOW, permission.LOCK_DEVICE)) { return; } final CallerIdentity caller = getCallerIdentity(); final int callingUserId = caller.getUserId(); Loading @@ -4861,6 +4849,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent, android.Manifest.permission.LOCK_DEVICE); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_LOCK_NOW); final long ident = mInjector.binderClearCallingIdentity(); try { adminComponent = admin == null ? null : admin.info.getComponent(); Loading Loading @@ -9398,6 +9387,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Preconditions.checkCallAuthorization(caller.getUserHandle().isSystem(), "createAndManageUser was called from non-system user"); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_CREATE_AND_MANAGE_USER); final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0; final boolean demo = (flags & DevicePolicyManager.MAKE_USER_DEMO) != 0 && UserManager.isDeviceInDemoMode(mContext); Loading Loading @@ -9526,6 +9517,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(userHandle, "UserHandle is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_USER); return mInjector.binderWithCleanCallingIdentity(() -> { String restriction = isManagedProfile(userHandle.getIdentifier()) Loading Loading @@ -9559,6 +9551,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(who, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SWITCH_USER); synchronized (getLockObject()) { long id = mInjector.binderClearCallingIdentity(); Loading @@ -9583,6 +9576,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(userHandle, "UserHandle is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_START_USER_IN_BACKGROUND); final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { Loading Loading @@ -9616,6 +9610,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(userHandle, "UserHandle is null"); final CallerIdentity caller = getCallerIdentity(who); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_STOP_USER); final int userId = userHandle.getIdentifier(); if (isManagedProfile(userId)) { Loading