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