Merge "Made changes to fix some policy transparency options."

This commit is contained in:
Sudheer Shanka
2016-02-04 19:14:14 +00:00
committed by Android (Google) Code Review
4 changed files with 260 additions and 58 deletions

View File

@@ -4108,6 +4108,29 @@ public class DevicePolicyManager {
return null;
}
/**
* 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.
@@ -4187,6 +4210,28 @@ public class DevicePolicyManager {
return null;
}
/**
* 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.)

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
@@ -6628,6 +6652,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");
@@ -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) {