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
getMetricsCategory()156     protected int getMetricsCategory() {
157         return MetricsEvent.SECURITY;
158     }
159 
160     @Override
onCreate(Bundle savedInstanceState)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 
getResIdForLockUnlockScreen(Context context, LockPatternUtils lockPatternUtils, ManagedLockPasswordProvider managedPasswordProvider, int userId)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      */
createPreferenceHierarchy()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      */
disableIfPasswordQualityManaged(String preferenceKey, int userId)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 
maybeAddFingerprintPreference(PreferenceGroup securityCategory, int userId)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 
addTrustAgentSettings(PreferenceGroup securityCategory)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      */
isSimIccReady()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      */
isSimReady()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 
getActiveTrustAgents( Context context, LockPatternUtils utils, DevicePolicyManager dpm)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 
isNonMarketAppsAllowed()529     private boolean isNonMarketAppsAllowed() {
530         return Settings.Global.getInt(getContentResolver(),
531                                       Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0;
532     }
533 
setNonMarketAppsAllowed(boolean enabled)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 
warnAppInstallation()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
onClick(DialogInterface dialog, int which)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
onGearClick(GearPreference p)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
onDestroy()574     public void onDestroy() {
575         super.onDestroy();
576         if (mWarnInstallApps != null) {
577             mWarnInstallApps.dismiss();
578         }
579     }
580 
581     @Override
onSaveInstanceState(Bundle outState)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
onResume()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 
updateUnificationPreference()614     private void updateUnificationPreference() {
615         if (mUnifyProfile != null) {
616             mUnifyProfile.setChecked(!mLockPatternUtils.isSeparateProfileChallengeEnabled(
617                     mProfileChallengeUserId));
618         }
619     }
620 
621     @Override
onPreferenceTreeClick(Preference preference)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
onActivityResult(int requestCode, int resultCode, Intent data)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 
launchConfirmDeviceLockForUnification()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 
launchConfirmProfileLockForUnification()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 
unifyLocks()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 
unifyUncompliantLocks()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 
ununifyLocks()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
onPreferenceChange(Preference preference, Object value)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
getHelpResource()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
getXmlResourcesToIndex( Context context, boolean enabled)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 
getSearchResource(Context context, int xmlResId)869         private SearchIndexableResource getSearchResource(Context context, int xmlResId) {
870             final SearchIndexableResource sir = new SearchIndexableResource(context);
871             sir.xmlResId = xmlResId;
872             return sir;
873         }
874 
isPasswordManaged(int userId, Context context, DevicePolicyManager dpm)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
getRawDataToIndex(Context context, boolean enabled)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
getNonIndexableKeys(Context context)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
getMetricsCategory()1014         protected int getMetricsCategory() {
1015             return MetricsEvent.SECURITY;
1016         }
1017 
1018         @Override
onCreate(Bundle icicle)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
onResume()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
onActivityResult(int requestCode, int resultCode, Intent data)1045         public void onActivityResult(int requestCode, int resultCode, Intent data) {
1046             super.onActivityResult(requestCode, resultCode, data);
1047 
1048             createPreferenceHierarchy();
1049         }
1050 
createPreferenceHierarchy()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 
setupLockAfterPreference()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 
updateLockAfterPreferenceSummary()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 
updateOwnerInfo()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 
getResIdForLockUnlockSubScreen(Context context, LockPatternUtils lockPatternUtils, ManagedLockPasswordProvider managedPasswordProvider)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
onPreferenceChange(Preference preference, Object value)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 
newIntance(boolean compliant)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
show(FragmentManager manager, String tag)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
onCreateDialog(Bundle savedInstanceState)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