| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.settingslib; |
| |
| import android.app.AppGlobals; |
| import android.app.admin.DevicePolicyManager; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.IPackageManager; |
| import android.content.pm.UserInfo; |
| import android.graphics.drawable.Drawable; |
| import android.os.RemoteException; |
| import android.os.UserHandle; |
| import android.os.UserManager; |
| import android.provider.Settings; |
| import android.text.Spanned; |
| import android.text.SpannableStringBuilder; |
| import android.text.style.ForegroundColorSpan; |
| import android.text.style.ImageSpan; |
| import android.view.MenuItem; |
| import android.widget.TextView; |
| |
| import com.android.internal.widget.LockPatternUtils; |
| |
| import java.util.List; |
| |
| /** |
| * Utility class to host methods usable in adding a restricted padlock icon and showing admin |
| * support message dialog. |
| */ |
| public class RestrictedLockUtils { |
| /** |
| * @return drawables for displaying with settings that are locked by a device admin. |
| */ |
| public static Drawable getRestrictedPadlock(Context context) { |
| Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_info); |
| final int iconSize = context.getResources().getDimensionPixelSize( |
| R.dimen.restricted_icon_size); |
| restrictedPadlock.setBounds(0, 0, iconSize, iconSize); |
| return restrictedPadlock; |
| } |
| |
| /** |
| * Checks if a restriction is enforced on a user and returns the enforced admin and |
| * admin userId. |
| * |
| * @param userRestriction Restriction to check |
| * @param userId User which we need to check if restriction is enforced on. |
| * @return EnforcedAdmin Object containing the enforced admin component and admin user details, |
| * or {@code null} If the restriction is not set. If the restriction is set by both device owner |
| * and profile owner, then the admin component will be set to {@code null} and userId to |
| * {@link UserHandle#USER_NULL}. |
| */ |
| public static EnforcedAdmin checkIfRestrictionEnforced(Context context, |
| String userRestriction, int userId) { |
| DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null) { |
| return null; |
| } |
| UserManager um = UserManager.get(context); |
| int restrictionSource = um.getUserRestrictionSource(userRestriction, |
| UserHandle.of(userId)); |
| |
| // If the restriction is not enforced or enforced only by system then return null |
| if (restrictionSource == UserManager.RESTRICTION_NOT_SET |
| || restrictionSource == UserManager.RESTRICTION_SOURCE_SYSTEM) { |
| return null; |
| } |
| |
| final boolean enforcedByProfileOwner = |
| (restrictionSource & UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) != 0; |
| final boolean enforcedByDeviceOwner = |
| (restrictionSource & UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) != 0; |
| if (enforcedByProfileOwner) { |
| return getProfileOwner(context, userId); |
| } else if (enforcedByDeviceOwner) { |
| // When the restriction is enforced by device owner, return the device owner admin only |
| // if the admin is for the {@param userId} otherwise return a default EnforcedAdmin. |
| final EnforcedAdmin deviceOwner = getDeviceOwner(context); |
| return deviceOwner.userId == userId |
| ? deviceOwner |
| : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; |
| } |
| return null; |
| } |
| |
| public static boolean hasBaseUserRestriction(Context context, |
| String userRestriction, int userId) { |
| UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); |
| return um.hasBaseUserRestriction(userRestriction, UserHandle.of(userId)); |
| } |
| |
| /** |
| * Checks if keyguard features are disabled by policy. |
| * |
| * @param keyguardFeatures Could be any of keyguard features that can be |
| * disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}. |
| * @return EnforcedAdmin Object containing the enforced admin component and admin user details, |
| * or {@code null} If the notification features are not disabled. If the restriction is set by |
| * multiple admins, then the admin component will be set to {@code null} and userId to |
| * {@link UserHandle#USER_NULL}. |
| */ |
| public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context, |
| int keyguardFeatures, int userId) { |
| final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null) { |
| return null; |
| } |
| final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); |
| LockPatternUtils lockPatternUtils = new LockPatternUtils(context); |
| EnforcedAdmin enforcedAdmin = null; |
| if (um.getUserInfo(userId).isManagedProfile()) { |
| final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId); |
| if (admins == null) { |
| return null; |
| } |
| for (ComponentName admin : admins) { |
| if ((dpm.getKeyguardDisabledFeatures(admin, userId) & keyguardFeatures) != 0) { |
| if (enforcedAdmin == null) { |
| enforcedAdmin = new EnforcedAdmin(admin, userId); |
| } else { |
| return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; |
| } |
| } |
| } |
| } else { |
| // Consider all admins for this user and the profiles that are visible from this |
| // user that do not use a separate work challenge. |
| 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.getKeyguardDisabledFeatures(admin, userInfo.id) |
| & keyguardFeatures) != 0) { |
| 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.getKeyguardDisabledFeatures(admin, userInfo.id) |
| & keyguardFeatures) != 0) { |
| if (enforcedAdmin == null) { |
| enforcedAdmin = new EnforcedAdmin(admin, userInfo.id); |
| } else { |
| return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; |
| } |
| } |
| } |
| } |
| } |
| } |
| return enforcedAdmin; |
| } |
| |
| public static EnforcedAdmin checkIfUninstallBlocked(Context context, |
| String packageName, int userId) { |
| EnforcedAdmin allAppsControlDisallowedAdmin = checkIfRestrictionEnforced(context, |
| UserManager.DISALLOW_APPS_CONTROL, userId); |
| if (allAppsControlDisallowedAdmin != null) { |
| return allAppsControlDisallowedAdmin; |
| } |
| EnforcedAdmin allAppsUninstallDisallowedAdmin = checkIfRestrictionEnforced(context, |
| UserManager.DISALLOW_UNINSTALL_APPS, userId); |
| if (allAppsUninstallDisallowedAdmin != null) { |
| return allAppsUninstallDisallowedAdmin; |
| } |
| IPackageManager ipm = AppGlobals.getPackageManager(); |
| try { |
| if (ipm.getBlockUninstallForUser(packageName, userId)) { |
| return getProfileOrDeviceOwner(context, userId); |
| } |
| } catch (RemoteException e) { |
| // Nothing to do |
| } |
| return null; |
| } |
| |
| /** |
| * Check if an application is suspended. |
| * |
| * @return EnforcedAdmin Object containing the enforced admin component and admin user details, |
| * or {@code null} if the application is not suspended. |
| */ |
| public static EnforcedAdmin checkIfApplicationIsSuspended(Context context, String packageName, |
| int userId) { |
| IPackageManager ipm = AppGlobals.getPackageManager(); |
| try { |
| if (ipm.isPackageSuspendedForUser(packageName, userId)) { |
| return getProfileOrDeviceOwner(context, userId); |
| } |
| } catch (RemoteException | IllegalArgumentException e) { |
| // Nothing to do |
| } |
| 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; |
| } |
| |
| /** |
| * @param context |
| * @param userId user id of a managed profile. |
| * @return is remote contacts search disallowed. |
| */ |
| public static EnforcedAdmin checkIfRemoteContactSearchDisallowed(Context context, int userId) { |
| DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null) { |
| return null; |
| } |
| EnforcedAdmin admin = getProfileOwner(context, userId); |
| if (admin == null) { |
| return null; |
| } |
| UserHandle userHandle = UserHandle.of(userId); |
| if (dpm.getCrossProfileContactsSearchDisabled(userHandle) |
| && dpm.getCrossProfileCallerIdDisabled(userHandle)) { |
| return admin; |
| } |
| 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 |
| * management is disabled and return profile or device owner on the calling user. |
| * |
| * @return EnforcedAdmin Object containing the enforced admin component and admin user details, |
| * or {@code null} if the account management is not disabled. |
| */ |
| public static EnforcedAdmin checkIfAccountManagementDisabled(Context context, |
| String accountType, int userId) { |
| if (accountType == null) { |
| return null; |
| } |
| DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null) { |
| return null; |
| } |
| boolean isAccountTypeDisabled = false; |
| String[] disabledTypes = dpm.getAccountTypesWithManagementDisabledAsUser(userId); |
| for (String type : disabledTypes) { |
| if (accountType.equals(type)) { |
| isAccountTypeDisabled = true; |
| break; |
| } |
| } |
| if (!isAccountTypeDisabled) { |
| return null; |
| } |
| return getProfileOrDeviceOwner(context, userId); |
| } |
| |
| /** |
| * Checks if {@link android.app.admin.DevicePolicyManager#setAutoTimeRequired} is enforced |
| * on the device. |
| * |
| * @return EnforcedAdmin Object containing the device owner component and |
| * userId the device owner is running as, or {@code null} setAutoTimeRequired is not enforced. |
| */ |
| public static EnforcedAdmin checkIfAutoTimeRequired(Context context) { |
| DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null || !dpm.getAutoTimeRequired()) { |
| return null; |
| } |
| ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser(); |
| return new EnforcedAdmin(adminComponent, UserHandle.myUserId()); |
| } |
| |
| /** |
| * 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 |
| * multiple device admins, then the admin component will be set to {@code null} and userId to |
| * {@link UserHandle#USER_NULL}. |
| * |
| */ |
| public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) { |
| final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null) { |
| return 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) { |
| if (dpm.getPasswordQuality(admin, userId) |
| > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) { |
| if (enforcedAdmin == null) { |
| enforcedAdmin = new EnforcedAdmin(admin, userId); |
| } else { |
| return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; |
| } |
| } |
| } |
| } 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; |
| } |
| |
| /** |
| * Checks if any admin has set maximum time to lock. |
| * |
| * @return EnforcedAdmin Object containing the enforced admin component and admin user details, |
| * or {@code null} if no admin has set this restriction. If multiple admins has set this, then |
| * the admin component will be set to {@code null} and userId to {@link UserHandle#USER_NULL} |
| */ |
| public static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) { |
| final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null) { |
| return null; |
| } |
| LockPatternUtils lockPatternUtils = new LockPatternUtils(context); |
| EnforcedAdmin enforcedAdmin = null; |
| final int userId = UserHandle.myUserId(); |
| final UserManager um = UserManager.get(context); |
| final List<UserInfo> profiles = um.getProfiles(userId); |
| final int profilesSize = profiles.size(); |
| // As we do not have a separate screen lock timeout settings for work challenge, |
| // we need to combine all profiles maximum time to lock even work challenge is |
| // enabled. |
| for (int i = 0; i < profilesSize; i++) { |
| final UserInfo userInfo = profiles.get(i); |
| final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id); |
| if (admins == null) { |
| continue; |
| } |
| for (ComponentName admin : admins) { |
| if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) { |
| 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. |
| final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo); |
| if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) { |
| if (enforcedAdmin == null) { |
| enforcedAdmin = new EnforcedAdmin(admin, userInfo.id); |
| } else { |
| return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN; |
| } |
| } |
| } |
| } |
| } |
| return enforcedAdmin; |
| } |
| |
| 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.getProfileOwnerAsUser(userId); |
| if (adminComponent != null) { |
| return new EnforcedAdmin(adminComponent, userId); |
| } |
| if (dpm.getDeviceOwnerUserId() == userId) { |
| adminComponent = dpm.getDeviceOwnerComponentOnAnyUser(); |
| if (adminComponent != null) { |
| return new EnforcedAdmin(adminComponent, userId); |
| } |
| } |
| return null; |
| } |
| |
| public static EnforcedAdmin getDeviceOwner(Context context) { |
| final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| if (dpm == null) { |
| return null; |
| } |
| ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser(); |
| if (adminComponent != null) { |
| return new EnforcedAdmin(adminComponent, dpm.getDeviceOwnerUserId()); |
| } |
| return null; |
| } |
| |
| private static EnforcedAdmin getProfileOwner(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.getProfileOwnerAsUser(userId); |
| if (adminComponent != null) { |
| return new EnforcedAdmin(adminComponent, userId); |
| } |
| return null; |
| } |
| |
| /** |
| * Set the menu item as disabled by admin by adding a restricted padlock at the end of the |
| * text and set the click listener which will send an intent to show the admin support details |
| * dialog. If the admin is null, remove the padlock and disabled color span. When the admin is |
| * null, we also set the OnMenuItemClickListener to null, so if you want to set a custom |
| * OnMenuItemClickListener, set it after calling this method. |
| */ |
| public static void setMenuItemAsDisabledByAdmin(final Context context, |
| final MenuItem item, final EnforcedAdmin admin) { |
| SpannableStringBuilder sb = new SpannableStringBuilder(item.getTitle()); |
| removeExistingRestrictedSpans(sb); |
| |
| if (admin != null) { |
| final int disabledColor = context.getColor(R.color.disabled_text_color); |
| sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(), |
| Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); |
| ImageSpan image = new RestrictedLockImageSpan(context); |
| sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); |
| |
| item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { |
| @Override |
| public boolean onMenuItemClick(MenuItem item) { |
| sendShowAdminSupportDetailsIntent(context, admin); |
| return true; |
| } |
| }); |
| } else { |
| item.setOnMenuItemClickListener(null); |
| } |
| item.setTitle(sb); |
| } |
| |
| private static void removeExistingRestrictedSpans(SpannableStringBuilder sb) { |
| final int length = sb.length(); |
| RestrictedLockImageSpan[] imageSpans = sb.getSpans(length - 1, length, |
| RestrictedLockImageSpan.class); |
| for (ImageSpan span : imageSpans) { |
| final int start = sb.getSpanStart(span); |
| final int end = sb.getSpanEnd(span); |
| sb.removeSpan(span); |
| sb.delete(start, end); |
| } |
| ForegroundColorSpan[] colorSpans = sb.getSpans(0, length, ForegroundColorSpan.class); |
| for (ForegroundColorSpan span : colorSpans) { |
| sb.removeSpan(span); |
| } |
| } |
| |
| /** |
| * Send the intent to trigger the {@link android.settings.ShowAdminSupportDetailsDialog}. |
| */ |
| public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) { |
| final Intent intent = getShowAdminSupportDetailsIntent(context, admin); |
| int targetUserId = UserHandle.myUserId(); |
| if (admin != null && admin.userId != UserHandle.USER_NULL |
| && isCurrentUserOrProfile(context, admin.userId)) { |
| targetUserId = admin.userId; |
| } |
| context.startActivityAsUser(intent, new UserHandle(targetUserId)); |
| } |
| |
| public static Intent getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) { |
| final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); |
| if (admin != null) { |
| if (admin.component != null) { |
| intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component); |
| } |
| int adminUserId = UserHandle.myUserId(); |
| if (admin.userId != UserHandle.USER_NULL) { |
| adminUserId = admin.userId; |
| } |
| intent.putExtra(Intent.EXTRA_USER_ID, adminUserId); |
| } |
| return intent; |
| } |
| |
| public static boolean isCurrentUserOrProfile(Context context, int userId) { |
| UserManager um = UserManager.get(context); |
| for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) { |
| if (userInfo.id == userId) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public static boolean isAdminInCurrentUserOrProfile(Context context, ComponentName admin) { |
| DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( |
| Context.DEVICE_POLICY_SERVICE); |
| UserManager um = UserManager.get(context); |
| for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) { |
| if (dpm.isAdminActiveAsUser(admin, userInfo.id)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public static void setTextViewPadlock(Context context, |
| TextView textView, boolean showPadlock) { |
| final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText()); |
| removeExistingRestrictedSpans(sb); |
| if (showPadlock) { |
| final ImageSpan image = new RestrictedLockImageSpan(context); |
| sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); |
| } |
| textView.setText(sb); |
| } |
| |
| /** |
| * Takes a {@link android.widget.TextView} and applies an alpha so that the text looks like |
| * disabled and appends a padlock to the text. This assumes that there are no |
| * ForegroundColorSpans and RestrictedLockImageSpans used on the TextView. |
| */ |
| public static void setTextViewAsDisabledByAdmin(Context context, |
| TextView textView, boolean disabled) { |
| final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText()); |
| removeExistingRestrictedSpans(sb); |
| if (disabled) { |
| final int disabledColor = context.getColor(R.color.disabled_text_color); |
| sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(), |
| Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); |
| textView.setCompoundDrawables(null, null, getRestrictedPadlock(context), null); |
| textView.setCompoundDrawablePadding(context.getResources().getDimensionPixelSize( |
| R.dimen.restricted_icon_padding)); |
| } else { |
| textView.setCompoundDrawables(null, null, null, null); |
| } |
| textView.setText(sb); |
| } |
| |
| public static class EnforcedAdmin { |
| public ComponentName component = null; |
| public int userId = UserHandle.USER_NULL; |
| |
| // We use this to represent the case where a policy is enforced by multiple admins. |
| public final static EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = new EnforcedAdmin(); |
| |
| public EnforcedAdmin(ComponentName component, int userId) { |
| this.component = component; |
| this.userId = userId; |
| } |
| |
| public EnforcedAdmin(EnforcedAdmin other) { |
| if (other == null) { |
| throw new IllegalArgumentException(); |
| } |
| this.component = other.component; |
| this.userId = other.userId; |
| } |
| |
| public EnforcedAdmin() {} |
| |
| @Override |
| public boolean equals(Object object) { |
| if (object == this) return true; |
| if (!(object instanceof EnforcedAdmin)) return false; |
| EnforcedAdmin other = (EnforcedAdmin) object; |
| if (userId != other.userId) { |
| return false; |
| } |
| if ((component == null && other.component == null) || |
| (component != null && component.equals(other.component))) { |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "EnforcedAdmin{component=" + component + ",userId=" + userId + "}"; |
| } |
| |
| public void copyTo(EnforcedAdmin other) { |
| if (other == null) { |
| throw new IllegalArgumentException(); |
| } |
| other.component = component; |
| other.userId = userId; |
| } |
| } |
| } |