Home | History | Annotate | Download | only in settingslib
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settingslib;
     18 
     19 import android.app.AppGlobals;
     20 import android.app.admin.DevicePolicyManager;
     21 import android.content.ComponentName;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.pm.IPackageManager;
     25 import android.content.pm.UserInfo;
     26 import android.graphics.drawable.Drawable;
     27 import android.os.RemoteException;
     28 import android.os.UserHandle;
     29 import android.os.UserManager;
     30 import android.provider.Settings;
     31 import android.text.Spanned;
     32 import android.text.SpannableStringBuilder;
     33 import android.text.style.ForegroundColorSpan;
     34 import android.text.style.ImageSpan;
     35 import android.view.MenuItem;
     36 import android.widget.TextView;
     37 
     38 import com.android.internal.widget.LockPatternUtils;
     39 
     40 import java.util.List;
     41 
     42 /**
     43  * Utility class to host methods usable in adding a restricted padlock icon and showing admin
     44  * support message dialog.
     45  */
     46 public class RestrictedLockUtils {
     47     /**
     48      * @return drawables for displaying with settings that are locked by a device admin.
     49      */
     50     public static Drawable getRestrictedPadlock(Context context) {
     51         Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_info);
     52         final int iconSize = context.getResources().getDimensionPixelSize(
     53                 R.dimen.restricted_icon_size);
     54         restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
     55         return restrictedPadlock;
     56     }
     57 
     58     /**
     59      * Checks if a restriction is enforced on a user and returns the enforced admin and
     60      * admin userId.
     61      *
     62      * @param userRestriction Restriction to check
     63      * @param userId User which we need to check if restriction is enforced on.
     64      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
     65      * or {@code null} If the restriction is not set. If the restriction is set by both device owner
     66      * and profile owner, then the admin component will be set to {@code null} and userId to
     67      * {@link UserHandle#USER_NULL}.
     68      */
     69     public static EnforcedAdmin checkIfRestrictionEnforced(Context context,
     70             String userRestriction, int userId) {
     71         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
     72                 Context.DEVICE_POLICY_SERVICE);
     73         if (dpm == null) {
     74             return null;
     75         }
     76         UserManager um = UserManager.get(context);
     77         int restrictionSource = um.getUserRestrictionSource(userRestriction,
     78                 UserHandle.of(userId));
     79 
     80         // If the restriction is not enforced or enforced only by system then return null
     81         if (restrictionSource == UserManager.RESTRICTION_NOT_SET
     82                 || restrictionSource == UserManager.RESTRICTION_SOURCE_SYSTEM) {
     83             return null;
     84         }
     85 
     86         final boolean enforcedByProfileOwner =
     87                 (restrictionSource & UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) != 0;
     88         final boolean enforcedByDeviceOwner =
     89                 (restrictionSource & UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) != 0;
     90         if (enforcedByProfileOwner) {
     91             return getProfileOwner(context, userId);
     92         } else if (enforcedByDeviceOwner) {
     93             // When the restriction is enforced by device owner, return the device owner admin only
     94             // if the admin is for the {@param userId} otherwise return a default EnforcedAdmin.
     95             final EnforcedAdmin deviceOwner = getDeviceOwner(context);
     96             return deviceOwner.userId == userId
     97                     ? deviceOwner
     98                     : EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
     99         }
    100         return null;
    101     }
    102 
    103     public static boolean hasBaseUserRestriction(Context context,
    104             String userRestriction, int userId) {
    105         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    106         return um.hasBaseUserRestriction(userRestriction, UserHandle.of(userId));
    107     }
    108 
    109     /**
    110      * Checks if keyguard features are disabled by policy.
    111      *
    112      * @param keyguardFeatures Could be any of keyguard features that can be
    113      * disabled by {@link android.app.admin.DevicePolicyManager#setKeyguardDisabledFeatures}.
    114      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
    115      * or {@code null} If the notification features are not disabled. If the restriction is set by
    116      * multiple admins, then the admin component will be set to {@code null} and userId to
    117      * {@link UserHandle#USER_NULL}.
    118      */
    119     public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
    120             int keyguardFeatures, int userId) {
    121         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    122                 Context.DEVICE_POLICY_SERVICE);
    123         if (dpm == null) {
    124             return null;
    125         }
    126         final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    127         LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
    128         EnforcedAdmin enforcedAdmin = null;
    129         if (um.getUserInfo(userId).isManagedProfile()) {
    130             final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
    131             if (admins == null) {
    132                 return null;
    133             }
    134             for (ComponentName admin : admins) {
    135                 if ((dpm.getKeyguardDisabledFeatures(admin, userId) & keyguardFeatures) != 0) {
    136                     if (enforcedAdmin == null) {
    137                         enforcedAdmin = new EnforcedAdmin(admin, userId);
    138                     } else {
    139                         return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    140                     }
    141                 }
    142             }
    143         } else {
    144             // Consider all admins for this user and the profiles that are visible from this
    145             // user that do not use a separate work challenge.
    146             for (UserInfo userInfo : um.getProfiles(userId)) {
    147                 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
    148                 if (admins == null) {
    149                     continue;
    150                 }
    151                 final boolean isSeparateProfileChallengeEnabled =
    152                         lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
    153                 for (ComponentName admin : admins) {
    154                     if (!isSeparateProfileChallengeEnabled) {
    155                         if ((dpm.getKeyguardDisabledFeatures(admin, userInfo.id)
    156                                     & keyguardFeatures) != 0) {
    157                             if (enforcedAdmin == null) {
    158                                 enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
    159                             } else {
    160                                 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    161                             }
    162                             // This same admins could have set policies both on the managed profile
    163                             // and on the parent. So, if the admin has set the policy on the
    164                             // managed profile here, we don't need to further check if that admin
    165                             // has set policy on the parent admin.
    166                             continue;
    167                         }
    168                     }
    169                     if (userInfo.isManagedProfile()) {
    170                         // If userInfo.id is a managed profile, we also need to look at
    171                         // the policies set on the parent.
    172                         DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
    173                         if ((parentDpm.getKeyguardDisabledFeatures(admin, userInfo.id)
    174                                 & keyguardFeatures) != 0) {
    175                             if (enforcedAdmin == null) {
    176                                 enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
    177                             } else {
    178                                 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    179                             }
    180                         }
    181                     }
    182                 }
    183             }
    184         }
    185         return enforcedAdmin;
    186     }
    187 
    188     public static EnforcedAdmin checkIfUninstallBlocked(Context context,
    189             String packageName, int userId) {
    190         EnforcedAdmin allAppsControlDisallowedAdmin = checkIfRestrictionEnforced(context,
    191                 UserManager.DISALLOW_APPS_CONTROL, userId);
    192         if (allAppsControlDisallowedAdmin != null) {
    193             return allAppsControlDisallowedAdmin;
    194         }
    195         EnforcedAdmin allAppsUninstallDisallowedAdmin = checkIfRestrictionEnforced(context,
    196                 UserManager.DISALLOW_UNINSTALL_APPS, userId);
    197         if (allAppsUninstallDisallowedAdmin != null) {
    198             return allAppsUninstallDisallowedAdmin;
    199         }
    200         IPackageManager ipm = AppGlobals.getPackageManager();
    201         try {
    202             if (ipm.getBlockUninstallForUser(packageName, userId)) {
    203                 return getProfileOrDeviceOwner(context, userId);
    204             }
    205         } catch (RemoteException e) {
    206             // Nothing to do
    207         }
    208         return null;
    209     }
    210 
    211     /**
    212      * Check if an application is suspended.
    213      *
    214      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
    215      * or {@code null} if the application is not suspended.
    216      */
    217     public static EnforcedAdmin checkIfApplicationIsSuspended(Context context, String packageName,
    218             int userId) {
    219         IPackageManager ipm = AppGlobals.getPackageManager();
    220         try {
    221             if (ipm.isPackageSuspendedForUser(packageName, userId)) {
    222                 return getProfileOrDeviceOwner(context, userId);
    223             }
    224         } catch (RemoteException | IllegalArgumentException e) {
    225             // Nothing to do
    226         }
    227         return null;
    228     }
    229 
    230     public static EnforcedAdmin checkIfInputMethodDisallowed(Context context,
    231             String packageName, int userId) {
    232         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    233                 Context.DEVICE_POLICY_SERVICE);
    234         if (dpm == null) {
    235             return null;
    236         }
    237         EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
    238         boolean permitted = true;
    239         if (admin != null) {
    240             permitted = dpm.isInputMethodPermittedByAdmin(admin.component,
    241                     packageName, userId);
    242         }
    243         int managedProfileId = getManagedProfileId(context, userId);
    244         EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
    245         boolean permittedByProfileAdmin = true;
    246         if (profileAdmin != null) {
    247             permittedByProfileAdmin = dpm.isInputMethodPermittedByAdmin(profileAdmin.component,
    248                     packageName, managedProfileId);
    249         }
    250         if (!permitted && !permittedByProfileAdmin) {
    251             return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    252         } else if (!permitted) {
    253             return admin;
    254         } else if (!permittedByProfileAdmin) {
    255             return profileAdmin;
    256         }
    257         return null;
    258     }
    259 
    260     /**
    261      * @param context
    262      * @param userId user id of a managed profile.
    263      * @return is remote contacts search disallowed.
    264      */
    265     public static EnforcedAdmin checkIfRemoteContactSearchDisallowed(Context context, int userId) {
    266         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    267                 Context.DEVICE_POLICY_SERVICE);
    268         if (dpm == null) {
    269             return null;
    270         }
    271         EnforcedAdmin admin = getProfileOwner(context, userId);
    272         if (admin == null) {
    273             return null;
    274         }
    275         UserHandle userHandle = UserHandle.of(userId);
    276         if (dpm.getCrossProfileContactsSearchDisabled(userHandle)
    277                 && dpm.getCrossProfileCallerIdDisabled(userHandle)) {
    278             return admin;
    279         }
    280         return null;
    281     }
    282 
    283     public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context,
    284             String packageName, int userId) {
    285         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    286                 Context.DEVICE_POLICY_SERVICE);
    287         if (dpm == null) {
    288             return null;
    289         }
    290         EnforcedAdmin admin = getProfileOrDeviceOwner(context, userId);
    291         boolean permitted = true;
    292         if (admin != null) {
    293             permitted = dpm.isAccessibilityServicePermittedByAdmin(admin.component,
    294                     packageName, userId);
    295         }
    296         int managedProfileId = getManagedProfileId(context, userId);
    297         EnforcedAdmin profileAdmin = getProfileOrDeviceOwner(context, managedProfileId);
    298         boolean permittedByProfileAdmin = true;
    299         if (profileAdmin != null) {
    300             permittedByProfileAdmin = dpm.isAccessibilityServicePermittedByAdmin(
    301                     profileAdmin.component, packageName, managedProfileId);
    302         }
    303         if (!permitted && !permittedByProfileAdmin) {
    304             return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    305         } else if (!permitted) {
    306             return admin;
    307         } else if (!permittedByProfileAdmin) {
    308             return profileAdmin;
    309         }
    310         return null;
    311     }
    312 
    313     private static int getManagedProfileId(Context context, int userId) {
    314         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    315         List<UserInfo> userProfiles = um.getProfiles(userId);
    316         for (UserInfo uInfo : userProfiles) {
    317             if (uInfo.id == userId) {
    318                 continue;
    319             }
    320             if (uInfo.isManagedProfile()) {
    321                 return uInfo.id;
    322             }
    323         }
    324         return UserHandle.USER_NULL;
    325     }
    326 
    327     /**
    328      * Check if account management for a specific type of account is disabled by admin.
    329      * Only a profile or device owner can disable account management. So, we check if account
    330      * management is disabled and return profile or device owner on the calling user.
    331      *
    332      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
    333      * or {@code null} if the account management is not disabled.
    334      */
    335     public static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
    336             String accountType, int userId) {
    337         if (accountType == null) {
    338             return null;
    339         }
    340         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    341                 Context.DEVICE_POLICY_SERVICE);
    342         if (dpm == null) {
    343             return null;
    344         }
    345         boolean isAccountTypeDisabled = false;
    346         String[] disabledTypes = dpm.getAccountTypesWithManagementDisabledAsUser(userId);
    347         for (String type : disabledTypes) {
    348             if (accountType.equals(type)) {
    349                 isAccountTypeDisabled = true;
    350                 break;
    351             }
    352         }
    353         if (!isAccountTypeDisabled) {
    354             return null;
    355         }
    356         return getProfileOrDeviceOwner(context, userId);
    357     }
    358 
    359     /**
    360      * Checks if {@link android.app.admin.DevicePolicyManager#setAutoTimeRequired} is enforced
    361      * on the device.
    362      *
    363      * @return EnforcedAdmin Object containing the device owner component and
    364      * userId the device owner is running as, or {@code null} setAutoTimeRequired is not enforced.
    365      */
    366     public static EnforcedAdmin checkIfAutoTimeRequired(Context context) {
    367         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    368                 Context.DEVICE_POLICY_SERVICE);
    369         if (dpm == null || !dpm.getAutoTimeRequired()) {
    370             return null;
    371         }
    372         ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser();
    373         return new EnforcedAdmin(adminComponent, UserHandle.myUserId());
    374     }
    375 
    376     /**
    377      * Checks if an admin has enforced minimum password quality requirements on the given user.
    378      *
    379      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
    380      * or {@code null} if no quality requirements are set. If the requirements are set by
    381      * multiple device admins, then the admin component will be set to {@code null} and userId to
    382      * {@link UserHandle#USER_NULL}.
    383      *
    384      */
    385     public static EnforcedAdmin checkIfPasswordQualityIsSet(Context context, int userId) {
    386         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    387                 Context.DEVICE_POLICY_SERVICE);
    388         if (dpm == null) {
    389             return null;
    390         }
    391 
    392         LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
    393         EnforcedAdmin enforcedAdmin = null;
    394         if (lockPatternUtils.isSeparateProfileChallengeEnabled(userId)) {
    395             // userId is managed profile and has a separate challenge, only consider
    396             // the admins in that user.
    397             final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userId);
    398             if (admins == null) {
    399                 return null;
    400             }
    401             for (ComponentName admin : admins) {
    402                 if (dpm.getPasswordQuality(admin, userId)
    403                         > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    404                     if (enforcedAdmin == null) {
    405                         enforcedAdmin = new EnforcedAdmin(admin, userId);
    406                     } else {
    407                         return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    408                     }
    409                 }
    410             }
    411         } else {
    412             // Return all admins for this user and the profiles that are visible from this
    413             // user that do not use a separate work challenge.
    414             final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    415             for (UserInfo userInfo : um.getProfiles(userId)) {
    416                 final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
    417                 if (admins == null) {
    418                     continue;
    419                 }
    420                 final boolean isSeparateProfileChallengeEnabled =
    421                         lockPatternUtils.isSeparateProfileChallengeEnabled(userInfo.id);
    422                 for (ComponentName admin : admins) {
    423                     if (!isSeparateProfileChallengeEnabled) {
    424                         if (dpm.getPasswordQuality(admin, userInfo.id)
    425                                 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    426                             if (enforcedAdmin == null) {
    427                                 enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
    428                             } else {
    429                                 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    430                             }
    431                             // This same admins could have set policies both on the managed profile
    432                             // and on the parent. So, if the admin has set the policy on the
    433                             // managed profile here, we don't need to further check if that admin
    434                             // has set policy on the parent admin.
    435                             continue;
    436                         }
    437                     }
    438                     if (userInfo.isManagedProfile()) {
    439                         // If userInfo.id is a managed profile, we also need to look at
    440                         // the policies set on the parent.
    441                         DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
    442                         if (parentDpm.getPasswordQuality(admin, userInfo.id)
    443                                 > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    444                             if (enforcedAdmin == null) {
    445                                 enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
    446                             } else {
    447                                 return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    448                             }
    449                         }
    450                     }
    451                 }
    452             }
    453         }
    454         return enforcedAdmin;
    455     }
    456 
    457     /**
    458      * Checks if any admin has set maximum time to lock.
    459      *
    460      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
    461      * or {@code null} if no admin has set this restriction. If multiple admins has set this, then
    462      * the admin component will be set to {@code null} and userId to {@link UserHandle#USER_NULL}
    463      */
    464     public static EnforcedAdmin checkIfMaximumTimeToLockIsSet(Context context) {
    465         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    466                 Context.DEVICE_POLICY_SERVICE);
    467         if (dpm == null) {
    468             return null;
    469         }
    470         LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
    471         EnforcedAdmin enforcedAdmin = null;
    472         final int userId = UserHandle.myUserId();
    473         final UserManager um = UserManager.get(context);
    474         final List<UserInfo> profiles = um.getProfiles(userId);
    475         final int profilesSize = profiles.size();
    476         // As we do not have a separate screen lock timeout settings for work challenge,
    477         // we need to combine all profiles maximum time to lock even work challenge is
    478         // enabled.
    479         for (int i = 0; i < profilesSize; i++) {
    480             final UserInfo userInfo = profiles.get(i);
    481             final List<ComponentName> admins = dpm.getActiveAdminsAsUser(userInfo.id);
    482             if (admins == null) {
    483                 continue;
    484             }
    485             for (ComponentName admin : admins) {
    486                 if (dpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
    487                     if (enforcedAdmin == null) {
    488                         enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
    489                     } else {
    490                         return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    491                     }
    492                     // This same admins could have set policies both on the managed profile
    493                     // and on the parent. So, if the admin has set the policy on the
    494                     // managed profile here, we don't need to further check if that admin
    495                     // has set policy on the parent admin.
    496                     continue;
    497                 }
    498                 if (userInfo.isManagedProfile()) {
    499                     // If userInfo.id is a managed profile, we also need to look at
    500                     // the policies set on the parent.
    501                     final DevicePolicyManager parentDpm = dpm.getParentProfileInstance(userInfo);
    502                     if (parentDpm.getMaximumTimeToLock(admin, userInfo.id) > 0) {
    503                         if (enforcedAdmin == null) {
    504                             enforcedAdmin = new EnforcedAdmin(admin, userInfo.id);
    505                         } else {
    506                             return EnforcedAdmin.MULTIPLE_ENFORCED_ADMIN;
    507                         }
    508                     }
    509                 }
    510             }
    511         }
    512         return enforcedAdmin;
    513     }
    514 
    515     public static EnforcedAdmin getProfileOrDeviceOwner(Context context, int userId) {
    516         if (userId == UserHandle.USER_NULL) {
    517             return null;
    518         }
    519         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    520                 Context.DEVICE_POLICY_SERVICE);
    521         if (dpm == null) {
    522             return null;
    523         }
    524         ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
    525         if (adminComponent != null) {
    526             return new EnforcedAdmin(adminComponent, userId);
    527         }
    528         if (dpm.getDeviceOwnerUserId() == userId) {
    529             adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
    530             if (adminComponent != null) {
    531                 return new EnforcedAdmin(adminComponent, userId);
    532             }
    533         }
    534         return null;
    535     }
    536 
    537     public static EnforcedAdmin getDeviceOwner(Context context) {
    538         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    539                 Context.DEVICE_POLICY_SERVICE);
    540         if (dpm == null) {
    541             return null;
    542         }
    543         ComponentName adminComponent = dpm.getDeviceOwnerComponentOnAnyUser();
    544         if (adminComponent != null) {
    545             return new EnforcedAdmin(adminComponent, dpm.getDeviceOwnerUserId());
    546         }
    547         return null;
    548     }
    549 
    550     private static EnforcedAdmin getProfileOwner(Context context, int userId) {
    551         if (userId == UserHandle.USER_NULL) {
    552             return null;
    553         }
    554         final DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    555                 Context.DEVICE_POLICY_SERVICE);
    556         if (dpm == null) {
    557             return null;
    558         }
    559         ComponentName adminComponent = dpm.getProfileOwnerAsUser(userId);
    560         if (adminComponent != null) {
    561             return new EnforcedAdmin(adminComponent, userId);
    562         }
    563         return null;
    564     }
    565 
    566     /**
    567      * Set the menu item as disabled by admin by adding a restricted padlock at the end of the
    568      * text and set the click listener which will send an intent to show the admin support details
    569      * dialog. If the admin is null, remove the padlock and disabled color span. When the admin is
    570      * null, we also set the OnMenuItemClickListener to null, so if you want to set a custom
    571      * OnMenuItemClickListener, set it after calling this method.
    572      */
    573     public static void setMenuItemAsDisabledByAdmin(final Context context,
    574             final MenuItem item, final EnforcedAdmin admin) {
    575         SpannableStringBuilder sb = new SpannableStringBuilder(item.getTitle());
    576         removeExistingRestrictedSpans(sb);
    577 
    578         if (admin != null) {
    579             final int disabledColor = context.getColor(R.color.disabled_text_color);
    580             sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
    581                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    582             ImageSpan image = new RestrictedLockImageSpan(context);
    583             sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    584 
    585             item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
    586                 @Override
    587                 public boolean onMenuItemClick(MenuItem item) {
    588                     sendShowAdminSupportDetailsIntent(context, admin);
    589                     return true;
    590                 }
    591             });
    592         } else {
    593             item.setOnMenuItemClickListener(null);
    594         }
    595         item.setTitle(sb);
    596     }
    597 
    598     private static void removeExistingRestrictedSpans(SpannableStringBuilder sb) {
    599         final int length = sb.length();
    600         RestrictedLockImageSpan[] imageSpans = sb.getSpans(length - 1, length,
    601                 RestrictedLockImageSpan.class);
    602         for (ImageSpan span : imageSpans) {
    603             final int start = sb.getSpanStart(span);
    604             final int end = sb.getSpanEnd(span);
    605             sb.removeSpan(span);
    606             sb.delete(start, end);
    607         }
    608         ForegroundColorSpan[] colorSpans = sb.getSpans(0, length, ForegroundColorSpan.class);
    609         for (ForegroundColorSpan span : colorSpans) {
    610             sb.removeSpan(span);
    611         }
    612     }
    613 
    614     /**
    615      * Send the intent to trigger the {@link android.settings.ShowAdminSupportDetailsDialog}.
    616      */
    617     public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
    618         final Intent intent = getShowAdminSupportDetailsIntent(context, admin);
    619         int targetUserId = UserHandle.myUserId();
    620         if (admin != null && admin.userId != UserHandle.USER_NULL
    621                 && isCurrentUserOrProfile(context, admin.userId)) {
    622             targetUserId = admin.userId;
    623         }
    624         context.startActivityAsUser(intent, new UserHandle(targetUserId));
    625     }
    626 
    627     public static Intent getShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
    628         final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
    629         if (admin != null) {
    630             if (admin.component != null) {
    631                 intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin.component);
    632             }
    633             int adminUserId = UserHandle.myUserId();
    634             if (admin.userId != UserHandle.USER_NULL) {
    635                 adminUserId = admin.userId;
    636             }
    637             intent.putExtra(Intent.EXTRA_USER_ID, adminUserId);
    638         }
    639         return intent;
    640     }
    641 
    642     public static boolean isCurrentUserOrProfile(Context context, int userId) {
    643         UserManager um = UserManager.get(context);
    644         for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
    645             if (userInfo.id == userId) {
    646                 return true;
    647             }
    648         }
    649         return false;
    650     }
    651 
    652     public static boolean isAdminInCurrentUserOrProfile(Context context, ComponentName admin) {
    653         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
    654                 Context.DEVICE_POLICY_SERVICE);
    655         UserManager um = UserManager.get(context);
    656         for (UserInfo userInfo : um.getProfiles(UserHandle.myUserId())) {
    657             if (dpm.isAdminActiveAsUser(admin, userInfo.id)) {
    658                 return true;
    659             }
    660         }
    661         return false;
    662     }
    663 
    664     public static void setTextViewPadlock(Context context,
    665             TextView textView, boolean showPadlock) {
    666         final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText());
    667         removeExistingRestrictedSpans(sb);
    668         if (showPadlock) {
    669             final ImageSpan image = new RestrictedLockImageSpan(context);
    670             sb.append(" ", image, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    671         }
    672         textView.setText(sb);
    673     }
    674 
    675     /**
    676      * Takes a {@link android.widget.TextView} and applies an alpha so that the text looks like
    677      * disabled and appends a padlock to the text. This assumes that there are no
    678      * ForegroundColorSpans and RestrictedLockImageSpans used on the TextView.
    679      */
    680     public static void setTextViewAsDisabledByAdmin(Context context,
    681             TextView textView, boolean disabled) {
    682         final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText());
    683         removeExistingRestrictedSpans(sb);
    684         if (disabled) {
    685             final int disabledColor = context.getColor(R.color.disabled_text_color);
    686             sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
    687                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    688             textView.setCompoundDrawables(null, null, getRestrictedPadlock(context), null);
    689             textView.setCompoundDrawablePadding(context.getResources().getDimensionPixelSize(
    690                     R.dimen.restricted_icon_padding));
    691         } else {
    692             textView.setCompoundDrawables(null, null, null, null);
    693         }
    694         textView.setText(sb);
    695     }
    696 
    697     public static class EnforcedAdmin {
    698         public ComponentName component = null;
    699         public int userId = UserHandle.USER_NULL;
    700 
    701         // We use this to represent the case where a policy is enforced by multiple admins.
    702         public final static EnforcedAdmin MULTIPLE_ENFORCED_ADMIN = new EnforcedAdmin();
    703 
    704         public EnforcedAdmin(ComponentName component, int userId) {
    705             this.component = component;
    706             this.userId = userId;
    707         }
    708 
    709         public EnforcedAdmin(EnforcedAdmin other) {
    710             if (other == null) {
    711                 throw new IllegalArgumentException();
    712             }
    713             this.component = other.component;
    714             this.userId = other.userId;
    715         }
    716 
    717         public EnforcedAdmin() {}
    718 
    719         @Override
    720         public boolean equals(Object object) {
    721             if (object == this) return true;
    722             if (!(object instanceof EnforcedAdmin)) return false;
    723             EnforcedAdmin other = (EnforcedAdmin) object;
    724             if (userId != other.userId) {
    725                 return false;
    726             }
    727             if ((component == null && other.component == null) ||
    728                     (component != null && component.equals(other.component))) {
    729                 return true;
    730             }
    731             return false;
    732         }
    733 
    734         @Override
    735         public String toString() {
    736             return "EnforcedAdmin{component=" + component + ",userId=" + userId + "}";
    737         }
    738 
    739         public void copyTo(EnforcedAdmin other) {
    740             if (other == null) {
    741                 throw new IllegalArgumentException();
    742             }
    743             other.component = component;
    744             other.userId = userId;
    745         }
    746     }
    747 }
    748