Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2007 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.settings;
     18 
     19 
     20 import android.app.Activity;
     21 import android.app.AlertDialog;
     22 import android.app.Dialog;
     23 import android.app.DialogFragment;
     24 import android.app.FragmentManager;
     25 import android.app.admin.DevicePolicyManager;
     26 import android.content.ComponentName;
     27 import android.content.Context;
     28 import android.content.DialogInterface;
     29 import android.content.Intent;
     30 import android.content.pm.PackageManager;
     31 import android.content.pm.ResolveInfo;
     32 import android.content.res.Resources;
     33 import android.hardware.fingerprint.FingerprintManager;
     34 import android.os.Bundle;
     35 import android.os.PersistableBundle;
     36 import android.os.UserHandle;
     37 import android.os.UserManager;
     38 import android.os.storage.StorageManager;
     39 import android.provider.SearchIndexableResource;
     40 import android.provider.Settings;
     41 import android.security.KeyStore;
     42 import android.service.trust.TrustAgentService;
     43 import android.support.v14.preference.SwitchPreference;
     44 import android.support.v7.preference.Preference;
     45 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
     46 import android.support.v7.preference.Preference.OnPreferenceClickListener;
     47 import android.support.v7.preference.PreferenceGroup;
     48 import android.support.v7.preference.PreferenceScreen;
     49 import android.telephony.CarrierConfigManager;
     50 import android.telephony.SubscriptionInfo;
     51 import android.telephony.SubscriptionManager;
     52 import android.telephony.TelephonyManager;
     53 import android.text.TextUtils;
     54 import android.util.Log;
     55 import com.android.internal.logging.MetricsProto.MetricsEvent;
     56 import com.android.internal.widget.LockPatternUtils;
     57 import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo;
     58 import com.android.settings.fingerprint.FingerprintSettings;
     59 import com.android.settings.search.BaseSearchIndexProvider;
     60 import com.android.settings.search.Index;
     61 import com.android.settings.search.Indexable;
     62 import com.android.settings.search.SearchIndexableRaw;
     63 import com.android.settingslib.RestrictedLockUtils;
     64 import com.android.settingslib.RestrictedPreference;
     65 import com.android.settingslib.RestrictedSwitchPreference;
     66 
     67 import java.util.ArrayList;
     68 import java.util.List;
     69 
     70 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
     71 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
     72 
     73 /**
     74  * Gesture lock pattern settings.
     75  */
     76 public class SecuritySettings extends SettingsPreferenceFragment
     77         implements OnPreferenceChangeListener, DialogInterface.OnClickListener, Indexable,
     78         GearPreference.OnGearClickListener {
     79 
     80     private static final String TAG = "SecuritySettings";
     81     private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
     82     private static final Intent TRUST_AGENT_INTENT =
     83             new Intent(TrustAgentService.SERVICE_INTERFACE);
     84 
     85     // Lock Settings
     86     private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
     87     private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "unlock_set_or_change_profile";
     88     private static final String KEY_VISIBLE_PATTERN_PROFILE = "visiblepattern_profile";
     89     private static final String KEY_SECURITY_CATEGORY = "security_category";
     90     private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category";
     91     private static final String KEY_ADVANCED_SECURITY = "advanced_security";
     92     private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
     93     private static final String KEY_UNIFICATION = "unification";
     94 
     95     private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
     96     private static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
     97     private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE = 127;
     98     private static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 128;
     99     private static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 129;
    100     private static final int UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 130;
    101     private static final String TAG_UNIFICATION_DIALOG = "unification_dialog";
    102 
    103     // Misc Settings
    104     private static final String KEY_SIM_LOCK = "sim_lock";
    105     private static final String KEY_SHOW_PASSWORD = "show_password";
    106     private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type";
    107     private static final String KEY_USER_CREDENTIALS = "user_credentials";
    108     private static final String KEY_RESET_CREDENTIALS = "credentials_reset";
    109     private static final String KEY_CREDENTIALS_INSTALL = "credentials_install";
    110     private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
    111     private static final String KEY_CREDENTIALS_MANAGER = "credentials_management";
    112     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
    113     private static final String KEY_TRUST_AGENT = "trust_agent";
    114     private static final String KEY_SCREEN_PINNING = "screen_pinning_settings";
    115 
    116     // These switch preferences need special handling since they're not all stored in Settings.
    117     private static final String SWITCH_PREFERENCE_KEYS[] = {
    118             KEY_SHOW_PASSWORD, KEY_TOGGLE_INSTALL_APPLICATIONS, KEY_UNIFICATION,
    119             KEY_VISIBLE_PATTERN_PROFILE
    120     };
    121 
    122     // Only allow one trust agent on the platform.
    123     private static final boolean ONLY_ONE_TRUST_AGENT = true;
    124 
    125     private static final int MY_USER_ID = UserHandle.myUserId();
    126 
    127     private DevicePolicyManager mDPM;
    128     private SubscriptionManager mSubscriptionManager;
    129     private UserManager mUm;
    130 
    131     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
    132     private LockPatternUtils mLockPatternUtils;
    133     private ManagedLockPasswordProvider mManagedPasswordProvider;
    134 
    135     private SwitchPreference mVisiblePatternProfile;
    136     private SwitchPreference mUnifyProfile;
    137 
    138     private SwitchPreference mShowPassword;
    139 
    140     private KeyStore mKeyStore;
    141     private RestrictedPreference mResetCredentials;
    142 
    143     private RestrictedSwitchPreference mToggleAppInstallation;
    144     private DialogInterface mWarnInstallApps;
    145 
    146     private boolean mIsAdmin;
    147 
    148     private Intent mTrustAgentClickIntent;
    149 
    150     private int mProfileChallengeUserId;
    151 
    152     private String mCurrentDevicePassword;
    153     private String mCurrentProfilePassword;
    154 
    155     @Override
    156     protected int getMetricsCategory() {
    157         return MetricsEvent.SECURITY;
    158     }
    159 
    160     @Override
    161     public void onCreate(Bundle savedInstanceState) {
    162         super.onCreate(savedInstanceState);
    163 
    164         mSubscriptionManager = SubscriptionManager.from(getActivity());
    165 
    166         mLockPatternUtils = new LockPatternUtils(getActivity());
    167 
    168         mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), MY_USER_ID);
    169 
    170         mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
    171 
    172         mUm = UserManager.get(getActivity());
    173 
    174         mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
    175 
    176         if (savedInstanceState != null
    177                 && savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) {
    178             mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
    179         }
    180     }
    181 
    182     private static int getResIdForLockUnlockScreen(Context context,
    183             LockPatternUtils lockPatternUtils, ManagedLockPasswordProvider managedPasswordProvider,
    184             int userId) {
    185         final boolean isMyUser = userId == MY_USER_ID;
    186         int resid = 0;
    187         if (!lockPatternUtils.isSecure(userId)) {
    188             if (!isMyUser) {
    189                 resid = R.xml.security_settings_lockscreen_profile;
    190             } else if (lockPatternUtils.isLockScreenDisabled(userId)) {
    191                 resid = R.xml.security_settings_lockscreen;
    192             } else {
    193                 resid = R.xml.security_settings_chooser;
    194             }
    195         } else {
    196             switch (lockPatternUtils.getKeyguardStoredPasswordQuality(userId)) {
    197                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
    198                     resid = isMyUser ? R.xml.security_settings_pattern
    199                             : R.xml.security_settings_pattern_profile;
    200                     break;
    201                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
    202                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
    203                     resid = isMyUser ? R.xml.security_settings_pin
    204                             : R.xml.security_settings_pin_profile;
    205                     break;
    206                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
    207                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
    208                 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
    209                     resid = isMyUser ? R.xml.security_settings_password
    210                             : R.xml.security_settings_password_profile;
    211                     break;
    212                 case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
    213                     resid = managedPasswordProvider.getResIdForLockUnlockScreen(!isMyUser);
    214                     break;
    215             }
    216         }
    217         return resid;
    218     }
    219 
    220     /**
    221      * Important!
    222      *
    223      * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the
    224      * logic or adding/removing preferences here.
    225      */
    226     private PreferenceScreen createPreferenceHierarchy() {
    227         PreferenceScreen root = getPreferenceScreen();
    228         if (root != null) {
    229             root.removeAll();
    230         }
    231         addPreferencesFromResource(R.xml.security_settings);
    232         root = getPreferenceScreen();
    233 
    234         // Add options for lock/unlock screen
    235         final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils,
    236                 mManagedPasswordProvider, MY_USER_ID);
    237         addPreferencesFromResource(resid);
    238 
    239         // DO or PO installed in the user may disallow to change password.
    240         disableIfPasswordQualityManaged(KEY_UNLOCK_SET_OR_CHANGE, MY_USER_ID);
    241 
    242         mProfileChallengeUserId = Utils.getManagedProfileId(mUm, MY_USER_ID);
    243         if (mProfileChallengeUserId != UserHandle.USER_NULL
    244                 && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) {
    245             addPreferencesFromResource(R.xml.security_settings_profile);
    246             addPreferencesFromResource(R.xml.security_settings_unification);
    247             final int profileResid = getResIdForLockUnlockScreen(
    248                     getActivity(), mLockPatternUtils, mManagedPasswordProvider,
    249                     mProfileChallengeUserId);
    250             addPreferencesFromResource(profileResid);
    251             maybeAddFingerprintPreference(root, mProfileChallengeUserId);
    252             if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) {
    253                 final Preference lockPreference =
    254                         root.findPreference(KEY_UNLOCK_SET_OR_CHANGE_PROFILE);
    255                 final String summary = getContext().getString(
    256                         R.string.lock_settings_profile_unified_summary);
    257                 lockPreference.setSummary(summary);
    258                 lockPreference.setEnabled(false);
    259                 // PO may disallow to change password for the profile, but screen lock and managed
    260                 // profile's lock is the same. Disable main "Screen lock" menu.
    261                 disableIfPasswordQualityManaged(KEY_UNLOCK_SET_OR_CHANGE, mProfileChallengeUserId);
    262             } else {
    263                 // PO may disallow to change profile password, and the profile's password is
    264                 // separated from screen lock password. Disable profile specific "Screen lock" menu.
    265                 disableIfPasswordQualityManaged(KEY_UNLOCK_SET_OR_CHANGE_PROFILE,
    266                         mProfileChallengeUserId);
    267             }
    268         }
    269 
    270         Preference unlockSetOrChange = findPreference(KEY_UNLOCK_SET_OR_CHANGE);
    271         if (unlockSetOrChange instanceof GearPreference) {
    272             ((GearPreference) unlockSetOrChange).setOnGearClickListener(this);
    273         }
    274 
    275         // Add options for device encryption
    276         mIsAdmin = mUm.isAdminUser();
    277 
    278         if (mIsAdmin) {
    279             if (LockPatternUtils.isDeviceEncryptionEnabled()) {
    280                 // The device is currently encrypted.
    281                 addPreferencesFromResource(R.xml.security_settings_encrypted);
    282             } else {
    283                 // This device supports encryption but isn't encrypted.
    284                 addPreferencesFromResource(R.xml.security_settings_unencrypted);
    285             }
    286         }
    287 
    288         // Fingerprint and trust agents
    289         PreferenceGroup securityCategory = (PreferenceGroup)
    290                 root.findPreference(KEY_SECURITY_CATEGORY);
    291         if (securityCategory != null) {
    292             maybeAddFingerprintPreference(securityCategory, UserHandle.myUserId());
    293             addTrustAgentSettings(securityCategory);
    294         }
    295 
    296         mVisiblePatternProfile =
    297                 (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN_PROFILE);
    298         mUnifyProfile = (SwitchPreference) root.findPreference(KEY_UNIFICATION);
    299 
    300         // Append the rest of the settings
    301         addPreferencesFromResource(R.xml.security_settings_misc);
    302 
    303         // Do not display SIM lock for devices without an Icc card
    304         TelephonyManager tm = TelephonyManager.getDefault();
    305         CarrierConfigManager cfgMgr = (CarrierConfigManager)
    306                 getActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE);
    307         PersistableBundle b = cfgMgr.getConfig();
    308         if (!mIsAdmin || !isSimIccReady() ||
    309                 b.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL)) {
    310             root.removePreference(root.findPreference(KEY_SIM_LOCK));
    311         } else {
    312             // Disable SIM lock if there is no ready SIM card.
    313             root.findPreference(KEY_SIM_LOCK).setEnabled(isSimReady());
    314         }
    315         if (Settings.System.getInt(getContentResolver(),
    316                 Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) {
    317             root.findPreference(KEY_SCREEN_PINNING).setSummary(
    318                     getResources().getString(R.string.switch_on_text));
    319         }
    320 
    321         // Show password
    322         mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD);
    323         mResetCredentials = (RestrictedPreference) root.findPreference(KEY_RESET_CREDENTIALS);
    324 
    325         // Credential storage
    326         final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
    327         mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume()
    328 
    329         if (!RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
    330                 UserManager.DISALLOW_CONFIG_CREDENTIALS, MY_USER_ID)) {
    331             RestrictedPreference userCredentials = (RestrictedPreference) root.findPreference(
    332                     KEY_USER_CREDENTIALS);
    333             userCredentials.checkRestrictionAndSetDisabled(
    334                     UserManager.DISALLOW_CONFIG_CREDENTIALS);
    335             RestrictedPreference credentialStorageType = (RestrictedPreference) root.findPreference(
    336                     KEY_CREDENTIAL_STORAGE_TYPE);
    337             credentialStorageType.checkRestrictionAndSetDisabled(
    338                     UserManager.DISALLOW_CONFIG_CREDENTIALS);
    339             RestrictedPreference installCredentials = (RestrictedPreference) root.findPreference(
    340                     KEY_CREDENTIALS_INSTALL);
    341             installCredentials.checkRestrictionAndSetDisabled(
    342                     UserManager.DISALLOW_CONFIG_CREDENTIALS);
    343             mResetCredentials.checkRestrictionAndSetDisabled(
    344                     UserManager.DISALLOW_CONFIG_CREDENTIALS);
    345 
    346             final int storageSummaryRes =
    347                     mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware
    348                             : R.string.credential_storage_type_software;
    349             credentialStorageType.setSummary(storageSummaryRes);
    350         } else {
    351             PreferenceGroup credentialsManager = (PreferenceGroup)
    352                     root.findPreference(KEY_CREDENTIALS_MANAGER);
    353             credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS));
    354             credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL));
    355             credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE));
    356             credentialsManager.removePreference(root.findPreference(KEY_USER_CREDENTIALS));
    357         }
    358 
    359 
    360         // Application install
    361         PreferenceGroup deviceAdminCategory = (PreferenceGroup)
    362                 root.findPreference(KEY_DEVICE_ADMIN_CATEGORY);
    363         mToggleAppInstallation = (RestrictedSwitchPreference) findPreference(
    364                 KEY_TOGGLE_INSTALL_APPLICATIONS);
    365         mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
    366         // Side loading of apps.
    367         // Disable for restricted profiles. For others, check if policy disallows it.
    368         mToggleAppInstallation.setEnabled(!um.getUserInfo(MY_USER_ID).isRestricted());
    369         if (RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
    370                 UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, MY_USER_ID)
    371                 || RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
    372                         UserManager.DISALLOW_INSTALL_APPS, MY_USER_ID)) {
    373             mToggleAppInstallation.setEnabled(false);
    374         }
    375         if (mToggleAppInstallation.isEnabled()) {
    376             mToggleAppInstallation.checkRestrictionAndSetDisabled(
    377                     UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
    378             if (!mToggleAppInstallation.isDisabledByAdmin()) {
    379                 mToggleAppInstallation.checkRestrictionAndSetDisabled(
    380                         UserManager.DISALLOW_INSTALL_APPS);
    381             }
    382         }
    383 
    384         // Advanced Security features
    385         PreferenceGroup advancedCategory =
    386                 (PreferenceGroup)root.findPreference(KEY_ADVANCED_SECURITY);
    387         if (advancedCategory != null) {
    388             Preference manageAgents = advancedCategory.findPreference(KEY_MANAGE_TRUST_AGENTS);
    389             if (manageAgents != null && !mLockPatternUtils.isSecure(MY_USER_ID)) {
    390                 manageAgents.setEnabled(false);
    391                 manageAgents.setSummary(R.string.disabled_because_no_backup_security);
    392             }
    393         }
    394 
    395         // The above preferences come and go based on security state, so we need to update
    396         // the index. This call is expected to be fairly cheap, but we may want to do something
    397         // smarter in the future.
    398         Index.getInstance(getActivity())
    399                 .updateFromClassNameResource(SecuritySettings.class.getName(), true, true);
    400 
    401         for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
    402             final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]);
    403             if (pref != null) pref.setOnPreferenceChangeListener(this);
    404         }
    405         return root;
    406     }
    407 
    408     /*
    409      * Sets the preference as disabled by admin if PASSWORD_QUALITY_MANAGED is set.
    410      * The preference must be a RestrictedPreference.
    411      */
    412     private void disableIfPasswordQualityManaged(String preferenceKey, int userId) {
    413         final EnforcedAdmin admin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
    414                 getActivity(), userId);
    415         if (admin != null && mDPM.getPasswordQuality(admin.component, userId) ==
    416                 DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
    417             final RestrictedPreference pref =
    418                     (RestrictedPreference) getPreferenceScreen().findPreference(preferenceKey);
    419             pref.setDisabledByAdmin(admin);
    420         }
    421     }
    422 
    423     private void maybeAddFingerprintPreference(PreferenceGroup securityCategory, int userId) {
    424         Preference fingerprintPreference =
    425                 FingerprintSettings.getFingerprintPreferenceForUser(
    426                         securityCategory.getContext(), userId);
    427         if (fingerprintPreference != null) {
    428             securityCategory.addPreference(fingerprintPreference);
    429         }
    430     }
    431 
    432     private void addTrustAgentSettings(PreferenceGroup securityCategory) {
    433         final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
    434         ArrayList<TrustAgentComponentInfo> agents =
    435                 getActiveTrustAgents(getActivity(), mLockPatternUtils, mDPM);
    436         for (int i = 0; i < agents.size(); i++) {
    437             final TrustAgentComponentInfo agent = agents.get(i);
    438             RestrictedPreference trustAgentPreference =
    439                     new RestrictedPreference(securityCategory.getContext());
    440             trustAgentPreference.setKey(KEY_TRUST_AGENT);
    441             trustAgentPreference.setTitle(agent.title);
    442             trustAgentPreference.setSummary(agent.summary);
    443             // Create intent for this preference.
    444             Intent intent = new Intent();
    445             intent.setComponent(agent.componentName);
    446             intent.setAction(Intent.ACTION_MAIN);
    447             trustAgentPreference.setIntent(intent);
    448             // Add preference to the settings menu.
    449             securityCategory.addPreference(trustAgentPreference);
    450 
    451             trustAgentPreference.setDisabledByAdmin(agent.admin);
    452             if (!trustAgentPreference.isDisabledByAdmin() && !hasSecurity) {
    453                 trustAgentPreference.setEnabled(false);
    454                 trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security);
    455             }
    456         }
    457     }
    458 
    459     /* Return true if a there is a Slot that has Icc.
    460      */
    461     private boolean isSimIccReady() {
    462         TelephonyManager tm = TelephonyManager.getDefault();
    463         final List<SubscriptionInfo> subInfoList =
    464                 mSubscriptionManager.getActiveSubscriptionInfoList();
    465 
    466         if (subInfoList != null) {
    467             for (SubscriptionInfo subInfo : subInfoList) {
    468                 if (tm.hasIccCard(subInfo.getSimSlotIndex())) {
    469                     return true;
    470                 }
    471             }
    472         }
    473 
    474         return false;
    475     }
    476 
    477     /* Return true if a SIM is ready for locking.
    478      * TODO: consider adding to TelephonyManager or SubscritpionManasger.
    479      */
    480     private boolean isSimReady() {
    481         int simState = TelephonyManager.SIM_STATE_UNKNOWN;
    482         final List<SubscriptionInfo> subInfoList =
    483                 mSubscriptionManager.getActiveSubscriptionInfoList();
    484         if (subInfoList != null) {
    485             for (SubscriptionInfo subInfo : subInfoList) {
    486                 simState = TelephonyManager.getDefault().getSimState(subInfo.getSimSlotIndex());
    487                 if((simState != TelephonyManager.SIM_STATE_ABSENT) &&
    488                             (simState != TelephonyManager.SIM_STATE_UNKNOWN)){
    489                     return true;
    490                 }
    491             }
    492         }
    493         return false;
    494     }
    495 
    496     private static ArrayList<TrustAgentComponentInfo> getActiveTrustAgents(
    497             Context context, LockPatternUtils utils, DevicePolicyManager dpm) {
    498         PackageManager pm = context.getPackageManager();
    499         ArrayList<TrustAgentComponentInfo> result = new ArrayList<TrustAgentComponentInfo>();
    500         List<ResolveInfo> resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT,
    501                 PackageManager.GET_META_DATA);
    502         List<ComponentName> enabledTrustAgents = utils.getEnabledTrustAgents(MY_USER_ID);
    503 
    504         EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(context,
    505                 DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, UserHandle.myUserId());
    506 
    507         if (enabledTrustAgents != null && !enabledTrustAgents.isEmpty()) {
    508             for (int i = 0; i < resolveInfos.size(); i++) {
    509                 ResolveInfo resolveInfo = resolveInfos.get(i);
    510                 if (resolveInfo.serviceInfo == null) continue;
    511                 if (!TrustAgentUtils.checkProvidePermission(resolveInfo, pm)) continue;
    512                 TrustAgentComponentInfo trustAgentComponentInfo =
    513                         TrustAgentUtils.getSettingsComponent(pm, resolveInfo);
    514                 if (trustAgentComponentInfo.componentName == null ||
    515                         !enabledTrustAgents.contains(
    516                                 TrustAgentUtils.getComponentName(resolveInfo)) ||
    517                         TextUtils.isEmpty(trustAgentComponentInfo.title)) continue;
    518                 if (admin != null && dpm.getTrustAgentConfiguration(
    519                         null, TrustAgentUtils.getComponentName(resolveInfo)) == null) {
    520                     trustAgentComponentInfo.admin = admin;
    521                 }
    522                 result.add(trustAgentComponentInfo);
    523                 if (ONLY_ONE_TRUST_AGENT) break;
    524             }
    525         }
    526         return result;
    527     }
    528 
    529     private boolean isNonMarketAppsAllowed() {
    530         return Settings.Global.getInt(getContentResolver(),
    531                                       Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0;
    532     }
    533 
    534     private void setNonMarketAppsAllowed(boolean enabled) {
    535         final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
    536         if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
    537             return;
    538         }
    539         // Change the system setting
    540         Settings.Global.putInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS,
    541                                 enabled ? 1 : 0);
    542     }
    543 
    544     private void warnAppInstallation() {
    545         // TODO: DialogFragment?
    546         mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle(
    547                 getResources().getString(R.string.error_title))
    548                 .setIcon(com.android.internal.R.drawable.ic_dialog_alert)
    549                 .setMessage(getResources().getString(R.string.install_all_warning))
    550                 .setPositiveButton(android.R.string.yes, this)
    551                 .setNegativeButton(android.R.string.no, this)
    552                 .show();
    553     }
    554 
    555     @Override
    556     public void onClick(DialogInterface dialog, int which) {
    557         if (dialog == mWarnInstallApps) {
    558             boolean turnOn = which == DialogInterface.BUTTON_POSITIVE;
    559             setNonMarketAppsAllowed(turnOn);
    560             if (mToggleAppInstallation != null) {
    561                 mToggleAppInstallation.setChecked(turnOn);
    562             }
    563         }
    564     }
    565 
    566     @Override
    567     public void onGearClick(GearPreference p) {
    568         if (KEY_UNLOCK_SET_OR_CHANGE.equals(p.getKey())) {
    569             startFragment(this, SecuritySubSettings.class.getName(), 0, 0, null);
    570         }
    571     }
    572 
    573     @Override
    574     public void onDestroy() {
    575         super.onDestroy();
    576         if (mWarnInstallApps != null) {
    577             mWarnInstallApps.dismiss();
    578         }
    579     }
    580 
    581     @Override
    582     public void onSaveInstanceState(Bundle outState) {
    583         super.onSaveInstanceState(outState);
    584         if (mTrustAgentClickIntent != null) {
    585             outState.putParcelable(TRUST_AGENT_CLICK_INTENT, mTrustAgentClickIntent);
    586         }
    587     }
    588 
    589     @Override
    590     public void onResume() {
    591         super.onResume();
    592 
    593         // Make sure we reload the preference hierarchy since some of these settings
    594         // depend on others...
    595         createPreferenceHierarchy();
    596 
    597         if (mVisiblePatternProfile != null) {
    598             mVisiblePatternProfile.setChecked(mLockPatternUtils.isVisiblePatternEnabled(
    599                     mProfileChallengeUserId));
    600         }
    601 
    602         updateUnificationPreference();
    603 
    604         if (mShowPassword != null) {
    605             mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
    606                     Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
    607         }
    608 
    609         if (mResetCredentials != null && !mResetCredentials.isDisabledByAdmin()) {
    610             mResetCredentials.setEnabled(!mKeyStore.isEmpty());
    611         }
    612     }
    613 
    614     private void updateUnificationPreference() {
    615         if (mUnifyProfile != null) {
    616             mUnifyProfile.setChecked(!mLockPatternUtils.isSeparateProfileChallengeEnabled(
    617                     mProfileChallengeUserId));
    618         }
    619     }
    620 
    621     @Override
    622     public boolean onPreferenceTreeClick(Preference preference) {
    623         final String key = preference.getKey();
    624         if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
    625             startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
    626                     R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
    627         } else if (KEY_UNLOCK_SET_OR_CHANGE_PROFILE.equals(key)) {
    628             if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm,
    629                     mProfileChallengeUserId)) {
    630                 return false;
    631             }
    632             Bundle extras = new Bundle();
    633             extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId);
    634             startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
    635                     R.string.lock_settings_picker_title_profile,
    636                     SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras);
    637         } else if (KEY_TRUST_AGENT.equals(key)) {
    638             ChooseLockSettingsHelper helper =
    639                     new ChooseLockSettingsHelper(this.getActivity(), this);
    640             mTrustAgentClickIntent = preference.getIntent();
    641             boolean confirmationLaunched = helper.launchConfirmationActivity(
    642                     CHANGE_TRUST_AGENT_SETTINGS, preference.getTitle());
    643             if (!confirmationLaunched&&  mTrustAgentClickIntent != null) {
    644                 // If this returns false, it means no password confirmation is required.
    645                 startActivity(mTrustAgentClickIntent);
    646                 mTrustAgentClickIntent = null;
    647             }
    648         } else {
    649             // If we didn't handle it, let preferences handle it.
    650             return super.onPreferenceTreeClick(preference);
    651         }
    652         return true;
    653     }
    654 
    655     /**
    656      * see confirmPatternThenDisableAndClear
    657      */
    658     @Override
    659     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    660         super.onActivityResult(requestCode, resultCode, data);
    661         if (requestCode == CHANGE_TRUST_AGENT_SETTINGS && resultCode == Activity.RESULT_OK) {
    662             if (mTrustAgentClickIntent != null) {
    663                 startActivity(mTrustAgentClickIntent);
    664                 mTrustAgentClickIntent = null;
    665             }
    666             return;
    667         } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST
    668                 && resultCode == Activity.RESULT_OK) {
    669             mCurrentDevicePassword =
    670                     data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
    671             launchConfirmProfileLockForUnification();
    672             return;
    673         } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST
    674                 && resultCode == Activity.RESULT_OK) {
    675             mCurrentProfilePassword =
    676                     data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
    677             unifyLocks();
    678             return;
    679         } else if (requestCode == UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST
    680                 && resultCode == Activity.RESULT_OK) {
    681             ununifyLocks();
    682             return;
    683         }
    684         createPreferenceHierarchy();
    685     }
    686 
    687     private void launchConfirmDeviceLockForUnification() {
    688         final String title = getActivity().getString(
    689                 R.string.unlock_set_unlock_launch_picker_title);
    690         final ChooseLockSettingsHelper helper =
    691                 new ChooseLockSettingsHelper(getActivity(), this);
    692         if (!helper.launchConfirmationActivity(
    693                 UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) {
    694             launchConfirmProfileLockForUnification();
    695         }
    696     }
    697 
    698     private void launchConfirmProfileLockForUnification() {
    699         final String title = getActivity().getString(
    700                 R.string.unlock_set_unlock_launch_picker_title_profile);
    701         final ChooseLockSettingsHelper helper =
    702                 new ChooseLockSettingsHelper(getActivity(), this);
    703         if (!helper.launchConfirmationActivity(
    704                 UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileChallengeUserId)) {
    705             unifyLocks();
    706             createPreferenceHierarchy();
    707         }
    708     }
    709 
    710     private void unifyLocks() {
    711         int profileQuality =
    712                 mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId);
    713         if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
    714             mLockPatternUtils.saveLockPattern(
    715                     LockPatternUtils.stringToPattern(mCurrentProfilePassword),
    716                     mCurrentDevicePassword, MY_USER_ID);
    717         } else {
    718             mLockPatternUtils.saveLockPassword(
    719                     mCurrentProfilePassword, mCurrentDevicePassword,
    720                     profileQuality, MY_USER_ID);
    721         }
    722         mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false,
    723                 mCurrentProfilePassword);
    724         final boolean profilePatternVisibility =
    725                 mLockPatternUtils.isVisiblePatternEnabled(mProfileChallengeUserId);
    726         mLockPatternUtils.setVisiblePatternEnabled(profilePatternVisibility, MY_USER_ID);
    727         mCurrentDevicePassword = null;
    728         mCurrentProfilePassword = null;
    729     }
    730 
    731     private void unifyUncompliantLocks() {
    732         mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false,
    733                 mCurrentProfilePassword);
    734         startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
    735                 R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
    736     }
    737 
    738     private void ununifyLocks() {
    739         Bundle extras = new Bundle();
    740         extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId);
    741         startFragment(this,
    742                 "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
    743                 R.string.lock_settings_picker_title_profile,
    744                 SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras);
    745     }
    746 
    747     @Override
    748     public boolean onPreferenceChange(Preference preference, Object value) {
    749         boolean result = true;
    750         final String key = preference.getKey();
    751         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
    752         if (KEY_VISIBLE_PATTERN_PROFILE.equals(key)) {
    753             if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm,
    754                     mProfileChallengeUserId)) {
    755                 return false;
    756             }
    757             lockPatternUtils.setVisiblePatternEnabled((Boolean) value, mProfileChallengeUserId);
    758         } else if (KEY_UNIFICATION.equals(key)) {
    759             if (Utils.startQuietModeDialogIfNecessary(this.getActivity(), mUm,
    760                     mProfileChallengeUserId)) {
    761                 return false;
    762             }
    763             if ((Boolean) value) {
    764                 final boolean compliantForDevice =
    765                         (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId)
    766                                 >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
    767                         && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify(
    768                                 mProfileChallengeUserId));
    769                 UnificationConfirmationDialog dialog =
    770                         UnificationConfirmationDialog.newIntance(compliantForDevice);
    771                 dialog.show(getChildFragmentManager(), TAG_UNIFICATION_DIALOG);
    772             } else {
    773                 final String title = getActivity().getString(
    774                         R.string.unlock_set_unlock_launch_picker_title);
    775                 final ChooseLockSettingsHelper helper =
    776                         new ChooseLockSettingsHelper(getActivity(), this);
    777                 if(!helper.launchConfirmationActivity(
    778                         UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) {
    779                     ununifyLocks();
    780                 }
    781             }
    782         } else if (KEY_SHOW_PASSWORD.equals(key)) {
    783             Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
    784                     ((Boolean) value) ? 1 : 0);
    785             lockPatternUtils.setVisiblePasswordEnabled((Boolean) value, MY_USER_ID);
    786         } else if (KEY_TOGGLE_INSTALL_APPLICATIONS.equals(key)) {
    787             if ((Boolean) value) {
    788                 mToggleAppInstallation.setChecked(false);
    789                 warnAppInstallation();
    790                 // Don't change Switch status until user makes choice in dialog, so return false.
    791                 result = false;
    792             } else {
    793                 setNonMarketAppsAllowed(false);
    794             }
    795         }
    796         return result;
    797     }
    798 
    799     @Override
    800     protected int getHelpResource() {
    801         return R.string.help_url_security;
    802     }
    803 
    804     /**
    805      * For Search. Please keep it in sync when updating "createPreferenceHierarchy()"
    806      */
    807     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
    808             new SecuritySearchIndexProvider();
    809 
    810     private static class SecuritySearchIndexProvider extends BaseSearchIndexProvider {
    811 
    812         @Override
    813         public List<SearchIndexableResource> getXmlResourcesToIndex(
    814                 Context context, boolean enabled) {
    815             final List<SearchIndexableResource> index = new ArrayList<SearchIndexableResource>();
    816 
    817             final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
    818             final ManagedLockPasswordProvider managedPasswordProvider =
    819                     ManagedLockPasswordProvider.get(context, MY_USER_ID);
    820             final DevicePolicyManager dpm = (DevicePolicyManager)
    821                     context.getSystemService(Context.DEVICE_POLICY_SERVICE);
    822             final UserManager um = UserManager.get(context);
    823             final int profileUserId = Utils.getManagedProfileId(um, MY_USER_ID);
    824 
    825             // To add option for unlock screen, user's password must not be managed and
    826             // must not be unified with managed profile, whose password is managed.
    827             if (!isPasswordManaged(MY_USER_ID, context, dpm)
    828                     && (profileUserId == UserHandle.USER_NULL
    829                             || lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)
    830                             || !isPasswordManaged(profileUserId, context, dpm))) {
    831                 // Add options for lock/unlock screen
    832                 final int resId = getResIdForLockUnlockScreen(context, lockPatternUtils,
    833                         managedPasswordProvider, MY_USER_ID);
    834                 index.add(getSearchResource(context, resId));
    835             }
    836 
    837             if (profileUserId != UserHandle.USER_NULL
    838                     && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)
    839                     && !isPasswordManaged(profileUserId, context, dpm)) {
    840                 index.add(getSearchResource(context, getResIdForLockUnlockScreen(context,
    841                         lockPatternUtils, managedPasswordProvider, profileUserId)));
    842             }
    843 
    844             if (um.isAdminUser()) {
    845                 switch (dpm.getStorageEncryptionStatus()) {
    846                     case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
    847                         // The device is currently encrypted.
    848                         index.add(getSearchResource(context, R.xml.security_settings_encrypted));
    849                         break;
    850                     case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE:
    851                         // This device supports encryption but isn't encrypted.
    852                         index.add(getSearchResource(context, R.xml.security_settings_unencrypted));
    853                         break;
    854                 }
    855             }
    856 
    857             final SearchIndexableResource sir = getSearchResource(context,
    858                     SecuritySubSettings.getResIdForLockUnlockSubScreen(context, lockPatternUtils,
    859                             managedPasswordProvider));
    860             sir.className = SecuritySubSettings.class.getName();
    861             index.add(sir);
    862 
    863             // Append the rest of the settings
    864             index.add(getSearchResource(context, R.xml.security_settings_misc));
    865 
    866             return index;
    867         }
    868 
    869         private SearchIndexableResource getSearchResource(Context context, int xmlResId) {
    870             final SearchIndexableResource sir = new SearchIndexableResource(context);
    871             sir.xmlResId = xmlResId;
    872             return sir;
    873         }
    874 
    875         private boolean isPasswordManaged(int userId, Context context, DevicePolicyManager dpm) {
    876             final EnforcedAdmin admin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
    877                     context, userId);
    878             return admin != null && dpm.getPasswordQuality(admin.component, userId) ==
    879                     DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
    880         }
    881 
    882         @Override
    883         public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
    884             final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
    885             final Resources res = context.getResources();
    886 
    887             final String screenTitle = res.getString(R.string.security_settings_title);
    888 
    889             SearchIndexableRaw data = new SearchIndexableRaw(context);
    890             data.title = screenTitle;
    891             data.screenTitle = screenTitle;
    892             result.add(data);
    893 
    894             final UserManager um = UserManager.get(context);
    895             if (!um.isAdminUser()) {
    896                 int resId = um.isLinkedUser() ?
    897                         R.string.profile_info_settings_title : R.string.user_info_settings_title;
    898 
    899                 data = new SearchIndexableRaw(context);
    900                 data.title = res.getString(resId);
    901                 data.screenTitle = screenTitle;
    902                 result.add(data);
    903             }
    904 
    905             // Fingerprint
    906             FingerprintManager fpm =
    907                     (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
    908             if (fpm != null && fpm.isHardwareDetected()) {
    909                 // This catches the title which can be overloaded in an overlay
    910                 data = new SearchIndexableRaw(context);
    911                 data.title = res.getString(R.string.security_settings_fingerprint_preference_title);
    912                 data.screenTitle = screenTitle;
    913                 result.add(data);
    914                 // Fallback for when the above doesn't contain "fingerprint"
    915                 data = new SearchIndexableRaw(context);
    916                 data.title = res.getString(R.string.fingerprint_manage_category_title);
    917                 data.screenTitle = screenTitle;
    918                 result.add(data);
    919             }
    920 
    921             final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
    922             final int profileUserId = Utils.getManagedProfileId(um, MY_USER_ID);
    923             if (profileUserId != UserHandle.USER_NULL
    924                     && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)) {
    925                 if (lockPatternUtils.getKeyguardStoredPasswordQuality(profileUserId)
    926                         >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
    927                         && lockPatternUtils.isSeparateProfileChallengeAllowedToUnify(
    928                                 profileUserId)) {
    929                     data = new SearchIndexableRaw(context);
    930                     data.title = res.getString(R.string.lock_settings_profile_unification_title);
    931                     data.screenTitle = screenTitle;
    932                     result.add(data);
    933                 }
    934             }
    935 
    936             // Credential storage
    937             if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
    938                 KeyStore keyStore = KeyStore.getInstance();
    939 
    940                 final int storageSummaryRes = keyStore.isHardwareBacked() ?
    941                         R.string.credential_storage_type_hardware :
    942                         R.string.credential_storage_type_software;
    943 
    944                 data = new SearchIndexableRaw(context);
    945                 data.title = res.getString(storageSummaryRes);
    946                 data.screenTitle = screenTitle;
    947                 result.add(data);
    948             }
    949 
    950             // Advanced
    951             if (lockPatternUtils.isSecure(MY_USER_ID)) {
    952                 ArrayList<TrustAgentComponentInfo> agents =
    953                         getActiveTrustAgents(context, lockPatternUtils,
    954                                 context.getSystemService(DevicePolicyManager.class));
    955                 for (int i = 0; i < agents.size(); i++) {
    956                     final TrustAgentComponentInfo agent = agents.get(i);
    957                     data = new SearchIndexableRaw(context);
    958                     data.title = agent.title;
    959                     data.screenTitle = screenTitle;
    960                     result.add(data);
    961                 }
    962             }
    963             return result;
    964         }
    965 
    966         @Override
    967         public List<String> getNonIndexableKeys(Context context) {
    968             final List<String> keys = new ArrayList<String>();
    969 
    970             LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
    971 
    972             // Do not display SIM lock for devices without an Icc card
    973             final UserManager um = UserManager.get(context);
    974             final TelephonyManager tm = TelephonyManager.from(context);
    975             if (!um.isAdminUser() || !tm.hasIccCard()) {
    976                 keys.add(KEY_SIM_LOCK);
    977             }
    978 
    979             if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
    980                 keys.add(KEY_CREDENTIALS_MANAGER);
    981             }
    982 
    983             // TrustAgent settings disappear when the user has no primary security.
    984             if (!lockPatternUtils.isSecure(MY_USER_ID)) {
    985                 keys.add(KEY_TRUST_AGENT);
    986                 keys.add(KEY_MANAGE_TRUST_AGENTS);
    987             }
    988 
    989             return keys;
    990         }
    991     }
    992 
    993     public static class SecuritySubSettings extends SettingsPreferenceFragment
    994             implements OnPreferenceChangeListener {
    995 
    996         private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
    997         private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
    998         private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
    999         private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
   1000 
   1001         // These switch preferences need special handling since they're not all stored in Settings.
   1002         private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT,
   1003                 KEY_VISIBLE_PATTERN, KEY_POWER_INSTANTLY_LOCKS };
   1004 
   1005         private TimeoutListPreference mLockAfter;
   1006         private SwitchPreference mVisiblePattern;
   1007         private SwitchPreference mPowerButtonInstantlyLocks;
   1008         private RestrictedPreference mOwnerInfoPref;
   1009 
   1010         private LockPatternUtils mLockPatternUtils;
   1011         private DevicePolicyManager mDPM;
   1012 
   1013         @Override
   1014         protected int getMetricsCategory() {
   1015             return MetricsEvent.SECURITY;
   1016         }
   1017 
   1018         @Override
   1019         public void onCreate(Bundle icicle) {
   1020             super.onCreate(icicle);
   1021             mLockPatternUtils = new LockPatternUtils(getContext());
   1022             mDPM = getContext().getSystemService(DevicePolicyManager.class);
   1023             createPreferenceHierarchy();
   1024         }
   1025 
   1026         @Override
   1027         public void onResume() {
   1028             super.onResume();
   1029 
   1030             createPreferenceHierarchy();
   1031 
   1032             if (mVisiblePattern != null) {
   1033                 mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled(
   1034                         MY_USER_ID));
   1035             }
   1036             if (mPowerButtonInstantlyLocks != null) {
   1037                 mPowerButtonInstantlyLocks.setChecked(mLockPatternUtils.getPowerButtonInstantlyLocks(
   1038                         MY_USER_ID));
   1039             }
   1040 
   1041             updateOwnerInfo();
   1042         }
   1043 
   1044         @Override
   1045         public void onActivityResult(int requestCode, int resultCode, Intent data) {
   1046             super.onActivityResult(requestCode, resultCode, data);
   1047 
   1048             createPreferenceHierarchy();
   1049         }
   1050 
   1051         private void createPreferenceHierarchy() {
   1052             PreferenceScreen root = getPreferenceScreen();
   1053             if (root != null) {
   1054                 root.removeAll();
   1055             }
   1056             root = null;
   1057 
   1058             final int resid = getResIdForLockUnlockSubScreen(getActivity(),
   1059                     new LockPatternUtils(getContext()),
   1060                     ManagedLockPasswordProvider.get(getContext(), MY_USER_ID));
   1061             addPreferencesFromResource(resid);
   1062 
   1063             // lock after preference
   1064             mLockAfter = (TimeoutListPreference) findPreference(KEY_LOCK_AFTER_TIMEOUT);
   1065             if (mLockAfter != null) {
   1066                 setupLockAfterPreference();
   1067                 updateLockAfterPreferenceSummary();
   1068             }
   1069 
   1070             // visible pattern
   1071             mVisiblePattern = (SwitchPreference) findPreference(KEY_VISIBLE_PATTERN);
   1072 
   1073             // lock instantly on power key press
   1074             mPowerButtonInstantlyLocks = (SwitchPreference) findPreference(
   1075                     KEY_POWER_INSTANTLY_LOCKS);
   1076             Preference trustAgentPreference = findPreference(KEY_TRUST_AGENT);
   1077             if (mPowerButtonInstantlyLocks != null &&
   1078                     trustAgentPreference != null &&
   1079                     trustAgentPreference.getTitle().length() > 0) {
   1080                 mPowerButtonInstantlyLocks.setSummary(getString(
   1081                         R.string.lockpattern_settings_power_button_instantly_locks_summary,
   1082                         trustAgentPreference.getTitle()));
   1083             }
   1084 
   1085             mOwnerInfoPref = (RestrictedPreference) findPreference(KEY_OWNER_INFO_SETTINGS);
   1086             if (mOwnerInfoPref != null) {
   1087                 if (mLockPatternUtils.isDeviceOwnerInfoEnabled()) {
   1088                     EnforcedAdmin admin = RestrictedLockUtils.getDeviceOwner(getActivity());
   1089                     mOwnerInfoPref.setDisabledByAdmin(admin);
   1090                 } else {
   1091                     mOwnerInfoPref.setDisabledByAdmin(null);
   1092                     mOwnerInfoPref.setEnabled(!mLockPatternUtils.isLockScreenDisabled(MY_USER_ID));
   1093                     if (mOwnerInfoPref.isEnabled()) {
   1094                         mOwnerInfoPref.setOnPreferenceClickListener(
   1095                                 new OnPreferenceClickListener() {
   1096                                     @Override
   1097                                     public boolean onPreferenceClick(Preference preference) {
   1098                                         OwnerInfoSettings.show(SecuritySubSettings.this);
   1099                                         return true;
   1100                                     }
   1101                                 });
   1102                     }
   1103                 }
   1104             }
   1105 
   1106             for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
   1107                 final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]);
   1108                 if (pref != null) pref.setOnPreferenceChangeListener(this);
   1109             }
   1110         }
   1111 
   1112         private void setupLockAfterPreference() {
   1113             // Compatible with pre-Froyo
   1114             long currentTimeout = Settings.Secure.getLong(getContentResolver(),
   1115                     Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
   1116             mLockAfter.setValue(String.valueOf(currentTimeout));
   1117             mLockAfter.setOnPreferenceChangeListener(this);
   1118             if (mDPM != null) {
   1119                 final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
   1120                         getActivity());
   1121                 final long adminTimeout = mDPM
   1122                         .getMaximumTimeToLockForUserAndProfiles(UserHandle.myUserId());
   1123                 final long displayTimeout = Math.max(0,
   1124                         Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
   1125                 // This setting is a slave to display timeout when a device policy is enforced.
   1126                 // As such, maxLockTimeout = adminTimeout - displayTimeout.
   1127                 // If there isn't enough time, shows "immediately" setting.
   1128                 final long maxTimeout = Math.max(0, adminTimeout - displayTimeout);
   1129                 mLockAfter.removeUnusableTimeouts(maxTimeout, admin);
   1130             }
   1131         }
   1132 
   1133         private void updateLockAfterPreferenceSummary() {
   1134             final String summary;
   1135             if (mLockAfter.isDisabledByAdmin()) {
   1136                 summary = getString(R.string.disabled_by_policy_title);
   1137             } else {
   1138                 // Update summary message with current value
   1139                 long currentTimeout = Settings.Secure.getLong(getContentResolver(),
   1140                         Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
   1141                 final CharSequence[] entries = mLockAfter.getEntries();
   1142                 final CharSequence[] values = mLockAfter.getEntryValues();
   1143                 int best = 0;
   1144                 for (int i = 0; i < values.length; i++) {
   1145                     long timeout = Long.valueOf(values[i].toString());
   1146                     if (currentTimeout >= timeout) {
   1147                         best = i;
   1148                     }
   1149                 }
   1150 
   1151                 Preference preference = findPreference(KEY_TRUST_AGENT);
   1152                 if (preference != null && preference.getTitle().length() > 0) {
   1153                     if (Long.valueOf(values[best].toString()) == 0) {
   1154                         summary = getString(R.string.lock_immediately_summary_with_exception,
   1155                                 preference.getTitle());
   1156                     } else {
   1157                         summary = getString(R.string.lock_after_timeout_summary_with_exception,
   1158                                 entries[best], preference.getTitle());
   1159                     }
   1160                 } else {
   1161                     summary = getString(R.string.lock_after_timeout_summary, entries[best]);
   1162                 }
   1163             }
   1164             mLockAfter.setSummary(summary);
   1165         }
   1166 
   1167         public void updateOwnerInfo() {
   1168             if (mOwnerInfoPref != null) {
   1169                 if (mLockPatternUtils.isDeviceOwnerInfoEnabled()) {
   1170                     mOwnerInfoPref.setSummary(
   1171                             mLockPatternUtils.getDeviceOwnerInfo());
   1172                 } else {
   1173                     mOwnerInfoPref.setSummary(mLockPatternUtils.isOwnerInfoEnabled(MY_USER_ID)
   1174                             ? mLockPatternUtils.getOwnerInfo(MY_USER_ID)
   1175                             : getString(R.string.owner_info_settings_summary));
   1176                 }
   1177             }
   1178         }
   1179 
   1180         private static int getResIdForLockUnlockSubScreen(Context context,
   1181                 LockPatternUtils lockPatternUtils,
   1182                 ManagedLockPasswordProvider managedPasswordProvider) {
   1183             if (lockPatternUtils.isSecure(MY_USER_ID)) {
   1184                 switch (lockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID)) {
   1185                     case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
   1186                         return R.xml.security_settings_pattern_sub;
   1187                     case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
   1188                     case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
   1189                         return R.xml.security_settings_pin_sub;
   1190                     case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
   1191                     case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
   1192                     case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
   1193                         return R.xml.security_settings_password_sub;
   1194                     case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
   1195                         return managedPasswordProvider.getResIdForLockUnlockSubScreen();
   1196                 }
   1197             } else if (!lockPatternUtils.isLockScreenDisabled(MY_USER_ID)) {
   1198                 return R.xml.security_settings_slide_sub;
   1199             }
   1200             return 0;
   1201         }
   1202 
   1203         @Override
   1204         public boolean onPreferenceChange(Preference preference, Object value) {
   1205             String key = preference.getKey();
   1206             if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
   1207                 mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value, MY_USER_ID);
   1208             } else if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) {
   1209                 int timeout = Integer.parseInt((String) value);
   1210                 try {
   1211                     Settings.Secure.putInt(getContentResolver(),
   1212                             Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
   1213                 } catch (NumberFormatException e) {
   1214                     Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
   1215                 }
   1216                 setupLockAfterPreference();
   1217                 updateLockAfterPreferenceSummary();
   1218             } else if (KEY_VISIBLE_PATTERN.equals(key)) {
   1219                 mLockPatternUtils.setVisiblePatternEnabled((Boolean) value, MY_USER_ID);
   1220             }
   1221             return true;
   1222         }
   1223     }
   1224 
   1225     public static class UnificationConfirmationDialog extends DialogFragment {
   1226         private static final String EXTRA_COMPLIANT = "compliant";
   1227 
   1228         public static UnificationConfirmationDialog newIntance(boolean compliant) {
   1229             UnificationConfirmationDialog dialog = new UnificationConfirmationDialog();
   1230             Bundle args = new Bundle();
   1231             args.putBoolean(EXTRA_COMPLIANT, compliant);
   1232             dialog.setArguments(args);
   1233             return dialog;
   1234         }
   1235 
   1236         @Override
   1237         public void show(FragmentManager manager, String tag) {
   1238             if (manager.findFragmentByTag(tag) == null) {
   1239                 // Prevent opening multiple dialogs if tapped on button quickly
   1240                 super.show(manager, tag);
   1241             }
   1242         }
   1243 
   1244         @Override
   1245         public Dialog onCreateDialog(Bundle savedInstanceState) {
   1246             final SecuritySettings parentFragment = ((SecuritySettings) getParentFragment());
   1247             final boolean compliant = getArguments().getBoolean(EXTRA_COMPLIANT);
   1248             return new AlertDialog.Builder(getActivity())
   1249                     .setTitle(R.string.lock_settings_profile_unification_dialog_title)
   1250                     .setMessage(compliant ? R.string.lock_settings_profile_unification_dialog_body
   1251                             : R.string.lock_settings_profile_unification_dialog_uncompliant_body)
   1252                     .setPositiveButton(
   1253                             compliant ? R.string.lock_settings_profile_unification_dialog_confirm
   1254                             : R.string.lock_settings_profile_unification_dialog_uncompliant_confirm,
   1255                             new DialogInterface.OnClickListener() {
   1256                                 @Override
   1257                                 public void onClick(DialogInterface dialog, int whichButton) {
   1258                                     if (compliant) {
   1259                                         parentFragment.launchConfirmDeviceLockForUnification();
   1260                                     }    else {
   1261                                         parentFragment.unifyUncompliantLocks();
   1262                                     }
   1263                                 }
   1264                             }
   1265                     )
   1266                     .setNegativeButton(R.string.cancel, null)
   1267                     .create();
   1268         }
   1269 
   1270         @Override
   1271         public void onDismiss(DialogInterface dialog) {
   1272             super.onDismiss(dialog);
   1273             ((SecuritySettings) getParentFragment()).updateUnificationPreference();
   1274         }
   1275     }
   1276 
   1277 }
   1278