Move lock screen setting behind gear

Bug: 19003093
Change-Id: I15baa5b1d19324521070d641ae6a227d782a4e9e
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f86ba75..bc2076a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7024,6 +7024,18 @@
     <!-- No default home set summary [CHAR LIMIT=NONE] -->
     <string name="no_default_home">No default Home</string>
 
+    <!-- Title of the preference controlling whether the device encryption password/PIN/Pattern must be entered before being able to start the device. [CHAR LIMIT=60]-->
+    <string name="lockpattern_settings_require_cred_before_startup">Secure start-up</string>
+
+    <!-- Summary of the preference controlling whether the device encryption *pattern* must be entered before being able to start the device. [CHAR LIMIT=NONE]-->
+    <string name="lockpattern_settings_require_pattern_before_startup_summary">Require pattern to start up your device. While off, this device can\'t receive calls, messages, notifications, or alarms.</string>
+
+    <!-- Summary of the preference controlling whether the device encryption *PIN* must be entered before being able to start the device. [CHAR LIMIT=NONE]-->
+    <string name="lockpattern_settings_require_pin_before_startup_summary">Require PIN to start up your device. While off, this device can\'t receive calls, messages, notifications, or alarms.</string>
+
+    <!-- Summary of the preference controlling whether the device encryption *password* must be entered before being able to start the device. [CHAR LIMIT=NONE]-->
+    <string name="lockpattern_settings_require_password_before_startup_summary">Require password to start up your device. While off, this device can\'t receive calls, messages, notifications, or alarms.</string>
+
     <!-- Title for suggestion adding more fingerprints [CHAR LIMIT=30] -->
     <string name="suggestion_additional_fingerprints">Additional Fingerprints</string>
 
diff --git a/res/xml/security_settings_chooser.xml b/res/xml/security_settings_chooser.xml
index af7bfeb..dd8ae55 100644
--- a/res/xml/security_settings_chooser.xml
+++ b/res/xml/security_settings_chooser.xml
@@ -15,23 +15,20 @@
 -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
                   android:title="@string/security_settings_title">
 
     <PreferenceCategory
         android:key="security_category"
         android:title="@string/lock_settings_title">
 
-        <PreferenceScreen
+        <com.android.settings.GearPreference
             android:key="unlock_set_or_change"
             android:title="@string/unlock_set_unlock_launch_picker_title"
             android:summary="@string/unlock_set_unlock_mode_none"
+            settings:keywords="@string/keywords_lockscreen"
             android:persistent="false"/>
 
-        <com.android.settings.SingleLineSummaryPreference
-            android:key="owner_info_settings"
-            android:title="@string/owner_info_settings_title"
-            android:summary="@string/owner_info_settings_summary"/>
-
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/security_settings_lockscreen.xml b/res/xml/security_settings_lockscreen.xml
index fde0446..a5aa767 100644
--- a/res/xml/security_settings_lockscreen.xml
+++ b/res/xml/security_settings_lockscreen.xml
@@ -29,12 +29,6 @@
             settings:keywords="@string/keywords_lockscreen"
             android:persistent="false"/>
 
-        <com.android.settings.SingleLineSummaryPreference
-            android:key="owner_info_settings"
-            android:enabled="false"
-            android:title="@string/owner_info_settings_title"
-            android:summary="@string/owner_info_settings_summary"/>
-
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/security_settings_password.xml b/res/xml/security_settings_password.xml
index a6fe1a4..d96ca4b 100644
--- a/res/xml/security_settings_password.xml
+++ b/res/xml/security_settings_password.xml
@@ -22,30 +22,13 @@
         android:key="security_category"
         android:title="@string/lock_settings_title">
 
-        <PreferenceScreen
+        <com.android.settings.GearPreference
             android:key="unlock_set_or_change"
             android:title="@string/unlock_set_unlock_launch_picker_title"
             android:summary="@string/unlock_set_unlock_mode_password"
             settings:keywords="@string/keywords_lockscreen"
             android:persistent="false"/>
 
-        <com.android.settings.RestrictedListPreference
-            android:key="lock_after_timeout"
-            android:title="@string/lock_after_timeout"
-            android:summary="@string/lock_after_timeout_summary"
-            android:entries="@array/lock_after_timeout_entries"
-            android:entryValues="@array/lock_after_timeout_values"
-            android:persistent="false"/>
-
-        <SwitchPreference
-            android:key="power_button_instantly_locks"
-            android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/>
-
-        <com.android.settings.SingleLineSummaryPreference
-            android:key="owner_info_settings"
-            android:title="@string/owner_info_settings_title"
-            android:summary="@string/owner_info_settings_summary"/>
-
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/security_settings_password_sub.xml b/res/xml/security_settings_password_sub.xml
new file mode 100644
index 0000000..0fa3731
--- /dev/null
+++ b/res/xml/security_settings_password_sub.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+                  android:title="@string/settings_label">
+
+        <com.android.settings.RestrictedListPreference
+                android:key="lock_after_timeout"
+                android:title="@string/lock_after_timeout"
+                android:summary="@string/lock_after_timeout_summary"
+                android:entries="@array/lock_after_timeout_entries"
+                android:entryValues="@array/lock_after_timeout_values"
+                android:persistent="false"/>
+
+        <SwitchPreference
+                android:key="power_button_instantly_locks"
+                android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/>
+
+        <com.android.settings.SingleLineSummaryPreference
+                android:key="owner_info_settings"
+                android:title="@string/owner_info_settings_title"
+                android:summary="@string/owner_info_settings_summary"/>
+
+        <SwitchPreference
+            android:key="require_cred_before_startup"
+            android:title="@string/lockpattern_settings_require_cred_before_startup"
+            android:summary="@string/lockpattern_settings_require_password_before_startup_summary"/>
+
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_pattern.xml b/res/xml/security_settings_pattern.xml
index f8c4bd9..d3fd97d 100644
--- a/res/xml/security_settings_pattern.xml
+++ b/res/xml/security_settings_pattern.xml
@@ -22,34 +22,13 @@
         android:key="security_category"
         android:title="@string/lock_settings_title">
 
