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.admin.DevicePolicyManager;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.pm.PackageManager;
28 import android.content.pm.ResolveInfo;
29 import android.content.pm.UserInfo;
30 import android.content.res.Resources;
31 import android.os.Bundle;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.preference.SwitchPreference;
35 import android.preference.ListPreference;
36 import android.preference.Preference;
37 import android.preference.Preference.OnPreferenceChangeListener;
38 import android.preference.PreferenceGroup;
39 import android.preference.PreferenceScreen;
40 import android.provider.SearchIndexableResource;
41 import android.provider.Settings;
42 import android.provider.Settings.SettingNotFoundException;
43 import android.security.KeyStore;
44 import android.service.trust.TrustAgentService;
45 import android.telephony.TelephonyManager;
46 import android.telephony.SubscriptionManager;
47 import android.telephony.SubscriptionInfo;
48 import android.text.TextUtils;
49 import android.util.Log;
50 
51 import com.android.internal.widget.LockPatternUtils;
52 import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo;
53 import com.android.settings.search.BaseSearchIndexProvider;
54 import com.android.settings.search.Index;
55 import com.android.settings.search.Indexable;
56 import com.android.settings.search.SearchIndexableRaw;
57 
58 import java.util.ArrayList;
59 import java.util.List;
60 
61 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
62 
63 /**
64  * Gesture lock pattern settings.
65  */
66 public class SecuritySettings extends SettingsPreferenceFragment
67         implements OnPreferenceChangeListener, DialogInterface.OnClickListener, Indexable {
68     private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
69     static final String TAG = "SecuritySettings";
70     private static final Intent TRUST_AGENT_INTENT =
71             new Intent(TrustAgentService.SERVICE_INTERFACE);
72 
73     // Lock Settings
74     private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
75     private static final String KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING =
76             "biometric_weak_improve_matching";
77     private static final String KEY_BIOMETRIC_WEAK_LIVELINESS = "biometric_weak_liveliness";
78     private static final String KEY_LOCK_ENABLED = "lockenabled";
79     private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
80     private static final String KEY_SECURITY_CATEGORY = "security_category";
81     private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category";
82     private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
83     private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
84     private static final String KEY_ADVANCED_SECURITY = "advanced_security";
85     private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
86 
87     private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
88     private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST = 124;
89     private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF = 125;
90     private static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
91 
92     // Misc Settings
93     private static final String KEY_SIM_LOCK = "sim_lock";
94     private static final String KEY_SHOW_PASSWORD = "show_password";
95     private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type";
96     private static final String KEY_RESET_CREDENTIALS = "credentials_reset";
97     private static final String KEY_CREDENTIALS_INSTALL = "credentials_install";
98     private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
99     private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
100     private static final String KEY_CREDENTIALS_MANAGER = "credentials_management";
101     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
102     private static final String KEY_TRUST_AGENT = "trust_agent";
103     private static final String KEY_SCREEN_PINNING = "screen_pinning_settings";
104 
105     // These switch preferences need special handling since they're not all stored in Settings.
106     private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT,
107             KEY_LOCK_ENABLED, KEY_VISIBLE_PATTERN, KEY_BIOMETRIC_WEAK_LIVELINESS,
108             KEY_POWER_INSTANTLY_LOCKS, KEY_SHOW_PASSWORD, KEY_TOGGLE_INSTALL_APPLICATIONS };
109 
110     // Only allow one trust agent on the platform.
111     private static final boolean ONLY_ONE_TRUST_AGENT = true;
112 
113     private DevicePolicyManager mDPM;
114     private SubscriptionManager mSubscriptionManager;
115 
116     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
117     private LockPatternUtils mLockPatternUtils;
118     private ListPreference mLockAfter;
119 
120     private SwitchPreference mBiometricWeakLiveliness;
121     private SwitchPreference mVisiblePattern;
122 
123     private SwitchPreference mShowPassword;
124 
125     private KeyStore mKeyStore;
126     private Preference mResetCredentials;
127 
128     private SwitchPreference mToggleAppInstallation;
129     private DialogInterface mWarnInstallApps;
130     private SwitchPreference mPowerButtonInstantlyLocks;
131 
132     private boolean mIsPrimary;
133 
134     private Intent mTrustAgentClickIntent;
135 
136     @Override
onCreate(Bundle savedInstanceState)137     public void onCreate(Bundle savedInstanceState) {
138         super.onCreate(savedInstanceState);
139 
140         mSubscriptionManager = SubscriptionManager.from(getActivity());
141 
142         mLockPatternUtils = new LockPatternUtils(getActivity());
143 
144         mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
145 
146         mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
147 
148         if (savedInstanceState != null
149                 && savedInstanceState.containsKey(TRUST_AGENT_CLICK_INTENT)) {
150             mTrustAgentClickIntent = savedInstanceState.getParcelable(TRUST_AGENT_CLICK_INTENT);
151         }
152     }
153 
getResIdForLockUnlockScreen(Context context, LockPatternUtils lockPatternUtils)154     private static int getResIdForLockUnlockScreen(Context context,
155             LockPatternUtils lockPatternUtils) {
156         int resid = 0;
157         if (!lockPatternUtils.isSecure()) {
158             // if there are multiple users, disable "None" setting
159             UserManager mUm = (UserManager) context. getSystemService(Context.USER_SERVICE);
160             List<UserInfo> users = mUm.getUsers(true);
161             final boolean singleUser = users.size() == 1;
162 
163             if (singleUser && lockPatternUtils.isLockScreenDisabled()) {
164                 resid = R.xml.security_settings_lockscreen;
165             } else {
166                 resid = R.xml.security_settings_chooser;
167             }
168         } else if (lockPatternUtils.usingBiometricWeak() &&
169                 lockPatternUtils.isBiometricWeakInstalled()) {
170             resid = R.xml.security_settings_biometric_weak;
171         } else {
172             switch (lockPatternUtils.getKeyguardStoredPasswordQuality()) {
173                 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
174                     resid = R.xml.security_settings_pattern;
175                     break;
176                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
177                 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
178                     resid = R.xml.security_settings_pin;
179                     break;
180                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
181                 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
182                 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
183                     resid = R.xml.security_settings_password;
184                     break;
185             }
186         }
187         return resid;
188     }
189 
190     /**
191      * Important!
192      *
193      * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the
194      * logic or adding/removing preferences here.
195      */
createPreferenceHierarchy()196     private PreferenceScreen createPreferenceHierarchy() {
197         PreferenceScreen root = getPreferenceScreen();
198         if (root != null) {
199             root.removeAll();
200         }
201         addPreferencesFromResource(R.xml.security_settings);
202         root = getPreferenceScreen();
203 
204         // Add options for lock/unlock screen
205         final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils);
206         addPreferencesFromResource(resid);
207 
208         // Add options for device encryption
209         mIsPrimary = UserHandle.myUserId() == UserHandle.USER_OWNER;
210 
211         if (!mIsPrimary) {
212             // Rename owner info settings
213             Preference ownerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS);
214             if (ownerInfoPref != null) {
215                 if (UserManager.get(getActivity()).isLinkedUser()) {
216                     ownerInfoPref.setTitle(R.string.profile_info_settings_title);
217                 } else {
218                     ownerInfoPref.setTitle(R.string.user_info_settings_title);
219                 }
220             }
221         }
222 
223         if (mIsPrimary) {
224             if (LockPatternUtils.isDeviceEncryptionEnabled()) {
225                 // The device is currently encrypted.
226                 addPreferencesFromResource(R.xml.security_settings_encrypted);
227             } else {
228                 // This device supports encryption but isn't encrypted.
229                 addPreferencesFromResource(R.xml.security_settings_unencrypted);
230             }
231         }
232 
233         // Trust Agent preferences
234         PreferenceGroup securityCategory = (PreferenceGroup)
235                 root.findPreference(KEY_SECURITY_CATEGORY);
236         if (securityCategory != null) {
237             final boolean hasSecurity = mLockPatternUtils.isSecure();
238             ArrayList<TrustAgentComponentInfo> agents =
239                     getActiveTrustAgents(getPackageManager(), mLockPatternUtils);
240             for (int i = 0; i < agents.size(); i++) {
241                 final TrustAgentComponentInfo agent = agents.get(i);
242                 Preference trustAgentPreference =
243                         new Preference(securityCategory.getContext());
244                 trustAgentPreference.setKey(KEY_TRUST_AGENT);
245                 trustAgentPreference.setTitle(agent.title);
246                 trustAgentPreference.setSummary(agent.summary);
247                 // Create intent for this preference.
248                 Intent intent = new Intent();
249                 intent.setComponent(agent.componentName);
250                 intent.setAction(Intent.ACTION_MAIN);
251                 trustAgentPreference.setIntent(intent);
252                 // Add preference to the settings menu.
253                 securityCategory.addPreference(trustAgentPreference);
254                 if (!hasSecurity) {
255                     trustAgentPreference.setEnabled(false);
256                     trustAgentPreference.setSummary(R.string.disabled_because_no_backup_security);
257                 }
258             }
259         }
260 
261         // lock after preference
262         mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
263         if (mLockAfter != null) {
264             setupLockAfterPreference();
265             updateLockAfterPreferenceSummary();
266         }
267 
268         // biometric weak liveliness
269         mBiometricWeakLiveliness =
270                 (SwitchPreference) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS);
271 
272         // visible pattern
273         mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN);
274 
275         // lock instantly on power key press
276         mPowerButtonInstantlyLocks = (SwitchPreference) root.findPreference(
277                 KEY_POWER_INSTANTLY_LOCKS);
278         Preference trustAgentPreference = root.findPreference(KEY_TRUST_AGENT);
279         if (mPowerButtonInstantlyLocks != null &&
280                 trustAgentPreference != null &&
281                 trustAgentPreference.getTitle().length() > 0) {
282             mPowerButtonInstantlyLocks.setSummary(getString(
283                     R.string.lockpattern_settings_power_button_instantly_locks_summary,
284                     trustAgentPreference.getTitle()));
285         }
286 
287         // don't display visible pattern if biometric and backup is not pattern
288         if (resid == R.xml.security_settings_biometric_weak &&
289                 mLockPatternUtils.getKeyguardStoredPasswordQuality() !=
290                 DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
291             if (securityCategory != null && mVisiblePattern != null) {
292                 securityCategory.removePreference(root.findPreference(KEY_VISIBLE_PATTERN));
293             }
294         }
295 
296         // Append the rest of the settings
297         addPreferencesFromResource(R.xml.security_settings_misc);
298 
299         // Do not display SIM lock for devices without an Icc card
300         TelephonyManager tm = TelephonyManager.getDefault();
301         if (!mIsPrimary || !isSimIccReady()) {
302             root.removePreference(root.findPreference(KEY_SIM_LOCK));
303         } else {
304             // Disable SIM lock if there is no ready SIM card.
305             root.findPreference(KEY_SIM_LOCK).setEnabled(isSimReady());
306         }
307         if (Settings.System.getInt(getContentResolver(),
308                 Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) {
309             root.findPreference(KEY_SCREEN_PINNING).setSummary(
310                     getResources().getString(R.string.switch_on_text));
311         }
312 
313         // Show password
314         mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD);
315         mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS);
316 
317         // Credential storage
318         final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
319         mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume()
320         if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
321             Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE);
322 
323             final int storageSummaryRes =
324                 mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware
325                         : R.string.credential_storage_type_software;
326             credentialStorageType.setSummary(storageSummaryRes);
327         } else {
328             PreferenceGroup credentialsManager = (PreferenceGroup)
329                     root.findPreference(KEY_CREDENTIALS_MANAGER);
330             credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS));
331             credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL));
332             credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE));
333         }
334 
335         // Application install
336         PreferenceGroup deviceAdminCategory = (PreferenceGroup)
337                 root.findPreference(KEY_DEVICE_ADMIN_CATEGORY);
338         mToggleAppInstallation = (SwitchPreference) findPreference(
339                 KEY_TOGGLE_INSTALL_APPLICATIONS);
340         mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
341         // Side loading of apps.
342         // Disable for restricted profiles. For others, check if policy disallows it.
343         mToggleAppInstallation.setEnabled(!um.getUserInfo(UserHandle.myUserId()).isRestricted());
344         if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
345                 || um.hasUserRestriction(UserManager.DISALLOW_INSTALL_APPS)) {
346             mToggleAppInstallation.setEnabled(false);
347         }
348 
349         // Advanced Security features
350         PreferenceGroup advancedCategory =
351                 (PreferenceGroup)root.findPreference(KEY_ADVANCED_SECURITY);
352         if (advancedCategory != null) {
353             Preference manageAgents = advancedCategory.findPreference(KEY_MANAGE_TRUST_AGENTS);
354             if (manageAgents != null && !mLockPatternUtils.isSecure()) {
355                 manageAgents.setEnabled(false);
356                 manageAgents.setSummary(R.string.disabled_because_no_backup_security);
357             }
358         }
359 
360         // The above preferences come and go based on security state, so we need to update
361         // the index. This call is expected to be fairly cheap, but we may want to do something
362         // smarter in the future.
363         Index.getInstance(getActivity())
364                 .updateFromClassNameResource(SecuritySettings.class.getName(), true, true);
365 
366         for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
367             final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]);
368             if (pref != null) pref.setOnPreferenceChangeListener(this);
369         }
370         return root;
371     }
372 
373     /* Return true if a there is a Slot that has Icc.
374      */
isSimIccReady()375     private boolean isSimIccReady() {
376         TelephonyManager tm = TelephonyManager.getDefault();
377         final List<SubscriptionInfo> subInfoList =
378                 mSubscriptionManager.getActiveSubscriptionInfoList();
379 
380         if (subInfoList != null) {
381             for (SubscriptionInfo subInfo : subInfoList) {
382                 if (tm.hasIccCard(subInfo.getSimSlotIndex())) {
383                     return true;
384                 }
385             }
386         }
387 
388         return false;
389     }
390 
391     /* Return true if a SIM is ready for locking.
392      * TODO: consider adding to TelephonyManager or SubscritpionManasger.
393      */
isSimReady()394     private boolean isSimReady() {
395         int simState = TelephonyManager.SIM_STATE_UNKNOWN;
396         final List<SubscriptionInfo> subInfoList =
397                 mSubscriptionManager.getActiveSubscriptionInfoList();
398         if (subInfoList != null) {
399             for (SubscriptionInfo subInfo : subInfoList) {
400                 simState = TelephonyManager.getDefault().getSimState(subInfo.getSimSlotIndex());
401                 if((simState != TelephonyManager.SIM_STATE_ABSENT) &&
402                             (simState != TelephonyManager.SIM_STATE_UNKNOWN)){
403                     return true;
404                 }
405             }
406         }
407         return false;
408     }
409 
getActiveTrustAgents( PackageManager pm, LockPatternUtils utils)410     private static ArrayList<TrustAgentComponentInfo> getActiveTrustAgents(
411             PackageManager pm, LockPatternUtils utils) {
412         ArrayList<TrustAgentComponentInfo> result = new ArrayList<TrustAgentComponentInfo>();
413         List<ResolveInfo> resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT,
414                 PackageManager.GET_META_DATA);
415         List<ComponentName> enabledTrustAgents = utils.getEnabledTrustAgents();
416         if (enabledTrustAgents != null && !enabledTrustAgents.isEmpty()) {
417             for (int i = 0; i < resolveInfos.size(); i++) {
418                 ResolveInfo resolveInfo = resolveInfos.get(i);
419                 if (resolveInfo.serviceInfo == null) continue;
420                 if (!TrustAgentUtils.checkProvidePermission(resolveInfo, pm)) continue;
421                 TrustAgentComponentInfo trustAgentComponentInfo =
422                         TrustAgentUtils.getSettingsComponent(pm, resolveInfo);
423                 if (trustAgentComponentInfo.componentName == null ||
424                         !enabledTrustAgents.contains(
425                                 TrustAgentUtils.getComponentName(resolveInfo)) ||
426                         TextUtils.isEmpty(trustAgentComponentInfo.title)) continue;
427                 result.add(trustAgentComponentInfo);
428                 if (ONLY_ONE_TRUST_AGENT) break;
429             }
430         }
431         return result;
432     }
433 
isNonMarketAppsAllowed()434     private boolean isNonMarketAppsAllowed() {
435         return Settings.Global.getInt(getContentResolver(),
436                                       Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0;
437     }
438 
setNonMarketAppsAllowed(boolean enabled)439     private void setNonMarketAppsAllowed(boolean enabled) {
440         final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
441         if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
442             return;
443         }
444         // Change the system setting
445         Settings.Global.putInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS,
446                                 enabled ? 1 : 0);
447     }
448 
warnAppInstallation()449     private void warnAppInstallation() {
450         // TODO: DialogFragment?
451         mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle(
452                 getResources().getString(R.string.error_title))
453                 .setIcon(com.android.internal.R.drawable.ic_dialog_alert)
454                 .setMessage(getResources().getString(R.string.install_all_warning))
455                 .setPositiveButton(android.R.string.yes, this)
456                 .setNegativeButton(android.R.string.no, this)
457                 .show();
458     }
459 
460     @Override
onClick(DialogInterface dialog, int which)461     public void onClick(DialogInterface dialog, int which) {
462         if (dialog == mWarnInstallApps) {
463             boolean turnOn = which == DialogInterface.BUTTON_POSITIVE;
464             setNonMarketAppsAllowed(turnOn);
465             if (mToggleAppInstallation != null) {
466                 mToggleAppInstallation.setChecked(turnOn);
467             }
468         }
469     }
470 
471     @Override
onDestroy()472     public void onDestroy() {
473         super.onDestroy();
474         if (mWarnInstallApps != null) {
475             mWarnInstallApps.dismiss();
476         }
477     }
478 
setupLockAfterPreference()479     private void setupLockAfterPreference() {
480         // Compatible with pre-Froyo
481         long currentTimeout = Settings.Secure.getLong(getContentResolver(),
482                 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
483         mLockAfter.setValue(String.valueOf(currentTimeout));
484         mLockAfter.setOnPreferenceChangeListener(this);
485         final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
486         final long displayTimeout = Math.max(0,
487                 Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
488         if (adminTimeout > 0) {
489             // This setting is a slave to display timeout when a device policy is enforced.
490             // As such, maxLockTimeout = adminTimeout - displayTimeout.
491             // If there isn't enough time, shows "immediately" setting.
492             disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout));
493         }
494     }
495 
updateLockAfterPreferenceSummary()496     private void updateLockAfterPreferenceSummary() {
497         // Update summary message with current value
498         long currentTimeout = Settings.Secure.getLong(getContentResolver(),
499                 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
500         final CharSequence[] entries = mLockAfter.getEntries();
501         final CharSequence[] values = mLockAfter.getEntryValues();
502         int best = 0;
503         for (int i = 0; i < values.length; i++) {
504             long timeout = Long.valueOf(values[i].toString());
505             if (currentTimeout >= timeout) {
506                 best = i;
507             }
508         }
509 
510         Preference preference = getPreferenceScreen().findPreference(KEY_TRUST_AGENT);
511         if (preference != null && preference.getTitle().length() > 0) {
512             mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary_with_exception,
513                     entries[best], preference.getTitle()));
514         } else {
515             mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary, entries[best]));
516         }
517     }
518 
disableUnusableTimeouts(long maxTimeout)519     private void disableUnusableTimeouts(long maxTimeout) {
520         final CharSequence[] entries = mLockAfter.getEntries();
521         final CharSequence[] values = mLockAfter.getEntryValues();
522         ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
523         ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
524         for (int i = 0; i < values.length; i++) {
525             long timeout = Long.valueOf(values[i].toString());
526             if (timeout <= maxTimeout) {
527                 revisedEntries.add(entries[i]);
528                 revisedValues.add(values[i]);
529             }
530         }
531         if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
532             mLockAfter.setEntries(
533                     revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
534             mLockAfter.setEntryValues(
535                     revisedValues.toArray(new CharSequence[revisedValues.size()]));
536             final int userPreference = Integer.valueOf(mLockAfter.getValue());
537             if (userPreference <= maxTimeout) {
538                 mLockAfter.setValue(String.valueOf(userPreference));
539             } else {
540                 // There will be no highlighted selection since nothing in the list matches
541                 // maxTimeout. The user can still select anything less than maxTimeout.
542                 // TODO: maybe append maxTimeout to the list and mark selected.
543             }
544         }
545         mLockAfter.setEnabled(revisedEntries.size() > 0);
546     }
547 
548     @Override
onSaveInstanceState(Bundle outState)549     public void onSaveInstanceState(Bundle outState) {
550         super.onSaveInstanceState(outState);
551         if (mTrustAgentClickIntent != null) {
552             outState.putParcelable(TRUST_AGENT_CLICK_INTENT, mTrustAgentClickIntent);
553         }
554     }
555 
556     @Override
onResume()557     public void onResume() {
558         super.onResume();
559 
560         // Make sure we reload the preference hierarchy since some of these settings
561         // depend on others...
562         createPreferenceHierarchy();
563 
564         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
565         if (mBiometricWeakLiveliness != null) {
566             mBiometricWeakLiveliness.setChecked(
567                     lockPatternUtils.isBiometricWeakLivelinessEnabled());
568         }
569         if (mVisiblePattern != null) {
570             mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled());
571         }
572         if (mPowerButtonInstantlyLocks != null) {
573             mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks());
574         }
575 
576         if (mShowPassword != null) {
577             mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
578                     Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
579         }
580 
581         if (mResetCredentials != null) {
582             mResetCredentials.setEnabled(!mKeyStore.isEmpty());
583         }
584     }
585 
586     @Override
onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)587     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
588         final String key = preference.getKey();
589         if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
590             startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
591                     R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
592         } else if (KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING.equals(key)) {
593             ChooseLockSettingsHelper helper =
594                     new ChooseLockSettingsHelper(this.getActivity(), this);
595             if (!helper.launchConfirmationActivity(
596                     CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST, null, null)) {
597                 // If this returns false, it means no password confirmation is required, so
598                 // go ahead and start improve.
599                 // Note: currently a backup is required for biometric_weak so this code path
600                 // can't be reached, but is here in case things change in the future
601                 startBiometricWeakImprove();
602             }
603         } else if (KEY_TRUST_AGENT.equals(key)) {
604             ChooseLockSettingsHelper helper =
605                     new ChooseLockSettingsHelper(this.getActivity(), this);
606             mTrustAgentClickIntent = preference.getIntent();
607             if (!helper.launchConfirmationActivity(CHANGE_TRUST_AGENT_SETTINGS, null, null) &&
608                     mTrustAgentClickIntent != null) {
609                 // If this returns false, it means no password confirmation is required.
610                 startActivity(mTrustAgentClickIntent);
611                 mTrustAgentClickIntent = null;
612             }
613         } else {
614             // If we didn't handle it, let preferences handle it.
615             return super.onPreferenceTreeClick(preferenceScreen, preference);
616         }
617         return true;
618     }
619 
620     /**
621      * see confirmPatternThenDisableAndClear
622      */
623     @Override
onActivityResult(int requestCode, int resultCode, Intent data)624     public void onActivityResult(int requestCode, int resultCode, Intent data) {
625         super.onActivityResult(requestCode, resultCode, data);
626         if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST &&
627                 resultCode == Activity.RESULT_OK) {
628             startBiometricWeakImprove();
629             return;
630         } else if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF &&
631                 resultCode == Activity.RESULT_OK) {
632             final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
633             lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
634             // Setting the mBiometricWeakLiveliness checked value to false is handled when onResume
635             // is called by grabbing the value from lockPatternUtils.  We can't set it here
636             // because mBiometricWeakLiveliness could be null
637             return;
638         } else if (requestCode == CHANGE_TRUST_AGENT_SETTINGS && resultCode == Activity.RESULT_OK) {
639             if (mTrustAgentClickIntent != null) {
640                 startActivity(mTrustAgentClickIntent);
641                 mTrustAgentClickIntent = null;
642             }
643             return;
644         }
645         createPreferenceHierarchy();
646     }
647 
648     @Override
onPreferenceChange(Preference preference, Object value)649     public boolean onPreferenceChange(Preference preference, Object value) {
650         boolean result = true;
651         final String key = preference.getKey();
652         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
653         if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) {
654             int timeout = Integer.parseInt((String) value);
655             try {
656                 Settings.Secure.putInt(getContentResolver(),
657                         Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
658             } catch (NumberFormatException e) {
659                 Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
660             }
661             updateLockAfterPreferenceSummary();
662         } else if (KEY_LOCK_ENABLED.equals(key)) {
663             lockPatternUtils.setLockPatternEnabled((Boolean) value);
664         } else if (KEY_VISIBLE_PATTERN.equals(key)) {
665             lockPatternUtils.setVisiblePatternEnabled((Boolean) value);
666         } else  if (KEY_BIOMETRIC_WEAK_LIVELINESS.equals(key)) {
667             if ((Boolean) value) {
668                 lockPatternUtils.setBiometricWeakLivelinessEnabled(true);
669             } else {
670                 // In this case the user has just unchecked the checkbox, but this action requires
671                 // them to confirm their password.  We need to re-check the checkbox until
672                 // they've confirmed their password
673                 mBiometricWeakLiveliness.setChecked(true);
674                 ChooseLockSettingsHelper helper =
675                         new ChooseLockSettingsHelper(this.getActivity(), this);
676                 if (!helper.launchConfirmationActivity(
677                                 CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) {
678                     // If this returns false, it means no password confirmation is required, so
679                     // go ahead and uncheck it here.
680                     // Note: currently a backup is required for biometric_weak so this code path
681                     // can't be reached, but is here in case things change in the future
682                     lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
683                     mBiometricWeakLiveliness.setChecked(false);
684                 }
685             }
686         } else if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
687             mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value);
688         } else if (KEY_SHOW_PASSWORD.equals(key)) {
689             Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
690                     ((Boolean) value) ? 1 : 0);
691         } else if (KEY_TOGGLE_INSTALL_APPLICATIONS.equals(key)) {
692             if ((Boolean) value) {
693                 mToggleAppInstallation.setChecked(false);
694                 warnAppInstallation();
695                 // Don't change Switch status until user makes choice in dialog, so return false.
696                 result = false;
697             } else {
698                 setNonMarketAppsAllowed(false);
699             }
700         }
701         return result;
702     }
703 
704     @Override
getHelpResource()705     protected int getHelpResource() {
706         return R.string.help_url_security;
707     }
708 
startBiometricWeakImprove()709     public void startBiometricWeakImprove(){
710         Intent intent = new Intent();
711         intent.setClassName("com.android.facelock", "com.android.facelock.AddToSetup");
712         startActivity(intent);
713     }
714 
715     /**
716      * For Search. Please keep it in sync when updating "createPreferenceHierarchy()"
717      */
718     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
719             new SecuritySearchIndexProvider();
720 
721     private static class SecuritySearchIndexProvider extends BaseSearchIndexProvider {
722 
723         boolean mIsPrimary;
724 
SecuritySearchIndexProvider()725         public SecuritySearchIndexProvider() {
726             super();
727 
728             mIsPrimary = UserHandle.myUserId() == UserHandle.USER_OWNER;
729         }
730 
731         @Override
getXmlResourcesToIndex( Context context, boolean enabled)732         public List<SearchIndexableResource> getXmlResourcesToIndex(
733                 Context context, boolean enabled) {
734 
735             List<SearchIndexableResource> result = new ArrayList<SearchIndexableResource>();
736 
737             LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
738             // Add options for lock/unlock screen
739             int resId = getResIdForLockUnlockScreen(context, lockPatternUtils);
740 
741             SearchIndexableResource sir = new SearchIndexableResource(context);
742             sir.xmlResId = resId;
743             result.add(sir);
744 
745             if (mIsPrimary) {
746                 DevicePolicyManager dpm = (DevicePolicyManager)
747                         context.getSystemService(Context.DEVICE_POLICY_SERVICE);
748 
749                 switch (dpm.getStorageEncryptionStatus()) {
750                     case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
751                         // The device is currently encrypted.
752                         resId = R.xml.security_settings_encrypted;
753                         break;
754                     case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE:
755                         // This device supports encryption but isn't encrypted.
756                         resId = R.xml.security_settings_unencrypted;
757                         break;
758                 }
759 
760                 sir = new SearchIndexableResource(context);
761                 sir.xmlResId = resId;
762                 result.add(sir);
763             }
764 
765             // Append the rest of the settings
766             sir = new SearchIndexableResource(context);
767             sir.xmlResId = R.xml.security_settings_misc;
768             result.add(sir);
769 
770             return result;
771         }
772 
773         @Override
getRawDataToIndex(Context context, boolean enabled)774         public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
775             final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
776             final Resources res = context.getResources();
777 
778             final String screenTitle = res.getString(R.string.security_settings_title);
779 
780             SearchIndexableRaw data = new SearchIndexableRaw(context);
781             data.title = screenTitle;
782             data.screenTitle = screenTitle;
783             result.add(data);
784 
785             if (!mIsPrimary) {
786                 int resId = (UserManager.get(context).isLinkedUser()) ?
787                         R.string.profile_info_settings_title : R.string.user_info_settings_title;
788 
789                 data = new SearchIndexableRaw(context);
790                 data.title = res.getString(resId);
791                 data.screenTitle = screenTitle;
792                 result.add(data);
793             }
794 
795             // Credential storage
796             final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
797 
798             if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
799                 KeyStore keyStore = KeyStore.getInstance();
800 
801                 final int storageSummaryRes = keyStore.isHardwareBacked() ?
802                         R.string.credential_storage_type_hardware :
803                         R.string.credential_storage_type_software;
804 
805                 data = new SearchIndexableRaw(context);
806                 data.title = res.getString(storageSummaryRes);
807                 data.screenTitle = screenTitle;
808                 result.add(data);
809             }
810 
811             // Advanced
812             final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
813             if (lockPatternUtils.isSecure()) {
814                 ArrayList<TrustAgentComponentInfo> agents =
815                         getActiveTrustAgents(context.getPackageManager(), lockPatternUtils);
816                 for (int i = 0; i < agents.size(); i++) {
817                     final TrustAgentComponentInfo agent = agents.get(i);
818                     data = new SearchIndexableRaw(context);
819                     data.title = agent.title;
820                     data.screenTitle = screenTitle;
821                     result.add(data);
822                 }
823             }
824             return result;
825         }
826 
827         @Override
getNonIndexableKeys(Context context)828         public List<String> getNonIndexableKeys(Context context) {
829             final List<String> keys = new ArrayList<String>();
830 
831             LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
832             // Add options for lock/unlock screen
833             int resId = getResIdForLockUnlockScreen(context, lockPatternUtils);
834 
835             // don't display visible pattern if biometric and backup is not pattern
836             if (resId == R.xml.security_settings_biometric_weak &&
837                     lockPatternUtils.getKeyguardStoredPasswordQuality() !=
838                             DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
839                 keys.add(KEY_VISIBLE_PATTERN);
840             }
841 
842             // Do not display SIM lock for devices without an Icc card
843             TelephonyManager tm = TelephonyManager.getDefault();
844             if (!mIsPrimary || !tm.hasIccCard()) {
845                 keys.add(KEY_SIM_LOCK);
846             }
847 
848             final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
849             if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
850                 keys.add(KEY_CREDENTIALS_MANAGER);
851             }
852 
853             // TrustAgent settings disappear when the user has no primary security.
854             if (!lockPatternUtils.isSecure()) {
855                 keys.add(KEY_TRUST_AGENT);
856                 keys.add(KEY_MANAGE_TRUST_AGENTS);
857             }
858 
859             return keys;
860         }
861     }
862 
863 }
864