Loading core/api/current.txt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -6896,6 +6896,7 @@ package android.app.admin { method public void onLockTaskModeEntering(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull String); method public void onLockTaskModeEntering(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull String); method public void onLockTaskModeExiting(@NonNull android.content.Context, @NonNull android.content.Intent); method public void onLockTaskModeExiting(@NonNull android.content.Context, @NonNull android.content.Intent); method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int); method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int); method public void onOperationSafetyStateChanged(@NonNull android.content.Context, int, boolean); method @Deprecated public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent); method @Deprecated public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent); method public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle); method public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle); method @Deprecated public void onPasswordExpiring(@NonNull android.content.Context, @NonNull android.content.Intent); method @Deprecated public void onPasswordExpiring(@NonNull android.content.Context, @NonNull android.content.Intent); Loading Loading @@ -7072,6 +7073,7 @@ package android.app.admin { method public boolean isProfileOwnerApp(String); method public boolean isProfileOwnerApp(String); method public boolean isProvisioningAllowed(@NonNull String); method public boolean isProvisioningAllowed(@NonNull String); method public boolean isResetPasswordTokenActive(android.content.ComponentName); method public boolean isResetPasswordTokenActive(android.content.ComponentName); method public boolean isSafeOperation(int); method public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName); method public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName); method public boolean isUninstallBlocked(@Nullable android.content.ComponentName, String); method public boolean isUninstallBlocked(@Nullable android.content.ComponentName, String); method public boolean isUniqueDeviceAttestationSupported(); method public boolean isUniqueDeviceAttestationSupported(); Loading Loading @@ -7300,6 +7302,7 @@ package android.app.admin { field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1 field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1 field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2 field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2 field public static final String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning"; field public static final String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning"; field public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1; // 0x1 field public static final int PASSWORD_COMPLEXITY_HIGH = 327680; // 0x50000 field public static final int PASSWORD_COMPLEXITY_HIGH = 327680; // 0x50000 field public static final int PASSWORD_COMPLEXITY_LOW = 65536; // 0x10000 field public static final int PASSWORD_COMPLEXITY_LOW = 65536; // 0x10000 field public static final int PASSWORD_COMPLEXITY_MEDIUM = 196608; // 0x30000 field public static final int PASSWORD_COMPLEXITY_MEDIUM = 196608; // 0x30000 Loading Loading @@ -7336,7 +7339,6 @@ package android.app.admin { field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 field public static final int UNSAFE_OPERATION_REASON_DRIVING_DISTRACTION = 1; // 0x1 field public static final int WIPE_EUICC = 4; // 0x4 field public static final int WIPE_EUICC = 4; // 0x4 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 Loading Loading @@ -7490,7 +7492,7 @@ package android.app.admin { public final class UnsafeStateException extends java.lang.IllegalStateException implements android.os.Parcelable { public final class UnsafeStateException extends java.lang.IllegalStateException implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method public int getReason(); method @NonNull public java.util.List<java.lang.Integer> getReasons(); method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.UnsafeStateException> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.UnsafeStateException> CREATOR; } } core/api/test-current.txt +2 −2 Original line number Original line Diff line number Diff line Loading @@ -391,11 +391,11 @@ package android.app.admin { method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle); method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle); method public boolean isCurrentInputMethodSetByOwner(); method public boolean isCurrentInputMethodSetByOwner(); method public boolean isFactoryResetProtectionPolicySupported(); method public boolean isFactoryResetProtectionPolicySupported(); method @NonNull public static String operationSafetyReasonToString(int); method @NonNull public static String operationToString(int); method @NonNull public static String operationToString(int); method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException; method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException; method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int); method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int); method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int); method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int); method @NonNull public static String unsafeOperationReasonToString(int); field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final int CODE_ACCOUNTS_NOT_EMPTY = 6; // 0x6 field public static final int CODE_ACCOUNTS_NOT_EMPTY = 6; // 0x6 field public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11; // 0xb field public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11; // 0xb Loading Loading @@ -425,6 +425,7 @@ package android.app.admin { field public static final int OPERATION_REMOVE_KEY_PAIR = 28; // 0x1c field public static final int OPERATION_REMOVE_KEY_PAIR = 28; // 0x1c field public static final int OPERATION_REMOVE_USER = 6; // 0x6 field public static final int OPERATION_REMOVE_USER = 6; // 0x6 field public static final int OPERATION_REQUEST_BUGREPORT = 29; // 0x1d field public static final int OPERATION_REQUEST_BUGREPORT = 29; // 0x1d field public static final int OPERATION_SAFETY_REASON_NONE = -1; // 0xffffffff field public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30; // 0x1e field public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30; // 0x1e field public static final int OPERATION_SET_APPLICATION_HIDDEN = 15; // 0xf field public static final int OPERATION_SET_APPLICATION_HIDDEN = 15; // 0xf field public static final int OPERATION_SET_APPLICATION_RESTRICTIONS = 16; // 0x10 field public static final int OPERATION_SET_APPLICATION_RESTRICTIONS = 16; // 0x10 Loading Loading @@ -460,7 +461,6 @@ package android.app.admin { field public static final int PROVISIONING_RESULT_SETTING_PROFILE_OWNER_FAILED = 4; // 0x4 field public static final int PROVISIONING_RESULT_SETTING_PROFILE_OWNER_FAILED = 4; // 0x4 field public static final int PROVISIONING_RESULT_SET_DEVICE_OWNER_FAILED = 7; // 0x7 field public static final int PROVISIONING_RESULT_SET_DEVICE_OWNER_FAILED = 7; // 0x7 field public static final int PROVISIONING_RESULT_STARTING_PROFILE_FAILED = 5; // 0x5 field public static final int PROVISIONING_RESULT_STARTING_PROFILE_FAILED = 5; // 0x5 field public static final int UNSAFE_OPERATION_REASON_NONE = -1; // 0xffffffff } } public final class FullyManagedDeviceProvisioningParams implements android.os.Parcelable { public final class FullyManagedDeviceProvisioningParams implements android.os.Parcelable { Loading core/java/android/app/admin/DeviceAdminReceiver.java +85 −2 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.app.admin; package android.app.admin; import static android.app.admin.DevicePolicyManager.OperationSafetyReason; import android.accounts.AccountManager; import android.accounts.AccountManager; import android.annotation.BroadcastBehavior; import android.annotation.BroadcastBehavior; import android.annotation.IntDef; import android.annotation.IntDef; Loading @@ -35,6 +37,7 @@ import android.os.PersistableBundle; import android.os.Process; import android.os.Process; import android.os.UserHandle; import android.os.UserHandle; import android.security.KeyChain; import android.security.KeyChain; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -72,8 +75,8 @@ import java.lang.annotation.RetentionPolicy; * </div> * </div> */ */ public class DeviceAdminReceiver extends BroadcastReceiver { public class DeviceAdminReceiver extends BroadcastReceiver { private static String TAG = "DevicePolicy"; private static final String TAG = "DevicePolicy"; private static boolean localLOGV = false; private static final boolean LOCAL_LOGV = false; /** /** * This is the primary action that a device administrator must implement to be * This is the primary action that a device administrator must implement to be Loading Loading @@ -509,6 +512,36 @@ public class DeviceAdminReceiver extends BroadcastReceiver { public static final String EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE = public static final String EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE = "android.app.extra.TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE"; "android.app.extra.TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE"; /** * Broadcast action: notify the admin that the state of operations that can be unsafe because * of a given reason (specified by the {@link #EXTRA_OPERATION_SAFETY_REASON} {@code int} extra) * has changed (the new value is specified by the {@link #EXTRA_OPERATION_SAFETY_STATE} * {@code boolean} extra). * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_OPERATION_SAFETY_STATE_CHANGED = "android.app.action.OPERATION_SAFETY_STATE_CHANGED"; /** * An {@code int} extra specifying an {@link OperationSafetyReason}. * * @hide */ public static final String EXTRA_OPERATION_SAFETY_REASON = "android.app.extra.OPERATION_SAFETY_REASON"; /** * An {@code boolean} extra specifying whether an operation will fail due to a * {@link OperationSafetyReason}. {@code true} means operations that rely on that reason are * safe, while {@code false} means they're unsafe. * * @hide */ public static final String EXTRA_OPERATION_SAFETY_STATE = "android.app.extra.OPERATION_SAFETY_STATE"; private DevicePolicyManager mManager; private DevicePolicyManager mManager; private ComponentName mWho; private ComponentName mWho; Loading Loading @@ -1017,6 +1050,51 @@ public class DeviceAdminReceiver extends BroadcastReceiver { @NonNull UserHandle user) { @NonNull UserHandle user) { } } /** * Called to notify the state of operations that can be unsafe to execute has changed. * * <p><b>Note:/b> notice that the operation safety state might change between the time this * callback is received and the operation's method on {@link DevicePolicyManager} is called, so * calls to the latter could still throw a {@link UnsafeStateException} even when this method * is called with {@code isSafe} as {@code true} * * @param context the running context as per {@link #onReceive} * @param reason the reason an operation could be unsafe. * @param isSafe whether the operation is safe to be executed. */ public void onOperationSafetyStateChanged(@NonNull Context context, @OperationSafetyReason int reason, boolean isSafe) { if (LOCAL_LOGV) { Log.v(TAG, String.format("onOperationSafetyStateChanged(): %s=%b", DevicePolicyManager.operationSafetyReasonToString(reason), isSafe)); } } private void onOperationSafetyStateChanged(Context context, Intent intent) { if (!hasRequiredExtra(intent, EXTRA_OPERATION_SAFETY_REASON) || !hasRequiredExtra(intent, EXTRA_OPERATION_SAFETY_STATE)) { return; } int reason = intent.getIntExtra(EXTRA_OPERATION_SAFETY_REASON, DevicePolicyManager.OPERATION_SAFETY_REASON_NONE); if (!DevicePolicyManager.isValidOperationSafetyReason(reason)) { Log.wtf(TAG, "Received invalid reason on " + intent.getAction() + ": " + reason); return; } boolean isSafe = intent.getBooleanExtra(EXTRA_OPERATION_SAFETY_STATE, /* defaultValue=*/ false); onOperationSafetyStateChanged(context, reason, isSafe); } private boolean hasRequiredExtra(Intent intent, String extra) { if (intent.hasExtra(extra)) return true; Log.wtf(TAG, "Missing '" + extra + "' on intent " + intent); return false; } /** /** * Intercept standard device administrator broadcasts. Implementations * Intercept standard device administrator broadcasts. Implementations * should not override this method; it is better to implement the * should not override this method; it is better to implement the Loading @@ -1025,6 +1103,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver { @Override @Override public void onReceive(@NonNull Context context, @NonNull Intent intent) { public void onReceive(@NonNull Context context, @NonNull Intent intent) { String action = intent.getAction(); String action = intent.getAction(); if (LOCAL_LOGV) { Log.v(TAG, "onReceive(): received " + action + " on user " + context.getUserId()); } if (ACTION_PASSWORD_CHANGED.equals(action)) { if (ACTION_PASSWORD_CHANGED.equals(action)) { onPasswordChanged(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER)); onPasswordChanged(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER)); Loading Loading @@ -1092,6 +1173,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver { } else if (ACTION_AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) { } else if (ACTION_AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) { onTransferAffiliatedProfileOwnershipComplete(context, onTransferAffiliatedProfileOwnershipComplete(context, intent.getParcelableExtra(Intent.EXTRA_USER)); intent.getParcelableExtra(Intent.EXTRA_USER)); } else if (ACTION_OPERATION_SAFETY_STATE_CHANGED.equals(action)) { onOperationSafetyStateChanged(context, intent); } } } } } } core/java/android/app/admin/DevicePolicyManager.java +38 −10 Original line number Original line Diff line number Diff line Loading @@ -2922,33 +2922,61 @@ public class DevicePolicyManager { return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); } } private static final String PREFIX_UNSAFE_OPERATION_REASON = "UNSAFE_OPERATION_REASON_"; private static final String PREFIX_OPERATION_SAFETY_REASON = "OPERATION_SAFETY_REASON_"; /** @hide */ /** @hide */ @IntDef(prefix = PREFIX_UNSAFE_OPERATION_REASON, value = { @IntDef(prefix = PREFIX_OPERATION_SAFETY_REASON, value = { UNSAFE_OPERATION_REASON_NONE, OPERATION_SAFETY_REASON_NONE, UNSAFE_OPERATION_REASON_DRIVING_DISTRACTION OPERATION_SAFETY_REASON_DRIVING_DISTRACTION }) }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) public static @interface UnsafeOperationReason { public static @interface OperationSafetyReason { } } /** @hide */ /** @hide */ @TestApi @TestApi public static final int UNSAFE_OPERATION_REASON_NONE = -1; public static final int OPERATION_SAFETY_REASON_NONE = -1; /** /** * Indicates that a {@link UnsafeStateException} was thrown because the operation would distract * Indicates that a {@link UnsafeStateException} was thrown because the operation would distract * the driver of the vehicle. * the driver of the vehicle. */ */ public static final int UNSAFE_OPERATION_REASON_DRIVING_DISTRACTION = 1; public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1; /** @hide */ /** @hide */ @NonNull @NonNull @TestApi @TestApi public static String unsafeOperationReasonToString(@UnsafeOperationReason int reason) { public static String operationSafetyReasonToString(@OperationSafetyReason int reason) { return DebugUtils.constantToString(DevicePolicyManager.class, return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_UNSAFE_OPERATION_REASON, reason); PREFIX_OPERATION_SAFETY_REASON, reason); } /** @hide */ public static boolean isValidOperationSafetyReason(@OperationSafetyReason int reason) { return reason == OPERATION_SAFETY_REASON_DRIVING_DISTRACTION; } /** * Checks if it's safe to run operations that can be affected by the given {@code reason}. * * <p><b>Note:/b> notice that the operation safety state might change between the time this * method returns and the operation's method is called, so calls to the latter could still throw * a {@link UnsafeStateException} even when this method returns {@code true}. * * @param reason currently, only supported reason is * {@link #OPERATION_SAFETY_REASON_DRIVING_DISTRACTION}. * * @return whether it's safe to run operations that can be affected by the given {@code reason}. */ // TODO(b/173541467): should it throw SecurityException if caller is not admin? public boolean isSafeOperation(@OperationSafetyReason int reason) { if (mService == null) return false; try { return mService.isSafeOperation(reason); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** @hide */ /** @hide */ Loading Loading @@ -13157,7 +13185,7 @@ public class DevicePolicyManager { @TestApi @TestApi @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(@DevicePolicyOperation int operation, public void setNextOperationSafety(@DevicePolicyOperation int operation, @UnsafeOperationReason int reason) { @OperationSafetyReason int reason) { if (mService != null) { if (mService != null) { try { try { mService.setNextOperationSafety(operation, reason); mService.setNextOperationSafety(operation, reason); core/java/android/app/admin/DevicePolicyManagerInternal.java +11 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.app.admin; import android.annotation.Nullable; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.admin.DevicePolicyManager.OperationSafetyReason; import android.content.ComponentName; import android.content.ComponentName; import android.content.Intent; import android.content.Intent; import android.os.UserHandle; import android.os.UserHandle; Loading Loading @@ -255,4 +256,14 @@ public abstract class DevicePolicyManagerInternal { * {@link #supportsResetOp(int)} is true. * {@link #supportsResetOp(int)} is true. */ */ public abstract void resetOp(int op, String packageName, @UserIdInt int userId); public abstract void resetOp(int op, String packageName, @UserIdInt int userId); /** * Notifies the system that an unsafe operation reason has changed. * * @throws IllegalArgumentException if {@code checker} is not the same as set on * {@code DevicePolicyManagerService}. */ public abstract void notifyUnsafeOperationStateChanged(DevicePolicySafetyChecker checker, @OperationSafetyReason int reason, boolean isSafe); } } Loading
core/api/current.txt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -6896,6 +6896,7 @@ package android.app.admin { method public void onLockTaskModeEntering(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull String); method public void onLockTaskModeEntering(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull String); method public void onLockTaskModeExiting(@NonNull android.content.Context, @NonNull android.content.Intent); method public void onLockTaskModeExiting(@NonNull android.content.Context, @NonNull android.content.Intent); method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int); method public void onNetworkLogsAvailable(@NonNull android.content.Context, @NonNull android.content.Intent, long, @IntRange(from=1) int); method public void onOperationSafetyStateChanged(@NonNull android.content.Context, int, boolean); method @Deprecated public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent); method @Deprecated public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent); method public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle); method public void onPasswordChanged(@NonNull android.content.Context, @NonNull android.content.Intent, @NonNull android.os.UserHandle); method @Deprecated public void onPasswordExpiring(@NonNull android.content.Context, @NonNull android.content.Intent); method @Deprecated public void onPasswordExpiring(@NonNull android.content.Context, @NonNull android.content.Intent); Loading Loading @@ -7072,6 +7073,7 @@ package android.app.admin { method public boolean isProfileOwnerApp(String); method public boolean isProfileOwnerApp(String); method public boolean isProvisioningAllowed(@NonNull String); method public boolean isProvisioningAllowed(@NonNull String); method public boolean isResetPasswordTokenActive(android.content.ComponentName); method public boolean isResetPasswordTokenActive(android.content.ComponentName); method public boolean isSafeOperation(int); method public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName); method public boolean isSecurityLoggingEnabled(@Nullable android.content.ComponentName); method public boolean isUninstallBlocked(@Nullable android.content.ComponentName, String); method public boolean isUninstallBlocked(@Nullable android.content.ComponentName, String); method public boolean isUniqueDeviceAttestationSupported(); method public boolean isUniqueDeviceAttestationSupported(); Loading Loading @@ -7300,6 +7302,7 @@ package android.app.admin { field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1 field public static final int LOCK_TASK_FEATURE_SYSTEM_INFO = 1; // 0x1 field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2 field public static final int MAKE_USER_EPHEMERAL = 2; // 0x2 field public static final String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning"; field public static final String MIME_TYPE_PROVISIONING_NFC = "application/com.android.managedprovisioning"; field public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1; // 0x1 field public static final int PASSWORD_COMPLEXITY_HIGH = 327680; // 0x50000 field public static final int PASSWORD_COMPLEXITY_HIGH = 327680; // 0x50000 field public static final int PASSWORD_COMPLEXITY_LOW = 65536; // 0x10000 field public static final int PASSWORD_COMPLEXITY_LOW = 65536; // 0x10000 field public static final int PASSWORD_COMPLEXITY_MEDIUM = 196608; // 0x30000 field public static final int PASSWORD_COMPLEXITY_MEDIUM = 196608; // 0x30000 Loading Loading @@ -7336,7 +7339,6 @@ package android.app.admin { field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 field public static final int UNSAFE_OPERATION_REASON_DRIVING_DISTRACTION = 1; // 0x1 field public static final int WIPE_EUICC = 4; // 0x4 field public static final int WIPE_EUICC = 4; // 0x4 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 Loading Loading @@ -7490,7 +7492,7 @@ package android.app.admin { public final class UnsafeStateException extends java.lang.IllegalStateException implements android.os.Parcelable { public final class UnsafeStateException extends java.lang.IllegalStateException implements android.os.Parcelable { method public int describeContents(); method public int describeContents(); method public int getReason(); method @NonNull public java.util.List<java.lang.Integer> getReasons(); method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.UnsafeStateException> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.UnsafeStateException> CREATOR; } }
core/api/test-current.txt +2 −2 Original line number Original line Diff line number Diff line Loading @@ -391,11 +391,11 @@ package android.app.admin { method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle); method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle); method public boolean isCurrentInputMethodSetByOwner(); method public boolean isCurrentInputMethodSetByOwner(); method public boolean isFactoryResetProtectionPolicySupported(); method public boolean isFactoryResetProtectionPolicySupported(); method @NonNull public static String operationSafetyReasonToString(int); method @NonNull public static String operationToString(int); method @NonNull public static String operationToString(int); method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException; method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException; method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int); method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int); method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int); method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int); method @NonNull public static String unsafeOperationReasonToString(int); field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final int CODE_ACCOUNTS_NOT_EMPTY = 6; // 0x6 field public static final int CODE_ACCOUNTS_NOT_EMPTY = 6; // 0x6 field public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11; // 0xb field public static final int CODE_CANNOT_ADD_MANAGED_PROFILE = 11; // 0xb Loading Loading @@ -425,6 +425,7 @@ package android.app.admin { field public static final int OPERATION_REMOVE_KEY_PAIR = 28; // 0x1c field public static final int OPERATION_REMOVE_KEY_PAIR = 28; // 0x1c field public static final int OPERATION_REMOVE_USER = 6; // 0x6 field public static final int OPERATION_REMOVE_USER = 6; // 0x6 field public static final int OPERATION_REQUEST_BUGREPORT = 29; // 0x1d field public static final int OPERATION_REQUEST_BUGREPORT = 29; // 0x1d field public static final int OPERATION_SAFETY_REASON_NONE = -1; // 0xffffffff field public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30; // 0x1e field public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30; // 0x1e field public static final int OPERATION_SET_APPLICATION_HIDDEN = 15; // 0xf field public static final int OPERATION_SET_APPLICATION_HIDDEN = 15; // 0xf field public static final int OPERATION_SET_APPLICATION_RESTRICTIONS = 16; // 0x10 field public static final int OPERATION_SET_APPLICATION_RESTRICTIONS = 16; // 0x10 Loading Loading @@ -460,7 +461,6 @@ package android.app.admin { field public static final int PROVISIONING_RESULT_SETTING_PROFILE_OWNER_FAILED = 4; // 0x4 field public static final int PROVISIONING_RESULT_SETTING_PROFILE_OWNER_FAILED = 4; // 0x4 field public static final int PROVISIONING_RESULT_SET_DEVICE_OWNER_FAILED = 7; // 0x7 field public static final int PROVISIONING_RESULT_SET_DEVICE_OWNER_FAILED = 7; // 0x7 field public static final int PROVISIONING_RESULT_STARTING_PROFILE_FAILED = 5; // 0x5 field public static final int PROVISIONING_RESULT_STARTING_PROFILE_FAILED = 5; // 0x5 field public static final int UNSAFE_OPERATION_REASON_NONE = -1; // 0xffffffff } } public final class FullyManagedDeviceProvisioningParams implements android.os.Parcelable { public final class FullyManagedDeviceProvisioningParams implements android.os.Parcelable { Loading
core/java/android/app/admin/DeviceAdminReceiver.java +85 −2 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.app.admin; package android.app.admin; import static android.app.admin.DevicePolicyManager.OperationSafetyReason; import android.accounts.AccountManager; import android.accounts.AccountManager; import android.annotation.BroadcastBehavior; import android.annotation.BroadcastBehavior; import android.annotation.IntDef; import android.annotation.IntDef; Loading @@ -35,6 +37,7 @@ import android.os.PersistableBundle; import android.os.Process; import android.os.Process; import android.os.UserHandle; import android.os.UserHandle; import android.security.KeyChain; import android.security.KeyChain; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -72,8 +75,8 @@ import java.lang.annotation.RetentionPolicy; * </div> * </div> */ */ public class DeviceAdminReceiver extends BroadcastReceiver { public class DeviceAdminReceiver extends BroadcastReceiver { private static String TAG = "DevicePolicy"; private static final String TAG = "DevicePolicy"; private static boolean localLOGV = false; private static final boolean LOCAL_LOGV = false; /** /** * This is the primary action that a device administrator must implement to be * This is the primary action that a device administrator must implement to be Loading Loading @@ -509,6 +512,36 @@ public class DeviceAdminReceiver extends BroadcastReceiver { public static final String EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE = public static final String EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE = "android.app.extra.TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE"; "android.app.extra.TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE"; /** * Broadcast action: notify the admin that the state of operations that can be unsafe because * of a given reason (specified by the {@link #EXTRA_OPERATION_SAFETY_REASON} {@code int} extra) * has changed (the new value is specified by the {@link #EXTRA_OPERATION_SAFETY_STATE} * {@code boolean} extra). * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_OPERATION_SAFETY_STATE_CHANGED = "android.app.action.OPERATION_SAFETY_STATE_CHANGED"; /** * An {@code int} extra specifying an {@link OperationSafetyReason}. * * @hide */ public static final String EXTRA_OPERATION_SAFETY_REASON = "android.app.extra.OPERATION_SAFETY_REASON"; /** * An {@code boolean} extra specifying whether an operation will fail due to a * {@link OperationSafetyReason}. {@code true} means operations that rely on that reason are * safe, while {@code false} means they're unsafe. * * @hide */ public static final String EXTRA_OPERATION_SAFETY_STATE = "android.app.extra.OPERATION_SAFETY_STATE"; private DevicePolicyManager mManager; private DevicePolicyManager mManager; private ComponentName mWho; private ComponentName mWho; Loading Loading @@ -1017,6 +1050,51 @@ public class DeviceAdminReceiver extends BroadcastReceiver { @NonNull UserHandle user) { @NonNull UserHandle user) { } } /** * Called to notify the state of operations that can be unsafe to execute has changed. * * <p><b>Note:/b> notice that the operation safety state might change between the time this * callback is received and the operation's method on {@link DevicePolicyManager} is called, so * calls to the latter could still throw a {@link UnsafeStateException} even when this method * is called with {@code isSafe} as {@code true} * * @param context the running context as per {@link #onReceive} * @param reason the reason an operation could be unsafe. * @param isSafe whether the operation is safe to be executed. */ public void onOperationSafetyStateChanged(@NonNull Context context, @OperationSafetyReason int reason, boolean isSafe) { if (LOCAL_LOGV) { Log.v(TAG, String.format("onOperationSafetyStateChanged(): %s=%b", DevicePolicyManager.operationSafetyReasonToString(reason), isSafe)); } } private void onOperationSafetyStateChanged(Context context, Intent intent) { if (!hasRequiredExtra(intent, EXTRA_OPERATION_SAFETY_REASON) || !hasRequiredExtra(intent, EXTRA_OPERATION_SAFETY_STATE)) { return; } int reason = intent.getIntExtra(EXTRA_OPERATION_SAFETY_REASON, DevicePolicyManager.OPERATION_SAFETY_REASON_NONE); if (!DevicePolicyManager.isValidOperationSafetyReason(reason)) { Log.wtf(TAG, "Received invalid reason on " + intent.getAction() + ": " + reason); return; } boolean isSafe = intent.getBooleanExtra(EXTRA_OPERATION_SAFETY_STATE, /* defaultValue=*/ false); onOperationSafetyStateChanged(context, reason, isSafe); } private boolean hasRequiredExtra(Intent intent, String extra) { if (intent.hasExtra(extra)) return true; Log.wtf(TAG, "Missing '" + extra + "' on intent " + intent); return false; } /** /** * Intercept standard device administrator broadcasts. Implementations * Intercept standard device administrator broadcasts. Implementations * should not override this method; it is better to implement the * should not override this method; it is better to implement the Loading @@ -1025,6 +1103,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver { @Override @Override public void onReceive(@NonNull Context context, @NonNull Intent intent) { public void onReceive(@NonNull Context context, @NonNull Intent intent) { String action = intent.getAction(); String action = intent.getAction(); if (LOCAL_LOGV) { Log.v(TAG, "onReceive(): received " + action + " on user " + context.getUserId()); } if (ACTION_PASSWORD_CHANGED.equals(action)) { if (ACTION_PASSWORD_CHANGED.equals(action)) { onPasswordChanged(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER)); onPasswordChanged(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER)); Loading Loading @@ -1092,6 +1173,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver { } else if (ACTION_AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) { } else if (ACTION_AFFILIATED_PROFILE_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) { onTransferAffiliatedProfileOwnershipComplete(context, onTransferAffiliatedProfileOwnershipComplete(context, intent.getParcelableExtra(Intent.EXTRA_USER)); intent.getParcelableExtra(Intent.EXTRA_USER)); } else if (ACTION_OPERATION_SAFETY_STATE_CHANGED.equals(action)) { onOperationSafetyStateChanged(context, intent); } } } } } }
core/java/android/app/admin/DevicePolicyManager.java +38 −10 Original line number Original line Diff line number Diff line Loading @@ -2922,33 +2922,61 @@ public class DevicePolicyManager { return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); } } private static final String PREFIX_UNSAFE_OPERATION_REASON = "UNSAFE_OPERATION_REASON_"; private static final String PREFIX_OPERATION_SAFETY_REASON = "OPERATION_SAFETY_REASON_"; /** @hide */ /** @hide */ @IntDef(prefix = PREFIX_UNSAFE_OPERATION_REASON, value = { @IntDef(prefix = PREFIX_OPERATION_SAFETY_REASON, value = { UNSAFE_OPERATION_REASON_NONE, OPERATION_SAFETY_REASON_NONE, UNSAFE_OPERATION_REASON_DRIVING_DISTRACTION OPERATION_SAFETY_REASON_DRIVING_DISTRACTION }) }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) public static @interface UnsafeOperationReason { public static @interface OperationSafetyReason { } } /** @hide */ /** @hide */ @TestApi @TestApi public static final int UNSAFE_OPERATION_REASON_NONE = -1; public static final int OPERATION_SAFETY_REASON_NONE = -1; /** /** * Indicates that a {@link UnsafeStateException} was thrown because the operation would distract * Indicates that a {@link UnsafeStateException} was thrown because the operation would distract * the driver of the vehicle. * the driver of the vehicle. */ */ public static final int UNSAFE_OPERATION_REASON_DRIVING_DISTRACTION = 1; public static final int OPERATION_SAFETY_REASON_DRIVING_DISTRACTION = 1; /** @hide */ /** @hide */ @NonNull @NonNull @TestApi @TestApi public static String unsafeOperationReasonToString(@UnsafeOperationReason int reason) { public static String operationSafetyReasonToString(@OperationSafetyReason int reason) { return DebugUtils.constantToString(DevicePolicyManager.class, return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_UNSAFE_OPERATION_REASON, reason); PREFIX_OPERATION_SAFETY_REASON, reason); } /** @hide */ public static boolean isValidOperationSafetyReason(@OperationSafetyReason int reason) { return reason == OPERATION_SAFETY_REASON_DRIVING_DISTRACTION; } /** * Checks if it's safe to run operations that can be affected by the given {@code reason}. * * <p><b>Note:/b> notice that the operation safety state might change between the time this * method returns and the operation's method is called, so calls to the latter could still throw * a {@link UnsafeStateException} even when this method returns {@code true}. * * @param reason currently, only supported reason is * {@link #OPERATION_SAFETY_REASON_DRIVING_DISTRACTION}. * * @return whether it's safe to run operations that can be affected by the given {@code reason}. */ // TODO(b/173541467): should it throw SecurityException if caller is not admin? public boolean isSafeOperation(@OperationSafetyReason int reason) { if (mService == null) return false; try { return mService.isSafeOperation(reason); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** @hide */ /** @hide */ Loading Loading @@ -13157,7 +13185,7 @@ public class DevicePolicyManager { @TestApi @TestApi @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(@DevicePolicyOperation int operation, public void setNextOperationSafety(@DevicePolicyOperation int operation, @UnsafeOperationReason int reason) { @OperationSafetyReason int reason) { if (mService != null) { if (mService != null) { try { try { mService.setNextOperationSafety(operation, reason); mService.setNextOperationSafety(operation, reason);
core/java/android/app/admin/DevicePolicyManagerInternal.java +11 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.app.admin; import android.annotation.Nullable; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.admin.DevicePolicyManager.OperationSafetyReason; import android.content.ComponentName; import android.content.ComponentName; import android.content.Intent; import android.content.Intent; import android.os.UserHandle; import android.os.UserHandle; Loading Loading @@ -255,4 +256,14 @@ public abstract class DevicePolicyManagerInternal { * {@link #supportsResetOp(int)} is true. * {@link #supportsResetOp(int)} is true. */ */ public abstract void resetOp(int op, String packageName, @UserIdInt int userId); public abstract void resetOp(int op, String packageName, @UserIdInt int userId); /** * Notifies the system that an unsafe operation reason has changed. * * @throws IllegalArgumentException if {@code checker} is not the same as set on * {@code DevicePolicyManagerService}. */ public abstract void notifyUnsafeOperationStateChanged(DevicePolicySafetyChecker checker, @OperationSafetyReason int reason, boolean isSafe); } }