-        <PreferenceScreen
+        <com.android.settings.GearPreference
             android:key="unlock_set_or_change"
             android:title="@string/unlock_set_unlock_launch_picker_title"
             android:summary="@string/unlock_set_unlock_mode_pattern"
             settings:keywords="@string/keywords_lockscreen"
             android:persistent="false"/>
 
-        <SwitchPreference
-            android:key="visiblepattern"
-            android:title="@string/lockpattern_settings_enable_visible_pattern_title"/>
-
-        <com.android.settings.RestrictedListPreference
-            android:key="lock_after_timeout"
-            android:title="@string/lock_after_timeout"
-            android:summary="@string/lock_after_timeout_summary"
-            android:entries="@array/lock_after_timeout_entries"
-            android:entryValues="@array/lock_after_timeout_values"
-            android:persistent="false"/>
-
-        <SwitchPreference
-            android:key="power_button_instantly_locks"
-            android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/>
-
-        <com.android.settings.SingleLineSummaryPreference
-            android:key="owner_info_settings"
-            android:title="@string/owner_info_settings_title"
-            android:summary="@string/owner_info_settings_summary"/>
-
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/security_settings_pattern_sub.xml b/res/xml/security_settings_pattern_sub.xml
new file mode 100644
index 0000000..adaaca6
--- /dev/null
+++ b/res/xml/security_settings_pattern_sub.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+                  android:title="@string/settings_label">
+
+        <SwitchPreference
+                android:key="visiblepattern"
+                android:title="@string/lockpattern_settings_enable_visible_pattern_title"/>
+
+        <com.android.settings.RestrictedListPreference
+                android:key="lock_after_timeout"
+                android:title="@string/lock_after_timeout"
+                android:summary="@string/lock_after_timeout_summary"
+                android:entries="@array/lock_after_timeout_entries"
+                android:entryValues="@array/lock_after_timeout_values"
+                android:persistent="false"/>
+
+        <SwitchPreference
+                android:key="power_button_instantly_locks"
+                android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/>
+
+        <com.android.settings.SingleLineSummaryPreference
+                android:key="owner_info_settings"
+                android:title="@string/owner_info_settings_title"
+                android:summary="@string/owner_info_settings_summary"/>
+
+        <SwitchPreference
+            android:key="require_cred_before_startup"
+            android:title="@string/lockpattern_settings_require_cred_before_startup"
+            android:summary="@string/lockpattern_settings_require_pattern_before_startup_summary"/>
+
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_pin.xml b/res/xml/security_settings_pin.xml
index abab140..ba19c43 100644
--- a/res/xml/security_settings_pin.xml
+++ b/res/xml/security_settings_pin.xml
@@ -22,30 +22,13 @@
         android:key="security_category"
         android:title="@string/lock_settings_title">
 
-        <PreferenceScreen
+        <com.android.settings.GearPreference
             android:key="unlock_set_or_change"
             android:title="@string/unlock_set_unlock_launch_picker_title"
             android:summary="@string/unlock_set_unlock_mode_pin"
             settings:keywords="@string/keywords_lockscreen"
             android:persistent="false"/>
 
-        <com.android.settings.RestrictedListPreference
-            android:key="lock_after_timeout"
-            android:title="@string/lock_after_timeout"
-            android:summary="@string/lock_after_timeout_summary"
-            android:entries="@array/lock_after_timeout_entries"
-            android:entryValues="@array/lock_after_timeout_values"
-            android:persistent="false"/>
-
-        <SwitchPreference
-            android:key="power_button_instantly_locks"
-            android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/>
-
-        <com.android.settings.SingleLineSummaryPreference
-            android:key="owner_info_settings"
-            android:title="@string/owner_info_settings_title"
-            android:summary="@string/owner_info_settings_summary"/>
-
     </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/res/xml/security_settings_pin_sub.xml b/res/xml/security_settings_pin_sub.xml
new file mode 100644
index 0000000..6dff551
--- /dev/null
+++ b/res/xml/security_settings_pin_sub.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+                  android:title="@string/settings_label">
+
+        <com.android.settings.RestrictedListPreference
+                android:key="lock_after_timeout"
+                android:title="@string/lock_after_timeout"
+                android:summary="@string/lock_after_timeout_summary"
+                android:entries="@array/lock_after_timeout_entries"
+                android:entryValues="@array/lock_after_timeout_values"
+                android:persistent="false"/>
+
+        <SwitchPreference
+                android:key="power_button_instantly_locks"
+                android:title="@string/lockpattern_settings_enable_power_button_instantly_locks"/>
+
+        <com.android.settings.SingleLineSummaryPreference
+                android:key="owner_info_settings"
+                android:title="@string/owner_info_settings_title"
+                android:summary="@string/owner_info_settings_summary"/>
+
+        <SwitchPreference
+            android:key="require_cred_before_startup"
+            android:title="@string/lockpattern_settings_require_cred_before_startup"
+            android:summary="@string/lockpattern_settings_require_pin_before_startup_summary"/>
+
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_slide_sub.xml b/res/xml/security_settings_slide_sub.xml
new file mode 100644
index 0000000..1efb370
--- /dev/null
+++ b/res/xml/security_settings_slide_sub.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+                  android:title="@string/settings_label">
+
+        <com.android.settings.SingleLineSummaryPreference
+            android:key="owner_info_settings"
+            android:title="@string/owner_info_settings_title"
+            android:summary="@string/owner_info_settings_summary"/>
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index b44ee48..03a3fef 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -37,6 +37,7 @@
 import android.security.KeyStore;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
 import android.view.View;
