Loading core/java/android/app/admin/DevicePolicyManager.java +21 −0 Original line number Diff line number Diff line Loading @@ -2729,6 +2729,17 @@ public class DevicePolicyManager { return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); } /** @hide */ public void resetNewUserDisclaimer() { if (mService != null) { try { mService.resetNewUserDisclaimer(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * Return true if the given administrator component is currently active (enabled) in the system. * Loading Loading @@ -5205,6 +5216,16 @@ public class DevicePolicyManager { public static final String ACTION_MANAGED_USER_CREATED = "android.app.action.MANAGED_USER_CREATED"; /** * Broadcast action: notify system that a new (Android) user was added when the device is * managed by a device owner, so receivers can show the proper disclaimer to the (human) user. * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SHOW_NEW_USER_DISCLAIMER = "android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER"; /** * Widgets are enabled in keyguard */ Loading core/java/android/app/admin/IDevicePolicyManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -252,6 +252,7 @@ interface IDevicePolicyManager { int stopUser(in ComponentName who, in UserHandle userHandle); int logoutUser(in ComponentName who); List<UserHandle> getSecondaryUsers(in ComponentName who); void resetNewUserDisclaimer(); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); Loading services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,12 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { * @see {@link SystemService#onUserUnlocking} */ abstract void handleUnlockUser(int userId); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} after a user is being unlocked. * * @see {@link SystemService#onUserUnlocked} */ abstract void handleOnUserUnlocked(int userId); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being stopped. * Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +15 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,12 @@ class DevicePolicyData { private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED = "device-provisioning-config-applied"; private static final String ATTR_DEVICE_PAIRED = "device-paired"; 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_NOT_NEEDED = "not_needed"; static final String NEW_USER_DISCLAIMER_NEEDED = "needed"; private static final String TAG = DevicePolicyManagerService.LOG_TAG; private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE Loading Loading @@ -146,6 +152,10 @@ class DevicePolicyData { // apps were suspended or unsuspended. boolean mAppsSuspended = false; // Whether it's necessary to show a disclaimer (that the device is managed) after the user // starts. String mNewUserDisclaimer = NEW_USER_DISCLAIMER_NOT_NEEDED; DevicePolicyData(@UserIdInt int userId) { mUserId = userId; } Loading Loading @@ -186,6 +196,9 @@ class DevicePolicyData { if (policyData.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) { out.attributeInt(null, ATTR_PERMISSION_POLICY, policyData.mPermissionPolicy); } if (NEW_USER_DISCLAIMER_NEEDED.equals(policyData.mNewUserDisclaimer)) { out.attribute(null, ATTR_NEW_USER_DISCLAIMER, policyData.mNewUserDisclaimer); } // Serialize delegations. for (int i = 0; i < policyData.mDelegationMap.size(); ++i) { Loading Loading @@ -412,6 +425,7 @@ class DevicePolicyData { if (permissionPolicy != -1) { policy.mPermissionPolicy = permissionPolicy; } policy.mNewUserDisclaimer = parser.getAttributeValue(null, ATTR_NEW_USER_DISCLAIMER); int outerDepth = parser.getDepth(); policy.mLockTaskPackages.clear(); Loading Loading @@ -588,6 +602,7 @@ class DevicePolicyData { pw.print("mAppsSuspended="); pw.println(mAppsSuspended); pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete); pw.print("mAffiliationIds="); pw.println(mAffiliationIds); pw.print("mNewUserDisclaimer="); pw.println(mNewUserDisclaimer); pw.decreaseIndent(); } } services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +73 −4 Original line number Diff line number Diff line Loading @@ -707,6 +707,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public void onUserStopping(@NonNull TargetUser user) { mService.handleStopUser(user.getUserIdentifier()); } @Override public void onUserUnlocked(@NonNull TargetUser user) { mService.handleOnUserUnlocked(user.getUserIdentifier()); } } @GuardedBy("getLockObject()") Loading Loading @@ -886,6 +891,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener { @Override public void onUserCreated(UserInfo user) { mHandler.post(() -> handleNewUserCreated(user)); } } private void handlePackagesChanged(@Nullable String packageName, int userHandle) { boolean removedAdmin = false; if (VERBOSE_LOG) { Loading Loading @@ -1561,6 +1574,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mSetupContentObserver = new SetupContentObserver(mHandler); mUserManagerInternal.addUserRestrictionsListener(new RestrictionsListener(mContext)); mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener()); loadOwners(); } Loading Loading @@ -2901,6 +2915,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { startOwnerService(userId, "unlock-user"); } @Override void handleOnUserUnlocked(int userId) { showNewUserDisclaimerIfNecessary(userId); } @Override void handleStopUser(int userId) { stopOwnerService(userId, "stop-user"); Loading Loading @@ -7687,8 +7706,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // Sets profile owner on current foreground user since // the human user will complete the DO setup workflow from there. manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin, /* managedUser= */ currentForegroundUser, /* adminExtras= */ null); /* managedUser= */ currentForegroundUser, /* adminExtras= */ null, /* showDisclaimer= */ false); } return true; } Loading Loading @@ -9740,7 +9759,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final long id = mInjector.binderClearCallingIdentity(); try { manageUserUnchecked(admin, profileOwner, userHandle, adminExtras); manageUserUnchecked(admin, profileOwner, userHandle, adminExtras, /* showDisclaimer= */ true); if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Loading @@ -9762,7 +9782,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void manageUserUnchecked(ComponentName admin, ComponentName profileOwner, @UserIdInt int userId, PersistableBundle adminExtras) { @UserIdInt int userId, PersistableBundle adminExtras, boolean showDisclaimer) { final String adminPkg = admin.getPackageName(); try { // Install the profile owner if not present. Loading @@ -9788,11 +9808,60 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DevicePolicyData policyData = getUserData(userId); policyData.mInitBundle = adminExtras; policyData.mAdminBroadcastPending = true; policyData.mNewUserDisclaimer = showDisclaimer ? DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED : DevicePolicyData.NEW_USER_DISCLAIMER_NOT_NEEDED; saveSettingsLocked(userId); } } private void handleNewUserCreated(UserInfo user) { if (!mOwners.hasDeviceOwner()) return; final int userId = user.id; Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer"); setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED); } @Override public void resetNewUserDisclaimer() { CallerIdentity callerIdentity = getCallerIdentity(); canManageUsers(callerIdentity); setShowNewUserDisclaimer(callerIdentity.getUserId(), DevicePolicyData.NEW_USER_DISCLAIMER_SHOWN); } private void setShowNewUserDisclaimer(@UserIdInt int userId, String value) { Slog.i(LOG_TAG, "Setting new user disclaimer for user " + userId + " as " + value); synchronized (getLockObject()) { DevicePolicyData policyData = getUserData(userId); policyData.mNewUserDisclaimer = value; saveSettingsLocked(userId); } } private void showNewUserDisclaimerIfNecessary(@UserIdInt int userId) { boolean mustShow; synchronized (getLockObject()) { DevicePolicyData policyData = getUserData(userId); if (VERBOSE_LOG) { Slog.v(LOG_TAG, "showNewUserDisclaimerIfNecessary(" + userId + "): " + policyData.mNewUserDisclaimer + ")"); } mustShow = DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED .equals(policyData.mNewUserDisclaimer); } if (!mustShow) return; Intent intent = new Intent(DevicePolicyManager.ACTION_SHOW_NEW_USER_DISCLAIMER); // TODO(b/172691310): add CTS tests to make sure disclaimer is shown Slog.i(LOG_TAG, "Dispatching ACTION_SHOW_NEW_USER_DISCLAIMER intent"); mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); } @Override public boolean removeUser(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null"); Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +21 −0 Original line number Diff line number Diff line Loading @@ -2729,6 +2729,17 @@ public class DevicePolicyManager { return DebugUtils.constantToString(DevicePolicyManager.class, PREFIX_OPERATION, operation); } /** @hide */ public void resetNewUserDisclaimer() { if (mService != null) { try { mService.resetNewUserDisclaimer(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * Return true if the given administrator component is currently active (enabled) in the system. * Loading Loading @@ -5205,6 +5216,16 @@ public class DevicePolicyManager { public static final String ACTION_MANAGED_USER_CREATED = "android.app.action.MANAGED_USER_CREATED"; /** * Broadcast action: notify system that a new (Android) user was added when the device is * managed by a device owner, so receivers can show the proper disclaimer to the (human) user. * * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SHOW_NEW_USER_DISCLAIMER = "android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER"; /** * Widgets are enabled in keyguard */ Loading
core/java/android/app/admin/IDevicePolicyManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -252,6 +252,7 @@ interface IDevicePolicyManager { int stopUser(in ComponentName who, in UserHandle userHandle); int logoutUser(in ComponentName who); List<UserHandle> getSecondaryUsers(in ComponentName who); void resetNewUserDisclaimer(); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); Loading
services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +6 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,12 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { * @see {@link SystemService#onUserUnlocking} */ abstract void handleUnlockUser(int userId); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} after a user is being unlocked. * * @see {@link SystemService#onUserUnlocked} */ abstract void handleOnUserUnlocked(int userId); /** * To be called by {@link DevicePolicyManagerService#Lifecycle} when a user is being stopped. * Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +15 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,12 @@ class DevicePolicyData { private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED = "device-provisioning-config-applied"; private static final String ATTR_DEVICE_PAIRED = "device-paired"; 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_NOT_NEEDED = "not_needed"; static final String NEW_USER_DISCLAIMER_NEEDED = "needed"; private static final String TAG = DevicePolicyManagerService.LOG_TAG; private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE Loading Loading @@ -146,6 +152,10 @@ class DevicePolicyData { // apps were suspended or unsuspended. boolean mAppsSuspended = false; // Whether it's necessary to show a disclaimer (that the device is managed) after the user // starts. String mNewUserDisclaimer = NEW_USER_DISCLAIMER_NOT_NEEDED; DevicePolicyData(@UserIdInt int userId) { mUserId = userId; } Loading Loading @@ -186,6 +196,9 @@ class DevicePolicyData { if (policyData.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) { out.attributeInt(null, ATTR_PERMISSION_POLICY, policyData.mPermissionPolicy); } if (NEW_USER_DISCLAIMER_NEEDED.equals(policyData.mNewUserDisclaimer)) { out.attribute(null, ATTR_NEW_USER_DISCLAIMER, policyData.mNewUserDisclaimer); } // Serialize delegations. for (int i = 0; i < policyData.mDelegationMap.size(); ++i) { Loading Loading @@ -412,6 +425,7 @@ class DevicePolicyData { if (permissionPolicy != -1) { policy.mPermissionPolicy = permissionPolicy; } policy.mNewUserDisclaimer = parser.getAttributeValue(null, ATTR_NEW_USER_DISCLAIMER); int outerDepth = parser.getDepth(); policy.mLockTaskPackages.clear(); Loading Loading @@ -588,6 +602,7 @@ class DevicePolicyData { pw.print("mAppsSuspended="); pw.println(mAppsSuspended); pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete); pw.print("mAffiliationIds="); pw.println(mAffiliationIds); pw.print("mNewUserDisclaimer="); pw.println(mNewUserDisclaimer); pw.decreaseIndent(); } }
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +73 −4 Original line number Diff line number Diff line Loading @@ -707,6 +707,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { public void onUserStopping(@NonNull TargetUser user) { mService.handleStopUser(user.getUserIdentifier()); } @Override public void onUserUnlocked(@NonNull TargetUser user) { mService.handleOnUserUnlocked(user.getUserIdentifier()); } } @GuardedBy("getLockObject()") Loading Loading @@ -886,6 +891,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener { @Override public void onUserCreated(UserInfo user) { mHandler.post(() -> handleNewUserCreated(user)); } } private void handlePackagesChanged(@Nullable String packageName, int userHandle) { boolean removedAdmin = false; if (VERBOSE_LOG) { Loading Loading @@ -1561,6 +1574,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mSetupContentObserver = new SetupContentObserver(mHandler); mUserManagerInternal.addUserRestrictionsListener(new RestrictionsListener(mContext)); mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener()); loadOwners(); } Loading Loading @@ -2901,6 +2915,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { startOwnerService(userId, "unlock-user"); } @Override void handleOnUserUnlocked(int userId) { showNewUserDisclaimerIfNecessary(userId); } @Override void handleStopUser(int userId) { stopOwnerService(userId, "stop-user"); Loading Loading @@ -7687,8 +7706,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // Sets profile owner on current foreground user since // the human user will complete the DO setup workflow from there. manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin, /* managedUser= */ currentForegroundUser, /* adminExtras= */ null); /* managedUser= */ currentForegroundUser, /* adminExtras= */ null, /* showDisclaimer= */ false); } return true; } Loading Loading @@ -9740,7 +9759,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final long id = mInjector.binderClearCallingIdentity(); try { manageUserUnchecked(admin, profileOwner, userHandle, adminExtras); manageUserUnchecked(admin, profileOwner, userHandle, adminExtras, /* showDisclaimer= */ true); if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Loading @@ -9762,7 +9782,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } private void manageUserUnchecked(ComponentName admin, ComponentName profileOwner, @UserIdInt int userId, PersistableBundle adminExtras) { @UserIdInt int userId, PersistableBundle adminExtras, boolean showDisclaimer) { final String adminPkg = admin.getPackageName(); try { // Install the profile owner if not present. Loading @@ -9788,11 +9808,60 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DevicePolicyData policyData = getUserData(userId); policyData.mInitBundle = adminExtras; policyData.mAdminBroadcastPending = true; policyData.mNewUserDisclaimer = showDisclaimer ? DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED : DevicePolicyData.NEW_USER_DISCLAIMER_NOT_NEEDED; saveSettingsLocked(userId); } } private void handleNewUserCreated(UserInfo user) { if (!mOwners.hasDeviceOwner()) return; final int userId = user.id; Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer"); setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED); } @Override public void resetNewUserDisclaimer() { CallerIdentity callerIdentity = getCallerIdentity(); canManageUsers(callerIdentity); setShowNewUserDisclaimer(callerIdentity.getUserId(), DevicePolicyData.NEW_USER_DISCLAIMER_SHOWN); } private void setShowNewUserDisclaimer(@UserIdInt int userId, String value) { Slog.i(LOG_TAG, "Setting new user disclaimer for user " + userId + " as " + value); synchronized (getLockObject()) { DevicePolicyData policyData = getUserData(userId); policyData.mNewUserDisclaimer = value; saveSettingsLocked(userId); } } private void showNewUserDisclaimerIfNecessary(@UserIdInt int userId) { boolean mustShow; synchronized (getLockObject()) { DevicePolicyData policyData = getUserData(userId); if (VERBOSE_LOG) { Slog.v(LOG_TAG, "showNewUserDisclaimerIfNecessary(" + userId + "): " + policyData.mNewUserDisclaimer + ")"); } mustShow = DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED .equals(policyData.mNewUserDisclaimer); } if (!mustShow) return; Intent intent = new Intent(DevicePolicyManager.ACTION_SHOW_NEW_USER_DISCLAIMER); // TODO(b/172691310): add CTS tests to make sure disclaimer is shown Slog.i(LOG_TAG, "Dispatching ACTION_SHOW_NEW_USER_DISCLAIMER intent"); mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); } @Override public boolean removeUser(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null"); Loading