diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index 9a0cd564e35f7..eef2f983cc551 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -80,15 +80,25 @@ public abstract class DevicePolicyManagerInternal { public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy); /** - * Creates an intent to show the admin support dialog to let the user know that the package is - * suspended by the admin. This assumes that {@param packageName} is suspended by the - * device/profile owner. The caller should check if the package is suspended or not. + * Creates an intent to show the admin support dialog to say that an action is disallowed by + * the device/profile owner. * *

This method does not take the DPMS lock. Safe to be called from anywhere. - * - * @param packageName The package that is suspended - * @param userId The user having the suspended package. + * @param userId The user where the action is disallowed. + * @param useDefaultIfNoAdmin If true, a non-null intent will be returned, even if we couldn't + * find a profile/device owner. * @return The intent to trigger the admin support dialog. */ - public abstract Intent createPackageSuspendedDialogIntent(String packageName, int userId); + public abstract Intent createShowAdminSupportIntent(int userId, boolean useDefaultIfNoAdmin); + + /** + * Creates an intent to show the admin support dialog showing the admin who has set a user + * restriction. + * + *

This method does not take the DPMS lock. Safe to be called from anywhere. + * @param userId The user where the user restriction is set. + * @return The intent to trigger the admin support dialog, or null if the user restriction is + * not enforced by the profile/device owner. + */ + public abstract Intent createUserRestrictionSupportIntent(int userId, String userRestriction); } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index feceb149ae3f5..bc511ae369d6e 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -590,8 +590,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku if (provider.maskedBySuspendedPackage) { UserInfo userInfo = mUserManager.getUserInfo(providerUserId); showBadge = userInfo.isManagedProfile(); - onClickIntent = mDevicePolicyManagerInternal.createPackageSuspendedDialogIntent( - providerPackage, providerUserId); + onClickIntent = mDevicePolicyManagerInternal.createShowAdminSupportIntent( + providerUserId, true); } else if (provider.maskedByQuietProfile) { showBadge = true; onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent( diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 8bdc21445c9a5..5b7f99c99ebb7 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -2962,17 +2962,36 @@ public class AccountManagerService } private void showCantAddAccount(int errorCode, int userId) { - Intent cantAddAccount = new Intent(mContext, CantAddAccountActivity.class); - cantAddAccount.putExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, errorCode); - cantAddAccount.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + final DevicePolicyManagerInternal dpmi = + LocalServices.getService(DevicePolicyManagerInternal.class); + Intent intent = null; + if (errorCode == AccountManager.ERROR_CODE_USER_RESTRICTED) { + intent = dpmi.createUserRestrictionSupportIntent(userId, + UserManager.DISALLOW_MODIFY_ACCOUNTS); + } else if (errorCode == AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE) { + intent = dpmi.createShowAdminSupportIntent(userId, false); + } + if (intent == null) { + intent = getDefaultCantAddAccountIntent(errorCode); + } long identityToken = clearCallingIdentity(); try { - mContext.startActivityAsUser(cantAddAccount, new UserHandle(userId)); + mContext.startActivityAsUser(intent, new UserHandle(userId)); } finally { restoreCallingIdentity(identityToken); } } + /** + * Called when we don't know precisely who is preventing us from adding an account. + */ + private Intent getDefaultCantAddAccountIntent(int errorCode) { + Intent cantAddAccount = new Intent(mContext, CantAddAccountActivity.class); + cantAddAccount.putExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, errorCode); + cantAddAccount.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return cantAddAccount; + } + @Override public void confirmCredentialsAsUser( IAccountManagerResponse response, diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java index f26e47e934c4c..a8ea5f417364e 100644 --- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java +++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java @@ -150,8 +150,7 @@ class ActivityStartInterceptor { if (devicePolicyManager == null) { return false; } - mIntent = devicePolicyManager.createPackageSuspendedDialogIntent( - mAInfo.packageName, mUserId); + mIntent = devicePolicyManager.createShowAdminSupportIntent(mUserId, true); mCallingPid = mRealCallingPid; mCallingUid = mRealCallingUid; mResolvedType = null; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index b5280165bb39a..3d11e0578d2f2 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8135,28 +8135,79 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public Intent createPackageSuspendedDialogIntent(String packageName, int userId) { - Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); - intent.putExtra(Intent.EXTRA_USER_ID, userId); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - + public Intent createShowAdminSupportIntent(int userId, boolean useDefaultIfNoAdmin) { // This method is called from AM with its lock held, so don't take the DPMS lock. // b/29242568 ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); if (profileOwner != null) { - intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner); - return intent; + return createShowAdminSupportIntent(profileOwner, userId); } final Pair deviceOwner = mOwners.getDeviceOwnerUserIdAndComponent(); if (deviceOwner != null && deviceOwner.first == userId) { - intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner.second); - return intent; + return createShowAdminSupportIntent(deviceOwner.second, userId); } // We're not specifying the device admin because there isn't one. + if (useDefaultIfNoAdmin) { + return createShowAdminSupportIntent(null, userId); + } + return null; + } + + @Override + public Intent createUserRestrictionSupportIntent(int userId, String userRestriction) { + int source; + long ident = mInjector.binderClearCallingIdentity(); + try { + source = mUserManager.getUserRestrictionSource(userRestriction, + UserHandle.of(userId)); + } finally { + mInjector.binderRestoreCallingIdentity(ident); + } + if ((source & UserManager.RESTRICTION_SOURCE_SYSTEM) != 0) { + /* + * In this case, the user restriction is enforced by the system. + * So we won't show an admin support intent, even if it is also + * enforced by a profile/device owner. + */ + return null; + } + boolean enforcedByDo = (source & UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) != 0; + boolean enforcedByPo = (source & UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) != 0; + if (enforcedByDo && enforcedByPo) { + // In this case, we'll show an admin support dialog that does not + // specify the admin. + return createShowAdminSupportIntent(null, userId); + } else if (enforcedByPo) { + final ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); + if (profileOwner != null) { + return createShowAdminSupportIntent(profileOwner, userId); + } + // This could happen if another thread has changed the profile owner since we called + // getUserRestrictionSource + return null; + } else if (enforcedByDo) { + final Pair deviceOwner + = mOwners.getDeviceOwnerUserIdAndComponent(); + if (deviceOwner != null) { + return createShowAdminSupportIntent(deviceOwner.second, deviceOwner.first); + } + // This could happen if another thread has changed the device owner since we called + // getUserRestrictionSource + return null; + } + return null; + } + + private Intent createShowAdminSupportIntent(ComponentName admin, int userId) { + // This method is called with AMS lock held, so don't take DPMS lock + final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); + intent.putExtra(Intent.EXTRA_USER_ID, userId); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return intent; } }