@@ -104,6 +105,7 @@
         private boolean mEncryptionRequestDisabled;
         private boolean mRequirePassword;
         private boolean mForFingerprint = false;
+        private boolean mForChangeCredRequiredForBoot = false;
         private String mUserPassword;
         private LockPatternUtils mLockPatternUtils;
         private FingerprintManager mFingerprintManager;
@@ -157,6 +159,8 @@
                     ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
             mForFingerprint = getActivity().getIntent().getBooleanExtra(
                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
+            mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
+                    ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
 
             if (savedInstanceState != null) {
                 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
@@ -183,6 +187,10 @@
 
             if (mPasswordConfirmed) {
                 updatePreferencesOrFinish();
+                if (mForChangeCredRequiredForBoot) {
+                    maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
+                            mUserId), false);
+                }
             } else if (!mWaitingForConfirmation) {
                 ChooseLockSettingsHelper helper =
                         new ChooseLockSettingsHelper(this.getActivity(), this);
@@ -238,6 +246,9 @@
                 // Get the intent that the encryption interstitial should start for creating
                 // the new unlock method.
                 Intent unlockMethodIntent = getIntentForUnlockMethod(quality, disabled);
+                unlockMethodIntent.putExtra(
+                        ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT,
+                        mForChangeCredRequiredForBoot);
                 final Context context = getActivity();
                 // If accessibility is enabled and the user hasn't seen this dialog before, set the
                 // default state to agree with that which is compatible with accessibility
@@ -250,6 +261,11 @@
                         mForFingerprint);
                 startActivityForResult(intent, ENABLE_ENCRYPTION_REQUEST);
             } else {
+                if (mForChangeCredRequiredForBoot) {
+                    // Welp, couldn't change it. Oh well.
+                    finish();
+                    return;
+                }
                 mRequirePassword = false; // device encryption not enabled or not device owner.
                 updateUnlockMethodAndFinish(quality, disabled);
             }
@@ -263,6 +279,14 @@
                 mPasswordConfirmed = true;
                 mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
                 updatePreferencesOrFinish();
+                if (mForChangeCredRequiredForBoot) {
+                    if (!TextUtils.isEmpty(mUserPassword)) {
+                        maybeEnableEncryption(
+                                mLockPatternUtils.getKeyguardStoredPasswordQuality(mUserId), false);
+                    } else {
+                        finish();
+                    }
+                }
             } else if (requestCode == CHOOSE_LOCK_REQUEST
                     || requestCode == ENABLE_ENCRYPTION_REQUEST) {
                 if (resultCode != RESULT_CANCELED) {
@@ -273,6 +297,9 @@
                 getActivity().setResult(Activity.RESULT_CANCELED);
                 finish();
             }
+            if (requestCode == Activity.RESULT_CANCELED && mForChangeCredRequiredForBoot) {
+                finish();
+            }
         }
 
         @Override
diff --git a/src/com/android/settings/ChooseLockPassword.java b/src/com/android/settings/ChooseLockPassword.java
index 2fd012e..fcedea3 100644
--- a/src/com/android/settings/ChooseLockPassword.java
+++ b/src/com/android/settings/ChooseLockPassword.java
@@ -267,6 +267,19 @@
                     mUserId));
 
             mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
