diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 96918ce39519c..a2762908941e3 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -450,6 +450,7 @@ package android.app.admin { method @NonNull @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public java.util.Set getPolicyExemptApps(); method public boolean isCurrentInputMethodSetByOwner(); method public boolean isFactoryResetProtectionPolicySupported(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean isNewUserDisclaimerAcknowledged(); method @RequiresPermission(anyOf={"android.permission.MARK_DEVICE_ORGANIZATION_OWNED", "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}, conditional=true) public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName); method @NonNull public static String operationSafetyReasonToString(int); method @NonNull public static String operationToString(int); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 3e236b5d72a0a..7fef2974f7c8e 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3110,7 +3110,8 @@ public class DevicePolicyManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}) public void acknowledgeNewUserDisclaimer() { if (mService != null) { try { @@ -3121,6 +3122,25 @@ public class DevicePolicyManager { } } + /** + * Checks whether the new managed user disclaimer was viewed by the current user. + * + * @hide + */ + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}) + @TestApi + public boolean isNewUserDisclaimerAcknowledged() { + if (mService != null) { + try { + return mService.isNewUserDisclaimerAcknowledged(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } + /** * Return true if the given administrator component is currently active (enabled) in the system. * diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 4f6ed5cb10490..7c508425dd6ac 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -266,6 +266,7 @@ interface IDevicePolicyManager { void clearLogoutUser(); List getSecondaryUsers(in ComponentName who); void acknowledgeNewUserDisclaimer(); + boolean isNewUserDisclaimerAcknowledged(); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java index 26c442dc1f476..e18e0020407f8 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java @@ -23,6 +23,7 @@ import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.os.FileUtils; import android.os.PersistableBundle; +import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; @@ -83,7 +84,7 @@ class DevicePolicyData { private static final String ATTR_NEW_USER_DISCLAIMER = "new-user-disclaimer"; // Values of ATTR_NEW_USER_DISCLAIMER - static final String NEW_USER_DISCLAIMER_SHOWN = "shown"; + static final String NEW_USER_DISCLAIMER_ACKNOWLEDGED = "acked"; static final String NEW_USER_DISCLAIMER_NOT_NEEDED = "not_needed"; static final String NEW_USER_DISCLAIMER_NEEDED = "needed"; @@ -613,6 +614,28 @@ class DevicePolicyData { } } + boolean isNewUserDisclaimerAcknowledged() { + if (mNewUserDisclaimer == null) { + if (mUserId == UserHandle.USER_SYSTEM) { + return true; + } + Slogf.w(TAG, "isNewUserDisclaimerAcknowledged(%d): mNewUserDisclaimer is null", + mUserId); + return false; + } + switch (mNewUserDisclaimer) { + case NEW_USER_DISCLAIMER_ACKNOWLEDGED: + case NEW_USER_DISCLAIMER_NOT_NEEDED: + return true; + case NEW_USER_DISCLAIMER_NEEDED: + return false; + default: + Slogf.w(TAG, "isNewUserDisclaimerAcknowledged(%d): invalid value %d", mUserId, + mNewUserDisclaimer); + return false; + } + } + void dump(IndentingPrintWriter pw) { pw.println(); pw.println("Enabled Device Admins (User " + mUserId + ", provisioningState: " diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index dabdff21964f4..04829118fbe99 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -10770,10 +10770,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void acknowledgeNewUserDisclaimer() { CallerIdentity callerIdentity = getCallerIdentity(); - canManageUsers(callerIdentity); + Preconditions.checkCallAuthorization(canManageUsers(callerIdentity) + || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS)); setShowNewUserDisclaimer(callerIdentity.getUserId(), - DevicePolicyData.NEW_USER_DISCLAIMER_SHOWN); + DevicePolicyData.NEW_USER_DISCLAIMER_ACKNOWLEDGED); } private void setShowNewUserDisclaimer(@UserIdInt int userId, String value) { @@ -10805,6 +10806,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); } + @Override + public boolean isNewUserDisclaimerAcknowledged() { + CallerIdentity callerIdentity = getCallerIdentity(); + Preconditions.checkCallAuthorization(canManageUsers(callerIdentity) + || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS)); + int userId = callerIdentity.getUserId(); + synchronized (getLockObject()) { + DevicePolicyData policyData = getUserData(userId); + return policyData.isNewUserDisclaimerAcknowledged(); + } + } + @Override public boolean removeUser(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null");