diff options
| author | 2016-02-04 19:14:14 +0000 | |
|---|---|---|
| committer | 2016-02-04 19:14:14 +0000 | |
| commit | 57218cbbf773f389e5e9493623dd3d017e459590 (patch) | |
| tree | 597e92e968c27dc591d7e042039e0b7f711284ca | |
| parent | 37e80e3167a3e79828e4e08575474b81b7ad3a2e (diff) | |
| parent | 569258689a0d28f25cbdf7189038833d45a63a80 (diff) | |
Merge "Made changes to fix some policy transparency options."
4 files changed, 260 insertions, 58 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 1247afefcd01..02eb115175fd 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4109,6 +4109,29 @@ public class DevicePolicyManager { } /** + * Called by the system to check if a specific accessibility service is disabled by admin. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName Accessibility service package name that needs to be checked. + * @param userHandle user id the admin is running as. + * @return true if the accessibility service is permitted, otherwise false. + * + * @hide + */ + public boolean isAccessibilityServicePermittedByAdmin(@NonNull ComponentName admin, + @NonNull String packageName, int userHandle) { + if (mService != null) { + try { + return mService.isAccessibilityServicePermittedByAdmin(admin, packageName, + userHandle); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + return false; + } + + /** * Returns the list of accessibility services permitted by the device or profiles * owners of this user. * @@ -4188,6 +4211,28 @@ public class DevicePolicyManager { } /** + * Called by the system to check if a specific input method is disabled by admin. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName Input method package name that needs to be checked. + * @param userHandle user id the admin is running as. + * @return true if the input method is permitted, otherwise false. + * + * @hide + */ + public boolean isInputMethodPermittedByAdmin(@NonNull ComponentName admin, + @NonNull String packageName, int userHandle) { + if (mService != null) { + try { + return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle); + } catch (RemoteException e) { + Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e); + } + } + return false; + } + + /** * Returns the list of input methods permitted by the device or profiles * owners of the current user. (*Not* calling user, due to a limitation in InputMethodManager.) * diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index b57e1b7d8081..c6a53443b51c 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -174,10 +174,12 @@ interface IDevicePolicyManager { boolean setPermittedAccessibilityServices(in ComponentName admin,in List packageList); List getPermittedAccessibilityServices(in ComponentName admin); List getPermittedAccessibilityServicesForUser(int userId); + boolean isAccessibilityServicePermittedByAdmin(in ComponentName admin, String packageName, int userId); boolean setPermittedInputMethods(in ComponentName admin,in List packageList); List getPermittedInputMethods(in ComponentName admin); List getPermittedInputMethodsForCurrentUser(); + boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId); boolean setApplicationHidden(in ComponentName admin, in String packageName, boolean hidden); boolean isApplicationHidden(in ComponentName admin, in String packageName); diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java index 78c530c2b0d7..f8851101abc2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java @@ -155,7 +155,7 @@ public class RestrictedLockUtils { for (UserInfo userInfo : um.getProfiles(userId)) { final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id); if (admins == null) { - return null; + continue; } final boolean isSeparateProfileChallengeEnabled = lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id); @@ -209,16 +209,7 @@ public class RestrictedLockUtils { IPackageManager ipm = AppGlobals.getPackageManager(); try { if (ipm.getBlockUninstallForUser(packageName, userId)) { - DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( - Context.DEVICE_POLICY_SERVICE); - if (dpm == null) { - return null; - } - ComponentName admin = dpm.getProfileOwner(); - if (admin == null) { - admin = dpm.getDeviceOwnerComponentOnCallingUser(); - } - return new EnforcedAdmin(admin, UserHandle.myUserId()); + return getProfileOrDeviceOwner(context, userId); } } catch (RemoteException e) { // Nothing to do @@ -238,7 +229,7 @@ public class RestrictedLockUtils { try { ApplicationInfo ai = ipm.getApplicationInfo(packageName, 0, userId); if (ai != null && ((ai.flags & ApplicationInfo.FLAG_SUSPENDED) != 0)) { - return getProfileOrDeviceOwnerOnCallingUser(context); + return getProfileOrDeviceOwner(context, userId); } } catch (RemoteException e) { // Nothing to do @@ -246,6 +237,80 @@ public class RestrictedLockUtils { return null; } + public static EnforcedAdmin checkIfInputMethodDisallowed(Context context, + String packageName, int userId) { + DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( + Context.DEVICE_POLICY_SERVICE); + if (dpm == null) { + return null; + } + EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId); + boolean permitted = true; + if (admin != null) { + permitted = dpm.isInputMethodPermittedByAdmin(admin.component, + packageName, userId); + } + int managedProfileId = getManagedProfileId(context, userId); + EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId); + boolean permittedByProfileAdmin = true; + if (profileAdmin != null) { + permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component, + packageName, managedProfileId); + } + if (!permitted && !permittedByProfileAdmin) { + return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; + } else if (!permitted) { + return admin; + } else if (!permittedByProfileAdmin) { + return profileAdmin; + } + return null; + } + + public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context, + String packageName, int userId) { + DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( + Context.DEVICE_POLICY_SERVICE); + if (dpm == null) { + return null; + } + EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId); + boolean permitted = true; + if (admin != null) { + permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component, + packageName, userId); + } + int managedProfileId = getManagedProfileId(context, userId); + EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId); + boolean permittedByProfileAdmin = true; + if (profileAdmin != null) { + permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin( + profileAdmin.component, packageName, managedProfileId); + } + if (!permitted && !permittedByProfileAdmin) { + return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; + } else if (!permitted) { + return admin; + } else if (!permittedByProfileAdmin) { + return profileAdmin; + } + return null; + } + + private static int getManagedProfileId(Context context, int userId) { + UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); + List<UserInfo> userProfiles = um.getProfiles(userId); + for (UserInfo uInfo : userProfiles) { + if (uInfo.id == userId) { + continue; + } + if (uInfo.isManagedProfile()) { + return uInfo.id; + } + } + return UserHandle.USER_NULL; + } + /** * Check if account management for a specific type of account is disabled by admin. * Only a profile or device owner can disable account management. So, we check if account @@ -255,7 +320,7 @@ public class RestrictedLockUtils { * or {@code null} if the account management is not disabled. */ public static EnforcedAdmin checkIfAccountManagementDisabled(Context context, - String accountType) { + String accountType, int userId) { if (accountType == null) { return null; } @@ -265,7 +330,7 @@ public class RestrictedLockUtils { return null; } boolean isAccountTypeDisabled = false; - String[] disabledTypes = dpm.getAccountTypesWithManagementDisabled(); + String[] disabledTypes = dpm.getAccountTypesWithManagementDisabledAsUser(userId); for (String type : disabledTypes) { if (accountType.equals(type)) { isAccountTypeDisabled = true; @@ -275,7 +340,7 @@ public class RestrictedLockUtils { if (!isAccountTypeDisabled) { return null; } - return getProfileOrDeviceOwnerOnCallingUser(context); + return getProfileOrDeviceOwner(context, userId); } /** @@ -296,7 +361,7 @@ public class RestrictedLockUtils { } /** - * Checks if an admin has enforced minimum password quality requirements on the device. + * Checks if an admin has enforced minimum password quality requirements on the given user. * * @return EnforcedAdmin Object containing the enforced admin component and admin user details, * or {@code null} if no quality requirements are set. If the requirements are set by @@ -304,35 +369,73 @@ public class RestrictedLockUtils { * {@link UserHandle#USER_NULL}. * */ - public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context) { + public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) { final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( Context.DEVICE_POLICY_SERVICE); if (dpm == null) { return null; } - boolean isDisabledByMultipleAdmins = false; - ComponentName adminComponent = null; - List<ComponentName> admins = dpm.getActiveAdmins(); - int quality; - if (admins != null) { + + LockPatternUtils lockPatternUtils = new LockPatternUtils(context); + EnforcedAdmin enforcedAdmin = null; + if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { + // userId is managed profile and has a separate challenge, only consider + // the admins in that user. + final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId); + if (admins == null) { + return null; + } for (ComponentName admin : admins) { - quality = dpm.getPasswordQuality(admin); - if (quality >= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { - if (adminComponent == null) { - adminComponent = admin; + if (dpm.getPasswordQuality(admin, userId) + > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { + if (enforcedAdmin == null) { + enforcedAdmin = new EnforcedAdmin(admin, userId); } else { - isDisabledByMultipleAdmins = true; - break; + return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; } } } - } - EnforcedAdmin enforcedAdmin = null; - if (adminComponent != null) { - if (!isDisabledByMultipleAdmins) { - enforcedAdmin = new EnforcedAdmin(adminComponent, UserHandle.myUserId()); - } else { - enforcedAdmin = new EnforcedAdmin(); + } else { + // Return all admins for this user and the profiles that are visible from this + // user that do not use a separate work challenge. + final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); + for (UserInfo userInfo : um.getProfiles(userId)) { + final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id); + if (admins == null) { + continue; + } + final boolean isSeparateProfileChallengeEnabled = + lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id); + for (ComponentName admin : admins) { + if (!isSeparateProfileChallengeEnabled) { + if (dpm.getPasswordQuality(admin, userInfo.id) + > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { + if (enforcedAdmin == null) { + enforcedAdmin = new EnforcedAdmin(admin, userInfo.id); + } else { + return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; + } + // This same admins could have set policies both on the managed profile + // and on the parent. So, if the admin has set the policy on the + // managed profile here, we don't need to further check if that admin + // has set policy on the parent admin. + continue; + } + } + if (userInfo.isManagedProfile()) { + // If userInfo.id is a managed profile, we also need to look at + // the policies set on the parent. + DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo); + if (parentDpm.getPasswordQuality(admin, userInfo.id) + > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { + if (enforcedAdmin == null) { + enforcedAdmin = new EnforcedAdmin(admin, userInfo.id); + } else { + return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; + } + } + } + } } } return enforcedAdmin; @@ -352,7 +455,8 @@ public class RestrictedLockUtils { EnforcedAdmin enforcedAdmin = null; final int userId = UserHandle.myUserId(); if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { - // If the user has a separate challenge, only consider the admins in that user. + // userId is managed profile and has a separate challenge, only consider + // the admins in that user. final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId); if (admins == null) { return null; @@ -373,7 +477,7 @@ public class RestrictedLockUtils { for (UserInfo userInfo : um.getProfiles(userId)) { final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id); if (admins == null) { - return null; + continue; } final boolean isSeparateProfileChallengeEnabled = lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id); @@ -410,19 +514,24 @@ public class RestrictedLockUtils { return enforcedAdmin; } - public static EnforcedAdmin getProfileOrDeviceOwnerOnCallingUser(Context context) { + public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) { + if (userId == UserHandle.USER_NULL) { + return null; + } final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( Context.DEVICE_POLICY_SERVICE); if (dpm == null) { return null; } - ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser(); + ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId); if (adminComponent != null) { - return new EnforcedAdmin(adminComponent, UserHandle.myUserId()); + return new EnforcedAdmin(adminComponent, userId); } - adminComponent = dpm.getProfileOwner(); - if (adminComponent != null) { - return new EnforcedAdmin(adminComponent, UserHandle.myUserId()); + if (dpm.getDeviceOwnerUserId() == userId) { + adminComponent = dpm.getDeviceOwnerComponentOnAnyUser(); + if (adminComponent != null) { + return new EnforcedAdmin(adminComponent, userId); + } } return null; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 908d2f0e8867..f296d68cedcf 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4132,7 +4132,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public void choosePrivateKeyAlias(final int uid, final Uri uri, final String alias, final IBinder response) { // Caller UID needs to be trusted, so we restrict this method to SYSTEM_UID callers. - if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) { + if (!isCallerWithSystemUid()) { return; } @@ -5860,8 +5860,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } mContext.enforceCallingOrSelfPermission( android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS, null); - if (hasUserSetupCompleted(userHandle) - && !UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) { + if (hasUserSetupCompleted(userHandle) && !isCallerWithSystemUid()) { throw new IllegalStateException("Cannot set the profile owner on a user which is " + "already set-up"); } @@ -5921,8 +5920,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void enforceManageUsers() { final int callingUid = mInjector.binderGetCallingUid(); - if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) - || callingUid == Process.ROOT_UID)) { + if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); } } @@ -5945,8 +5943,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (userHandle == UserHandle.getUserId(callingUid)) { return; } - if (!(UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) - || callingUid == Process.ROOT_UID)) { + if (!(isCallerWithSystemUid() || callingUid == Process.ROOT_UID)) { mContext.enforceCallingOrSelfPermission(permission, "Must be system or have " + permission + " permission"); } @@ -5964,6 +5961,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private boolean isCallerWithSystemUid() { + return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID); + } + private int getProfileParentId(int userHandle) { final long ident = mInjector.binderClearCallingIdentity(); try { @@ -6248,7 +6249,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public ComponentName getRestrictionsProvider(int userHandle) { synchronized (this) { - if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) { + if (!isCallerWithSystemUid()) { throw new SecurityException("Only the system can query the permission provider"); } DevicePolicyData userData = getUserData(userHandle); @@ -6321,8 +6322,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * permittedList or are a system app. */ private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages, - List<String> permittedList) { - int userIdToCheck = UserHandle.getCallingUserId(); + List<String> permittedList, int userIdToCheck) { long id = mInjector.binderClearCallingIdentity(); try { // If we have an enabled packages list for a managed profile the packages @@ -6389,7 +6389,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { for (AccessibilityServiceInfo service : enabledServices) { enabledPackages.add(service.getResolveInfo().serviceInfo.packageName); } - if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) { + if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList, + userId)) { Slog.e(LOG_TAG, "Cannot set permitted accessibility services, " + "because it contains already enabled accesibility services."); return false; @@ -6481,6 +6482,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public boolean isAccessibilityServicePermittedByAdmin(ComponentName who, String packageName, + int userHandle) { + if (!mHasFeature) { + return true; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + Preconditions.checkStringNotEmpty(packageName, "packageName is null"); + if (!isCallerWithSystemUid()){ + throw new SecurityException( + "Only the system can query if an accessibility service is disabled by admin"); + } + synchronized (this) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); + if (admin.permittedAccessiblityServices == null) { + return true; + } + return checkPackagesInPermittedListOrSystem(Arrays.asList(packageName), + admin.permittedAccessiblityServices, userHandle); + } + } + private boolean checkCallerIsCurrentUserOrProfile() { int callingUserId = UserHandle.getCallingUserId(); long token = mInjector.binderClearCallingIdentity(); @@ -6536,7 +6559,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { for (InputMethodInfo ime : enabledImes) { enabledPackages.add(ime.getPackageName()); } - if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) { + if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList, + mInjector.binderGetCallingUserHandle().getIdentifier())) { Slog.e(LOG_TAG, "Cannot set permitted input methods, " + "because it contains already enabled input method."); return false; @@ -6629,6 +6653,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override + public boolean isInputMethodPermittedByAdmin(ComponentName who, String packageName, + int userHandle) { + if (!mHasFeature) { + return true; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + Preconditions.checkStringNotEmpty(packageName, "packageName is null"); + if (!isCallerWithSystemUid()) { + throw new SecurityException( + "Only the system can query if an input method is disabled by admin"); + } + synchronized (this) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle); + if (admin.permittedInputMethods == null) { + return true; + } + return checkPackagesInPermittedListOrSystem(Arrays.asList(packageName), + admin.permittedInputMethods, userHandle); + } + } + + @Override public UserHandle createUser(ComponentName who, String name) { Preconditions.checkNotNull(who, "ComponentName is null"); synchronized (this) { @@ -7425,7 +7471,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) { - if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) { + if (!isCallerWithSystemUid()) { throw new SecurityException("notifyLockTaskModeChanged can only be called by system"); } synchronized (this) { @@ -8180,7 +8226,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return null; } Preconditions.checkNotNull(who, "ComponentName is null"); - if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) { + if (!isCallerWithSystemUid()) { throw new SecurityException("Only the system can query support message for user"); } synchronized (this) { @@ -8198,7 +8244,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return null; } Preconditions.checkNotNull(who, "ComponentName is null"); - if (!UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID)) { + if (!isCallerWithSystemUid()) { throw new SecurityException("Only the system can query support message for user"); } synchronized (this) { |