+
+            if (intent.getBooleanExtra(
+                    ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) {
+                SaveAndFinishWorker w = new SaveAndFinishWorker();
+                final boolean required = getActivity().getIntent().getBooleanExtra(
+                        EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
+                String current = intent.getStringExtra(
+                        ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
+                w.setBlocking(true);
+                w.setListener(this);
+                w.start(mChooseLockSettingsHelper.utils(), required,
+                        false, 0, current, current, mRequestedQuality, mUserId);
+            }
         }
 
         @Override
diff --git a/src/com/android/settings/ChooseLockPattern.java b/src/com/android/settings/ChooseLockPattern.java
index 960ec1a..4a92951 100644
--- a/src/com/android/settings/ChooseLockPattern.java
+++ b/src/com/android/settings/ChooseLockPattern.java
@@ -371,6 +371,19 @@
             Intent intent = getActivity().getIntent();
             // Only take this argument into account if it belongs to the current profile.
             mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
+
+            if (intent.getBooleanExtra(
+                    ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, false)) {
+                SaveAndFinishWorker w = new SaveAndFinishWorker();
+                final boolean required = getActivity().getIntent().getBooleanExtra(
+                        EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
+                String current = intent.getStringExtra(
+                        ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
+                w.setBlocking(true);
+                w.setListener(this);
+                w.start(mChooseLockSettingsHelper.utils(), required,
+                        false, 0, LockPatternUtils.stringToPattern(current), current, mUserId);
+            }
         }
 
         @Override
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index 1035ef1..dda8da2 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -33,6 +33,7 @@
     public static final String EXTRA_KEY_CHALLENGE = "challenge";
     public static final String EXTRA_KEY_CHALLENGE_TOKEN = "hw_auth_token";
     public static final String EXTRA_KEY_FOR_FINGERPRINT = "for_fingerprint";
+    public static final String EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT = "for_cred_req_boot";
 
 
     private LockPatternUtils mLockPatternUtils;
diff --git a/src/com/android/settings/GearPreference.java b/src/com/android/settings/GearPreference.java
new file mode 100644
index 0000000..a8c1e9d
--- /dev/null
+++ b/src/com/android/settings/GearPreference.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * A preference with a Gear on the side
+ */
+public class GearPreference extends Preference implements View.OnClickListener {
+
+    private OnGearClickListener mOnGearClickListener;
+
+    public GearPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setWidgetLayoutResource(R.layout.preference_widget_settings);
+    }
+
+    public void setOnGearClickListener(OnGearClickListener l) {
+        mOnGearClickListener = l;
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        holder.findViewById(R.id.settings_button).setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.settings_button) {
+            if (mOnGearClickListener != null) {
+                mOnGearClickListener.onGearClick(this);
+            }
+        }
+    }
+
+    public interface OnGearClickListener {
+        void onGearClick(GearPreference p);
+    }
+}
diff --git a/src/com/android/settings/OwnerInfoSettings.java b/src/com/android/settings/OwnerInfoSettings.java
index 7fffb11..cad0693 100644
--- a/src/com/android/settings/OwnerInfoSettings.java
+++ b/src/com/android/settings/OwnerInfoSettings.java
@@ -75,8 +75,8 @@
             mLockPatternUtils.setOwnerInfoEnabled(!TextUtils.isEmpty(info), mUserId);
             mLockPatternUtils.setOwnerInfo(info, mUserId);
 
-            if (getTargetFragment() instanceof SecuritySettings) {
-                ((SecuritySettings) getTargetFragment()).updateOwnerInfo();
+            if (getTargetFragment() instanceof SecuritySettings.SecuritySubSettings) {
+                ((SecuritySettings.SecuritySubSettings) getTargetFragment()).updateOwnerInfo();
             }
         }
     }
diff --git a/src/com/android/settings/SaveChosenLockWorkerBase.java b/src/com/android/settings/SaveChosenLockWorkerBase.java
index 4d8964a..155dcb8 100644
--- a/src/com/android/settings/SaveChosenLockWorkerBase.java
+++ b/src/com/android/settings/SaveChosenLockWorkerBase.java
@@ -39,6 +39,8 @@
     protected boolean mWasSecureBefore;
     protected int mUserId;
 
+    private boolean mBlocking;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -74,7 +76,11 @@
     }
 
     protected void start() {
-        new Task().execute();
+        if (mBlocking) {
+            finish(saveAndVerifyInBackground());
+        } else {
+            new Task().execute();
+        }
     }
 
     /**
@@ -91,6 +97,10 @@
         }
     }
 
+    public void setBlocking(boolean blocking) {
+        mBlocking = blocking;
+    }
+
     private class Task extends AsyncTask<Void, Void, Intent> {
         @Override
         protected Intent doInBackground(Void... params){
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 415f4d3..3e873d4 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -28,7 +28,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
-import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.os.PersistableBundle;
@@ -55,7 +54,6 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.RestrictedListPreference;
 import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo;
-import com.android.settings.fingerprint.FingerprintEnrollIntroduction;
 import com.android.settings.fingerprint.FingerprintSettings;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Index;
@@ -77,7 +75,8 @@
  * Gesture lock pattern settings.
  */
 public class SecuritySettings extends SettingsPreferenceFragment
-        implements OnPreferenceChangeListener, DialogInterface.OnClickListener, Indexable {
+        implements OnPreferenceChangeListener, DialogInterface.OnClickListener, Indexable,
+        GearPreference.OnGearClickListener {
 
     private static final String TAG = "SecuritySettings";
     private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
@@ -87,11 +86,8 @@
     // Lock Settings
     private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
     private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "profile_challenge";
-    private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
     private static final String KEY_SECURITY_CATEGORY = "security_category";
     private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category";
-    private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
-    private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
     private static final String KEY_ADVANCED_SECURITY = "advanced_security";
     private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
 
@@ -105,16 +101,14 @@
     private static final String KEY_RESET_CREDENTIALS = "credentials_reset";
     private static final String KEY_CREDENTIALS_INSTALL = "credentials_install";
     private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
-    private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
     private static final String KEY_CREDENTIALS_MANAGER = "credentials_management";
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
     private static final String KEY_TRUST_AGENT = "trust_agent";
     private static final String KEY_SCREEN_PINNING = "screen_pinning_settings";
 
     // These switch preferences need special handling since they're not all stored in Settings.
-    private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT,
-            KEY_VISIBLE_PATTERN, KEY_POWER_INSTANTLY_LOCKS, KEY_SHOW_PASSWORD,
-            KEY_TOGGLE_INSTALL_APPLICATIONS };
+    private static final String SWITCH_PREFERENCE_KEYS[] = {
+            KEY_SHOW_PASSWORD, KEY_TOGGLE_INSTALL_APPLICATIONS };
 
     // Only allow one trust agent on the platform.
     private static final boolean ONLY_ONE_TRUST_AGENT = true;
@@ -127,9 +121,6 @@
 
     private ChooseLockSettingsHelper mChooseLockSettingsHelper;
     private LockPatternUtils mLockPatternUtils;
-    private RestrictedListPreference mLockAfter;
-
-    private SwitchPreference mVisiblePattern;
 
     private SwitchPreference mShowPassword;
 
@@ -138,12 +129,10 @@
 
     private RestrictedSwitchPreference mToggleAppInstallation;
     private DialogInterface mWarnInstallApps;
-    private SwitchPreference mPowerButtonInstantlyLocks;
 
     private boolean mIsAdmin;
 
     private Intent mTrustAgentClickIntent;
-    private Preference mOwnerInfoPref;
 
     private int mProfileChallengeUserId;
 
@@ -232,25 +221,14 @@
             }
         }
 
+        Preference unlockSetOrChange = findPreference(KEY_UNLOCK_SET_OR_CHANGE);
+        if (unlockSetOrChange instanceof GearPreference) {
+            ((GearPreference) unlockSetOrChange).setOnGearClickListener(this);
+        }
+
         // Add options for device encryption
         mIsAdmin = mUm.isAdminUser();
 
-        mOwnerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS);
-        if (mOwnerInfoPref != null) {
-            mOwnerInfoPref.setEnabled(!mLockPatternUtils.isLockScreenDisabled(MY_USER_ID)
-                    && !mLockPatternUtils.isDeviceOwnerInfoEnabled());
-
-            if (mOwnerInfoPref.isEnabled()) {
-                mOwnerInfoPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
-                    @Override
-                    public boolean onPreferenceClick(Preference preference) {
-                        OwnerInfoSettings.show(SecuritySettings.this);
-                        return true;
-                    }
-                });
-            }
-        }
-
         if (mIsAdmin) {
             if (LockPatternUtils.isDeviceEncryptionEnabled()) {
                 // The device is currently encrypted.
@@ -269,28 +247,6 @@
             addTrustAgentSettings(securityCategory);
         }
 
-        // lock after preference
-        mLockAfter = (RestrictedListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
-        if (mLockAfter != null) {
-            setupLockAfterPreference();
-            updateLockAfterPreferenceSummary();
-        }
-
-        // visible pattern
-        mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN);
-
-        // lock instantly on power key press
-        mPowerButtonInstantlyLocks = (SwitchPreference) root.findPreference(
-                KEY_POWER_INSTANTLY_LOCKS);
-        Preference trustAgentPreference = root.findPreference(KEY_TRUST_AGENT);
-        if (mPowerButtonInstantlyLocks != null &&
-                trustAgentPreference != null &&
-                trustAgentPreference.getTitle().length() > 0) {
-            mPowerButtonInstantlyLocks.setSummary(getString(
-                    R.string.lockpattern_settings_power_button_instantly_locks_summary,
-                    trustAgentPreference.getTitle()));
-        }
-
         // Append the rest of the settings
         addPreferencesFromResource(R.xml.security_settings_misc);
 
@@ -522,6 +478,13 @@
     }
 
     @Override
+    public void onGearClick(GearPreference p) {
+        if (KEY_UNLOCK_SET_OR_CHANGE.equals(p.getKey())) {
+            startFragment(this, SecuritySubSettings.class.getName(), 0, 0, null);
+        }
+    }
+
+    @Override
     public void onDestroy() {
         super.onDestroy();
         if (mWarnInstallApps != null) {
@@ -529,105 +492,6 @@
         }
     }
 
-    private void setupLockAfterPreference() {
-        // Compatible with pre-Froyo
-        long currentTimeout = Settings.Secure.getLong(getContentResolver(),
-                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
-        mLockAfter.setValue(String.valueOf(currentTimeout));
-        mLockAfter.setOnPreferenceChangeListener(this);
-        final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
-                getActivity());
-        if (admin != null) {
-            final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
-            final long displayTimeout = Math.max(0,
-                    Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
-            if (adminTimeout > 0) {
-                // This setting is a slave to display timeout when a device policy is enforced.
-                // As such, maxLockTimeout = adminTimeout - displayTimeout.
-                // If there isn't enough time, shows "immediately" setting.
-                disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout), admin);
-            }
-        }
-    }
-
-    private void updateLockAfterPreferenceSummary() {
-        final String summary;
-        if (mLockAfter.isDisabledByAdmin()) {
-            summary = getString(R.string.disabled_by_policy_title);
-        } else {
-            // Update summary message with current value
-            long currentTimeout = Settings.Secure.getLong(getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
-            final CharSequence[] entries = mLockAfter.getEntries();
-            final CharSequence[] values = mLockAfter.getEntryValues();
-            int best = 0;
-            for (int i = 0; i < values.length; i++) {
-                if (mLockAfter.isRestrictedForEntry(entries[i])) {
-                    break;
-                }
-                long timeout = Long.valueOf(values[i].toString());
-                if (currentTimeout >= timeout) {
-                    best = i;
-                }
-            }
-
-            Preference preference = getPreferenceScreen().findPreference(KEY_TRUST_AGENT);
-            if (preference != null && preference.getTitle().length() > 0) {
-                if (Long.valueOf(values[best].toString()) == 0) {
-                    summary = getString(R.string.lock_immediately_summary_with_exception,
-                            preference.getTitle());
-                } else {
-                    summary = getString(R.string.lock_after_timeout_summary_with_exception,
-                            entries[best], preference.getTitle());
-                }
-            } else {
-                summary = getString(R.string.lock_after_timeout_summary, entries[best]);
-            }
-        }
-        mLockAfter.setSummary(summary);
-    }
-
-    private void disableUnusableTimeouts(long maxTimeout, EnforcedAdmin admin) {
-        final CharSequence[] entries = mLockAfter.getEntries();
-        final CharSequence[] values = mLockAfter.getEntryValues();
-        long maxTimeoutSelectable = 0;
-        int maxTimeoutEntryIndex = -1;
-        for (int i = 0; i < values.length; i++) {
-            long timeout = Long.parseLong(values[i].toString());
-            if (timeout > maxTimeout) {
-                break;
-            }
-            maxTimeoutSelectable = timeout;
-            maxTimeoutEntryIndex = i;
-        }
-        // If there are no possible options for the user, then set this preference as
-        // disabled by admin, otherwise remove the padlock in case it was set earlier.
-        if (maxTimeoutSelectable == 0) {
-            mLockAfter.setDisabledByAdmin(admin);
-            return;
-        } else {
-            mLockAfter.setDisabledByAdmin(null);
-        }
-
-        mLockAfter.clearRestrictedItems();
-        // Set all the entries after the maximum selectable timeout as disabled by admin.
-        for (int i = maxTimeoutEntryIndex + 1; i < values.length; i++) {
-            mLockAfter.addRestrictedItem(
-                    new RestrictedItem(entries[i], values[i], admin));
-        }
-
-        final int userPreference = Integer.valueOf(mLockAfter.getValue());
-        if (userPreference <= maxTimeout) {
-            mLockAfter.setValue(String.valueOf(userPreference));
-        } else if (maxTimeoutSelectable == maxTimeout) {
-            mLockAfter.setValue(String.valueOf(maxTimeout));
-        } else {
-            // There will be no highlighted selection since nothing in the list matches
-            // maxTimeout. The user can still select anything less than maxTimeout.
-            // TODO: maybe append maxTimeout to the list and mark selected.
-        }
-    }
-
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
@@ -645,15 +509,6 @@
         createPreferenceHierarchy();
 
         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
-        if (mVisiblePattern != null) {
-            mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled(
-                    MY_USER_ID));
-        }
-        if (mPowerButtonInstantlyLocks != null) {
-            mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks(
-                    MY_USER_ID));
-        }
-
         if (mShowPassword != null) {
             mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
                     Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
@@ -662,20 +517,6 @@
         if (mResetCredentials != null) {
             mResetCredentials.setEnabled(!mKeyStore.isEmpty());
         }
-
-        updateOwnerInfo();
-    }
-
-    public void updateOwnerInfo() {
-        if (mOwnerInfoPref != null) {
-            if (mLockPatternUtils.isDeviceOwnerInfoEnabled()) {
-                mOwnerInfoPref.setSummary(R.string.disabled_by_administrator_summary);
-            } else {
-                mOwnerInfoPref.setSummary(mLockPatternUtils.isOwnerInfoEnabled(MY_USER_ID)
-                        ? mLockPatternUtils.getOwnerInfo(MY_USER_ID)
-                        : getString(R.string.owner_info_settings_summary));
-            }
-        }
     }
 
     @Override
@@ -728,20 +569,7 @@
         boolean result = true;
         final String key = preference.getKey();
         final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
-        if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) {
-            int timeout = Integer.parseInt((String) value);
-            try {
-                Settings.Secure.putInt(getContentResolver(),
-                        Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
-            } catch (NumberFormatException e) {
-                Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
-            }
-            updateLockAfterPreferenceSummary();
-        } else if (KEY_VISIBLE_PATTERN.equals(key)) {
-            lockPatternUtils.setVisiblePatternEnabled((Boolean) value, MY_USER_ID);
-        } else if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
-            mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value, MY_USER_ID);
-        } else if (KEY_SHOW_PASSWORD.equals(key)) {
+        if (KEY_SHOW_PASSWORD.equals(key)) {
             Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
                     ((Boolean) value) ? 1 : 0);
             lockPatternUtils.setVisiblePasswordEnabled((Boolean) value, MY_USER_ID);
@@ -823,6 +651,12 @@
                 result.add(sir);
             }
 
+            sir = new SearchIndexableResource(context);
+            sir.xmlResId = SecuritySubSettings.getResIdForLockUnlockSubScreen(context,
+                    lockPatternUtils);
+            sir.className = SecuritySubSettings.class.getName();
+            result.add(sir);
+
             // Append the rest of the settings
             sir = new SearchIndexableResource(context);
             sir.xmlResId = R.xml.security_settings_misc;
@@ -924,8 +758,304 @@
                 keys.add(KEY_MANAGE_TRUST_AGENTS);
             }
 
+            if (!SecuritySubSettings.canChangeRequireCredentialBeforeStartup(context)) {
+                keys.add(SecuritySubSettings.KEY_REQUIRE_CRED_BEFORE_STARTUP);
+            }
+
             return keys;
         }
     }
 
+    public static class SecuritySubSettings extends SettingsPreferenceFragment
+            implements OnPreferenceChangeListener {
+
+        private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
+        private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
+        private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
+        private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
+        private static final String KEY_REQUIRE_CRED_BEFORE_STARTUP = "require_cred_before_startup";
+
+        public static final int REQUEST_CHANGE_REQUIRE_CRED_FOR_START = 2;
+
+        // These switch preferences need special handling since they're not all stored in Settings.
+        private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT,
+                KEY_VISIBLE_PATTERN, KEY_POWER_INSTANTLY_LOCKS, KEY_REQUIRE_CRED_BEFORE_STARTUP };
+
+        private RestrictedListPreference mLockAfter;
+        private SwitchPreference mVisiblePattern;
+        private SwitchPreference mPowerButtonInstantlyLocks;
+        private Preference mOwnerInfoPref;
+
+        private LockPatternUtils mLockPatternUtils;
+        private DevicePolicyManager mDPM;
+
+        @Override
+        protected int getMetricsCategory() {
+            return MetricsEvent.SECURITY;
+        }
+
+        @Override
+        public void onCreate(Bundle icicle) {
+            super.onCreate(icicle);
+            mLockPatternUtils = new LockPatternUtils(getContext());
+            mDPM = getContext().getSystemService(DevicePolicyManager.class);
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+
+            createPreferenceHierarchy();
+
+            final LockPatternUtils lockPatternUtils = mLockPatternUtils;
+            if (mVisiblePattern != null) {
+                mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled(
+                        MY_USER_ID));
+            }
+            if (mPowerButtonInstantlyLocks != null) {
+                mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks(
+                        MY_USER_ID));
+            }
+
+            updateOwnerInfo();
+        }
+
+        @Override
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+            super.onActivityResult(requestCode, resultCode, data);
+
+            createPreferenceHierarchy();
+        }
+
+        private void createPreferenceHierarchy() {
+            PreferenceScreen root = getPreferenceScreen();
+            if (root != null) {
+                root.removeAll();
+            }
+            root = null;
+
+            final int resid = getResIdForLockUnlockSubScreen(getActivity(),
+                    new LockPatternUtils(getContext()));
+            addPreferencesFromResource(resid);
+
+            // lock after preference
+            mLockAfter = (RestrictedListPreference) findPreference(KEY_LOCK_AFTER_TIMEOUT);
+            if (mLockAfter != null) {
+                setupLockAfterPreference();
+                updateLockAfterPreferenceSummary();
+            }
+
+            // visible pattern
+            mVisiblePattern = (SwitchPreference) findPreference(KEY_VISIBLE_PATTERN);
+
+            // lock instantly on power key press
+            mPowerButtonInstantlyLocks = (SwitchPreference) findPreference(
+                    KEY_POWER_INSTANTLY_LOCKS);
+            Preference trustAgentPreference = findPreference(KEY_TRUST_AGENT);
+            if (mPowerButtonInstantlyLocks != null &&
+                    trustAgentPreference != null &&
+                    trustAgentPreference.getTitle().length() > 0) {
+                mPowerButtonInstantlyLocks.setSummary(getString(
+                        R.string.lockpattern_settings_power_button_instantly_locks_summary,
+                        trustAgentPreference.getTitle()));
+            }
+
+            mOwnerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS);
+            if (mOwnerInfoPref != null) {
+                mOwnerInfoPref.setEnabled(!mLockPatternUtils.isLockScreenDisabled(MY_USER_ID)
+                        && !mLockPatternUtils.isDeviceOwnerInfoEnabled());
+
+                if (mOwnerInfoPref.isEnabled()) {
+                    mOwnerInfoPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                        @Override
+                        public boolean onPreferenceClick(Preference preference) {
+                            OwnerInfoSettings.show(SecuritySubSettings.this);
+                            return true;
+                        }
+                    });
+                }
+            }
+
+            Preference requireCredForStartup = findPreference(KEY_REQUIRE_CRED_BEFORE_STARTUP);
+            if (requireCredForStartup instanceof SwitchPreference) {
+                ((SwitchPreference) requireCredForStartup).setChecked(
+                        mLockPatternUtils.isCredentialRequiredToDecrypt(false));
+                if (!canChangeRequireCredentialBeforeStartup(getContext())) {
+                    removePreference(KEY_REQUIRE_CRED_BEFORE_STARTUP);
+                }
+            }
+
+            for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
+                final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]);
+                if (pref != null) pref.setOnPreferenceChangeListener(this);
+            }
+        }
+
+        static boolean canChangeRequireCredentialBeforeStartup(Context context) {
+            DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+            return UserManager.get(context).isAdminUser()
+                    && LockPatternUtils.isDeviceEncryptionEnabled()
+                    && !dpm.getDoNotAskCredentialsOnBoot();
+        }
+
+        private void setupLockAfterPreference() {
+            // Compatible with pre-Froyo
+            long currentTimeout = Settings.Secure.getLong(getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
+            mLockAfter.setValue(String.valueOf(currentTimeout));
+            mLockAfter.setOnPreferenceChangeListener(this);
+            final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
+                    getActivity());
+            if (admin != null) {
+                final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
+                final long displayTimeout = Math.max(0,
+                        Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
+                if (adminTimeout > 0) {
+                    // This setting is a slave to display timeout when a device policy is enforced.
+                    // As such, maxLockTimeout = adminTimeout - displayTimeout.
+                    // If there isn't enough time, shows "immediately" setting.
+                    disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout), admin);
+                }
+            }
+        }
+
+        private void updateLockAfterPreferenceSummary() {
+            final String summary;
+            if (mLockAfter.isDisabledByAdmin()) {
+                summary = getString(R.string.disabled_by_policy_title);
+            } else {
+                // Update summary message with current value
+                long currentTimeout = Settings.Secure.getLong(getContentResolver(),
+                        Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
+                final CharSequence[] entries = mLockAfter.getEntries();
+                final CharSequence[] values = mLockAfter.getEntryValues();
+                int best = 0;
+                for (int i = 0; i < values.length; i++) {
+                    if (mLockAfter.isRestrictedForEntry(entries[i])) {
+                        break;
+                    }
+                    long timeout = Long.valueOf(values[i].toString());
+                    if (currentTimeout >= timeout) {
+                        best = i;
+                    }
+                }
+
+                Preference preference = findPreference(KEY_TRUST_AGENT);
+                if (preference != null && preference.getTitle().length() > 0) {
+                    if (Long.valueOf(values[best].toString()) == 0) {
+                        summary = getString(R.string.lock_immediately_summary_with_exception,
+                                preference.getTitle());
+                    } else {
+                        summary = getString(R.string.lock_after_timeout_summary_with_exception,
+                                entries[best], preference.getTitle());
+                    }
+                } else {
+                    summary = getString(R.string.lock_after_timeout_summary, entries[best]);
+                }
+            }
+            mLockAfter.setSummary(summary);
+        }
+
+        private void disableUnusableTimeouts(long maxTimeout, EnforcedAdmin admin) {
+            final CharSequence[] entries = mLockAfter.getEntries();
+            final CharSequence[] values = mLockAfter.getEntryValues();
+            long maxTimeoutSelectable = 0;
+            int maxTimeoutEntryIndex = -1;
+            for (int i = 0; i < values.length; i++) {
+                long timeout = Long.parseLong(values[i].toString());
+                if (timeout > maxTimeout) {
+                    break;
+                }
+                maxTimeoutSelectable = timeout;
+                maxTimeoutEntryIndex = i;
+            }
+            // If there are no possible options for the user, then set this preference as
+            // disabled by admin, otherwise remove the padlock in case it was set earlier.
+            if (maxTimeoutSelectable == 0) {
+                mLockAfter.setDisabledByAdmin(admin);
+                return;
+            } else {
+                mLockAfter.setDisabledByAdmin(null);
+            }
+
+            mLockAfter.clearRestrictedItems();
+            // Set all the entries after the maximum selectable timeout as disabled by admin.
+            for (int i = maxTimeoutEntryIndex + 1; i < values.length; i++) {
+                mLockAfter.addRestrictedItem(
+                        new RestrictedItem(entries[i], values[i], admin));
+            }
+
+            final int userPreference = Integer.valueOf(mLockAfter.getValue());
+            if (userPreference <= maxTimeout) {
+                mLockAfter.setValue(String.valueOf(userPreference));
+            } else if (maxTimeoutSelectable == maxTimeout) {
+                mLockAfter.setValue(String.valueOf(maxTimeout));
+            } else {
+                // There will be no highlighted selection since nothing in the list matches
+                // maxTimeout. The user can still select anything less than maxTimeout.
+                // TODO: maybe append maxTimeout to the list and mark selected.
+            }
+        }
+
+        public void updateOwnerInfo() {
+            if (mOwnerInfoPref != null) {
+                if (mLockPatternUtils.isDeviceOwnerInfoEnabled()) {
+                    mOwnerInfoPref.setSummary(R.string.disabled_by_administrator_summary);
+                } else {
+                    mOwnerInfoPref.setSummary(mLockPatternUtils.isOwnerInfoEnabled(MY_USER_ID)
+                            ? mLockPatternUtils.getOwnerInfo(MY_USER_ID)
+                            : getString(R.string.owner_info_settings_summary));
+                }
+            }
+        }
+
+        private static int getResIdForLockUnlockSubScreen(Context context,
+                LockPatternUtils lockPatternUtils) {
+            if (lockPatternUtils.isSecure(MY_USER_ID)) {
+                switch (lockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID)) {
+                    case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                        return R.xml.security_settings_pattern_sub;
+                    case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+                    case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+                        return R.xml.security_settings_pin_sub;
+                    case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+                    case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+                    case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+                        return R.xml.security_settings_password_sub;
+                }
+            } else if (!lockPatternUtils.isLockScreenDisabled(MY_USER_ID)) {
+                return R.xml.security_settings_slide_sub;
+            }
+            return 0;
+        }
+
+        @Override
+        public boolean onPreferenceChange(Preference preference, Object value) {
+            String key = preference.getKey();
+            if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
+                mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value, MY_USER_ID);
+            } else if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) {
+                int timeout = Integer.parseInt((String) value);
+                try {
+                    Settings.Secure.putInt(getContentResolver(),
+                            Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
+                } catch (NumberFormatException e) {
+                    Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
+                }
+                updateLockAfterPreferenceSummary();
+            } else if (KEY_VISIBLE_PATTERN.equals(key)) {
+                mLockPatternUtils.setVisiblePatternEnabled((Boolean) value, MY_USER_ID);
+            } else if (KEY_REQUIRE_CRED_BEFORE_STARTUP.equals(key)) {
+                Bundle extras = new Bundle();
+                extras.putBoolean(
+                        ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT, true);
+                startFragment(this,
+                        "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
+                        R.string.lock_settings_picker_title, REQUEST_CHANGE_REQUIRE_CRED_FOR_START,
+                        extras);
+                return false;
+            }
+            return true;
+        }
+    }
 }