Merge "Import translations. DO NOT MERGE"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 970ee76..b04c8ab 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -166,8 +166,6 @@
                 android:value="com.android.settings.category.ia.homepage"/>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.network.NetworkDashboardFragment"/>
-            <meta-data android:name="com.android.settings.summary"
-                android:resource="@string/network_dashboard_summary"/>
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
         </activity>
@@ -193,8 +191,6 @@
                 android:value="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"/>
             <meta-data android:name="com.android.settings.category"
                 android:value="com.android.settings.category.ia.homepage"/>
-            <meta-data android:name="com.android.settings.summary"
-                android:resource="@string/connected_devices_dashboard_summary"/>
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
         </activity>
diff --git a/res/drawable-hdpi/empty_search_results.png b/res/drawable-hdpi/empty_search_results.png
new file mode 100644
index 0000000..290f0ed
--- /dev/null
+++ b/res/drawable-hdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-mdpi/empty_search_results.png b/res/drawable-mdpi/empty_search_results.png
new file mode 100644
index 0000000..9ef49a6
--- /dev/null
+++ b/res/drawable-mdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-xhdpi/empty_search_results.png b/res/drawable-xhdpi/empty_search_results.png
new file mode 100644
index 0000000..92a9392
--- /dev/null
+++ b/res/drawable-xhdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-xxhdpi/empty_search_results.png b/res/drawable-xxhdpi/empty_search_results.png
new file mode 100644
index 0000000..894ed7b
--- /dev/null
+++ b/res/drawable-xxhdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/empty_search_results.png b/res/drawable-xxxhdpi/empty_search_results.png
new file mode 100644
index 0000000..8f12e96
--- /dev/null
+++ b/res/drawable-xxxhdpi/empty_search_results.png
Binary files differ
diff --git a/res/drawable/no_search_results.xml b/res/drawable/no_search_results.xml
deleted file mode 100644
index a75a443..0000000
--- a/res/drawable/no_search_results.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<!--
-  Copyright (C) 2017 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.
-
-  -->
-
-<vector android:height="24dp" android:viewportHeight="267.9"
-    android:viewportWidth="236.3" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillAlpha="0.9" android:fillColor="#00000000"
-        android:pathData="M18,-19c0,-0.4 0,-0.5 -0.3,-0.3l-12,7c-0.3,0.2 -0.2,0.5 0.1,0.6l11.9,7C18,-4.5 18,-4.7 18,-5V-19z"
-        android:strokeColor="#FFFFFF" android:strokeWidth="2"/>
-    <path android:fillAlpha="0.9" android:fillColor="#00000000"
-        android:pathData="M18.9,-12c0,-3.8 -3.1,-6.9 -6.9,-6.9c-3.8,0 -6.9,3.1 -6.9,6.9c0,3.8 3.1,6.9 6.9,6.9C15.8,-5.1 18.9,-8.2 18.9,-12z"
-        android:strokeColor="#FFFFFF" android:strokeWidth="1.8033"/>
-    <path android:fillAlpha="0.9" android:fillColor="#00000000"
-        android:pathData="M19,-5.7C19,-5.4 18.6,-5 18.2,-5H5.8C5.4,-5 5,-5.4 5,-5.7v-12.6C5,-18.6 5.4,-19 5.8,-19h12.4c0.4,0 0.8,0.4 0.8,0.7V-5.7z"
-        android:strokeColor="#FFFFFF" android:strokeWidth="2"/>
-    <path android:fillColor="#FAFAFA" android:pathData="M118.2,134.4m-118.2,0a118.2,118.2 0,1 1,236.4 0a118.2,118.2 0,1 1,-236.4 0"/>
-    <path android:fillColor="#F5F5F5" android:pathData="M22.8,239L96,206.2c0.2,-0.1 0.3,-0.1 0.5,-0.1l117.3,23c0.7,0.2 0.9,1.2 0.2,1.5l-75.9,37.2c-0.2,0.1 -0.3,0.1 -0.5,0.1L23,240.5C22.2,240.3 22.1,239.3 22.8,239z"/>
-    <path android:fillColor="#E8E8E8" android:pathData="M35.6,76.5l102,17.3l0,167.4l-102,-23.2z"/>
-    <path android:fillColor="#E8E8E8" android:pathData="M35.7,19.6l102,17.3l0,79.2l-102,-23.2z"/>
-    <path android:fillColor="#EFEFEF" android:pathData="M35.7,19.6l66.6,-19.6l100.5,19.1l-65.1,18.5z"/>
-    <path android:fillColor="#00000000"
-        android:pathData="M37.6,131.9L135.2,150"
-        android:strokeColor="#E0E0E0" android:strokeWidth="0.1816"/>
-    <path android:fillAlpha="0.5" android:fillColor="#00000000"
-        android:pathData="M39.1,185.3L132.3,204.8"
-        android:strokeColor="#C1C1C1" android:strokeWidth="0.1816"/>
-    <path android:fillColor="#00000000"
-        android:pathData="M137.7,147.6L116.5,154.5"
-        android:strokeColor="#E0E0E0" android:strokeWidth="0.1816"/>
-    <path android:fillColor="#00000000" android:pathData="M35.7,142.2"
-        android:strokeColor="#E0E0E0" android:strokeWidth="0.1816"/>
-    <path android:fillAlpha="5.000000e-02" android:fillColor="#FF000000" android:pathData="M35.7,140.9l101.7,9.2l0,33.1l-101.8,-21.3z"/>
-    <path android:fillColor="#CECECE" android:pathData="M71,36.9l28.8,5l0,5.8l-28.8,-5.3z"/>
-    <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M71,36.9l28.8,5l0,1.7l-28.8,-5.3z"/>
-    <path android:fillAlpha="0.5" android:fillColor="#CECECE" android:pathData="M68.4,147.3l28.8,5.1l0,5.8l-28.8,-5.4z"/>
-    <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M68.4,147.3l28.8,5.1l0,1.7l-28.8,-5.4z"/>
-    <path android:fillAlpha="0.7" android:fillColor="#CECECE" android:pathData="M68.4,201.2l28.8,5.4l0,5.8l-28.8,-5.7z"/>
-    <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M68.4,201.2l28.8,5.4l0,1.6l-28.8,-5.6z"/>
-    <path android:fillColor="#EAEAEA" android:pathData="M16.2,80.3l100.3,18.1l0,58.5l-100.3,-20.2z"/>
-    <path android:fillColor="#EFEFEF" android:pathData="M137.7,37.6l0,53.9l-21.2,6.9l0,58.5l21.2,-6.9l0,111.1l65.1,-30l0,-212z"/>
-    <path android:fillColor="#E57373" android:pathData="M16.2,80.3l19.5,-8.2l0,11.7z"/>
-    <path android:fillAlpha="0.6" android:fillColor="#E57373" android:pathData="M137.7,91.5l-102,-19.4l0,11.7l80.8,14.6z"/>
-    <path android:fillColor="#CECECE" android:pathData="M47.2,95.5l28.8,5l0,5.8l-28.8,-5.2z"/>
-    <path android:fillAlpha="0.1" android:fillColor="#1F1F1F" android:pathData="M47.2,95.5l28.8,5l0,1.7l-28.8,-5.2z"/>
-    <path android:fillColor="#EAEAEA" android:pathData="M35.7,72.1L35.7,72.1l-19.6,8.1l0,0.1l0,0l100.3,18.1l0,0l0,0l21.6,-7L35.7,72.1zM116.5,97.5L19.4,80l16.4,-6.8L134,91.8L116.5,97.5z"/>
-</vector>
diff --git a/res/layout/account_header.xml b/res/layout/account_header.xml
deleted file mode 100755
index 818d47c..0000000
--- a/res/layout/account_header.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?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.
--->
-
-<LinearLayout
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        style="@style/EntityHeader"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-        android:gravity="center_vertical"
-        android:paddingTop="24dip"
-        android:paddingBottom="24dip"
-        android:orientation="horizontal">
-
-        <LinearLayout
-          android:id="@+id/icon_container"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:minWidth="56dp"
-          android:orientation="horizontal"
-          android:paddingEnd="12dp"
-          android:paddingTop="12dp"
-          android:paddingBottom="12dp">
-                <ImageView
-                  android:id="@android:id/icon"
-                  android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"
-                  android:maxWidth="48dp"
-                  android:maxHeight="48dp"/>
-        </LinearLayout>
-
-        <TextView
-          android:id="@android:id/title"
-          style="@style/TextAppearance.EntityHeaderTitle"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:singleLine="true"/>
-
-</LinearLayout>
diff --git a/res/layout/app_details.xml b/res/layout/app_details.xml
deleted file mode 100644
index 2db23e4..0000000
--- a/res/layout/app_details.xml
+++ /dev/null
@@ -1,116 +0,0 @@
-<?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.
-  -->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <!-- App snippet with buttons -->
-    <RelativeLayout
-        android:id="@+id/app_snippet"
-        style="@style/EntityHeader"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-        android:paddingEnd="0dp"
-        android:paddingTop="24dp"
-        android:paddingBottom="24dp">
-        <ImageView
-            android:id="@+id/app_detail_icon"
-            android:layout_width="56dp"
-            android:layout_height="56dp"
-            android:scaleType="fitXY"
-            android:layout_gravity="center_horizontal"
-            android:antialias="true"/>
-
-        <LinearLayout
-            android:id="@+id/app_detail_links"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_alignParentEnd="true"
-            android:orientation="vertical">
-
-            <ImageButton
-                android:id="@+id/right_button"
-                style="?android:attr/actionOverflowButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_weight="1"
-                android:layout_height="0dp"
-                android:minWidth="@dimen/min_tap_target_size"
-                android:src="@drawable/ic_settings_24dp"
-                android:tint="?android:attr/colorAccent"/>
-
-            <ImageButton
-                android:id="@+id/left_button"
-                style="?android:attr/actionOverflowButtonStyle"
-                android:layout_width="wrap_content"
-                android:layout_weight="1"
-                android:layout_height="0dp"
-                android:minWidth="@dimen/min_tap_target_size"
-                android:src="@null"
-                android:tint="?android:attr/colorAccent"/>
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_toEndOf="@id/app_detail_icon"
-            android:layout_toStartOf="@id/app_detail_links"
-            android:paddingStart="24dp"
-            android:paddingEnd="24dp"
-            android:orientation="vertical">
-
-            <TextView
-                android:id="@+id/app_detail_title"
-                style="@style/TextAppearance.EntityHeaderTitle"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:singleLine="false"
-                android:ellipsize="marquee"
-                android:gravity="start"
-                android:textDirection="locale"
-                android:paddingTop="8dp"/>
-
-            <TextView
-                android:id="@+id/install_type"
-                android:visibility="gone"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:gravity="start"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                android:textColor="?android:attr/textColorSecondary"/>
-
-            <TextView
-                android:id="@+id/app_detail_summary"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:gravity="start"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:textAppearance="@android:style/TextAppearance.Material.Body1"
-                android:textColor="?android:attr/textColorSecondary"/>
-
-        </LinearLayout>
-
-    </RelativeLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index b0ba043..988f331 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -43,11 +43,13 @@
             android:textAppearance="?android:attr/textAppearanceMedium"/>
 
         <LinearLayout
+            android:id="@+id/password_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:clipChildren="false"
             android:clipToPadding="false"
             android:orientation="vertical"
+            android:layoutMode="opticalBounds"
             android:paddingBottom="8dp">
 
             <!-- Password entry field -->
@@ -68,6 +70,15 @@
                 android:layout_height="wrap_content"/>
 
         </LinearLayout>
+
+        <Button
+            android:id="@+id/screen_lock_options"
+            style="@style/SuwGlifButton.Tertiary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/setup_lock_settings_options_button_label"
+            android:visibility="gone" />
+
     </LinearLayout>
 
 </com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/password_requirement_item.xml b/res/layout/password_requirement_item.xml
index df7f45c..8080f10 100644
--- a/res/layout/password_requirement_item.xml
+++ b/res/layout/password_requirement_item.xml
@@ -15,8 +15,8 @@
 -->
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/description_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:paddingStart="4dp"
-        android:textSize="14sp"/>
\ No newline at end of file
+    android:id="@+id/description_text"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="?attr/suwGlifHeaderGravity"
+    android:textSize="14sp"/>
diff --git a/res/layout/search_panel.xml b/res/layout/search_panel.xml
index 8f72847..9445e0c 100644
--- a/res/layout/search_panel.xml
+++ b/res/layout/search_panel.xml
@@ -61,18 +61,20 @@
             android:id="@+id/no_results_layout"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:gravity="center"
+            android:paddingTop="80dp"
             android:orientation="vertical"
             android:visibility="gone">
 
             <ImageView
-            android:layout_height="112dp"
-            android:layout_width="112dp"
-            android:src="@drawable/no_search_results"/>
+            android:layout_height="160dp"
+            android:layout_width="160dp"
+            android:layout_gravity="center_horizontal"
+            android:src="@drawable/empty_search_results"/>
 
             <TextView
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
+            android:paddingTop="24dp"
             android:textSize="18sp"
             android:text="@string/search_settings_no_results"
             android:gravity="center"/>
diff --git a/res/layout/settings_entity_header.xml b/res/layout/settings_entity_header.xml
new file mode 100644
index 0000000..ce81b49
--- /dev/null
+++ b/res/layout/settings_entity_header.xml
@@ -0,0 +1,110 @@
+<?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.
+  -->
+
+<!-- Entity header -->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/entity_header"
+    style="@style/EntityHeader"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="0dp"
+    android:paddingTop="24dp"
+    android:paddingBottom="24dp">
+
+    <ImageView
+        android:id="@+id/entity_header_icon"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:scaleType="fitXY"
+        android:layout_gravity="center_horizontal"
+        android:antialias="true" />
+
+    <LinearLayout
+        android:id="@+id/entity_header_links"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentEnd="true"
+        android:orientation="vertical">
+
+        <ImageButton
+            android:id="@android:id/button1"
+            style="?android:attr/actionOverflowButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_weight="1"
+            android:layout_height="0dp"
+            android:minWidth="@dimen/min_tap_target_size"
+            android:src="@drawable/ic_settings_24dp"
+            android:tint="?android:attr/colorAccent" />
+
+        <ImageButton
+            android:id="@android:id/button2"
+            style="?android:attr/actionOverflowButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_weight="1"
+            android:layout_height="0dp"
+            android:minWidth="@dimen/min_tap_target_size"
+            android:src="@null"
+            android:tint="?android:attr/colorAccent" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_toEndOf="@id/entity_header_icon"
+        android:layout_toStartOf="@id/entity_header_links"
+        android:paddingStart="24dp"
+        android:paddingEnd="24dp"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/entity_header_title"
+            style="@style/TextAppearance.EntityHeaderTitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:singleLine="false"
+            android:ellipsize="marquee"
+            android:gravity="start"
+            android:textDirection="locale"
+            android:paddingTop="8dp" />
+
+        <TextView
+            android:id="@+id/install_type"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="start"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary" />
+
+        <TextView
+            android:id="@+id/entity_header_summary"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="start"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary" />
+
+    </LinearLayout>
+
+</RelativeLayout>
diff --git a/res/values-mcc262-mnc02/strings.xml b/res/values-mcc262-mnc02/strings.xml
new file mode 100644
index 0000000..17f9272
--- /dev/null
+++ b/res/values-mcc262-mnc02/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
+    <string name="wifi_calling_off_explanation_2">\n\nYou can\u2019t make emergency calls through Wi-Fi calling. If you try to make an emergency call, your device will automatically use the mobile network. Emergency calls can only be made in areas with mobile network coverage.</string>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6b12237..038b184 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1091,6 +1091,9 @@
     <!-- Message shown in screen lock picker while setting up the backup/fallback screen lock method for fingerprint. Users can choose to use this method to unlock the screen instead of fingerprint, or when fingerprint is not accepted. [CHAR LIMIT=80] [BACKUP_MESSAGE_ID=2799884038398627882] -->
     <string name="lock_settings_picker_fingerprint_message">Choose your backup screen lock method</string>
 
+    <!-- Label for button in screen lock settings, allowing users to choose other types of screen locks. [CHAR LIMIT=40] -->
+    <string name="setup_lock_settings_options_button_label">Screen lock options</string>
+
     <!--  Main Security lock settings --><skip />
     <!--  Title for PreferenceScreen to launch picker for security method when there is none [CHAR LIMIT=22] -->
     <string name="unlock_set_unlock_launch_picker_title">Screen lock</string>
@@ -2124,6 +2127,8 @@
     </string-array>
     <!-- Wi-Fi Calling settings. Text displayed when Wi-Fi Calling is off -->
     <string name="wifi_calling_off_explanation">When Wi-Fi calling is on, your phone can route calls via Wi-Fi networks or your carrier\u2019s network, depending on your preference and which signal is stronger. Before turning on this feature, check with your carrier regarding fees and other details.</string>
+    <!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
+    <string name="wifi_calling_off_explanation_2"></string>
     <!-- Title of a preference for updating emergency address [CHAR LIMIT=40] -->
     <string name="emergency_address_title">Update Emergency Address</string>
     <!-- Summary of Update Emergency Address preference, explaining usage of emergency address [CHAR LIMIT=NONE] -->
@@ -4720,6 +4725,8 @@
 
     <!-- Description for battery usage time for an app, i.e. Used for 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
     <string name="battery_used_for">Used for <xliff:g id="time">^1</xliff:g></string>
+    <!-- Description for battery screen usage time for an app, i.e. Screen usage 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
+    <string name="battery_screen_usage">Screen usage <xliff:g id="time">^1</xliff:g></string>
     <!-- Description for battery usage info for an app, i.e. 60% used by facebook. [CHAR LIMIT=60] -->
     <string name="battery_used_by"><xliff:g id="percent">%1$s</xliff:g> used by <xliff:g id="app">%2$s</xliff:g></string>
     <!-- Description for percentage of battery usage for an app, i.e. Screen: 30% of overall battery. [CHAR LIMIT=60] -->
@@ -6273,12 +6280,19 @@
 
     <!-- Title for setting tile leading to network and Internet settings [CHAR LIMIT=40]-->
     <string name="network_dashboard_title">Network &amp; Internet</string>
-    <!-- Summary for Network and Internet settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
-    <string name="network_dashboard_summary">Wi-Fi, mobile, data usage, hotspot</string>
+    <!-- Summary for Network and Internet settings, explaining it contains mobile network setting [CHAR LIMIT=NONE]-->
+    <string name="network_dashboard_summary_mobile">mobile</string>
+    <!-- Summary for Network and Internet settings, explaining it contains network data usage setting [CHAR LIMIT=NONE]-->
+    <string name="network_dashboard_summary_data_usage">data usage</string>
+    <!-- Summary for Network and Internet settings, explaining it contains hotspot (tethering) setting [CHAR LIMIT=NONE]-->
+    <string name="network_dashboard_summary_hotspot">hotspot</string>
+
     <!-- Title for setting tile leading to Connected devices settings [CHAR LIMIT=40]-->
     <string name="connected_devices_dashboard_title">Connected devices</string>
     <!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
     <string name="connected_devices_dashboard_summary">Bluetooth, Cast, NFC</string>
+    <!-- Summary for Connected devices settings, explaning a few important settings under it [CHAR LIMIT=NONE]-->
+    <string name="connected_devices_dashboard_no_nfc_summary">Bluetooth, Cast</string>
     <!-- Title for setting tile leading to Apps & Notification settings [CHAR LIMIT=40]-->
     <string name="app_and_notification_dashboard_title">Apps &amp; notifications</string>
     <!-- Summary for Apps & Notification settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
@@ -8651,10 +8665,6 @@
     <!-- Preference label for the Files storage section. [CHAR LIMIT=50] -->
     <string name="storage_files">Files</string>
 
-    <!-- Main settings screen item's title to go into the storage settings screen [CHAR LIMIT=25] -->
-    <string name="storage_settings_2" product="tablet">Tablet storage</string>
-    <string name="storage_settings_2" product="default">Phone storage</string>
-
     <!-- Summary of a single storage volume used space. [CHAR LIMIT=24] -->
     <string name="storage_size_large_alternate"><xliff:g id="number" example="128">^1</xliff:g><small> <xliff:g id="unit" example="KB">^2</xliff:g></small></string>
     <!-- Summary of a single storage volume total space. [CHAR LIMIT=48]-->
diff --git a/res/xml/account_type_settings.xml b/res/xml/account_type_settings.xml
index ab997a5..0ba961f 100644
--- a/res/xml/account_type_settings.xml
+++ b/res/xml/account_type_settings.xml
@@ -19,11 +19,11 @@
         android:title="@string/account_settings_title"
         settings:keywords="@string/keywords_accounts">
 
-    <Preference
-      android:key="account_header"
-      android:layout="@layout/account_header"
-      android:selectable="false"
-      android:order="-10000"/>
+    <com.android.settings.applications.LayoutPreference
+        android:key="account_header"
+        android:layout="@layout/settings_entity_header"
+        android:selectable="false"
+        android:order="-10000"/>
 
     <Preference
         android:key="account_sync"
diff --git a/res/xml/app_list_disclosure_settings.xml b/res/xml/app_list_disclosure_settings.xml
index 2aae95e..1daf15d 100644
--- a/res/xml/app_list_disclosure_settings.xml
+++ b/res/xml/app_list_disclosure_settings.xml
@@ -21,7 +21,7 @@
     <PreferenceCategory
             android:key="dashboard_tile_placeholder"/>
 
-    <com.android.settings.widget.FooterPreference
+    <com.android.settingslib.widget.FooterPreference
             android:title="@string/enterprise_privacy_apps_count_estimation_info"
             android:selectable="false"/>
 </PreferenceScreen>
diff --git a/res/xml/assist_gesture_settings.xml b/res/xml/assist_gesture_settings.xml
index 2cc5189..0dbf9c7 100644
--- a/res/xml/assist_gesture_settings.xml
+++ b/res/xml/assist_gesture_settings.xml
@@ -32,7 +32,7 @@
     <com.android.settings.widget.SeekBarPreference
         android:key="gesture_assist_sensitivity"
         android:title="@string/assist_gesture_sensitivity_title"
-        android:defaultValue="2"
-        android:max="4" />
+        android:defaultValue="5"
+        android:max="10" />
 
 </PreferenceScreen>
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index bed3aa6..718bb23 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -39,7 +39,7 @@
         android:summary="@string/summary_placeholder"/>
 
     <SwitchPreference
-        android:key="gesture_swipe_down_fingerprint"
+        android:key="gesture_swipe_down_fingerprint_notifications"
         android:title="@string/fingerprint_swipe_for_notifications_title"
         android:summary="@string/fingerprint_swipe_for_notifications_summary"/>
 
diff --git a/res/xml/data_usage_metered_prefs.xml b/res/xml/data_usage_metered_prefs.xml
index a1f3110..aca87fb 100644
--- a/res/xml/data_usage_metered_prefs.xml
+++ b/res/xml/data_usage_metered_prefs.xml
@@ -35,7 +35,7 @@
 
     </PreferenceCategory>
 
-    <com.android.settings.widget.FooterPreference
+    <com.android.settingslib.widget.FooterPreference
         android:title="@string/data_usage_metered_body"
         android:selectable="false" />
 
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index 1eea8dd..273b80d 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -412,12 +412,12 @@
             android:entries="@array/app_process_limit_entries"
             android:entryValues="@array/app_process_limit_values" />
 
-        <!-- hiding for now.
+
         <Preference
                 android:key="background_check"
                 android:fragment="com.android.settings.applications.BackgroundCheckSummary"
                 android:title="@string/background_check_pref" />
-        -->
+
 
         <SwitchPreference
             android:key="show_all_anrs"
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index b3b6692..749b87d 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -97,12 +97,12 @@
         android:title="@string/lift_to_wake_title" />
 
     <Preference
-        android:key="gesture_double_tap_screen"
+        android:key="gesture_double_tap_screen_display_summary"
         android:title="@string/ambient_display_title"
         android:fragment="com.android.settings.gestures.DoubleTapScreenSettings" />
 
     <Preference
-        android:key="gesture_pick_up"
+        android:key="gesture_pick_up_display_summary"
         android:title="@string/ambient_display_pickup_title"
         android:fragment="com.android.settings.gestures.PickupGestureSettings" />
 
diff --git a/res/xml/installed_app_details_ia.xml b/res/xml/installed_app_details.xml
similarity index 97%
rename from res/xml/installed_app_details_ia.xml
rename to res/xml/installed_app_details.xml
index 5f8e866..12f0442 100644
--- a/res/xml/installed_app_details_ia.xml
+++ b/res/xml/installed_app_details.xml
@@ -19,7 +19,7 @@
 
     <com.android.settings.applications.LayoutPreference
         android:key="header_view"
-        android:layout="@layout/app_details"
+        android:layout="@layout/settings_entity_header"
         android:selectable="false"
         android:order="-10000"/>
 
diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml
index 330ef9e..8c83767 100644
--- a/res/xml/language_and_input.xml
+++ b/res/xml/language_and_input.xml
@@ -66,22 +66,22 @@
         android:title="@string/gesture_preference_title">
 
         <Preference
-            android:key="gesture_assist"
+            android:key="gesture_assist_input_summary"
             android:title="@string/assist_gesture_title"
             android:fragment="com.android.settings.gestures.AssistGestureSettings"/>
 
         <Preference
-            android:key="gesture_swipe_down_fingerprint"
+            android:key="gesture_swipe_down_fingerprint_input_summary"
             android:title="@string/fingerprint_swipe_for_notifications_title"
             android:fragment="com.android.settings.gestures.SwipeToNotificationSettings"/>
 
         <Preference
-            android:key="gesture_double_tap_screen"
+            android:key="gesture_double_tap_screen_input_summary"
             android:title="@string/ambient_display_title"
             android:fragment="com.android.settings.gestures.DoubleTapScreenSettings"/>
 
         <Preference
-            android:key="gesture_pick_up"
+            android:key="gesture_pick_up_input_summary"
             android:title="@string/ambient_display_pickup_title"
             android:fragment="com.android.settings.gestures.PickupGestureSettings"/>
 
@@ -91,12 +91,12 @@
             android:fragment="com.android.settings.gestures.CameraLiftTriggerSettings"/>
 
         <Preference
-            android:key="gesture_double_tap_power"
+            android:key="gesture_double_tap_power_input_summary"
             android:title="@string/double_tap_power_for_camera_title"
             android:fragment="com.android.settings.gestures.DoubleTapPowerSettings"/>
 
         <Preference
-            android:key="gesture_double_twist"
+            android:key="gesture_double_twist_input_summary"
             android:title="@string/double_twist_for_camera_mode_title"
             android:fragment="com.android.settings.gestures.DoubleTwistGestureSettings"/>
 
@@ -110,7 +110,7 @@
             android:dialogTitle="@string/pointer_speed"/>
 
         <Preference
-            android:key="tts_settings"
+            android:key="tts_settings_summary"
             android:title="@string/tts_settings_title"
             android:fragment="com.android.settings.tts.TextToSpeechSettings"/>
 
diff --git a/res/xml/manage_assist.xml b/res/xml/manage_assist.xml
index eadf45f..a96fb6b 100644
--- a/res/xml/manage_assist.xml
+++ b/res/xml/manage_assist.xml
@@ -26,7 +26,7 @@
         android:fragment="com.android.settings.applications.assist.DefaultAssistPicker"/>
 
     <Preference
-        android:key="gesture_assist"
+        android:key="gesture_assist_application"
         android:title="@string/assist_gesture_title"
         android:fragment="com.android.settings.gestures.AssistGestureSettings"/>
 
diff --git a/res/xml/power_usage_detail_ia.xml b/res/xml/power_usage_detail.xml
similarity index 97%
rename from res/xml/power_usage_detail_ia.xml
rename to res/xml/power_usage_detail.xml
index 39e6c38..b7865d2 100644
--- a/res/xml/power_usage_detail_ia.xml
+++ b/res/xml/power_usage_detail.xml
@@ -19,7 +19,7 @@
 
     <com.android.settings.applications.LayoutPreference
         android:key="header_view"
-        android:layout="@layout/app_details"
+        android:layout="@layout/settings_entity_header"
         android:selectable="false"
         android:order="-10000"/>
 
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 336110d..26503e4 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -57,6 +57,8 @@
     public static final String KEY_DISPLAY_SIZE = "screen_zoom";
 
     private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
+    private static final String KEY_PICK_UP = "gesture_pick_up_display_summary";
+    private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen_display_summary";
 
     @Override
     public int getMetricsCategory() {
@@ -105,9 +107,10 @@
         controllers.add(new NightModePreferenceController(context));
         controllers.add(new ScreenSaverPreferenceController(context));
         controllers.add(new PickupGesturePreferenceController(
-                context, lifecycle, ambientDisplayConfig, UserHandle.myUserId()));
+                context, lifecycle, ambientDisplayConfig, UserHandle.myUserId(), KEY_PICK_UP));
         controllers.add(new DoubleTapScreenPreferenceController(
-                context, lifecycle, ambientDisplayConfig, UserHandle.myUserId()));
+                context, lifecycle, ambientDisplayConfig, UserHandle.myUserId(),
+                KEY_DOUBLE_TAP_SCREEN));
         controllers.add(new TapToWakePreferenceController(context));
         controllers.add(new TimeoutPreferenceController(context, KEY_SCREEN_TIMEOUT));
         controllers.add(new VrDisplayPreferenceController(context));
diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java
index 78f9de6..cb661ed 100644
--- a/src/com/android/settings/WifiCallingSettings.java
+++ b/src/com/android/settings/WifiCallingSettings.java
@@ -152,7 +152,9 @@
 
         mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
         setEmptyView(mEmptyView);
-        mEmptyView.setText(R.string.wifi_calling_off_explanation);
+        String emptyViewText = activity.getString(R.string.wifi_calling_off_explanation)
+                + activity.getString(R.string.wifi_calling_off_explanation_2);
+        mEmptyView.setText(emptyViewText);
     }
 
     @Override
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index 65959b4..5aee39f 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -22,9 +22,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.support.annotation.VisibleForTesting;
-import android.support.v7.preference.Preference;
-
 import android.support.v7.preference.PreferenceScreen;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.Utils;
@@ -45,13 +44,12 @@
     public static final String KEY_ACCOUNT_TYPE = "account_type";
     public static final String KEY_ACCOUNT_LABEL = "account_label";
     public static final String KEY_ACCOUNT_TITLE_RES = "account_title_res";
-    public static final String KEY_ACCOUNT_HEADER = "account_header";
     public static final String KEY_USER_HANDLE = "user_handle";
 
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    @VisibleForTesting
     Account mAccount;
     private String mAccountLabel;
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    @VisibleForTesting
     String mAccountType;
     private AccountSyncPreferenceController mAccountSynController;
     private RemoveAccountPreferenceController mRemoveAccountController;
@@ -110,6 +108,8 @@
         controllers.add(mAccountSynController);
         mRemoveAccountController = new RemoveAccountPreferenceController(context, this);
         controllers.add(mRemoveAccountController);
+        controllers.add(new AccountHeaderPreferenceController(
+                context, getActivity(), this, getArguments()));
         return controllers;
     }
 
@@ -127,8 +127,6 @@
 
     @VisibleForTesting
     void updateUi() {
-        final Preference headerPreference = findPreference(KEY_ACCOUNT_HEADER);
-        headerPreference.setTitle(mAccount.name);
         final Context context = getContext();
         UserHandle userHandle = null;
         Bundle args = getArguments();
@@ -136,14 +134,12 @@
             userHandle = args.getParcelable(KEY_USER_HANDLE);
         }
         final AuthenticatorHelper helper = new AuthenticatorHelper(context, userHandle, null);
-        headerPreference.setIcon(helper.getDrawableForType(context, mAccountType));
         final AccountTypePreferenceLoader accountTypePreferenceLoader =
-            new AccountTypePreferenceLoader(this, helper, userHandle);
-        PreferenceScreen prefs =
-            accountTypePreferenceLoader.addPreferencesForType(mAccountType, getPreferenceScreen());
+                new AccountTypePreferenceLoader(this, helper, userHandle);
+        PreferenceScreen prefs = accountTypePreferenceLoader.addPreferencesForType(
+                mAccountType, getPreferenceScreen());
         if (prefs != null) {
             accountTypePreferenceLoader.updatePreferenceIntents(prefs, mAccountType, mAccount);
         }
     }
-
 }
\ No newline at end of file
diff --git a/src/com/android/settings/accounts/AccountHeaderPreferenceController.java b/src/com/android/settings/accounts/AccountHeaderPreferenceController.java
new file mode 100644
index 0000000..4730e9e
--- /dev/null
+++ b/src/com/android/settings/accounts/AccountHeaderPreferenceController.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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.accounts;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.accounts.AuthenticatorHelper;
+
+import static com.android.settings.accounts.AccountDetailDashboardFragment.KEY_ACCOUNT;
+import static com.android.settings.accounts.AccountDetailDashboardFragment.KEY_USER_HANDLE;
+
+public class AccountHeaderPreferenceController extends PreferenceController {
+
+    private static final String KEY_ACCOUNT_HEADER = "account_header";
+
+    private final Activity mActivity;
+    private final Fragment mHost;
+    private final Account mAccount;
+    private final UserHandle mUserHandle;
+
+    public AccountHeaderPreferenceController(Context context, Activity activity, Fragment host,
+            Bundle args) {
+        super(context);
+        mActivity = activity;
+        mHost = host;
+        if (args != null && args.containsKey(KEY_ACCOUNT)) {
+            mAccount = args.getParcelable(KEY_ACCOUNT);
+        } else {
+            mAccount = null;
+        }
+
+        if (args != null && args.containsKey(KEY_USER_HANDLE)) {
+            mUserHandle = args.getParcelable(KEY_USER_HANDLE);
+        } else {
+            mUserHandle = null;
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mAccount != null && mUserHandle != null;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_ACCOUNT_HEADER;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        final LayoutPreference headerPreference =
+                (LayoutPreference) screen.findPreference(KEY_ACCOUNT_HEADER);
+
+        final AuthenticatorHelper helper = new AuthenticatorHelper(mContext, mUserHandle, null);
+
+        EntityHeaderController
+                .newInstance(mActivity, mHost, headerPreference.findViewById(R.id.entity_header))
+                .setLabel(mAccount.name)
+                .setIcon(helper.getDrawableForType(mContext, mAccount.type))
+                .done(mActivity, true /* rebindButtons */);
+    }
+}
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index 2801f04..b0403b8 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -123,9 +123,9 @@
          */
         public boolean pendingRemoval;
         /**
-         * The map from account name to account preference
+         * The map from account key to account preference
          */
-        public ArrayMap<CharSequence, AccountTypePreference> accountPreferences = new ArrayMap<>();
+        public ArrayMap<String, AccountTypePreference> accountPreferences = new ArrayMap<>();
     }
 
     public AccountPreferenceController(Context context, SettingsPreferenceFragment parent,
@@ -299,6 +299,11 @@
         final ProfileData data = mProfiles.get(userInfo.id);
         if (data != null) {
             data.pendingRemoval = false;
+            if (userInfo.isEnabled()) {
+                // recreate the authentication helper to refresh the list of enabled accounts
+                data.authenticatorHelper =
+                    new AuthenticatorHelper(mContext, userInfo.getUserHandle(), this);
+            }
             return;
         }
         final Context context = mContext;
@@ -426,7 +431,7 @@
             return;
         }
         if (profileData.userInfo.isEnabled()) {
-            final ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove =
+            final ArrayMap<String, AccountTypePreference> preferenceToRemove =
                     new ArrayMap<>(profileData.accountPreferences);
             final ArrayList<AccountTypePreference> preferences = getAccountTypePreferences(
                     profileData.authenticatorHelper, profileData.userInfo.getUserHandle(),
@@ -435,18 +440,19 @@
             for (int i = 0; i < count; i++) {
                 final AccountTypePreference preference = preferences.get(i);
                 preference.setOrder(i);
-                if (!profileData.accountPreferences.containsValue(preference)) {
-                    profileData.preferenceGroup.addPreference(preferences.get(i));
-                    profileData.accountPreferences.put(preference.getTitle(), preference);
+                final String key = preference.getKey();
+                if (!profileData.accountPreferences.containsKey(key)) {
+                    profileData.preferenceGroup.addPreference(preference);
+                    profileData.accountPreferences.put(key, preference);
                 }
             }
             if (profileData.addAccountPreference != null) {
                 profileData.preferenceGroup.addPreference(profileData.addAccountPreference);
             }
-            for (CharSequence name : preferenceToRemove.keySet()) {
+            for (String key : preferenceToRemove.keySet()) {
                 profileData.preferenceGroup.removePreference(
-                    profileData.accountPreferences.get(name));
-                profileData.accountPreferences.remove(name);
+                    profileData.accountPreferences.get(key));
+                profileData.accountPreferences.remove(key);
             }
         } else {
             profileData.preferenceGroup.removeAll();
@@ -471,8 +477,7 @@
     }
 
     private ArrayList<AccountTypePreference> getAccountTypePreferences(AuthenticatorHelper helper,
-            UserHandle userHandle,
-            ArrayMap<CharSequence, AccountTypePreference> preferenceToRemove) {
+            UserHandle userHandle, ArrayMap<String, AccountTypePreference> preferenceToRemove) {
         final String[] accountTypes = helper.getEnabledAccountTypes();
         final ArrayList<AccountTypePreference> accountTypePreferences =
                 new ArrayList<>(accountTypes.length);
@@ -497,7 +502,8 @@
 
             // Add a preference row for each individual account
             for (Account account : accounts) {
-                final AccountTypePreference preference = preferenceToRemove.remove(account.name);
+                final AccountTypePreference preference =
+                        preferenceToRemove.remove(AccountTypePreference.buildKey(account));
                 if (preference != null) {
                     accountTypePreferences.add(preference);
                     continue;
@@ -521,7 +527,7 @@
                 fragmentArguments.putParcelable(EXTRA_USER, userHandle);
                 accountTypePreferences.add(new AccountTypePreference(
                     prefContext, mMetricsFeatureProvider.getMetricsCategory(mParent),
-                    account.name, titleResPackageName, titleResId, label,
+                    account, titleResPackageName, titleResId, label,
                     AccountDetailDashboardFragment.class.getName(), fragmentArguments, icon));
             }
             helper.preloadDrawableForType(mContext, accountType);
diff --git a/src/com/android/settings/accounts/AccountTypePreference.java b/src/com/android/settings/accounts/AccountTypePreference.java
index 0abfb50..4f92829 100644
--- a/src/com/android/settings/accounts/AccountTypePreference.java
+++ b/src/com/android/settings/accounts/AccountTypePreference.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.accounts;
 
+import android.accounts.Account;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -67,18 +68,11 @@
 
     private final int mMetricsCategory;
 
-    public AccountTypePreference(Context context, int metricsCategory, CharSequence title,
-            String titleResPackageName, int titleResId, String fragment, Bundle fragmentArguments,
-            Drawable icon) {
-        this(context, metricsCategory, title, titleResPackageName, titleResId, null, fragment,
-                fragmentArguments, icon);
-    }
-
-    public AccountTypePreference(Context context, int metricsCategory, CharSequence title,
+    public AccountTypePreference(Context context, int metricsCategory, Account account,
             String titleResPackageName, int titleResId, CharSequence summary, String fragment,
             Bundle fragmentArguments, Drawable icon) {
         super(context);
-        mTitle = title;
+        mTitle = account.name;
         mTitleResPackageName = titleResPackageName;
         mTitleResId = titleResId;
         mSummary = summary;
@@ -87,7 +81,8 @@
         mMetricsCategory = metricsCategory;
         setWidgetLayoutResource(R.layout.account_type_preference);
 
-        setTitle(title);
+        setKey(buildKey(account));
+        setTitle(mTitle);
         setSummary(summary);
         setIcon(icon);
 
@@ -115,6 +110,13 @@
         return false;
     }
 
+    /**
+     * Build a unique preference key based on account.
+     */
+    public static String buildKey(Account account) {
+        return String.valueOf(account.hashCode());
+    }
+
     public CharSequence getTitle() {
         return mTitle;
     }
@@ -122,5 +124,4 @@
     public CharSequence getSummary() {
         return mSummary;
     }
-
 }
diff --git a/src/com/android/settings/applications/AppInfoWithHeader.java b/src/com/android/settings/applications/AppInfoWithHeader.java
index 6b1ef67..bbcec3c 100644
--- a/src/com/android/settings/applications/AppInfoWithHeader.java
+++ b/src/com/android/settings/applications/AppInfoWithHeader.java
@@ -16,17 +16,17 @@
 
 package com.android.settings.applications;
 
-import static com.android.settings.applications.AppHeaderController.ActionType;
-
 import android.app.Activity;
 import android.os.Bundle;
 import android.support.v7.preference.Preference;
 import android.util.IconDrawableFactory;
 import android.util.Log;
 
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.applications.AppUtils;
 
+import static com.android.settings.widget.EntityHeaderController.ActionType;
+
 public abstract class AppInfoWithHeader extends AppInfoBase {
 
     private boolean mCreated;
@@ -41,9 +41,8 @@
         mCreated = true;
         if (mPackageInfo == null) return;
         final Activity activity = getActivity();
-        final Preference pref = FeatureFactory.getFactory(activity)
-                .getApplicationFeatureProvider(activity)
-                .newAppHeaderController(this, null /* appHeader */)
+        final Preference pref = EntityHeaderController
+                .newInstance(activity, this, null /* header */)
                 .setIcon(IconDrawableFactory.newInstance(activity)
                         .getBadgedIcon(mPackageInfo.applicationInfo))
                 .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
diff --git a/src/com/android/settings/applications/AppOpsDetails.java b/src/com/android/settings/applications/AppOpsDetails.java
index e6c040b..b488af6 100644
--- a/src/com/android/settings/applications/AppOpsDetails.java
+++ b/src/com/android/settings/applications/AppOpsDetails.java
@@ -28,6 +28,7 @@
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -43,6 +44,7 @@
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
+import com.android.settings.widget.EntityHeaderController;
 
 import java.util.List;
 
@@ -64,7 +66,7 @@
         final View appSnippet = mRootView.findViewById(R.id.app_snippet);
         CharSequence label = mPm.getApplicationLabel(pkgInfo.applicationInfo);
         Drawable icon = mPm.getApplicationIcon(pkgInfo.applicationInfo);
-        InstalledAppDetails.setupAppSnippet(appSnippet, label, icon,
+        setupAppSnippet(appSnippet, label, icon,
                 pkgInfo != null ? pkgInfo.versionName : null);
     }
 
@@ -191,4 +193,30 @@
             setIntentAndFinish(true, true);
         }
     }
+
+    /**
+     * @deprecated app info pages should use {@link EntityHeaderController} to show the app header.
+     */
+    void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon,
+            CharSequence versionName) {
+        LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views,
+                appSnippet.findViewById(android.R.id.widget_frame));
+
+        ImageView iconView = appSnippet.findViewById(android.R.id.icon);
+        iconView.setImageDrawable(icon);
+        // Set application name.
+        TextView labelView = appSnippet.findViewById(android.R.id.title);
+        labelView.setText(label);
+        // Version number of application
+        TextView appVersion = appSnippet.findViewById(R.id.widget_text1);
+
+        if (!TextUtils.isEmpty(versionName)) {
+            appVersion.setSelected(true);
+            appVersion.setVisibility(View.VISIBLE);
+            appVersion.setText(appSnippet.getContext().getString(R.string.version_text,
+                    String.valueOf(versionName)));
+        } else {
+            appVersion.setVisibility(View.INVISIBLE);
+        }
+    }
 }
diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java
index 3266fe0..bff93b8e 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProvider.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java
@@ -28,14 +28,8 @@
 public interface ApplicationFeatureProvider {
 
     /**
-     * Returns a new {@link AppHeaderController} instance to customize app header.
-     */
-    AppHeaderController newAppHeaderController(Fragment fragment, View appHeader);
-
-    /**
-     *
-     *  Returns a new {@link InstantAppButtonsController} instance for showing buttons
-     *  only relevant to instant apps.
+     * Returns a new {@link InstantAppButtonsController} instance for showing buttons
+     * only relevant to instant apps.
      */
     InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
             View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate);
@@ -44,7 +38,7 @@
      * Calculates the total number of apps installed on the device via policy in the current user
      * and all its managed profiles.
      *
-     * @param async Whether to count asynchronously in a background thread
+     * @param async    Whether to count asynchronously in a background thread
      * @param callback The callback to invoke with the result
      */
     void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback);
@@ -61,10 +55,10 @@
      * Asynchronously calculates the total number of apps installed in the current user and all its
      * managed profiles that have been granted one or more of the given permissions by the admin.
      *
-     * @param permissions Only consider apps that have been granted one or more of these permissions
-     *        by the admin, either at run-time or install-time
-     * @param async Whether to count asynchronously in a background thread
-     * @param callback The callback to invoke with the result
+     * @param permissions Only consider apps that have been granted one or more of these
+     *                    permissions by the admin, either at run-time or install-time
+     * @param async       Whether to count asynchronously in a background thread
+     * @param callback    The callback to invoke with the result
      */
     void calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions, boolean async,
             NumberOfAppsCallback callback);
@@ -73,9 +67,9 @@
      * Asynchronously builds the list of apps installed in the current user and all its
      * managed profiles that have been granted one or more of the given permissions by the admin.
      *
-     * @param permissions Only consider apps that have been granted one or more of these permissions
-     *        by the admin, either at run-time or install-time
-     * @param callback The callback to invoke with the result
+     * @param permissions Only consider apps that have been granted one or more of these
+     *                    permissions by the admin, either at run-time or install-time
+     * @param callback    The callback to invoke with the result
      */
     void listAppsWithAdminGrantedPermissions(String[] permissions, ListOfAppsCallback callback);
 
@@ -85,10 +79,9 @@
      * given intent (e.g. open browser), even if the user has other apps installed that would also
      * be able to handle the intent.
      *
-     * @param userId ID of the user for which to find persistent preferred activities
-     * @param intent The intents for which to find persistent preferred activities
-     *
-     * @return the persistent preferred activites for the given intents, ordered first by user id,
+     * @param userId  ID of the user for which to find persistent preferred activities
+     * @param intents The intents for which to find persistent preferred activities
+     * @return the persistent preferred activities for the given intents, ordered first by user id,
      * then by package name
      */
     List<UserAppInfo> findPersistentPreferredActivities(@UserIdInt int userId, Intent[] intents);
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index a744792..36e0965 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -24,7 +24,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArraySet;
 import android.view.View;
@@ -54,11 +53,6 @@
     }
 
     @Override
-    public AppHeaderController newAppHeaderController(Fragment fragment, View appHeader) {
-        return new AppHeaderController(mContext, fragment, appHeader);
-    }
-
-    @Override
     public InstantAppButtonsController newInstantAppButtonsController(Fragment fragment,
             View view, InstantAppButtonsController.ShowDialogDelegate showDialogDelegate) {
         return new InstantAppButtonsController(mContext, fragment, view, showDialogDelegate);
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 6cc37e7..3021f75 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -37,7 +37,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
 import android.icu.text.ListFormatter;
 import android.net.INetworkStatsService;
 import android.net.INetworkStatsSession;
@@ -60,16 +59,12 @@
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
 import android.util.Log;
-import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.ViewGroup;
 import android.webkit.IWebViewUpdateService;
 import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.BatterySipper;
@@ -96,6 +91,7 @@
 import com.android.settings.notification.NotificationBackend;
 import com.android.settings.notification.NotificationBackend.AppRow;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.AppItem;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.applications.AppUtils;
@@ -349,7 +345,7 @@
         }
 
         setHasOptionsMenu(true);
-        addPreferencesFromResource(R.xml.installed_app_details_ia);
+        addPreferencesFromResource(R.xml.installed_app_details);
         addDynamicPrefs();
         if (Utils.isBandwidthControlEnabled()) {
             INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
@@ -411,14 +407,12 @@
         final Activity activity = getActivity();
         mHeader = (LayoutPreference) findPreference(KEY_HEADER);
         mActionButtons = (LayoutPreference) findPreference(KEY_ACTION_BUTTONS);
-        FeatureFactory.getFactory(activity)
-                .getApplicationFeatureProvider(activity)
-                .newAppHeaderController(this, mHeader.findViewById(R.id.app_snippet))
+        EntityHeaderController.newInstance(activity, this, mHeader.findViewById(R.id.entity_header))
                 .setPackageName(mPackageName)
-                .setButtonActions(AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
-                        AppHeaderController.ActionType.ACTION_NONE)
+                .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
+                        EntityHeaderController.ActionType.ACTION_NONE)
                 .styleActionBar(activity)
-                .bindAppHeaderButtons();
+                .bindHeaderButtons();
         prepareUninstallAndStop();
 
         mNotificationPreference = findPreference(KEY_NOTIFICATION);
@@ -584,15 +578,13 @@
 
     // Utility method to set application label and icon.
     private void setAppLabelAndIcon(PackageInfo pkgInfo) {
-        final View appSnippet = mHeader.findViewById(R.id.app_snippet);
+        final View appSnippet = mHeader.findViewById(R.id.entity_header);
         mState.ensureIcon(mAppEntry);
         final Activity activity = getActivity();
         final boolean isInstantApp = AppUtils.isInstant(mPackageInfo.applicationInfo);
         final CharSequence summary =
                 isInstantApp ? null : getString(Utils.getInstallationStatus(mAppEntry.info));
-        FeatureFactory.getFactory(activity)
-            .getApplicationFeatureProvider(activity)
-            .newAppHeaderController(this, appSnippet)
+        EntityHeaderController.newInstance(activity, this, appSnippet)
             .setLabel(mAppEntry)
             .setIcon(mAppEntry)
             .setSummary(summary)
@@ -1245,32 +1237,6 @@
         }
     }
 
-    /**
-     * @deprecated app info pages should use {@link AppHeaderController} to show the app header.
-     */
-    public static void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon,
-            CharSequence versionName) {
-        LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views,
-                (ViewGroup) appSnippet.findViewById(android.R.id.widget_frame));
-
-        ImageView iconView = (ImageView) appSnippet.findViewById(R.id.app_detail_icon);
-        iconView.setImageDrawable(icon);
-        // Set application name.
-        TextView labelView = (TextView) appSnippet.findViewById(R.id.app_detail_title);
-        labelView.setText(label);
-        // Version number of application
-        TextView appVersion = (TextView) appSnippet.findViewById(R.id.widget_text1);
-
-        if (!TextUtils.isEmpty(versionName)) {
-            appVersion.setSelected(true);
-            appVersion.setVisibility(View.VISIBLE);
-            appVersion.setText(appSnippet.getContext().getString(R.string.version_text,
-                    String.valueOf(versionName)));
-        } else {
-            appVersion.setVisibility(View.INVISIBLE);
-        }
-    }
-
     public static NetworkTemplate getTemplate(Context context) {
         if (DataUsageList.hasReadyMobileRadio(context)) {
             return NetworkTemplate.buildTemplateMobileWildcard();
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index b6b5861..6274374 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -506,10 +506,9 @@
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
+    public void onStart() {
+        super.onStart();
         updateView();
-        updateOptionsMenu();
         if (mApplications != null) {
             mApplications.resume(mSortOrder);
             mApplications.updateLoading();
@@ -527,16 +526,11 @@
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
+    public void onStop() {
+        super.onStop();
         if (mApplications != null) {
             mApplications.pause();
         }
-    }
-
-    @Override
-    public void onStop() {
-        super.onStop();
         mResetAppsHelper.stop();
     }
 
diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java
index 6c0928c..9f229af 100644
--- a/src/com/android/settings/applications/ProcessStatsDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsDetail.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.applications;
 
-import static com.android.settings.applications.AppHeaderController.ActionType;
-
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManager.RunningServiceInfo;
@@ -53,7 +51,7 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.SummaryPreference;
 import com.android.settings.applications.ProcStatsEntry.Service;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -61,6 +59,8 @@
 import java.util.HashMap;
 import java.util.List;
 
+import static com.android.settings.widget.EntityHeaderController.ActionType;
+
 public class ProcessStatsDetail extends SettingsPreferenceFragment {
 
     private static final String TAG = "ProcessStatsDetail";
@@ -126,9 +126,8 @@
             return;
         }
         final Activity activity = getActivity();
-        final Preference pref = FeatureFactory.getFactory(activity)
-            .getApplicationFeatureProvider(activity)
-            .newAppHeaderController(this, null /* appHeader */)
+        final Preference pref = EntityHeaderController
+                .newInstance(activity, this, null /* appHeader */)
             .setIcon(mApp.mUiTargetApp != null
                 ? IconDrawableFactory.newInstance(activity).getBadgedIcon(mApp.mUiTargetApp)
                 : new ColorDrawable(0))
diff --git a/src/com/android/settings/applications/assist/ManageAssist.java b/src/com/android/settings/applications/assist/ManageAssist.java
index e78e6e1..3b8edf3 100644
--- a/src/com/android/settings/applications/assist/ManageAssist.java
+++ b/src/com/android/settings/applications/assist/ManageAssist.java
@@ -38,6 +38,7 @@
 public class ManageAssist extends DashboardFragment {
 
     private static final String TAG = "ManageAssist";
+    private static final String KEY_ASSIST = "gesture_assist_application";
 
     @Override
     protected String getLogTag() {
@@ -71,7 +72,7 @@
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
         controllers.add(new DefaultAssistPreferenceController(context));
-        controllers.add(new AssistGesturePreferenceController(context, lifecycle));
+        controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST));
         controllers.add(new AssistContextPreferenceController(context, lifecycle));
         controllers.add(new AssistScreenshotPreferenceController(context, lifecycle));
         controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle));
@@ -94,5 +95,12 @@
                 public List<PreferenceController> getPreferenceControllers(Context context) {
                     return buildPreferenceControllers(context, null /* lifecycle */);
                 }
+
+                @Override
+                public List<String> getNonIndexableKeys(Context context) {
+                    List<String> keys = super.getNonIndexableKeys(context);
+                    keys.add(KEY_ASSIST);
+                    return keys;
+                }
             };
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
index 7eb7fdd..59496dd 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
@@ -17,6 +17,7 @@
 package com.android.settings.bluetooth;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
@@ -45,6 +46,12 @@
     private static final String NOTIFICATION_TAG_PBAP = "Phonebook Access" ;
     private static final String NOTIFICATION_TAG_MAP = "Message Access";
     private static final String NOTIFICATION_TAG_SAP = "SIM Access";
+    /* TODO: Consolidate this multiple defined but common channel ID with other
+     * handlers that declare and use the same channel ID */
+    private static final String BLUETOOTH_NOTIFICATION_CHANNEL =
+        "bluetooth_notification_channel";
+
+    private NotificationChannel mNotificationChannel = null;
 
     Context mContext;
     int mRequestType;
@@ -151,7 +158,16 @@
                                 deviceAlias, deviceAlias);
                         break;
                 }
-                Notification notification = new Notification.Builder(context)
+                NotificationManager notificationManager =
+                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+                if (mNotificationChannel == null) {
+                    mNotificationChannel = new NotificationChannel(BLUETOOTH_NOTIFICATION_CHANNEL,
+                            context.getString(R.string.bluetooth),
+                            NotificationManager.IMPORTANCE_HIGH);
+                    notificationManager.createNotificationChannel(mNotificationChannel);
+                }
+                Notification notification = new Notification.Builder(context,
+                        BLUETOOTH_NOTIFICATION_CHANNEL)
                         .setContentTitle(title)
                         .setTicker(message)
                         .setContentText(message)
@@ -169,9 +185,6 @@
 
                 notification.flags |= Notification.FLAG_NO_CLEAR; // Cannot be set with the builder.
 
-                NotificationManager notificationManager =
-                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-
                 notificationManager.notify(getNotificationTag(mRequestType), NOTIFICATION_ID,
                         notification);
             }
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index cc519a7..6b172c2 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -15,9 +15,11 @@
  */
 package com.android.settings.connecteddevice;
 
+import android.app.Activity;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.provider.SearchIndexableResource;
+import android.support.annotation.VisibleForTesting;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
@@ -25,6 +27,7 @@
 import com.android.settings.bluetooth.Utils;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.deviceinfo.UsbBackend;
 import com.android.settings.nfc.NfcPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
@@ -67,13 +70,50 @@
         lifecycle.addObserver(mUsbPrefController);
         controllers.add(mUsbPrefController);
         final BluetoothMasterSwitchPreferenceController bluetoothPreferenceController =
-            new BluetoothMasterSwitchPreferenceController(
-                context, Utils.getLocalBtManager(context));
+                new BluetoothMasterSwitchPreferenceController(
+                        context, Utils.getLocalBtManager(context));
         lifecycle.addObserver(bluetoothPreferenceController);
         controllers.add(bluetoothPreferenceController);
         return controllers;
     }
 
+    @VisibleForTesting
+    static class SummaryProvider implements SummaryLoader.SummaryProvider {
+
+        private final Context mContext;
+        private final SummaryLoader mSummaryLoader;
+        private final NfcPreferenceController mNfcPreferenceController;
+
+        public SummaryProvider(Context context, SummaryLoader summaryLoader) {
+            mContext = context;
+            mSummaryLoader = summaryLoader;
+            mNfcPreferenceController = new NfcPreferenceController(context);
+        }
+
+
+        @Override
+        public void setListening(boolean listening) {
+            if (listening) {
+                if (mNfcPreferenceController.isAvailable()) {
+                    mSummaryLoader.setSummary(this,
+                            mContext.getString(R.string.connected_devices_dashboard_summary));
+                } else {
+                    mSummaryLoader.setSummary(this, mContext.getString(
+                            R.string.connected_devices_dashboard_no_nfc_summary));
+                }
+            }
+        }
+    }
+
+    public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
+            = new SummaryLoader.SummaryProviderFactory() {
+        @Override
+        public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
+                SummaryLoader summaryLoader) {
+            return new SummaryProvider(activity, summaryLoader);
+        }
+    };
+
     /**
      * For Search.
      */
diff --git a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
index 69f174b..d1c7c7a 100644
--- a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
+++ b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
@@ -111,6 +111,9 @@
             mPreferenceKeySet.add(prefKey);
             return;
         }
+        // TODO: Remove count logging to save some resource.
+        mMetricsFeature.count(mContext, prefKey + "|" + value, 1);
+
         // Pref key exists in set, log it's change in metrics.
         mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
                 Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 3d2db96..a47e135 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -41,9 +41,8 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
-import com.android.settings.applications.AppHeaderController;
 import com.android.settings.applications.AppInfoBase;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.AppItem;
 import com.android.settingslib.net.ChartData;
 import com.android.settingslib.net.ChartDataLoader;
@@ -326,13 +325,12 @@
         final boolean showInfoButton = mAppItem.key > 0;
 
         final Activity activity = getActivity();
-        final Preference pref = FeatureFactory.getFactory(activity)
-                .getApplicationFeatureProvider(activity)
-                .newAppHeaderController(this, null /* appHeader */)
+        final Preference pref = EntityHeaderController
+                .newInstance(activity, this, null /* header */)
                 .setButtonActions(showInfoButton
-                                ? AppHeaderController.ActionType.ACTION_APP_INFO
-                                : AppHeaderController.ActionType.ACTION_NONE,
-                        AppHeaderController.ActionType.ACTION_NONE)
+                                ? EntityHeaderController.ActionType.ACTION_APP_INFO
+                                : EntityHeaderController.ActionType.ACTION_NONE,
+                        EntityHeaderController.ActionType.ACTION_NONE)
                 .setIcon(mIcon)
                 .setLabel(mLabel)
                 .setPackageName(pkg)
diff --git a/src/com/android/settings/development/TelephonyMonitorPreferenceController.java b/src/com/android/settings/development/TelephonyMonitorPreferenceController.java
index 135af7d..c21ccda 100644
--- a/src/com/android/settings/development/TelephonyMonitorPreferenceController.java
+++ b/src/com/android/settings/development/TelephonyMonitorPreferenceController.java
@@ -23,15 +23,27 @@
 import android.support.v7.preference.PreferenceScreen;
 import android.widget.Toast;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.R;
 
 public class TelephonyMonitorPreferenceController extends PreferenceController {
 
     private static final String KEY_TELEPHONY_MONITOR_SWITCH = "telephony_monitor_switch";
+    @VisibleForTesting
     static final String BUILD_TYPE = "ro.build.type";
+    @VisibleForTesting
     static final String PROPERTY_TELEPHONY_MONITOR = "persist.radio.enable_tel_mon";
 
+    @VisibleForTesting
+    static final String ENABLED_STATUS = "enabled";
+    @VisibleForTesting
+    static final String DISABLED_STATUS = "disabled";
+    @VisibleForTesting
+    static final String USER_ENABLED_STATUS = "user_enabled";
+    @VisibleForTesting
+    static final String USER_DISABLED_STATUS = "user_disabled";
+
     private SwitchPreference mPreference;
 
     public TelephonyMonitorPreferenceController(Context context) {
@@ -43,7 +55,7 @@
         super.displayPreference(screen);
         if (isAvailable()) {
             mPreference = (SwitchPreference) screen.findPreference(KEY_TELEPHONY_MONITOR_SWITCH);
-            mPreference.setChecked(SystemProperties.getBoolean(PROPERTY_TELEPHONY_MONITOR, false));
+            mPreference.setChecked(isTelephonyMonitorEnabled());
         }
     }
 
@@ -69,7 +81,7 @@
         if (KEY_TELEPHONY_MONITOR_SWITCH.equals(preference.getKey())) {
             final SwitchPreference switchPreference = (SwitchPreference) preference;
             SystemProperties.set(PROPERTY_TELEPHONY_MONITOR,
-                    switchPreference.isChecked() ? "true" : "false");
+                    switchPreference.isChecked() ? USER_ENABLED_STATUS : USER_DISABLED_STATUS);
             Toast.makeText(mContext, R.string.telephony_monitor_toast,
                     Toast.LENGTH_LONG).show();
             return true;
@@ -87,9 +99,14 @@
         if (!isAvailable()) {
             return false;
         }
-        final boolean enabled = SystemProperties.getBoolean(PROPERTY_TELEPHONY_MONITOR, false);
+        final boolean enabled = isTelephonyMonitorEnabled();
         mPreference.setChecked(enabled);
         return enabled;
     }
 
+    private boolean isTelephonyMonitorEnabled() {
+        final String tmStatus = SystemProperties.get(PROPERTY_TELEPHONY_MONITOR, DISABLED_STATUS);
+        return ENABLED_STATUS.equals(tmStatus) || USER_ENABLED_STATUS.equals(tmStatus);
+    }
+
 }
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
index b2bad3a..ce9ea9b 100644
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
@@ -235,7 +235,7 @@
             args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
             Intent intent = Utils.onBuildStartFragmentIntent(getActivity(),
                     StorageDashboardFragment.class.getName(), args, null,
-                    R.string.storage_settings_2, null, false, getMetricsCategory());
+                    R.string.storage_settings, null, false, getMetricsCategory());
             intent.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true);
             getActivity().startActivity(intent);
             finish();
@@ -280,7 +280,7 @@
 
                 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
                     startFragment(this, StorageDashboardFragment.class.getCanonicalName(),
-                            R.string.storage_settings_2, 0, args);
+                            R.string.storage_settings, 0, args);
                 } else {
                     // TODO: Go to the StorageDashboardFragment once it fully handles all of the
                     //       SD card cases and other private internal storage cases.
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
index b46fef7..2aad313 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -134,7 +134,7 @@
                     return;
                 }
             }
-            getFragmentManager().beginTransaction().remove(mSidecar).commit();
+            getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
             mSidecar = null;
             startActivityForResult(getEnrollingIntent(), ENROLLING);
         }
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
index a1f4017..26b3427 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -17,6 +17,7 @@
 package com.android.settings.fingerprint;
 
 import android.app.KeyguardManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.os.UserHandle;
@@ -27,13 +28,19 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SetupWizardUtils;
+import com.android.settings.password.ChooseLockGeneric;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
 import com.android.settings.password.SetupChooseLockGeneric;
 
 public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
 
     @Override
     protected Intent getChooseLockIntent() {
-        Intent intent = new Intent(this, SetupChooseLockGeneric.class);
+        Intent intent = new Intent(this, SetupChooseLockGeneric.class)
+                .putExtra(
+                        LockPatternUtils.PASSWORD_TYPE_KEY,
+                        DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+        intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
         SetupWizardUtils.copySetupExtras(getIntent(), intent);
         return intent;
     }
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 7a2e4c0..1822341 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -37,13 +37,12 @@
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
-import com.android.settings.applications.AppHeaderController;
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.enterprise.DevicePolicyManagerWrapper;
 import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 
@@ -180,14 +179,13 @@
 
     @VisibleForTesting
     void initHeader() {
-        final View appSnippet = mHeaderPreference.findViewById(R.id.app_snippet);
+        final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
         final Activity context = getActivity();
         final Bundle bundle = getArguments();
-        AppHeaderController controller = FeatureFactory.getFactory(context)
-                .getApplicationFeatureProvider(context)
-                .newAppHeaderController(this, appSnippet)
-                .setButtonActions(AppHeaderController.ActionType.ACTION_NONE,
-                        AppHeaderController.ActionType.ACTION_NONE);
+        EntityHeaderController controller = EntityHeaderController
+                .newInstance(context, this, appSnippet)
+                .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
+                        EntityHeaderController.ActionType.ACTION_NONE);
 
         if (mAppEntry == null) {
             controller.setLabel(bundle.getString(EXTRA_LABEL));
@@ -224,7 +222,7 @@
 
     @Override
     protected int getPreferenceScreenResId() {
-        return R.xml.power_usage_detail_ia;
+        return R.xml.power_usage_detail;
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 86cb203..849144a 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -22,7 +22,9 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
+import android.text.format.DateUtils;
 import android.util.Log;
+import android.util.SparseLongArray;
 
 import com.android.internal.os.BatterySipper;
 import com.android.settings.overlay.FeatureFactory;
@@ -115,25 +117,64 @@
     }
 
     /**
-     * Remove the {@link BatterySipper} that we should hide.
+     * Remove the {@link BatterySipper} that we should hide and smear the screen usage based on
+     * foreground activity time.
      *
      * @param sippers sipper list that need to check and remove
      * @return the total power of the hidden items of {@link BatterySipper}
+     * for proportional smearing
      */
     public double removeHiddenBatterySippers(List<BatterySipper> sippers) {
-        double totalPowerMah = 0;
+        double proportionalSmearPowerMah = 0;
+        BatterySipper screenSipper = null;
         for (int i = sippers.size() - 1; i >= 0; i--) {
             final BatterySipper sipper = sippers.get(i);
             if (shouldHideSipper(sipper)) {
                 sippers.remove(i);
-                if (sipper.drainType != BatterySipper.DrainType.OVERCOUNTED) {
-                    // Don't add it if it is overcounted
-                    totalPowerMah += sipper.totalPowerMah;
+                if (sipper.drainType != BatterySipper.DrainType.OVERCOUNTED
+                        && sipper.drainType != BatterySipper.DrainType.SCREEN
+                        && sipper.drainType != BatterySipper.DrainType.UNACCOUNTED) {
+                    // Don't add it if it is overcounted, unaccounted or screen
+                    proportionalSmearPowerMah += sipper.totalPowerMah;
                 }
             }
+
+            if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
+                screenSipper = sipper;
+            }
         }
 
-        return totalPowerMah;
+        smearScreenBatterySipper(sippers, screenSipper);
+
+        return proportionalSmearPowerMah;
+    }
+
+    /**
+     * Smear the screen on power usage among {@code sippers}, based on ratio of foreground activity
+     * time.
+     */
+    @VisibleForTesting
+    void smearScreenBatterySipper(List<BatterySipper> sippers, BatterySipper screenSipper) {
+        final long rawRealtimeMs = SystemClock.elapsedRealtime();
+        long totalActivityTimeMs = 0;
+        final SparseLongArray activityTimeArray = new SparseLongArray();
+        for (int i = 0, size = sippers.size(); i < size; i++) {
+            final BatteryStats.Uid uid = sippers.get(i).uidObj;
+            if (uid != null) {
+                final long timeMs = getForegroundActivityTotalTimeMs(uid, rawRealtimeMs);
+                activityTimeArray.put(uid.getUid(), timeMs);
+                totalActivityTimeMs += timeMs;
+            }
+        }
+
+        if (totalActivityTimeMs >= 10 * DateUtils.MINUTE_IN_MILLIS) {
+            final double screenPowerMah = screenSipper.totalPowerMah;
+            for (int i = 0, size = sippers.size(); i < size; i++) {
+                final BatterySipper sipper = sippers.get(i);
+                sipper.totalPowerMah += screenPowerMah * activityTimeArray.get(sipper.getUid(), 0)
+                        / totalActivityTimeMs;
+            }
+        }
     }
 
     /**
@@ -144,9 +185,7 @@
 
         return drainType == BatterySipper.DrainType.IDLE
                 || drainType == BatterySipper.DrainType.CELL
-                || drainType == BatterySipper.DrainType.WIFI
                 || drainType == BatterySipper.DrainType.SCREEN
-                || drainType == BatterySipper.DrainType.BLUETOOTH
                 || drainType == BatterySipper.DrainType.UNACCOUNTED
                 || drainType == BatterySipper.DrainType.OVERCOUNTED
                 || (sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP
@@ -186,5 +225,15 @@
         return mPackageManager == null;
     }
 
+    @VisibleForTesting
+    long getForegroundActivityTotalTimeMs(BatteryStats.Uid uid, long rawRealtimeMs) {
+        final BatteryStats.Timer timer = uid.getForegroundActivityTimer();
+        if (timer != null) {
+            return timer.getTotalTimeLocked(rawRealtimeMs, BatteryStats.STATS_SINCE_CHARGED);
+        }
+
+        return 0;
+    }
+
 }
 
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index 6f92b3d..6cb5c64 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -45,6 +45,11 @@
     }
 
     @Override
+    public Timer getAggregatedPartialWakelockTimer() {
+        return null;
+    }
+
+    @Override
     public ArrayMap<String, ? extends Timer> getSyncStats() {
         return null;
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
index aee55d6..060abdd 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -57,7 +57,7 @@
 
         mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext());
         mBatteryBroadcastReceiver.setBatteryChangedListener(() -> {
-            getLoaderManager().restartLoader(0, null, this);
+            restartBatteryStatsLoader();
         });
 
         getLoaderManager().initLoader(0, icicle, this);
@@ -95,6 +95,10 @@
         }
     }
 
+    protected void restartBatteryStatsLoader() {
+        getLoaderManager().restartLoader(0, Bundle.EMPTY, this);
+    }
+
     protected abstract void refreshUi();
 
     protected void updatePreference(BatteryHistoryPreference historyPref) {
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 23895e3..c27ea22 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -113,7 +113,8 @@
 
     @VisibleForTesting
     static final int ANOMALY_LOADER = 1;
-    private static final int BATTERY_ESTIMATE_LOADER = 2;
+    @VisibleForTesting
+    static final int BATTERY_ESTIMATE_LOADER = 2;
     private static final int MENU_STATS_TYPE = Menu.FIRST;
     @VisibleForTesting
     static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
@@ -182,6 +183,7 @@
                 @Override
                 public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
                     final Uri queryUri = mPowerFeatureProvider.getEnhancedBatteryPredictionUri();
+
                     return new CursorLoader(getContext(), queryUri, null, null, null, null);
                 }
 
@@ -228,10 +230,7 @@
         mAnomalySparseArray = new SparseArray<>();
 
         initFeatureProvider();
-        if (mPowerFeatureProvider != null) {
-            getLoaderManager().initLoader(BATTERY_ESTIMATE_LOADER, Bundle.EMPTY,
-                    mBatteryPredictionLoaderCallbacks);
-        }
+        initializeBatteryEstimateLoader();
     }
 
     @Override
@@ -377,7 +376,7 @@
                 item.setTitle(mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
                 metricsFeatureProvider.action(context,
                         MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE, mShowAllApps);
-                refreshUi();
+                restartBatteryStatsLoader();
                 return true;
             default:
                 return super.onOptionsItemSelected(item);
@@ -760,7 +759,7 @@
             final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), usageTimeMs,
                     false);
             preference.setSummary(
-                    TextUtils.expandTemplate(getText(R.string.battery_used_for), timeSequence));
+                    TextUtils.expandTemplate(getText(R.string.battery_screen_usage), timeSequence));
         }
     }
 
@@ -815,6 +814,15 @@
         }
     }
 
+    @VisibleForTesting
+    void initializeBatteryEstimateLoader() {
+        if (mPowerFeatureProvider != null
+                && mPowerFeatureProvider.isEnhancedBatteryPredictionEnabled(getContext())) {
+            getLoaderManager().initLoader(BATTERY_ESTIMATE_LOADER, Bundle.EMPTY,
+                    mBatteryPredictionLoaderCallbacks);
+        }
+    }
+
     private static List<BatterySipper> getFakeStats() {
         ArrayList<BatterySipper> stats = new ArrayList<>();
         float use = 5;
diff --git a/src/com/android/settings/gestures/AssistGesturePreferenceController.java b/src/com/android/settings/gestures/AssistGesturePreferenceController.java
index c59c328..3230804 100644
--- a/src/com/android/settings/gestures/AssistGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/AssistGesturePreferenceController.java
@@ -35,7 +35,7 @@
         implements OnPause, OnResume {
 
     private static final String PREF_KEY_VIDEO = "gesture_assist_video";
-    private static final String PREF_KEY_ASSIST_GESTURE = "gesture_assist";
+    private final String mAssistGesturePrefKey;
 
     private final AssistGestureFeatureProvider mFeatureProvider;
     private final SettingObserver mSettingObserver;
@@ -44,11 +44,12 @@
     private PreferenceScreen mScreen;
     private Preference mPreference;
 
-    public AssistGesturePreferenceController(Context context, Lifecycle lifecycle) {
+    public AssistGesturePreferenceController(Context context, Lifecycle lifecycle, String key) {
         super(context, lifecycle);
         mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider();
         mSettingObserver = new SettingObserver();
         mWasAvailable = isAvailable();
+        mAssistGesturePrefKey = key;
     }
 
     @Override
@@ -110,7 +111,7 @@
 
     @Override
     public String getPreferenceKey() {
-        return PREF_KEY_ASSIST_GESTURE;
+        return mAssistGesturePrefKey;
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/AssistGestureSettings.java b/src/com/android/settings/gestures/AssistGestureSettings.java
index 8874e3f..a080bec 100644
--- a/src/com/android/settings/gestures/AssistGestureSettings.java
+++ b/src/com/android/settings/gestures/AssistGestureSettings.java
@@ -34,6 +34,8 @@
 
     private static final String TAG = "AssistGesture";
 
+    private static final String KEY_ASSIST = "gesture_assist";
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
@@ -57,7 +59,7 @@
     private static List<PreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
-        controllers.add(new AssistGesturePreferenceController(context, lifecycle));
+        controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST));
         controllers.add(new AssistGestureSensitivityPreferenceController(context, lifecycle));
         return controllers;
     }
diff --git a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
index df7f734..d36ecc4 100644
--- a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
@@ -20,18 +20,16 @@
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
-import android.util.ArrayMap;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class DoubleTapPowerPreferenceController extends GesturePreferenceController {
 
     private static final String PREF_KEY_VIDEO = "gesture_double_tap_power_video";
-    private static final String PREF_KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
+    private final String mDoubleTapPowerKey;
 
-    public DoubleTapPowerPreferenceController(Context context, Lifecycle lifecycle) {
+    public DoubleTapPowerPreferenceController(Context context, Lifecycle lifecycle, String key) {
         super(context, lifecycle);
+        mDoubleTapPowerKey = key;
     }
 
     @Override
@@ -47,7 +45,7 @@
 
     @Override
     public String getPreferenceKey() {
-        return PREF_KEY_DOUBLE_TAP_POWER;
+        return mDoubleTapPowerKey;
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/DoubleTapPowerSettings.java b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
index 111281f..d38292d 100644
--- a/src/com/android/settings/gestures/DoubleTapPowerSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
@@ -33,6 +33,7 @@
 public class DoubleTapPowerSettings extends DashboardFragment {
 
     private static final String TAG = "DoubleTapPower";
+    private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
 
     @Override
     public int getMetricsCategory() {
@@ -57,7 +58,8 @@
     private static List<PreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
-        controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle));
+        controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle,
+                KEY_DOUBLE_TAP_POWER));
         return controllers;
     }
 
diff --git a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
index 38d29a0..a38e4b6 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
@@ -21,26 +21,24 @@
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
-import android.util.ArrayMap;
 import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class DoubleTapScreenPreferenceController extends GesturePreferenceController {
 
     private static final String PREF_KEY_VIDEO = "gesture_double_tap_screen_video";
-    private static final String PREF_KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
+    private final String mDoubleTapScreenPrefKey;
 
     private final AmbientDisplayConfiguration mAmbientConfig;
     @UserIdInt
     private final int mUserId;
 
     public DoubleTapScreenPreferenceController(Context context, Lifecycle lifecycle,
-            AmbientDisplayConfiguration config, @UserIdInt int userId) {
+            AmbientDisplayConfiguration config, @UserIdInt int userId, String key) {
         super(context, lifecycle);
         mAmbientConfig = config;
         mUserId = userId;
+        mDoubleTapScreenPrefKey = key;
     }
 
     @Override
@@ -50,7 +48,7 @@
 
     @Override
     public String getPreferenceKey() {
-        return PREF_KEY_DOUBLE_TAP_SCREEN;
+        return mDoubleTapScreenPrefKey;
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/DoubleTapScreenSettings.java b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
index 20adbbe..4a80273 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
@@ -35,6 +35,7 @@
 public class DoubleTapScreenSettings extends DashboardFragment {
 
     private static final String TAG = "DoubleTapScreen";
+    private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
 
     @Override
     public int getMetricsCategory() {
@@ -60,7 +61,8 @@
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
         controllers.add(new DoubleTapScreenPreferenceController(context, lifecycle,
-                new AmbientDisplayConfiguration(context), UserHandle.myUserId()));
+                new AmbientDisplayConfiguration(context), UserHandle.myUserId(),
+                KEY_DOUBLE_TAP_SCREEN));
         return controllers;
     }
 
diff --git a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
index 5a0ff12..2b46cce 100644
--- a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
+++ b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
@@ -33,6 +33,7 @@
 public class DoubleTwistGestureSettings extends DashboardFragment {
 
     private static final String TAG = "DoubleTwistGesture";
+    private static final String KEY_DOUBLE_TWIST = "gesture_double_twist";
 
     @Override
     public int getMetricsCategory() {
@@ -57,7 +58,7 @@
     private static List<PreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
-        controllers.add(new DoubleTwistPreferenceController(context, lifecycle));
+        controllers.add(new DoubleTwistPreferenceController(context, lifecycle, KEY_DOUBLE_TWIST));
         return controllers;
     }
 
diff --git a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
index eb47588..69f9e8d 100644
--- a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
@@ -24,19 +24,17 @@
 import android.support.v7.preference.Preference;
 import android.text.TextUtils;
 
-import android.util.ArrayMap;
 import com.android.settings.R;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class DoubleTwistPreferenceController extends GesturePreferenceController {
 
     private static final String PREF_KEY_VIDEO = "gesture_double_twist_video";
-    private static final String PREF_KEY_DOUBLE_TWIST = "gesture_double_twist";
+    private final String mDoubleTwistPrefKey;
 
-    public DoubleTwistPreferenceController(Context context, Lifecycle lifecycle) {
+    public DoubleTwistPreferenceController(Context context, Lifecycle lifecycle, String key) {
         super(context, lifecycle);
+        mDoubleTwistPrefKey = key;
     }
 
     @Override
@@ -52,7 +50,7 @@
 
     @Override
     public String getPreferenceKey() {
-        return PREF_KEY_DOUBLE_TWIST;
+        return mDoubleTwistPrefKey;
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/PickupGesturePreferenceController.java b/src/com/android/settings/gestures/PickupGesturePreferenceController.java
index 19537f6..a6ce1a1 100644
--- a/src/com/android/settings/gestures/PickupGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/PickupGesturePreferenceController.java
@@ -21,26 +21,24 @@
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
-import android.util.ArrayMap;
 import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.settings.search2.InlineSwitchPayload;
-import com.android.settings.search2.ResultPayload;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class PickupGesturePreferenceController extends GesturePreferenceController {
 
     private static final String PREF_VIDEO_KEY = "gesture_pick_up_video";
-    private static final String PREF_KEY_PICK_UP = "gesture_pick_up";
+    private final String mPickUpPrefKey;
 
     private final AmbientDisplayConfiguration mAmbientConfig;
     @UserIdInt
     private final int mUserId;
 
     public PickupGesturePreferenceController(Context context, Lifecycle lifecycle,
-            AmbientDisplayConfiguration config, @UserIdInt int userId) {
+            AmbientDisplayConfiguration config, @UserIdInt int userId, String key) {
         super(context, lifecycle);
         mAmbientConfig = config;
         mUserId = userId;
+        mPickUpPrefKey = key;
     }
 
     @Override
@@ -60,7 +58,7 @@
 
     @Override
     public String getPreferenceKey() {
-        return PREF_KEY_PICK_UP;
+        return mPickUpPrefKey;
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/PickupGestureSettings.java b/src/com/android/settings/gestures/PickupGestureSettings.java
index ce4d9d7..6ed412f 100644
--- a/src/com/android/settings/gestures/PickupGestureSettings.java
+++ b/src/com/android/settings/gestures/PickupGestureSettings.java
@@ -35,6 +35,7 @@
 public class PickupGestureSettings extends DashboardFragment {
 
     private static final String TAG = "PickupGestureSettings";
+    private static final String KEY_PICK_UP = "gesture_pick_up";
 
     @Override
     public int getMetricsCategory() {
@@ -60,7 +61,7 @@
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
         controllers.add(new PickupGesturePreferenceController(context, lifecycle,
-                new AmbientDisplayConfiguration(context), UserHandle.myUserId()));
+                new AmbientDisplayConfiguration(context), UserHandle.myUserId(), KEY_PICK_UP));
         return controllers;
     }
 
diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
index 821eb04..75cffa5 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
@@ -28,15 +28,17 @@
 public class SwipeToNotificationPreferenceController extends GesturePreferenceController {
 
     private static final String PREF_KEY_VIDEO = "gesture_swipe_down_fingerprint_video";
-    private static final String PREF_KEY_SWIPE_DOWN_FINGERPRINT = "gesture_swipe_down_fingerprint";
+    private final String mSwipeDownFingerPrefKey;
 
-    public SwipeToNotificationPreferenceController(Context context, Lifecycle lifecycle) {
+    public SwipeToNotificationPreferenceController(Context context, Lifecycle lifecycle,
+            String key) {
         super(context, lifecycle);
+        mSwipeDownFingerPrefKey = key;
     }
 
     @Override
     public String getPreferenceKey() {
-        return PREF_KEY_SWIPE_DOWN_FINGERPRINT;
+        return mSwipeDownFingerPrefKey;
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/SwipeToNotificationSettings.java b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
index 0cfc922..00d4700 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationSettings.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
@@ -34,6 +34,8 @@
 
     private static final String TAG = "SwipeToNotifSettings";
 
+    private static final String KEY = "gesture_swipe_down_fingerprint";
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_GESTURE_SWIPE_TO_NOTIFICATION;
@@ -57,7 +59,7 @@
     private static List<PreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
         final List<PreferenceController> controllers = new ArrayList<>();
-        controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
+        controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle, KEY));
         return controllers;
     }
 
diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java
index ffaab67..3818511 100644
--- a/src/com/android/settings/language/LanguageAndInputSettings.java
+++ b/src/com/android/settings/language/LanguageAndInputSettings.java
@@ -60,6 +60,13 @@
 
     private static final String TAG = "LangAndInputSettings";
 
+    private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary";
+    private static final String KEY_ASSIST = "gesture_assist_input_summary";
+    private static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint_input_summary";
+    private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power_input_summary";
+    private static final String KEY_DOUBLE_TWIST = "gesture_double_twist_input_summary";
+    private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen_input_summary";
+    private static final String KEY_PICK_UP = "gesture_pick_up_input_summary";
     private static final String KEY_CAMERA_LIFT_TRIGGER = "gesture_camera_lift_trigger_summary";
 
     private AmbientDisplayConfiguration mAmbientDisplayConfig;
@@ -128,14 +135,16 @@
 
         controllers.add(gameControllerPreferenceController);
         // Gestures
-        controllers.add(new AssistGesturePreferenceController(context, lifecycle));
-        controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
-        controllers.add(new DoubleTwistPreferenceController(context, lifecycle));
-        controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle));
-        controllers.add(new PickupGesturePreferenceController(
-                context, lifecycle, ambientDisplayConfiguration, UserHandle.myUserId()));
-        controllers.add(new DoubleTapScreenPreferenceController(
-                context, lifecycle, ambientDisplayConfiguration, UserHandle.myUserId()));
+        controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST));
+        controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
+                KEY_SWIPE_DOWN));
+        controllers.add(new DoubleTwistPreferenceController(context, lifecycle, KEY_DOUBLE_TWIST));
+        controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle,
+                KEY_DOUBLE_TAP_POWER));
+        controllers.add(new PickupGesturePreferenceController(context, lifecycle,
+                ambientDisplayConfiguration, UserHandle.myUserId(), KEY_PICK_UP));
+        controllers.add(new DoubleTapScreenPreferenceController(context, lifecycle,
+                ambientDisplayConfiguration, UserHandle.myUserId(), KEY_DOUBLE_TAP_SCREEN));
         controllers.add(new CameraLiftTriggerPreferenceController(context, lifecycle,
                 KEY_CAMERA_LIFT_TRIGGER));
         controllers.add(new DefaultAutofillPreferenceController(context));
@@ -199,5 +208,20 @@
                     return buildPreferenceControllers(context, null,
                             new AmbientDisplayConfiguration(context));
                 }
+
+                @Override
+                public List<String> getNonIndexableKeys(Context context) {
+                    List<String> keys = super.getNonIndexableKeys(context);
+                    // Duplicates in summary and details pages.
+                    keys.add(KEY_TEXT_TO_SPEECH);
+                    keys.add(KEY_ASSIST);
+                    keys.add(KEY_SWIPE_DOWN);
+                    keys.add(KEY_DOUBLE_TAP_POWER);
+                    keys.add(KEY_DOUBLE_TWIST);
+                    keys.add(KEY_DOUBLE_TAP_SCREEN);
+                    keys.add(KEY_PICK_UP);
+
+                    return keys;
+                }
             };
 }
diff --git a/src/com/android/settings/language/TtsPreferenceController.java b/src/com/android/settings/language/TtsPreferenceController.java
index 0d1c753..a734e4b 100644
--- a/src/com/android/settings/language/TtsPreferenceController.java
+++ b/src/com/android/settings/language/TtsPreferenceController.java
@@ -23,7 +23,8 @@
 
 public class TtsPreferenceController extends PreferenceController {
 
-    private static final String KEY_TTS_SETTINGS = "tts_settings";
+    private static final String KEY_VOICE_CATEGORY = "voice_category";
+    private static final String KEY_TTS_SETTINGS = "tts_settings_summary";
 
     private final TtsEngines mTtsEngines;
 
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index d567971..869cef9 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -15,10 +15,12 @@
  */
 package com.android.settings.network;
 
+import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
 import android.provider.SearchIndexableResource;
+import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -27,7 +29,7 @@
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.wifi.WifiMasterSwitchPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -133,6 +135,66 @@
         return 0;
     }
 
+    @VisibleForTesting
+    static class SummaryProvider implements SummaryLoader.SummaryProvider {
+
+        private final Context mContext;
+        private final SummaryLoader mSummaryLoader;
+        private final MobileNetworkPreferenceController mMobileNetworkPreferenceController;
+        private final TetherPreferenceController mTetherPreferenceController;
+
+        public SummaryProvider(Context context, SummaryLoader summaryLoader) {
+            this(context, summaryLoader,
+                    new MobileNetworkPreferenceController(context),
+                    new TetherPreferenceController(context, null /* lifecycle */));
+        }
+
+        @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+        SummaryProvider(Context context, SummaryLoader summaryLoader,
+                MobileNetworkPreferenceController mobileNetworkPreferenceController,
+                TetherPreferenceController tetherPreferenceController) {
+            mContext = context;
+            mSummaryLoader = summaryLoader;
+            mMobileNetworkPreferenceController = mobileNetworkPreferenceController;
+            mTetherPreferenceController = tetherPreferenceController;
+        }
+
+
+        @Override
+        public void setListening(boolean listening) {
+            if (listening) {
+                String summary = mContext.getString(R.string.wifi_settings_title);
+                if (mMobileNetworkPreferenceController.isAvailable()) {
+                    final String mobileSettingSummary = mContext.getString(
+                            R.string.network_dashboard_summary_mobile);
+                    summary = mContext.getString(R.string.join_many_items_middle, summary,
+                            mobileSettingSummary);
+                }
+                final String dataUsageSettingSummary = mContext.getString(
+                        R.string.network_dashboard_summary_data_usage);
+                summary = mContext.getString(R.string.join_many_items_middle, summary,
+                        dataUsageSettingSummary);
+                if (mTetherPreferenceController.isAvailable()) {
+                    final String hotspotSettingSummary = mContext.getString(
+                            R.string.network_dashboard_summary_hotspot);
+                    summary = mContext.getString(R.string.join_many_items_middle, summary,
+                            hotspotSettingSummary);
+                }
+                mSummaryLoader.setSummary(this, summary);
+            }
+        }
+    }
+
+    public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
+            = new SummaryLoader.SummaryProviderFactory() {
+        @Override
+        public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
+                SummaryLoader summaryLoader) {
+            return new SummaryProvider(activity, summaryLoader);
+        }
+    };
+
+
     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
                 @Override
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 03a71ca..92ad3f1 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -16,10 +16,6 @@
 
 package com.android.settings.notification;
 
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-
 import android.app.Activity;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -41,22 +37,24 @@
 import com.android.settings.AppHeader;
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settings.applications.AppHeaderController;
 import com.android.settings.applications.AppInfoBase;
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.notification.NotificationBackend.AppRow;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settings.widget.MasterSwitchPreference;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.widget.FooterPreference;
 
-import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
 /** These settings are per app, so should not be returned in global search results. */
 public class AppNotificationSettings extends NotificationSettingsBase {
     private static final String TAG = "AppNotificationSettings";
@@ -128,19 +126,18 @@
     }
 
     private void addHeaderPref() {
-        ArrayMap<String, AppRow> rows = new ArrayMap<String, AppRow>();
+        ArrayMap<String, AppRow> rows = new ArrayMap<>();
         rows.put(mAppRow.pkg, mAppRow);
         collectConfigActivities(rows);
         final Activity activity = getActivity();
-        final Preference pref = FeatureFactory.getFactory(activity)
-                .getApplicationFeatureProvider(activity)
-                .newAppHeaderController(this /* fragment */, null /* appHeader */)
+        final Preference pref = EntityHeaderController
+                .newInstance(activity, this /* fragment */, null /* header */)
                 .setIcon(mAppRow.icon)
                 .setLabel(mAppRow.label)
                 .setPackageName(mAppRow.pkg)
                 .setUid(mAppRow.uid)
-                .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
-                        AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
+                .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_INFO,
+                        EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
                 .done(activity, getPrefContext());
         pref.setKey(KEY_HEADER);
         getPreferenceScreen().addPreference(pref);
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index 0ce9ec3..85a56ba 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -16,18 +16,12 @@
 
 package com.android.settings.notification;
 
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
-
 import android.app.Activity;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.Intent;
-import android.content.pm.UserInfo;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 import android.text.TextUtils;
@@ -38,19 +32,21 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.AppHeader;
 import com.android.settings.R;
 import com.android.settings.RingtonePreference;
 import com.android.settings.Utils;
-import com.android.settings.applications.AppHeaderController;
 import com.android.settings.applications.AppInfoBase;
 import com.android.settings.applications.LayoutPreference;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.widget.FooterPreference;
 
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+
 public class ChannelNotificationSettings extends NotificationSettingsBase {
     private static final String TAG = "ChannelSettings";
 
@@ -110,20 +106,19 @@
     }
 
     private void addHeaderPref() {
-        ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<String, NotificationBackend.AppRow>();
+        ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<>();
         rows.put(mAppRow.pkg, mAppRow);
         collectConfigActivities(rows);
         final Activity activity = getActivity();
-        final Preference pref = FeatureFactory.getFactory(activity)
-                .getApplicationFeatureProvider(activity)
-                .newAppHeaderController(this /* fragment */, null /* appHeader */)
+        final Preference pref = EntityHeaderController
+                .newInstance(activity, this /* fragment */, null /* header */)
                 .setIcon(mAppRow.icon)
                 .setLabel(mChannel.getName())
                 .setSummary(mAppRow.label)
                 .setPackageName(mAppRow.pkg)
                 .setUid(mAppRow.uid)
-                .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
-                        AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
+                .setButtonActions(EntityHeaderController.ActionType.ACTION_APP_INFO,
+                        EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
                 .done(activity, getPrefContext());
         getPreferenceScreen().addPreference(pref);
     }
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index c3d8b81..ad71e83 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -35,6 +35,8 @@
 public class ConfigureNotificationSettings extends DashboardFragment {
     private static final String TAG = "ConfigNotiSettings";
 
+    private static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint_notifications";
+
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.CONFIGURE_NOTIFICATION;
@@ -68,7 +70,8 @@
             lifecycle.addObserver(pulseController);
             lifecycle.addObserver(lockScreenNotificationController);
         }
-        controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
+        controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
+                KEY_SWIPE_DOWN));
         controllers.add(badgeController);
         controllers.add(pulseController);
         controllers.add(lockScreenNotificationController);
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 6f1d350..60893b2 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -30,8 +30,8 @@
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.gestures.AssistGestureFeatureProvider;
 import com.android.settings.localepicker.LocaleFeatureProvider;
-import com.android.settings.security.SecurityFeatureProvider;
 import com.android.settings.search2.SearchFeatureProvider;
+import com.android.settings.security.SecurityFeatureProvider;
 import com.android.settings.users.UserFeatureProvider;
 
 /**
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index a56ac83..3f68e5a 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -29,7 +29,6 @@
 import android.app.FragmentManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.UserInfo;
 import android.hardware.fingerprint.Fingerprint;
@@ -40,6 +39,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.security.KeyStore;
+import android.support.annotation.StringRes;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 import android.text.TextUtils;
@@ -95,14 +95,9 @@
     }
 
     public static class ChooseLockGenericFragment extends SettingsPreferenceFragment {
+
         private static final String TAG = "ChooseLockGenericFragment";
         private static final int MIN_PASSWORD_LENGTH = 4;
-        private static final String KEY_UNLOCK_SET_OFF = "unlock_set_off";
-        private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
-        private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
-        private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
-        private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
-        private static final String KEY_UNLOCK_SET_MANAGED = "unlock_set_managed";
         private static final String KEY_SKIP_FINGERPRINT = "unlock_skip_fingerprint";
         private static final String PASSWORD_CONFIRMED = "password_confirmed";
         private static final String WAITING_FOR_CONFIRMATION = "waiting_for_confirmation";
@@ -112,6 +107,27 @@
         public static final String ENCRYPT_REQUESTED_DISABLED = "encrypt_requested_disabled";
         public static final String TAG_FRP_WARNING_DIALOG = "frp_warning_dialog";
 
+        /**
+         * Boolean extra determining whether a "screen lock options" button should be shown. This
+         * extra is both sent and received by ChooseLockGeneric.
+         *
+         * When this extra is false, nothing will be done.
+         * When ChooseLockGeneric receives this extra set as true, and if ChooseLockGeneric is
+         * starting ChooseLockPassword or ChooseLockPattern automatically without user interaction,
+         * ChooseLockGeneric will set this extra to true when starting ChooseLockPassword/Pattern.
+         *
+         * This gives the user the choice to select a different screen lock type, even if
+         * ChooseLockGeneric selected a default.
+         */
+        public static final String EXTRA_SHOW_OPTIONS_BUTTON = "show_options_button";
+
+        /**
+         * Original intent extras used to start this activity. This is passed to ChooseLockPassword
+         * when the "screen lock options" button is shown, so that when that button is clicked,
+         * ChooseLockGeneric can be relaunched with the same extras.
+         */
+        public static final String EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS = "choose_lock_generic_extras";
+
         private static final int CONFIRM_EXISTING_REQUEST = 100;
         private static final int ENABLE_ENCRYPTION_REQUEST = 101;
         private static final int CHOOSE_LOCK_REQUEST = 102;
@@ -136,6 +152,7 @@
         private ManagedLockPasswordProvider mManagedPasswordProvider;
         private boolean mIsSetNewPassword = false;
         private UserManager mUserManager;
+        private ChooseLockGenericController mController;
 
         protected boolean mForFingerprint = false;
 
@@ -192,6 +209,7 @@
                     UserManager.get(getActivity()),
                     getArguments(),
                     getActivity().getIntent().getExtras()).getIdentifier();
+            mController = new ChooseLockGenericController(getContext(), mUserId);
             if (ACTION_SET_NEW_PASSWORD.equals(chooseLockAction)
                     && UserManager.get(getActivity()).isManagedProfile(mUserId)
                     && mLockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
@@ -303,7 +321,7 @@
                     finish();
                     return;
                 }
-                updateUnlockMethodAndFinish(quality, disabled);
+                updateUnlockMethodAndFinish(quality, disabled, false /* chooseLockSkipped */);
             }
         }
 
@@ -328,6 +346,15 @@
                 if (resultCode != RESULT_CANCELED || mForChangeCredRequiredForBoot) {
                     getActivity().setResult(resultCode, data);
                     finish();
+                } else {
+                    // If PASSWORD_TYPE_KEY is set, this activity is used as a trampoline to start
+                    // the actual password enrollment. If the result is canceled, which means the
+                    // user pressed back, finish the activity with result canceled.
+                    int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
+                    if (quality != -1) {
+                        getActivity().setResult(RESULT_CANCELED, data);
+                        finish();
+                    }
                 }
             } else if (requestCode == CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
                     && resultCode == FingerprintEnrollBase.RESULT_FINISHED) {
@@ -374,7 +401,7 @@
             if (quality == -1) {
                 // If caller didn't specify password quality, show UI and allow the user to choose.
                 quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
-                quality = upgradeQuality(quality);
+                quality = mController.upgradeQuality(quality);
                 final boolean hideDisabledPrefs = intent.getBooleanExtra(
                         HIDE_DISABLED_PREFS, false);
                 final PreferenceScreen prefScreen = getPreferenceScreen();
@@ -387,7 +414,7 @@
                 updateCurrentPreference();
                 updatePreferenceSummaryIfNeeded();
             } else {
-                updateUnlockMethodAndFinish(quality, false);
+                updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
             }
         }
 
@@ -395,33 +422,26 @@
             addPreferencesFromResource(R.xml.security_settings_picker);
 
             // Used for testing purposes
-            findPreference(KEY_UNLOCK_SET_NONE).setViewId(R.id.lock_none);
+            findPreference(ScreenLockType.NONE.preferenceKey).setViewId(R.id.lock_none);
             findPreference(KEY_SKIP_FINGERPRINT).setViewId(R.id.lock_none);
-            findPreference(KEY_UNLOCK_SET_PIN).setViewId(R.id.lock_pin);
-            findPreference(KEY_UNLOCK_SET_PASSWORD).setViewId(R.id.lock_password);
+            findPreference(ScreenLockType.PIN.preferenceKey).setViewId(R.id.lock_pin);
+            findPreference(ScreenLockType.PASSWORD.preferenceKey).setViewId(R.id.lock_password);
         }
 
         private void updatePreferenceText() {
             if (mForFingerprint) {
-                final String key[] = { KEY_UNLOCK_SET_PATTERN,
-                        KEY_UNLOCK_SET_PIN,
-                        KEY_UNLOCK_SET_PASSWORD };
-                final int res[] = { R.string.fingerprint_unlock_set_unlock_pattern,
-                        R.string.fingerprint_unlock_set_unlock_pin,
-                        R.string.fingerprint_unlock_set_unlock_password };
-                for (int i = 0; i < key.length; i++) {
-                    Preference pref = findPreference(key[i]);
-                    if (pref != null) { // can be removed by device admin
-                        pref.setTitle(res[i]);
-                    }
-                }
+                setPreferenceTitle(ScreenLockType.PATTERN,
+                        R.string.fingerprint_unlock_set_unlock_pattern);
+                setPreferenceTitle(ScreenLockType.PIN, R.string.fingerprint_unlock_set_unlock_pin);
+                setPreferenceTitle(ScreenLockType.PASSWORD,
+                        R.string.fingerprint_unlock_set_unlock_password);
             }
 
             if (mManagedPasswordProvider.isSettingManagedPasswordSupported()) {
-                Preference managed = findPreference(KEY_UNLOCK_SET_MANAGED);
-                managed.setTitle(mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
+                setPreferenceTitle(ScreenLockType.MANAGED,
+                        mManagedPasswordProvider.getPickerOptionTitle(mForFingerprint));
             } else {
-                removePreference(KEY_UNLOCK_SET_MANAGED);
+                removePreference(ScreenLockType.MANAGED.preferenceKey);
             }
 
             if (!(mForFingerprint && mIsSetNewPassword)) {
@@ -429,6 +449,27 @@
             }
         }
 
+        private void setPreferenceTitle(ScreenLockType lock, @StringRes int title) {
+            Preference preference = findPreference(lock.preferenceKey);
+            if (preference != null) {
+                preference.setTitle(title);
+            }
+        }
+
+        private void setPreferenceTitle(ScreenLockType lock, CharSequence title) {
+            Preference preference = findPreference(lock.preferenceKey);
+            if (preference != null) {
+                preference.setTitle(title);
+            }
+        }
+
+        private void setPreferenceSummary(ScreenLockType lock, @StringRes int summary) {
+            Preference preference = findPreference(lock.preferenceKey);
+            if (preference != null) {
+                preference.setSummary(summary);
+            }
+        }
+
         private void updateCurrentPreference() {
             String currentKey = getKeyForCurrent();
             Preference preference = findPreference(currentKey);
@@ -441,39 +482,12 @@
             final int credentialOwner = UserManager.get(getContext())
                     .getCredentialOwnerProfile(mUserId);
             if (mLockPatternUtils.isLockScreenDisabled(credentialOwner)) {
-                return KEY_UNLOCK_SET_OFF;
+                return ScreenLockType.NONE.preferenceKey;
             }
-            switch (mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner)) {
-                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
-                    return KEY_UNLOCK_SET_PATTERN;
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
-                    return KEY_UNLOCK_SET_PIN;
-                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
-                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
-                    return KEY_UNLOCK_SET_PASSWORD;
-                case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
-                    return KEY_UNLOCK_SET_MANAGED;
-                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
-                    return KEY_UNLOCK_SET_NONE;
-            }
-            return null;
-        }
-
-        /** increases the quality if necessary */
-        private int upgradeQuality(int quality) {
-            quality = upgradeQualityForDPM(quality);
-            return quality;
-        }
-
-        private int upgradeQualityForDPM(int quality) {
-            // Compare min allowed password quality
-            int minQuality = mDPM.getPasswordQuality(null, mUserId);
-            if (quality < minQuality) {
-                quality = minQuality;
-            }
-            return quality;
+            ScreenLockType lock =
+                    ScreenLockType.fromQuality(
+                            mLockPatternUtils.getKeyguardStoredPasswordQuality(credentialOwner));
+            return lock != null ? lock.preferenceKey : null;
         }
 
         /***
@@ -501,54 +515,17 @@
             int adminEnforcedQuality = mDPM.getPasswordQuality(null, mUserId);
             EnforcedAdmin enforcedAdmin = RestrictedLockUtils.checkIfPasswordQualityIsSet(
                     getActivity(), mUserId);
-            for (int i = entries.getPreferenceCount() - 1; i >= 0; --i) {
-                Preference pref = entries.getPreference(i);
+
+            for (ScreenLockType lock : ScreenLockType.values()) {
+                String key = lock.preferenceKey;
+                Preference pref = findPreference(key);
                 if (pref instanceof RestrictedPreference) {
-                    final String key = pref.getKey();
-                    boolean enabled = true;
-                    boolean visible = true;
-                    boolean disabledByAdmin = false;
-                    if (KEY_UNLOCK_SET_OFF.equals(key)) {
-                        enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-                        if (getResources().getBoolean(R.bool.config_hide_none_security_option)) {
-                            enabled = false;
-                            visible = false;
-                        }
-                        disabledByAdmin = adminEnforcedQuality
-                                > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-                    } else if (KEY_UNLOCK_SET_NONE.equals(key)) {
-                        if (getResources().getBoolean(R.bool.config_hide_swipe_security_option)) {
-                            enabled = false;
-                            visible = false;
-                        } else {
-                            if (mUserId != UserHandle.myUserId()) {
-                                // Swipe doesn't make sense for profiles.
-                                visible = false;
-                            }
-                            enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-                        }
-                        disabledByAdmin = adminEnforcedQuality
-                                > DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
-                    } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
-                        enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-                        disabledByAdmin = adminEnforcedQuality
-                                > DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
-                    } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
-                        enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
-                        disabledByAdmin = adminEnforcedQuality
-                                > DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
-                    } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
-                        enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-                        disabledByAdmin = adminEnforcedQuality
-                                > DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
-                    } else if (KEY_UNLOCK_SET_MANAGED.equals(key)) {
-                        enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_MANAGED
-                                && mManagedPasswordProvider.isManagedPasswordChoosable();
-                        disabledByAdmin = adminEnforcedQuality
-                                > DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
-                    }
+                    boolean visible = mController.isScreenLockVisible(lock);
+                    boolean enabled = mController.isScreenLockEnabled(lock, quality);
+                    boolean disabledByAdmin =
+                            mController.isScreenLockDisabledByAdmin(lock, adminEnforcedQuality);
                     if (hideDisabled) {
-                        visible = enabled;
+                        visible = visible && enabled;
                     }
                     if (!visible) {
                         entries.removePreference(pref);
@@ -583,21 +560,10 @@
                 return;
             }
 
-            CharSequence summary = getString(R.string.secure_lock_encryption_warning);
-
-            PreferenceScreen screen = getPreferenceScreen();
-            final int preferenceCount = screen.getPreferenceCount();
-            for (int i = 0; i < preferenceCount; i++) {
-                Preference preference = screen.getPreference(i);
-                switch (preference.getKey()) {
-                    case KEY_UNLOCK_SET_PATTERN:
-                    case KEY_UNLOCK_SET_PIN:
-                    case KEY_UNLOCK_SET_PASSWORD:
-                    case KEY_UNLOCK_SET_MANAGED: {
-                        preference.setSummary(summary);
-                    } break;
-                }
-            }
+            setPreferenceSummary(ScreenLockType.PATTERN, R.string.secure_lock_encryption_warning);
+            setPreferenceSummary(ScreenLockType.PIN, R.string.secure_lock_encryption_warning);
+            setPreferenceSummary(ScreenLockType.PASSWORD, R.string.secure_lock_encryption_warning);
+            setPreferenceSummary(ScreenLockType.MANAGED, R.string.secure_lock_encryption_warning);
         }
 
         protected Intent getLockManagedPasswordIntent(String password) {
@@ -643,17 +609,24 @@
          *
          * @param quality the desired quality. Ignored if DevicePolicyManager requires more security
          * @param disabled whether or not to show LockScreen at all. Only meaningful when quality is
+         * @param chooseLockSkipped whether or not this activity is skipped. This is true when this
+         * activity was not shown to the user at all, instead automatically proceeding based on
+         * the given intent extras, typically {@link LockPatternUtils#PASSWORD_TYPE_KEY}.
          * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}
          */
-        void updateUnlockMethodAndFinish(int quality, boolean disabled) {
+        void updateUnlockMethodAndFinish(int quality, boolean disabled, boolean chooseLockSkipped) {
             // Sanity check. We should never get here without confirming user's existing password.
             if (!mPasswordConfirmed) {
                 throw new IllegalStateException("Tried to update password without confirming it");
             }
 
-            quality = upgradeQuality(quality);
+            quality = mController.upgradeQuality(quality);
             Intent intent = getIntentForUnlockMethod(quality);
             if (intent != null) {
+                if (getIntent().getBooleanExtra(EXTRA_SHOW_OPTIONS_BUTTON, false)) {
+                    intent.putExtra(EXTRA_SHOW_OPTIONS_BUTTON, chooseLockSkipped);
+                }
+                intent.putExtra(EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, getIntent().getExtras());
                 startActivityForResult(intent,
                         mIsSetNewPassword && mHasChallenge
                                 ? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
@@ -832,35 +805,33 @@
         }
 
         private boolean isUnlockMethodSecure(String unlockMethod) {
-            return !(KEY_UNLOCK_SET_OFF.equals(unlockMethod) ||
-                    KEY_UNLOCK_SET_NONE.equals(unlockMethod));
+            return !(ScreenLockType.SWIPE.preferenceKey.equals(unlockMethod) ||
+                    ScreenLockType.NONE.preferenceKey.equals(unlockMethod));
         }
 
         private boolean setUnlockMethod(String unlockMethod) {
             EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
 
-            if (KEY_UNLOCK_SET_OFF.equals(unlockMethod)) {
-                updateUnlockMethodAndFinish(
-                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, true /* disabled */ );
-            } else if (KEY_UNLOCK_SET_NONE.equals(unlockMethod)) {
-                updateUnlockMethodAndFinish(
-                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, false /* disabled */ );
-            } else if (KEY_UNLOCK_SET_MANAGED.equals(unlockMethod)) {
-                maybeEnableEncryption(DevicePolicyManager.PASSWORD_QUALITY_MANAGED, false);
-            } else if (KEY_UNLOCK_SET_PATTERN.equals(unlockMethod)) {
-                maybeEnableEncryption(
-                        DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false);
-            } else if (KEY_UNLOCK_SET_PIN.equals(unlockMethod)) {
-                maybeEnableEncryption(
-                        DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, false);
-            } else if (KEY_UNLOCK_SET_PASSWORD.equals(unlockMethod)) {
-                maybeEnableEncryption(
-                        DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, false);
-            } else {
-                Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
-                return false;
+            ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
+            if (lock != null) {
+                switch (lock) {
+                    case NONE:
+                    case SWIPE:
+                        updateUnlockMethodAndFinish(
+                                lock.defaultQuality,
+                                lock == ScreenLockType.NONE,
+                                false /* chooseLockSkipped */);
+                        return true;
+                    case PATTERN:
+                    case PIN:
+                    case PASSWORD:
+                    case MANAGED:
+                        maybeEnableEncryption(lock.defaultQuality, false);
+                        return true;
+                }
             }
-            return true;
+            Log.e(TAG, "Encountered unknown unlock method to set: " + unlockMethod);
+            return false;
         }
 
         private void showFactoryResetProtectionWarningDialog(String unlockMethodToSet) {
@@ -906,23 +877,12 @@
                         .setTitle(args.getInt(ARG_TITLE_RES))
                         .setMessage(args.getInt(ARG_MESSAGE_RES))
                         .setPositiveButton(R.string.unlock_disable_frp_warning_ok,
-                                new DialogInterface.OnClickListener() {
-                                    @Override
-                                    public void onClick(DialogInterface dialog, int whichButton) {
-                                        ((ChooseLockGenericFragment) getParentFragment())
-                                                .setUnlockMethod(
-                                                        args.getString(ARG_UNLOCK_METHOD_TO_SET));
-                                    }
-                                }
-                        )
-                        .setNegativeButton(R.string.cancel,
-                                new DialogInterface.OnClickListener() {
-                                    @Override
-                                    public void onClick(DialogInterface dialog, int whichButton) {
-                                        dismiss();
-                                    }
-                                }
-                        )
+                                (dialog, whichButton) -> {
+                                    String unlockMethod = args.getString(ARG_UNLOCK_METHOD_TO_SET);
+                                    ((ChooseLockGenericFragment) getParentFragment())
+                                            .setUnlockMethod(unlockMethod);
+                                })
+                        .setNegativeButton(R.string.cancel, (dialog, whichButton) -> dismiss())
                         .create();
             }
 
diff --git a/src/com/android/settings/password/ChooseLockGenericController.java b/src/com/android/settings/password/ChooseLockGenericController.java
new file mode 100644
index 0000000..a6a1701
--- /dev/null
+++ b/src/com/android/settings/password/ChooseLockGenericController.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2017 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.password;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.os.UserHandle;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A controller for ChooseLockGeneric, and other similar classes which shows a list of possible
+ * screen locks for the user to choose from.
+ */
+public class ChooseLockGenericController {
+
+    private final Context mContext;
+    private final int mUserId;
+    private ManagedLockPasswordProvider mManagedPasswordProvider;
+    private DevicePolicyManager mDpm;
+
+    public ChooseLockGenericController(Context context, int userId) {
+        this(
+                context,
+                userId,
+                context.getSystemService(DevicePolicyManager.class),
+                ManagedLockPasswordProvider.get(context, userId));
+    }
+
+    @VisibleForTesting
+    ChooseLockGenericController(
+            Context context,
+            int userId,
+            DevicePolicyManager dpm,
+            ManagedLockPasswordProvider managedLockPasswordProvider) {
+        mContext = context;
+        mUserId = userId;
+        mManagedPasswordProvider = managedLockPasswordProvider;
+        mDpm = dpm;
+    }
+
+    /**
+     * @return The higher quality of either the specified {@code quality} or the quality required
+     *         by {@link DevicePolicyManager#getPasswordQuality}.
+     */
+    public int upgradeQuality(int quality) {
+        // Compare min allowed password quality
+        return Math.max(quality, mDpm.getPasswordQuality(null, mUserId));
+    }
+
+    /**
+     * Whether the given screen lock type should be visible in the given context.
+     */
+    public boolean isScreenLockVisible(ScreenLockType type) {
+        switch (type) {
+            case NONE:
+                return !mContext.getResources().getBoolean(R.bool.config_hide_none_security_option);
+            case SWIPE:
+                return !mContext.getResources().getBoolean(R.bool.config_hide_swipe_security_option)
+                    // Swipe doesn't make sense for profiles.
+                    && mUserId == UserHandle.myUserId();
+            case MANAGED:
+                return mManagedPasswordProvider.isManagedPasswordChoosable();
+        }
+        return true;
+    }
+
+    /**
+     * Whether screen lock with {@code type} should be enabled.
+     *
+     * @param type The screen lock type.
+     * @param quality The minimum required quality. This can either be requirement by device policy
+     *                manager or because some flow only makes sense with secure lock screens.
+     */
+    public boolean isScreenLockEnabled(ScreenLockType type, int quality) {
+        return type.maxQuality >= quality;
+    }
+
+    /**
+     * Whether screen lock with {@code type} is disabled by device policy admin.
+     *
+     * @param type The screen lock type.
+     * @param adminEnforcedQuality The minimum quality that the admin enforces.
+     */
+    public boolean isScreenLockDisabledByAdmin(ScreenLockType type, int adminEnforcedQuality) {
+        boolean disabledByAdmin = type.maxQuality < adminEnforcedQuality;
+        if (type == ScreenLockType.MANAGED) {
+            disabledByAdmin = disabledByAdmin
+                    || !mManagedPasswordProvider.isManagedPasswordChoosable();
+        }
+        return disabledByAdmin;
+    }
+
+    /**
+     * User friendly title for the given screen lock type.
+     */
+    public CharSequence getTitle(ScreenLockType type) {
+        switch (type) {
+            case NONE:
+                return mContext.getText(R.string.unlock_set_unlock_off_title);
+            case SWIPE:
+                return mContext.getText(R.string.unlock_set_unlock_none_title);
+            case PATTERN:
+                return mContext.getText(R.string.unlock_set_unlock_pattern_title);
+            case PIN:
+                return mContext.getText(R.string.unlock_set_unlock_pin_title);
+            case PASSWORD:
+                return mContext.getText(R.string.unlock_set_unlock_password_title);
+            case MANAGED:
+                return mManagedPasswordProvider.getPickerOptionTitle(false);
+        }
+        return null;
+    }
+
+    /**
+     * Gets a list of screen locks that should be visible for the given quality. The returned list
+     * is ordered in the natural order of the enum (the order those enums were defined).
+     *
+     * @param quality The minimum quality required in the context of the current flow. This should
+     *                be one of the constants defined in
+     *                {@code DevicePolicyManager#PASSWORD_QUALITY_*}.
+     * @param includeDisabled Whether to include screen locks disabled by {@code quality}
+     *                        requirements in the returned list.
+     */
+    @NonNull
+    public List<ScreenLockType> getVisibleScreenLockTypes(int quality, boolean includeDisabled) {
+        int upgradedQuality = upgradeQuality(quality);
+        List<ScreenLockType> locks = new ArrayList<>();
+        // EnumSet's iterator guarantees the natural order of the enums
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            if (isScreenLockVisible(lock)) {
+                if (includeDisabled || isScreenLockEnabled(lock, upgradedQuality)) {
+                    locks.add(lock);
+                }
+            }
+        }
+        return locks;
+    }
+}
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index f9aabd6..df0621e 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -28,6 +28,7 @@
 import android.app.admin.PasswordMetrics;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Insets;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
@@ -171,7 +172,7 @@
         private int mPasswordMinNumeric = 0;
         private int mPasswordMinNonLetter = 0;
         private int mPasswordMinLengthToFulfillAllPolicies = 0;
-        private int mUserId;
+        protected int mUserId;
         private boolean mHideDrawer = false;
         /**
          * Password requirements that we need to verify.
@@ -188,7 +189,7 @@
         private TextView mHeaderText;
         private String mFirstPin;
         private RecyclerView mPasswordRestrictionView;
-        private boolean mIsAlphaMode;
+        protected boolean mIsAlphaMode;
         private Button mCancelButton;
         private Button mNextButton;
 
@@ -291,6 +292,11 @@
         public void onViewCreated(View view, Bundle savedInstanceState) {
             super.onViewCreated(view, savedInstanceState);
 
+            // Make the password container consume the optical insets so the edit text is aligned
+            // with the sides of the parent visually.
+            ViewGroup container = view.findViewById(R.id.password_container);
+            container.setOpticalInsets(Insets.NONE);
+
             mCancelButton = (Button) view.findViewById(R.id.cancel_button);
             mCancelButton.setOnClickListener(this);
             mNextButton = (Button) view.findViewById(R.id.next_button);
diff --git a/src/com/android/settings/password/ChooseLockTypeDialogFragment.java b/src/com/android/settings/password/ChooseLockTypeDialogFragment.java
new file mode 100644
index 0000000..2581483
--- /dev/null
+++ b/src/com/android/settings/password/ChooseLockTypeDialogFragment.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 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.password;
+
+import android.app.AlertDialog.Builder;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+import java.util.List;
+
+/**
+ * A dialog fragment similar to {@link ChooseLockGeneric} where the user can select from a few
+ * lock screen types.
+ */
+public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
+        implements OnClickListener {
+
+    private static final String ARG_USER_ID = "userId";
+    private static final String ARG_EXCLUDE_LOCK = "excludeLock";
+
+    private ScreenLockAdapter mAdapter;
+    private ChooseLockGenericController mController;
+
+    public static ChooseLockTypeDialogFragment newInstance(int userId, String excludeLock) {
+        Bundle args = new Bundle();
+        args.putInt(ARG_USER_ID, userId);
+        args.putString(ARG_EXCLUDE_LOCK, excludeLock);
+        ChooseLockTypeDialogFragment fragment = new ChooseLockTypeDialogFragment();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public interface OnLockTypeSelectedListener {
+        void onLockTypeSelected(ScreenLockType lock);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final int userId = getArguments().getInt(ARG_USER_ID);
+        mController = new ChooseLockGenericController(getContext(), userId);
+    }
+
+    @Override
+    public void onClick(DialogInterface dialogInterface, int i) {
+        OnLockTypeSelectedListener listener = null;
+        Fragment parentFragment = getParentFragment();
+        if (parentFragment instanceof OnLockTypeSelectedListener) {
+            listener = (OnLockTypeSelectedListener) parentFragment;
+        } else {
+            Context context = getContext();
+            if (context instanceof OnLockTypeSelectedListener) {
+                listener = (OnLockTypeSelectedListener) context;
+            }
+        }
+        if (listener != null) {
+            listener.onLockTypeSelected(mAdapter.getItem(i));
+        }
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        Context context = getContext();
+        Builder builder = new Builder(context);
+        List<ScreenLockType> locks =
+                mController.getVisibleScreenLockTypes(
+                        DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
+                        false /* includeDisabled */);
+        String excludeLockName = getArguments().getString(ARG_EXCLUDE_LOCK);
+        if (excludeLockName != null) {
+            locks.remove(ScreenLockType.valueOf(excludeLockName));
+        }
+        mAdapter = new ScreenLockAdapter(context, locks, mController);
+        builder.setAdapter(mAdapter, this);
+        return builder.create();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.SETTINGS_CHOOSE_LOCK_DIALOG;
+    }
+
+    private static class ScreenLockAdapter extends ArrayAdapter<ScreenLockType> {
+
+        private final ChooseLockGenericController mController;
+
+        ScreenLockAdapter(
+                Context context,
+                List<ScreenLockType> locks,
+                ChooseLockGenericController controller) {
+            super(context, android.R.layout.simple_list_item_1, locks);
+            mController = controller;
+        }
+
+        @Override
+        public View getView(int position, View view, ViewGroup parent) {
+            if (view == null) {
+                view = LayoutInflater.from(parent.getContext())
+                        .inflate(android.R.layout.simple_list_item_1, parent, false);
+            }
+            ((TextView) view).setText(mController.getTitle(getItem(position)));
+            return view;
+        }
+    }
+}
diff --git a/src/com/android/settings/password/ManagedLockPasswordProvider.java b/src/com/android/settings/password/ManagedLockPasswordProvider.java
index 65bf1f6..09fe104 100644
--- a/src/com/android/settings/password/ManagedLockPasswordProvider.java
+++ b/src/com/android/settings/password/ManagedLockPasswordProvider.java
@@ -52,7 +52,7 @@
      * Should be overridden if {@link #isManagedPasswordSupported()} returns true.
      * @param forFingerprint Whether fingerprint unlock is enabled.
      */
-    String getPickerOptionTitle(boolean forFingerprint) { return ""; }
+    CharSequence getPickerOptionTitle(boolean forFingerprint) { return ""; }
 
     /**
      * Gets resource id of the lock screen preference that should be displayed in security settings
diff --git a/src/com/android/settings/password/ScreenLockType.java b/src/com/android/settings/password/ScreenLockType.java
new file mode 100644
index 0000000..608c8f6
--- /dev/null
+++ b/src/com/android/settings/password/ScreenLockType.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 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.password;
+
+import android.app.admin.DevicePolicyManager;
+
+/**
+ * List of screen lock type options that are available in ChooseLockGeneric. Provides the key and
+ * the associated quality, and also some helper functions to translate between them.
+ */
+public enum ScreenLockType {
+
+    NONE(
+            DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+            "unlock_set_off"),
+    SWIPE(
+            DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
+            "unlock_set_none"),
+    PATTERN(
+            DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
+            "unlock_set_pattern"),
+    PIN(
+            DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
+            DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
+            "unlock_set_pin"),
+    PASSWORD(
+            DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
+            DevicePolicyManager.PASSWORD_QUALITY_COMPLEX,
+            "unlock_set_password"),
+    MANAGED(
+            DevicePolicyManager.PASSWORD_QUALITY_MANAGED,
+            "unlock_set_managed");
+
+    private static final ScreenLockType MIN_QUALITY = ScreenLockType.NONE;
+    private static final ScreenLockType MAX_QUALITY = ScreenLockType.MANAGED;
+
+    /**
+     * The default quality of the type of lock used. For example, in the case of PIN, the default
+     * quality if PASSWORD_QUALITY_NUMERIC, while the highest quality is
+     * PASSWORD_QUALITY_NUMERIC_COMPLEX.
+     */
+    public final int defaultQuality;
+
+    /**
+     * The highest quality for the given type of lock. For example, in the case of password, the
+     * default quality is PASSWORD_QUALITY_ALPHABETIC, but the highest possible quality is
+     * PASSWORD_QUALITY_COMPLEX.
+     */
+    public final int maxQuality;
+
+    public final String preferenceKey;
+
+    ScreenLockType(int quality, String preferenceKey) {
+        this(quality, quality, preferenceKey);
+    }
+
+    ScreenLockType(int defaultQuality, int maxQuality, String preferenceKey) {
+        this.defaultQuality = defaultQuality;
+        this.maxQuality = maxQuality;
+        this.preferenceKey = preferenceKey;
+    }
+
+    /**
+     * Gets the screen lock type for the given quality. Note that this method assumes that a screen
+     * lock is enabled, which means if the quality is
+     * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, the returned type will be
+     * {@link #SWIPE} and not {@link #NONE}.
+     */
+    public static ScreenLockType fromQuality(int quality) {
+        switch (quality) {
+            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+                return ScreenLockType.PATTERN;
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+                return ScreenLockType.PIN;
+            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+                return ScreenLockType.PASSWORD;
+            case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
+                return ScreenLockType.MANAGED;
+            case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
+                return ScreenLockType.SWIPE;
+        }
+        return null;
+    }
+
+    public static ScreenLockType fromKey(String key) {
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            if (lock.preferenceKey.equals(key)) {
+                return lock;
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index 74aac2c..4e73b87 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -111,20 +111,16 @@
 
         @Override
         public void onActivityResult(int requestCode, int resultCode, Intent data) {
-            if (resultCode != RESULT_CANCELED) {
-                if (data == null) {
-                    data = new Intent();
-                }
-                // Add the password quality extra to the intent data that will be sent back for
-                // Setup Wizard.
-                LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
-                data.putExtra(EXTRA_PASSWORD_QUALITY,
-                        lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
-
-                super.onActivityResult(requestCode, resultCode, data);
+            if (data == null) {
+                data = new Intent();
             }
-            // If the started activity was cancelled (e.g. the user presses back), then this
-            // activity will be resumed to foreground.
+            // Add the password quality extra to the intent data that will be sent back for
+            // Setup Wizard.
+            LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
+            data.putExtra(EXTRA_PASSWORD_QUALITY,
+                    lockPatternUtils.getKeyguardStoredPasswordQuality(UserHandle.myUserId()));
+
+            super.onActivityResult(requestCode, resultCode, data);
         }
 
         @Override
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index b8a741d..0c62c7c 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -16,16 +16,24 @@
 
 package com.android.settings.password;
 
+import android.app.Activity;
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
 import android.widget.LinearLayout;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SetupRedactionInterstitial;
 import com.android.settings.SetupWizardUtils;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
+import com.android.settings.password.ChooseLockTypeDialogFragment.OnLockTypeSelectedListener;
+import com.android.setupwizardlib.util.WizardManagerHelper;
 
 /**
  * Setup Wizard's version of ChooseLockPassword screen. It inherits the logic and basic structure
@@ -67,7 +75,41 @@
         super.onApplyThemeResource(theme, resid, first);
     }
 
-    public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment {
+    public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment
+            implements OnLockTypeSelectedListener {
+
+        @VisibleForTesting
+        static final int REQUEST_SCREEN_LOCK_OPTIONS = 1;
+
+        @Override
+        public void onViewCreated(View view, Bundle savedInstanceState) {
+            super.onViewCreated(view, savedInstanceState);
+            boolean showOptionsButton = getActivity().getIntent().getBooleanExtra(
+                    ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
+            if (showOptionsButton) {
+                Button optionsButton = view.findViewById(R.id.screen_lock_options);
+                optionsButton.setVisibility(View.VISIBLE);
+                optionsButton.setOnClickListener(this);
+            }
+        }
+
+        @Override
+        public void onClick(View v) {
+            switch (v.getId()) {
+                case R.id.screen_lock_options:
+                    launchChooseLockGeneric();
+                    break;
+                default:
+                    super.onClick(v);
+            }
+        }
+
+        private void launchChooseLockGeneric() {
+            ScreenLockType currentLock = mIsAlphaMode
+                    ? ScreenLockType.PASSWORD : ScreenLockType.PIN;
+            ChooseLockTypeDialogFragment.newInstance(mUserId, currentLock.toString())
+                    .show(getChildFragmentManager(), null);
+        }
 
         @Override
         protected Intent getRedactionInterstitialIntent(Context context) {
@@ -76,5 +118,46 @@
             SetupRedactionInterstitial.setEnabled(context, true);
             return null;
         }
+
+        @Override
+        public void onLockTypeSelected(ScreenLockType lock) {
+            Intent activityIntent = getActivity().getIntent();
+            Intent intent = new Intent(getContext(), SetupChooseLockGeneric.class);
+
+            // Copy the original extras into the new intent
+            if (activityIntent
+                    .hasExtra(ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS)) {
+                intent.putExtras(activityIntent.getBundleExtra(
+                        ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS));
+            }
+            intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, lock.defaultQuality);
+
+            // Propagate the fingerprint challenge
+            intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE,
+                    activityIntent.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE,
+                            false));
+            intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE,
+                    activityIntent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0));
+
+            // The user is already given the choice of the what screen lock to set up. No need to
+            // show this button again.
+            intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
+
+            WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
+
+            startActivityForResult(intent, REQUEST_SCREEN_LOCK_OPTIONS);
+        }
+
+        @Override
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+            super.onActivityResult(requestCode, resultCode, data);
+            if (requestCode == REQUEST_SCREEN_LOCK_OPTIONS) {
+                if (resultCode != Activity.RESULT_CANCELED) {
+                    Activity activity = getActivity();
+                    activity.setResult(resultCode, data);
+                    activity.finish();
+                }
+            }
+        }
     }
 }
diff --git a/src/com/android/settings/applications/AppHeaderController.java b/src/com/android/settings/widget/EntityHeaderController.java
similarity index 64%
rename from src/com/android/settings/applications/AppHeaderController.java
rename to src/com/android/settings/widget/EntityHeaderController.java
index 804d645..d7ba35a 100644
--- a/src/com/android/settings/applications/AppHeaderController.java
+++ b/src/com/android/settings/widget/EntityHeaderController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings.applications;
+package com.android.settings.widget;
 
 import android.annotation.IdRes;
 import android.annotation.UserIdInt;
@@ -41,13 +41,16 @@
 import com.android.settings.AppHeader;
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.applications.InstalledAppDetails;
+import com.android.settings.applications.LayoutPreference;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.applications.ApplicationsState;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-public class AppHeaderController {
+public class EntityHeaderController {
 
     @IntDef({ActionType.ACTION_NONE,
             ActionType.ACTION_APP_INFO,
@@ -68,7 +71,7 @@
     private final Context mContext;
     private final Fragment mFragment;
     private final int mMetricsCategory;
-    private final View mAppHeader;
+    private final View mHeader;
 
     private Drawable mIcon;
     private CharSequence mLabel;
@@ -78,90 +81,101 @@
     @UserIdInt
     private int mUid = UserHandle.USER_NULL;
     @ActionType
-    private int mLeftAction;
+    private int mAction1;
     @ActionType
-    private int mRightAction;
+    private int mAction2;
 
     private boolean mIsInstantApp;
 
-    public AppHeaderController(Context context, Fragment fragment, View appHeader) {
+    /**
+     * Creates a new instance of the controller.
+     *
+     * @param fragment The fragment that header will be placed in.
+     * @param header   Optional: header view if it's already created.
+     */
+    public static EntityHeaderController newInstance(Context context, Fragment fragment,
+            View header) {
+        return new EntityHeaderController(context.getApplicationContext(), fragment, header);
+    }
+
+    private EntityHeaderController(Context context, Fragment fragment, View header) {
         mContext = context;
         mFragment = fragment;
         mMetricsCategory = FeatureFactory.getFactory(context).getMetricsFeatureProvider()
                 .getMetricsCategory(fragment);
-        if (appHeader != null) {
-            mAppHeader = appHeader;
+        if (header != null) {
+            mHeader = header;
         } else {
-            mAppHeader = LayoutInflater.from(fragment.getContext())
-                    .inflate(R.layout.app_details, null /* root */);
+            mHeader = LayoutInflater.from(fragment.getContext())
+                    .inflate(R.layout.settings_entity_header, null /* root */);
         }
     }
 
-    public AppHeaderController setIcon(Drawable icon) {
+    public EntityHeaderController setIcon(Drawable icon) {
         if (icon != null) {
             mIcon = icon.getConstantState().newDrawable(mContext.getResources());
         }
         return this;
     }
 
-    public AppHeaderController setIcon(ApplicationsState.AppEntry appEntry) {
+    public EntityHeaderController setIcon(ApplicationsState.AppEntry appEntry) {
         if (appEntry.icon != null) {
             mIcon = appEntry.icon.getConstantState().newDrawable(mContext.getResources());
         }
         return this;
     }
 
-    public AppHeaderController setLabel(CharSequence label) {
+    public EntityHeaderController setLabel(CharSequence label) {
         mLabel = label;
         return this;
     }
 
-    public AppHeaderController setLabel(ApplicationsState.AppEntry appEntry) {
+    public EntityHeaderController setLabel(ApplicationsState.AppEntry appEntry) {
         mLabel = appEntry.label;
         return this;
     }
 
-    public AppHeaderController setSummary(CharSequence summary) {
+    public EntityHeaderController setSummary(CharSequence summary) {
         mSummary = summary;
         return this;
     }
 
-    public AppHeaderController setSummary(PackageInfo packageInfo) {
+    public EntityHeaderController setSummary(PackageInfo packageInfo) {
         if (packageInfo != null) {
             mSummary = packageInfo.versionName;
         }
         return this;
     }
 
-    public AppHeaderController setButtonActions(@ActionType int leftAction,
-            @ActionType int rightAction) {
-        mLeftAction = leftAction;
-        mRightAction = rightAction;
+    public EntityHeaderController setButtonActions(@ActionType int action1,
+            @ActionType int action2) {
+        mAction1 = action1;
+        mAction2 = action2;
         return this;
     }
 
-    public AppHeaderController setPackageName(String packageName) {
+    public EntityHeaderController setPackageName(String packageName) {
         mPackageName = packageName;
         return this;
     }
 
-    public AppHeaderController setUid(int uid) {
+    public EntityHeaderController setUid(int uid) {
         mUid = uid;
         return this;
     }
 
-    public AppHeaderController setAppNotifPrefIntent(Intent appNotifPrefIntent) {
+    public EntityHeaderController setAppNotifPrefIntent(Intent appNotifPrefIntent) {
         mAppNotifPrefIntent = appNotifPrefIntent;
         return this;
     }
 
-    public AppHeaderController setIsInstantApp(boolean isInstantApp) {
+    public EntityHeaderController setIsInstantApp(boolean isInstantApp) {
         this.mIsInstantApp = isInstantApp;
         return this;
     }
 
     /**
-     * Done mutating appheader, rebinds everything and return a new {@link LayoutPreference}.
+     * Done mutating entity header, rebinds everything and return a new {@link LayoutPreference}.
      */
     public LayoutPreference done(Activity activity, Context uiContext) {
         final LayoutPreference pref = new LayoutPreference(uiContext, done(activity));
@@ -172,41 +186,41 @@
     }
 
     /**
-     * Done mutating appheader, rebinds everything (optionally skip rebinding buttons).
+     * Done mutating entity header, rebinds everything (optionally skip rebinding buttons).
      */
     public View done(Activity activity, boolean rebindActions) {
         styleActionBar(activity);
-        ImageView iconView = mAppHeader.findViewById(R.id.app_detail_icon);
+        ImageView iconView = mHeader.findViewById(R.id.entity_header_icon);
         if (iconView != null) {
             iconView.setImageDrawable(mIcon);
         }
-        setText(R.id.app_detail_title, mLabel);
-        setText(R.id.app_detail_summary, mSummary);
+        setText(R.id.entity_header_title, mLabel);
+        setText(R.id.entity_header_summary, mSummary);
         if (mIsInstantApp) {
             setText(R.id.install_type,
-                    mAppHeader.getResources().getString(R.string.install_type_instant));
+                    mHeader.getResources().getString(R.string.install_type_instant));
         }
 
         if (rebindActions) {
-            bindAppHeaderButtons();
+            bindHeaderButtons();
         }
 
-        return mAppHeader;
+        return mHeader;
     }
 
     /**
-     * Only binds app header with button actions.
+     * Only binds entity header with button actions.
      */
-    public AppHeaderController bindAppHeaderButtons() {
-        ImageButton leftButton = mAppHeader.findViewById(R.id.left_button);
-        ImageButton rightButton = mAppHeader.findViewById(R.id.right_button);
+    public EntityHeaderController bindHeaderButtons() {
+        ImageButton button1 = mHeader.findViewById(android.R.id.button1);
+        ImageButton button2 = mHeader.findViewById(android.R.id.button2);
 
-        bindButton(leftButton, mLeftAction);
-        bindButton(rightButton, mRightAction);
+        bindButton(button1, mAction1);
+        bindButton(button2, mAction2);
         return this;
     }
 
-    public AppHeaderController styleActionBar(Activity activity) {
+    public EntityHeaderController styleActionBar(Activity activity) {
         if (activity == null) {
             Log.w(TAG, "No activity, cannot style actionbar.");
             return this;
@@ -224,7 +238,7 @@
     }
 
     /**
-     * Done mutating appheader, rebinds everything.
+     * Done mutating entity header, rebinds everything.
      */
     @VisibleForTesting
     View done(Activity activity) {
@@ -245,9 +259,16 @@
                     button.setContentDescription(
                             mContext.getString(R.string.application_info_label));
                     button.setImageResource(com.android.settings.R.drawable.ic_info);
-                    button.setOnClickListener(v -> AppInfoBase.startAppInfoFragment(
-                            InstalledAppDetails.class, R.string.application_info_label,
-                            mPackageName, mUid, mFragment, 0 /* request */, mMetricsCategory));
+                    button.setOnClickListener(new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            AppInfoBase.startAppInfoFragment(
+                                    InstalledAppDetails.class, R.string.application_info_label,
+                                    mPackageName, mUid, mFragment, 0 /* request */,
+                                    mMetricsCategory);
+
+                        }
+                    });
                     button.setVisibility(View.VISIBLE);
                 }
                 return;
@@ -256,7 +277,12 @@
                 if (mAppNotifPrefIntent == null) {
                     button.setVisibility(View.GONE);
                 } else {
-                    button.setOnClickListener(v -> mFragment.startActivity(mAppNotifPrefIntent));
+                    button.setOnClickListener(new View.OnClickListener() {
+                        @Override
+                        public void onClick(View v) {
+                            mFragment.startActivity(mAppNotifPrefIntent);
+                        }
+                    });
                     button.setVisibility(View.VISIBLE);
                 }
                 return;
@@ -268,7 +294,12 @@
                     button.setVisibility(View.GONE);
                     return;
                 }
-                button.setOnClickListener(v -> mFragment.startActivity(intent));
+                button.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mFragment.startActivity(intent);
+                    }
+                });
                 button.setVisibility(View.VISIBLE);
                 return;
             }
@@ -289,7 +320,7 @@
     }
 
     private void setText(@IdRes int id, CharSequence text) {
-        TextView textView = mAppHeader.findViewById(id);
+        TextView textView = mHeader.findViewById(id);
         if (textView != null) {
             textView.setText(text);
             textView.setVisibility(TextUtils.isEmpty(text) ? View.GONE : View.VISIBLE);
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 2f1139b..39d90e1 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -225,7 +225,7 @@
 
         mButtonsPref = (LayoutPreference) screen.findPreference(KEY_BUTTONS_PREF);
         mSignInButton = (Button) mButtonsPref.findViewById(R.id.right_button);
-        mSignInButton.setText(com.android.internal.R.string.network_available_sign_in);
+        mSignInButton.setText(R.string.support_sign_in_button_text);
         mSignInButton.setOnClickListener(
             view -> mConnectivityManagerWrapper.startCaptivePortalApp(mNetwork));
 
diff --git a/tests/robotests/assets/whitelist_duplicate_index_key b/tests/robotests/assets/whitelist_duplicate_index_key
index 4446403..0b8d675 100644
--- a/tests/robotests/assets/whitelist_duplicate_index_key
+++ b/tests/robotests/assets/whitelist_duplicate_index_key
@@ -1,12 +1,6 @@
-dashboard_tile_placeholder
-gesture_pick_up
 add_users_when_locked
 additional_system_update_settings
-gesture_assist
 screen_zoom
-gesture_swipe_down_fingerprint
-gesture_double_twist
+dashboard_tile_placeholder
 lock_screen_notifications
-gesture_double_tap_power
-gesture_double_tap_screen
 usage_access
\ No newline at end of file
diff --git a/tests/robotests/src/android/app/admin/PasswordMetrics.java b/tests/robotests/src/android/app/admin/PasswordMetrics.java
new file mode 100644
index 0000000..a461306
--- /dev/null
+++ b/tests/robotests/src/android/app/admin/PasswordMetrics.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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 android.app.admin;
+
+import android.annotation.NonNull;
+
+/**
+ * Stub implementation of framework's PasswordMetrics for Robolectric tests. Otherwise Robolectric
+ * is throwing ClassNotFoundError.
+ *
+ * TODO: Remove this class when Robolectric supports O
+ */
+public class PasswordMetrics {
+
+    // Maximum allowed number of repeated or ordered characters in a sequence before we'll
+    // consider it a complex PIN/password.
+    public static final int MAX_ALLOWED_SEQUENCE = 3;
+
+    public int length = 0;
+    public int letters = 0;
+    public int upperCase = 0;
+    public int lowerCase = 0;
+    public int numeric = 0;
+    public int symbols = 0;
+    public int nonLetter = 0;
+
+    public static int maxLengthSequence(@NonNull String string) {
+        // Stub implementation
+        return 1;
+    }
+
+    public static PasswordMetrics computeForPassword(@NonNull String password) {
+        return new PasswordMetrics();
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/DisplaySettingsTest.java b/tests/robotests/src/com/android/settings/DisplaySettingsTest.java
new file mode 100644
index 0000000..716eacf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/DisplaySettingsTest.java
@@ -0,0 +1,44 @@
+package com.android.settings;
+
+import android.content.Context;
+import android.os.PowerManager;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.testutils.XmlTestUtils;
+import com.android.settings.testutils.shadow.ShadowPowerManagerWrapper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class DisplaySettingsTest {
+
+    @Test
+    @Config(shadows = ShadowPowerManagerWrapper.class)
+    public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
+        final Context context = RuntimeEnvironment.application;
+//        PowerManager wrapper = mock(PowerManager.class);
+//        doReturn(wrapper).when(context).getSystemService(Context.POWER_SERVICE);
+        final DisplaySettings fragment = new DisplaySettings();
+        final List<String> preferenceScreenKeys = XmlTestUtils.getKeysFromPreferenceXml(context,
+                fragment.getPreferenceScreenResId());
+        final List<String> preferenceKeys = new ArrayList<>();
+
+        for (PreferenceController controller : fragment.getPreferenceControllers(context)) {
+            preferenceKeys.add(controller.getPreferenceKey());
+        }
+        // Nightmode is currently hidden
+        preferenceKeys.remove("night_mode");
+
+        assertThat(preferenceScreenKeys).containsAllIn(preferenceKeys);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
index 90728e8..a215d13 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountDetailDashboardFragmentTest.java
@@ -17,7 +17,6 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.AuthenticatorDescription;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -26,8 +25,6 @@
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.shadow.ShadowAccountManager;
-import com.android.settings.testutils.shadow.ShadowContentResolver;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.Tile;
 
@@ -41,11 +38,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Answers.RETURNS_DEEP_STUBS;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -54,7 +47,6 @@
     private static final String METADATA_CATEGORY = "com.android.settings.category";
     private static final String METADATA_ACCOUNT_TYPE = "com.android.settings.ia.account";
     private static final String METADATA_USER_HANDLE = "user_handle";
-    private static final String PREF_ACCOUNT_HEADER = "account_header";
 
     @Mock(answer = RETURNS_DEEP_STUBS)
     private AccountManager mAccountManager;
@@ -118,20 +110,4 @@
 
         assertThat(mFragment.displayTile(tile)).isFalse();
     }
-
-    @Test
-    @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
-    public void updateAccountHeader_shouldShowAccountName() throws Exception {
-        when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(
-            new AuthenticatorDescription[0]);
-        when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
-        when(mFragment.getContext()).thenReturn(mContext);
-        doReturn(mScreen).when(mFragment).getPreferenceScreen();
-        doReturn(mPreference).when(mFragment).findPreference(PREF_ACCOUNT_HEADER);
-
-        mFragment.updateUi();
-
-        verify(mPreference).setTitle("name1@abc.com");
-    }
-
 }
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java
new file mode 100644
index 0000000..0668379
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/AccountHeaderPreferenceControllerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 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.accounts;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.v7.preference.PreferenceScreen;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.accounts.AuthenticatorHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AccountHeaderPreferenceControllerTest {
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock
+    private Activity mActivity;
+    @Mock
+    private Fragment mFragment;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private LayoutPreference mHeaderPreference;
+
+    private AccountHeaderPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
+        mHeaderPreference = new LayoutPreference(
+                RuntimeEnvironment.application, R.layout.settings_entity_header);
+    }
+
+    @Test
+    public void isAvailable_noArgs_shouldReturnNull() {
+        mController = new AccountHeaderPreferenceController(RuntimeEnvironment.application,
+                mActivity, mFragment, null /* args */);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    @Config(shadows = ShadowAuthenticatorHelper.class)
+    public void displayPreference_shouldDisplayAccountInEntityHeader() {
+        final Account account = new Account("name1@abc.com", "com.abc");
+        Bundle args = new Bundle();
+        args.putParcelable(AccountDetailDashboardFragment.KEY_ACCOUNT, account);
+        args.putParcelable(AccountDetailDashboardFragment.KEY_USER_HANDLE, UserHandle.CURRENT);
+        mController = new AccountHeaderPreferenceController(RuntimeEnvironment.application,
+                mActivity, mFragment, args);
+
+        assertThat(mController.isAvailable()).isTrue();
+
+        when(mScreen.findPreference(anyString())).thenReturn(mHeaderPreference);
+
+        mController.displayPreference(mScreen);
+
+        final CharSequence label =
+                ((TextView) mHeaderPreference.findViewById(R.id.entity_header_title)).getText();
+
+        assertThat(label).isEqualTo(account.name);
+
+    }
+
+    @Implements(AuthenticatorHelper.class)
+    public static class ShadowAuthenticatorHelper {
+        @Implementation
+        public void onAccountsUpdated(Account[] accounts) {
+
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
index 8453da5..f1ad142 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
@@ -26,8 +26,8 @@
 import android.support.v7.preference.PreferenceGroup;
 import android.support.v7.preference.PreferenceManager;
 import android.support.v7.preference.PreferenceScreen;
-
 import android.text.TextUtils;
+
 import com.android.settings.AccessiblePreferenceCategory;
 import com.android.settings.R;
 import com.android.settings.SettingsPreferenceFragment;
@@ -92,7 +92,7 @@
         when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
         when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
         when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(
-            new AuthenticatorDescription[0]);
+                new AuthenticatorDescription[0]);
         when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
         mController = new AccountPreferenceController(mContext, mFragment, null, mAccountHelper);
     }
@@ -367,6 +367,51 @@
 
     @Test
     @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
+    public void onResume_twoAccountsOfSameName_shouldAddFivePreferences() {
+        final List<UserInfo> infos = new ArrayList<>();
+        infos.add(new UserInfo(1, "user 1", 0));
+        when(mUserManager.isManagedProfile()).thenReturn(false);
+        when(mUserManager.isLinkedUser()).thenReturn(false);
+        when(mUserManager.getProfiles(anyInt())).thenReturn(infos);
+
+        final Account[] accountType1 = new Account[2];
+        accountType1[0] = new Account("Account1", "com.acct1");
+        accountType1[1] = new Account("Account2", "com.acct1");
+        final Account[] accountType2 = new Account[2];
+        accountType2[0] = new Account("Account1", "com.acct2");
+        accountType2[1] = new Account("Account2", "com.acct2");
+        final Account[] allAccounts = new Account[4];
+        allAccounts[0] = accountType1[0];
+        allAccounts[1] = accountType1[1];
+        allAccounts[2] = accountType2[0];
+        allAccounts[3] = accountType2[1];
+        final AuthenticatorDescription[] authDescs = {
+                new AuthenticatorDescription("com.acct1", "com.android.settings",
+                        R.string.account_settings_title, 0, 0, 0, false),
+                new AuthenticatorDescription("com.acct2", "com.android.settings",
+                        R.string.account_settings_title, 0, 0, 0, false)
+        };
+
+        when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(allAccounts);
+        when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class)))
+                .thenReturn(accountType1);
+        when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct2"), any(UserHandle.class)))
+                .thenReturn(accountType2);
+        when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs);
+
+        AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class);
+        when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
+        when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn(
+                preferenceGroup);
+
+        mController.onResume();
+
+        // should add 4 individual account and the Add account preference
+        verify(preferenceGroup, times(5)).addPreference(any(Preference.class));
+    }
+
+    @Test
+    @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
     public void onResume_noAccountChange_shouldNotAddAccountPreference() {
         final List<UserInfo> infos = new ArrayList<>();
         infos.add(new UserInfo(1, "user 1", 0));
@@ -448,6 +493,42 @@
 
     @Test
     @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
+    public void onResume_oneNewAccountType_shouldAddOneAccountPreference() {
+        final List<UserInfo> infos = new ArrayList<>();
+        infos.add(new UserInfo(1, "user 1", 0));
+        infos.add(new UserInfo(2, "user 2", UserInfo.FLAG_MANAGED_PROFILE));
+        when(mUserManager.isManagedProfile()).thenReturn(false);
+        when(mUserManager.isLinkedUser()).thenReturn(false);
+        when(mUserManager.getProfiles(anyInt())).thenReturn(infos);
+
+        AccessiblePreferenceCategory preferenceGroup = mock(AccessiblePreferenceCategory.class);
+        when(preferenceGroup.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
+        when(mAccountHelper.createAccessiblePreferenceCategory(any(Context.class))).thenReturn(
+            preferenceGroup);
+
+        // First time resume will build the UI with no account
+        mController.onResume();
+
+        // Add new account
+        Account[] accounts = {new Account("Acct1", "com.acct1")};
+        when(mAccountManager.getAccountsAsUser(2)).thenReturn(accounts);
+        when(mAccountManager.getAccountsByTypeAsUser(eq("com.acct1"), any(UserHandle.class)))
+            .thenReturn(accounts);
+
+        AuthenticatorDescription[] authDescs = {
+            new AuthenticatorDescription("com.acct1", "com.android.settings",
+                R.string.account_settings_title, 0, 0, 0, false)
+        };
+        when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(authDescs);
+
+        // Resume should show the newly added account
+        mController.onResume();
+
+        verify(preferenceGroup).addPreference(argThat(new PreferenceMatcher("Acct1")));
+    }
+
+    @Test
+    @Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
     public void onResume_oneAccountRemoved_shouldRemoveOneAccountPreference() {
         final List<UserInfo> infos = new ArrayList<>();
         infos.add(new UserInfo(1, "user 1", 0));
diff --git a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
index 68c153c..5a526e7 100644
--- a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
@@ -28,9 +28,12 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -47,10 +50,13 @@
 import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = ShadowEntityHeaderController.class)
 public class AppInfoWithHeaderTest {
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private EntityHeaderController mHeaderController;
 
     private FakeFeatureFactory mFactory;
     private TestFragment mAppInfoWithHeader;
@@ -64,16 +70,16 @@
         when(mFactory.metricsFeatureProvider.getMetricsCategory(any(Object.class)))
                 .thenReturn(MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY);
         mAppInfoWithHeader = new TestFragment();
+        ShadowEntityHeaderController.setUseMock(mHeaderController);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowEntityHeaderController.reset();
     }
 
     @Test
     public void testAppHeaderIsAdded() {
-        final AppHeaderController appHeaderController = new AppHeaderController(
-                ShadowApplication.getInstance().getApplicationContext(),
-                mAppInfoWithHeader,
-                null);
-        when(mFactory.applicationFeatureProvider.newAppHeaderController(mAppInfoWithHeader, null))
-                .thenReturn(appHeaderController);
         mAppInfoWithHeader.onActivityCreated(null);
 
         verify(mAppInfoWithHeader.mScreen).addPreference(any(LayoutPreference.class));
@@ -93,7 +99,7 @@
             mPackageInfo.applicationInfo = new ApplicationInfo();
             mShadowContext = ShadowApplication.getInstance().getApplicationContext();
             ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
-                                             (InstantAppDataProvider) (info -> false));
+                    (InstantAppDataProvider) (info -> false));
             when(mManager.getContext()).thenReturn(mShadowContext);
         }
 
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
index e792845..7421570 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
@@ -17,12 +17,15 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
 import android.provider.SearchIndexableResource;
 
-import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController;
-import com.android.settings.nfc.NfcPreferenceController;
+import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.dashboard.SummaryLoader;
+import com.android.settings.nfc.NfcPreferenceController;
 import com.android.settings.testutils.XmlTestUtils;
 import com.android.settingslib.drawer.CategoryKey;
 
@@ -36,12 +39,17 @@
 
 import java.util.List;
 
+import static android.content.Context.NFC_SERVICE;
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ConnectedDeviceDashboardFragmentTest {
+
     @Mock
     Context mContext;
 
@@ -65,7 +73,8 @@
     @Test
     public void testSearchIndexProvider_shouldIndexResource() {
         final List<SearchIndexableResource> indexRes =
-                mFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(mContext, true /* enabled */);
+                mFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(mContext,
+                        true /* enabled */);
 
         assertThat(indexRes).isNotNull();
         assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
@@ -74,7 +83,8 @@
     @Test
     public void testSearchIndexProvider_NoNfc_KeyAdded() {
         when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(false);
-        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+                mContext);
 
         assertThat(keys).isNotNull();
         assertThat(keys).contains(NfcPreferenceController.KEY_TOGGLE_NFC);
@@ -84,7 +94,8 @@
     @Test
     public void testSearchIndexProvider_NFC_KeyNotAdded() {
         when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(true);
-        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+        final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+                mContext);
 
         assertThat(keys).isNotNull();
         assertThat(keys).doesNotContain(NfcPreferenceController.KEY_TOGGLE_NFC);
@@ -103,4 +114,43 @@
 
         assertThat(keys).containsAllIn(niks);
     }
+
+    @Test
+    public void testSummaryProvider_hasNfc_shouldReturnNfcSummary() {
+        final NfcManager nfcManager = mock(NfcManager.class);
+        final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+
+        when(mContext.getApplicationContext()).thenReturn(mContext);
+        when(mContext.getSystemService(NFC_SERVICE)).thenReturn(nfcManager);
+        when(nfcManager.getDefaultAdapter()).thenReturn(mock(NfcAdapter.class));
+
+        SummaryLoader.SummaryProvider provider =
+                new ConnectedDeviceDashboardFragment.SummaryProvider(mContext, summaryLoader);
+
+        provider.setListening(false);
+
+        verifyZeroInteractions(summaryLoader);
+
+        provider.setListening(true);
+
+        verify(mContext).getString(R.string.connected_devices_dashboard_summary);
+    }
+
+    @Test
+    public void testSummaryProvider_noNfc_shouldReturnNoNfcSummary() {
+        final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+
+        when(mContext.getApplicationContext()).thenReturn(mContext);
+
+        SummaryLoader.SummaryProvider provider =
+                new ConnectedDeviceDashboardFragment.SummaryProvider(mContext, summaryLoader);
+
+        provider.setListening(false);
+
+        verifyZeroInteractions(summaryLoader);
+
+        provider.setListening(true);
+
+        verify(mContext).getString(R.string.connected_devices_dashboard_no_nfc_summary);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 2e49ed2..2d0f031 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -25,11 +25,13 @@
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.applications.AppHeaderController;
-import com.android.settings.applications.AppHeaderController.ActionType;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settings.widget.EntityHeaderController.ActionType;
 import com.android.settingslib.AppItem;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,28 +47,33 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = ShadowEntityHeaderController.class)
 public class AppDataUsageTest {
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private AppHeaderController mHeaderController;
-    private FakeFeatureFactory mFeatureFactory;
+    private EntityHeaderController mHeaderController;
+
     private AppDataUsage mFragment;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         FakeFeatureFactory.setupForTest(mContext);
-        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+    }
+
+    @After
+    public void tearDown() {
+        ShadowEntityHeaderController.reset();
     }
 
     @Test
     public void bindAppHeader_allWorkApps_shouldNotShowAppInfoLink() {
+        ShadowEntityHeaderController.setUseMock(mHeaderController);
         mFragment = spy(new AppDataUsage());
 
         doReturn(mock(PreferenceManager.class, RETURNS_DEEP_STUBS))
@@ -74,8 +81,6 @@
                 .getPreferenceManager();
         doReturn(mock(PreferenceScreen.class)).when(mFragment).getPreferenceScreen();
         ReflectionHelpers.setField(mFragment, "mAppItem", mock(AppItem.class));
-        when(mFeatureFactory.applicationFeatureProvider.newAppHeaderController(mFragment, null))
-                .thenReturn(mHeaderController);
 
         mFragment.onViewCreated(new View(RuntimeEnvironment.application), new Bundle());
 
diff --git a/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java
index 5167c68..9a1a3b6 100644
--- a/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/TelephonyMonitorPreferenceControllerTest.java
@@ -134,7 +134,24 @@
         when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
                 .thenReturn(true);
         SettingsShadowSystemProperties.set(
-                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, "true");
+                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+                TelephonyMonitorPreferenceController.ENABLED_STATUS);
+        SettingsShadowSystemProperties.set(
+                TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
+
+        mController.displayPreference(mScreen);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void displayPreference_telephonyMonitorUserEnabled_shouldCheckedPreference() {
+        when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
+                .thenReturn(true);
+        SettingsShadowSystemProperties.set(
+                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+                TelephonyMonitorPreferenceController.USER_ENABLED_STATUS);
         SettingsShadowSystemProperties.set(
                 TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
 
@@ -149,7 +166,24 @@
         when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
                 .thenReturn(true);
         SettingsShadowSystemProperties.set(
-                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, "false");
+                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+                TelephonyMonitorPreferenceController.DISABLED_STATUS);
+        SettingsShadowSystemProperties.set(
+                TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
+
+        mController.displayPreference(mScreen);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Config(shadows = {SettingsShadowSystemProperties.class})
+    @Test
+    public void displayPreference_telephonyMonitorUserDisabled_shouldUncheckedPreference() {
+        when(mContext.getResources().getBoolean(R.bool.config_show_telephony_monitor))
+                .thenReturn(true);
+        SettingsShadowSystemProperties.set(
+                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+                TelephonyMonitorPreferenceController.USER_DISABLED_STATUS);
         SettingsShadowSystemProperties.set(
                 TelephonyMonitorPreferenceController.BUILD_TYPE, "userdebug");
 
@@ -168,8 +202,10 @@
 
         mController.handlePreferenceTreeClick(mPreference);
 
-        assertThat(SystemProperties.getBoolean(
-                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, false)).isTrue();
+        assertThat(TelephonyMonitorPreferenceController.USER_ENABLED_STATUS.equals(
+                SystemProperties.get(
+                        TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+                        TelephonyMonitorPreferenceController.DISABLED_STATUS))).isTrue();
     }
 
     @Config(shadows = {SettingsShadowSystemProperties.class})
@@ -182,8 +218,10 @@
 
         mController.handlePreferenceTreeClick(mPreference);
 
-        assertThat(SystemProperties.getBoolean(
-                TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR, false)).isFalse();
+        assertThat(TelephonyMonitorPreferenceController.USER_DISABLED_STATUS.equals(
+                SystemProperties.get(
+                        TelephonyMonitorPreferenceController.PROPERTY_TELEPHONY_MONITOR,
+                        TelephonyMonitorPreferenceController.DISABLED_STATUS))).isTrue();
     }
 
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 69bd767..7b2d8cc 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -16,41 +16,28 @@
 
 package com.android.settings.fuelgauge;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
 import android.app.Activity;
-import android.app.Fragment;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.os.BatteryStats;
 import android.os.Bundle;
-import android.view.View;
 
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.applications.AppHeaderController;
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -64,8 +51,21 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = ShadowEntityHeaderController.class)
 public class AdvancedPowerUsageDetailTest {
     private static final String APP_LABEL = "app label";
     private static final String SUMMARY = "summary";
@@ -85,7 +85,7 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Activity mActivity;
     @Mock
-    private AppHeaderController mAppHeaderController;
+    private EntityHeaderController mEntityHeaderController;
     @Mock
     private LayoutPreference mHeaderPreference;
     @Mock
@@ -121,18 +121,17 @@
         doReturn(APP_LABEL).when(mBundle).getString(anyString());
         doReturn(mBundle).when(mFragment).getArguments();
 
-        doReturn(mAppHeaderController).when(mFeatureFactory.applicationFeatureProvider)
-                .newAppHeaderController(any(Fragment.class), any(View.class));
-        doReturn(mAppHeaderController).when(mAppHeaderController).setButtonActions(anyInt(),
-                anyInt());
-        doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any(Drawable.class));
-        doReturn(mAppHeaderController).when(mAppHeaderController).setIcon(any(
+        ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setButtonActions(anyInt(), anyInt());
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setIcon(any(Drawable.class));
+        doReturn(mEntityHeaderController).when(mEntityHeaderController).setIcon(any(
                 ApplicationsState.AppEntry.class));
-        doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(anyString());
-        doReturn(mAppHeaderController).when(mAppHeaderController).setLabel(any(
-                ApplicationsState.AppEntry.class));
-        doReturn(mAppHeaderController).when(mAppHeaderController).setSummary(anyString());
-
+        doReturn(mEntityHeaderController).when(mEntityHeaderController).setLabel(anyString());
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setLabel(any(ApplicationsState.AppEntry.class));
+        doReturn(mEntityHeaderController).when(mEntityHeaderController).setSummary(anyString());
 
         doReturn(UID).when(mBatterySipper).getUid();
         doReturn(APP_LABEL).when(mBatteryEntry).getLabel();
@@ -166,13 +165,18 @@
                 captor.capture(), anyInt(), any(), any());
     }
 
+    @After
+    public void reset() {
+        ShadowEntityHeaderController.reset();
+    }
+
     @Test
     public void testInitHeader_NoAppEntry_BuildByBundle() {
         mFragment.mAppEntry = null;
         mFragment.initHeader();
 
-        verify(mAppHeaderController).setIcon(any(Drawable.class));
-        verify(mAppHeaderController).setLabel(APP_LABEL);
+        verify(mEntityHeaderController).setIcon(any(Drawable.class));
+        verify(mEntityHeaderController).setLabel(APP_LABEL);
     }
 
     @Test
@@ -187,9 +191,9 @@
         mFragment.mAppEntry = mAppEntry;
         mFragment.initHeader();
 
-        verify(mAppHeaderController).setIcon(mAppEntry);
-        verify(mAppHeaderController).setLabel(mAppEntry);
-        verify(mAppHeaderController).setIsInstantApp(false);
+        verify(mEntityHeaderController).setIcon(mAppEntry);
+        verify(mEntityHeaderController).setLabel(mAppEntry);
+        verify(mEntityHeaderController).setIsInstantApp(false);
     }
 
     @Test
@@ -204,10 +208,10 @@
         mFragment.mAppEntry = mAppEntry;
         mFragment.initHeader();
 
-        verify(mAppHeaderController).setIcon(mAppEntry);
-        verify(mAppHeaderController).setLabel(mAppEntry);
-        verify(mAppHeaderController).setIsInstantApp(true);
-        verify(mAppHeaderController).setSummary((CharSequence) null);
+        verify(mEntityHeaderController).setIcon(mAppEntry);
+        verify(mEntityHeaderController).setLabel(mAppEntry);
+        verify(mEntityHeaderController).setIsInstantApp(true);
+        verify(mEntityHeaderController).setSummary((CharSequence) null);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index fd89558..03759ec 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.os.BatteryStats;
 import android.os.Process;
+import android.text.format.DateUtils;
 
 import com.android.internal.os.BatterySipper;
 import com.android.settings.SettingsRobolectricTestRunner;
@@ -47,8 +48,11 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.spy;
 
@@ -62,6 +66,8 @@
     private static final long TIME_STATE_TOP_SLEEPING = 2500 * UNIT;
     private static final long TIME_STATE_FOREGROUND = 3000 * UNIT;
     private static final long TIME_STATE_BACKGROUND = 6000 * UNIT;
+    private static final long TIME_FOREGROUND_ACTIVITY_ZERO = 0;
+    private static final long TIME_FOREGROUND_ACTIVITY = 100 * DateUtils.MINUTE_IN_MILLIS;
 
     private static final int UID = 123;
     private static final long TIME_EXPECTED_FOREGROUND = 1500;
@@ -71,6 +77,7 @@
     private static final double BATTERY_SYSTEM_USAGE = 600;
     private static final double BATTERY_OVERACCOUNTED_USAGE = 500;
     private static final double BATTERY_UNACCOUNTED_USAGE = 700;
+    private static final double BATTERY_APP_USAGE = 100;
     private static final double TOTAL_BATTERY_USAGE = 1000;
     private static final double HIDDEN_USAGE = 200;
     private static final int DISCHARGE_AMOUNT = 80;
@@ -180,11 +187,12 @@
         sippers.add(mUnaccountedBatterySipper);
         when(mProvider.isTypeSystem(mSystemBatterySipper))
                 .thenReturn(true);
+        doNothing().when(mBatteryUtils).smearScreenBatterySipper(any(), any());
 
         final double totalUsage = mBatteryUtils.removeHiddenBatterySippers(sippers);
+
         assertThat(sippers).containsExactly(mNormalBatterySipper);
-        assertThat(totalUsage).isWithin(PRECISION).of(
-                BATTERY_SCREEN_USAGE + BATTERY_SYSTEM_USAGE + BATTERY_UNACCOUNTED_USAGE);
+        assertThat(totalUsage).isWithin(PRECISION).of(BATTERY_SYSTEM_USAGE);
     }
 
     @Test
@@ -206,12 +214,6 @@
     }
 
     @Test
-    public void testShouldHideSipper_TypeWifi_ReturnTrue() {
-        mNormalBatterySipper.drainType = BatterySipper.DrainType.WIFI;
-        assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
-    }
-
-    @Test
     public void testShouldHideSipper_TypeCell_ReturnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.CELL;
         assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
@@ -224,12 +226,6 @@
     }
 
     @Test
-    public void testShouldHideSipper_TypeBluetooth_ReturnTrue() {
-        mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
-        assertThat(mBatteryUtils.shouldHideSipper(mNormalBatterySipper)).isTrue();
-    }
-
-    @Test
     public void testShouldHideSipper_TypeSystem_ReturnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
         when(mNormalBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
@@ -259,4 +255,43 @@
                 HIDDEN_USAGE, DISCHARGE_AMOUNT))
                 .isWithin(PRECISION).of(PERCENT_SYSTEM_USAGE);
     }
+
+    @Test
+    public void testSmearScreenBatterySipper() {
+        final BatterySipper sipperNull = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY_ZERO,
+                BATTERY_APP_USAGE, 0 /* uid */, true /* isUidNull */);
+        final BatterySipper sipperBg = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY_ZERO,
+                BATTERY_APP_USAGE, 1 /* uid */, false /* isUidNull */);
+        final BatterySipper sipperFg = createTestSmearBatterySipper(TIME_FOREGROUND_ACTIVITY,
+                BATTERY_APP_USAGE, 2 /* uid */, false /* isUidNull */);
+
+        final List<BatterySipper> sippers = new ArrayList<>();
+        sippers.add(sipperNull);
+        sippers.add(sipperBg);
+        sippers.add(sipperFg);
+
+        mBatteryUtils.smearScreenBatterySipper(sippers, mScreenBatterySipper);
+
+        assertThat(sipperNull.totalPowerMah).isWithin(PRECISION).of(BATTERY_APP_USAGE);
+        assertThat(sipperBg.totalPowerMah).isWithin(PRECISION).of(BATTERY_APP_USAGE);
+        assertThat(sipperFg.totalPowerMah).isWithin(PRECISION).of(
+                BATTERY_APP_USAGE + BATTERY_SCREEN_USAGE);
+    }
+
+    private BatterySipper createTestSmearBatterySipper(long activityTime, double totalPowerMah,
+            int uidCode, boolean isUidNull) {
+        final BatterySipper sipper = mock(BatterySipper.class);
+        sipper.drainType = BatterySipper.DrainType.APP;
+        sipper.totalPowerMah = totalPowerMah;
+        doReturn(uidCode).when(sipper).getUid();
+        if (!isUidNull) {
+            final BatteryStats.Uid uid = mock(BatteryStats.Uid.class, RETURNS_DEEP_STUBS);
+            doReturn(activityTime).when(mBatteryUtils).getForegroundActivityTotalTimeMs(eq(uid),
+                    anyLong());
+            doReturn(uidCode).when(uid).getUid();
+            sipper.uidObj = uid;
+        }
+
+        return sipper;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index c068d11..efbfbda 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -69,6 +69,7 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -172,6 +173,7 @@
         mFragment.initFeatureProvider();
         mBatteryMeterView = spy(new BatteryMeterView(mRealContext));
         mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0);
+        doNothing().when(mFragment).restartBatteryStatsLoader();
 
         when(mFragment.getActivity()).thenReturn(mSettingsActivity);
         when(mAdditionalBatteryInfoMenu.getItemId())
@@ -367,10 +369,10 @@
     @Test
     public void testSetUsageSummary_timeMoreThanOneMinute_setSummary() {
         final long usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS;
-        doReturn(mRealContext.getText(R.string.battery_used_for)).when(mFragment).getText(
-                R.string.battery_used_for);
+        doReturn(mRealContext.getText(R.string.battery_screen_usage)).when(mFragment).getText(
+                R.string.battery_screen_usage);
         doReturn(mRealContext).when(mFragment).getContext();
-        final String expectedSummary = "Used for 2m";
+        final String expectedSummary = "Screen usage 2m";
 
         mFragment.setUsageSummary(mPreference, usageTimeMs);
 
@@ -575,6 +577,18 @@
     }
 
     @Test
+    public void testOnCreate_BatteryPredictionSkippedWhenDisabled() {
+        PowerUsageFeatureProvider provider = mFeatureFactory.getPowerUsageFeatureProvider(mContext);
+        when(provider.isEnhancedBatteryPredictionEnabled(any())).thenReturn(false);
+        mFragment.mPowerFeatureProvider = provider;
+        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+        mFragment.initializeBatteryEstimateLoader();
+
+        verify(mLoaderManager, never()).initLoader(eq(PowerUsageSummary.BATTERY_ESTIMATE_LOADER),
+                eq(Bundle.EMPTY), any());
+    }
+
+    @Test
     public void testInitAnomalyDetectionIfPossible_detectionEnabled_init() {
         when(mFeatureFactory.powerUsageFeatureProvider.isAnomalyDetectionEnabled()).thenReturn(
                 true);
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
index 9862f83..e83e237 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
@@ -52,12 +52,14 @@
     private FakeFeatureFactory mFactory;
     private AssistGesturePreferenceController mController;
 
+    private static final String KEY_ASSIST = "gesture_assist";
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         FakeFeatureFactory.setupForTest(mContext);
         mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        mController = new AssistGesturePreferenceController(mContext, null);
+        mController = new AssistGesturePreferenceController(mContext, null, KEY_ASSIST);
     }
 
     @Test
@@ -77,7 +79,7 @@
         // Set the setting to be enabled.
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 1);
-        mController = new AssistGesturePreferenceController(context, null);
+        mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST);
 
         assertThat(mController.isSwitchPrefEnabled()).isTrue();
     }
@@ -87,7 +89,7 @@
         // Set the setting to be disabled.
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 0);
-        mController = new AssistGesturePreferenceController(context, null);
+        mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST);
 
         assertThat(mController.isSwitchPrefEnabled()).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java
index bdb3522..d7961e3 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java
@@ -47,11 +47,12 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private PreferenceScreen mScreen;
     private DoubleTapPowerPreferenceController mController;
+    private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mController = new DoubleTapPowerPreferenceController(mContext, null);
+        mController = new DoubleTapPowerPreferenceController(mContext, null, KEY_DOUBLE_TAP_POWER);
     }
 
     @Test
@@ -78,7 +79,7 @@
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(),
                 CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
-        mController = new DoubleTapPowerPreferenceController(context, null);
+        mController = new DoubleTapPowerPreferenceController(context, null, KEY_DOUBLE_TAP_POWER);
 
         assertThat(mController.isSwitchPrefEnabled()).isTrue();
     }
@@ -89,7 +90,7 @@
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(),
                 CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 1);
-        mController = new DoubleTapPowerPreferenceController(context, null);
+        mController = new DoubleTapPowerPreferenceController(context, null, KEY_DOUBLE_TAP_POWER);
 
         assertThat(mController.isSwitchPrefEnabled()).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java
index adf8b75..442d11d 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java
@@ -46,11 +46,13 @@
     private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
     private DoubleTapScreenPreferenceController mController;
 
+    private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mController = new DoubleTapScreenPreferenceController(
-                mContext, null, mAmbientDisplayConfiguration, 0);
+                mContext, null, mAmbientDisplayConfiguration, 0, KEY_DOUBLE_TAP_SCREEN);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
index 9bf6655..8393fc3 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java
@@ -53,11 +53,12 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private SensorManager mSensorManager;
     private DoubleTwistPreferenceController mController;
+    private static final String KEY_DOUBLE_TWIST = "gesture_double_twist";
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mController = new DoubleTwistPreferenceController(mContext, null);
+        mController = new DoubleTwistPreferenceController(mContext, null, KEY_DOUBLE_TWIST);
     }
 
     @Test
@@ -98,7 +99,7 @@
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(),
                 CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1);
-        mController = new DoubleTwistPreferenceController(context, null);
+        mController = new DoubleTwistPreferenceController(context, null, KEY_DOUBLE_TWIST);
 
         assertThat(mController.isSwitchPrefEnabled()).isTrue();
     }
@@ -109,7 +110,7 @@
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(),
                 CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 0);
-        mController = new DoubleTwistPreferenceController(context, null);
+        mController = new DoubleTwistPreferenceController(context, null, KEY_DOUBLE_TWIST);
 
         assertThat(mController.isSwitchPrefEnabled()).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java
index 9dce074..46c0f65 100644
--- a/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java
@@ -47,11 +47,13 @@
 
     private PickupGesturePreferenceController mController;
 
+    private static final String KEY_PICK_UP = "gesture_pick_up";
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mController = new PickupGesturePreferenceController(
-                mContext, null, mAmbientDisplayConfiguration, 0);
+                mContext, null, mAmbientDisplayConfiguration, 0, KEY_PICK_UP);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
index e909667..cf26cb2 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
@@ -45,11 +45,12 @@
     private Context mContext;
 
     private SwipeToNotificationPreferenceController mController;
+    private static final String KEY_SWIPE_DOWN = "gesture_swipe_down_fingerprint";
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mController = new SwipeToNotificationPreferenceController(mContext, null);
+        mController = new SwipeToNotificationPreferenceController(mContext, null, KEY_SWIPE_DOWN);
     }
 
     @Test
@@ -75,7 +76,7 @@
         // Set the setting to be enabled.
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(), SYSTEM_NAVIGATION_KEYS_ENABLED, 1);
-        mController = new SwipeToNotificationPreferenceController(context, null);
+        mController = new SwipeToNotificationPreferenceController(context, null, KEY_SWIPE_DOWN);
 
         assertThat(mController.isSwitchPrefEnabled()).isTrue();
     }
@@ -85,7 +86,7 @@
         // Set the setting to be disabled.
         final Context context = ShadowApplication.getInstance().getApplicationContext();
         Settings.System.putInt(context.getContentResolver(), SYSTEM_NAVIGATION_KEYS_ENABLED, 0);
-        mController = new SwipeToNotificationPreferenceController(context, null);
+        mController = new SwipeToNotificationPreferenceController(context, null, KEY_SWIPE_DOWN);
 
         assertThat(mController.isSwitchPrefEnabled()).isFalse();
     }
diff --git a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
index fe67449..195e007 100644
--- a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
@@ -16,13 +16,6 @@
 
 package com.android.settings.language;
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
@@ -42,6 +35,8 @@
 import com.android.settings.TestConfig;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.SummaryLoader;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.XmlTestUtils;
 import com.android.settings.testutils.shadow.ShadowSecureSettings;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -52,11 +47,21 @@
 import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class LanguageAndInputSettingsTest {
@@ -80,6 +85,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mock(UserManager.class));
         when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mock(InputManager.class));
         when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mIm);
@@ -145,6 +151,37 @@
         verify(loader).setSummary(provider, null);
     }
 
+    @Test
+    public void testNonIndexableKeys_existInXmlLayout() {
+        final Context context = spy(RuntimeEnvironment.application);
+        //(InputManager) context.getSystemService(Context.INPUT_SERVICE);
+        InputManager manager = mock(InputManager.class);
+        when(manager.getInputDeviceIds()).thenReturn(new int[]{});
+        doReturn(manager).when(context).getSystemService(Context.INPUT_SERVICE);
+        final List<String> niks = LanguageAndInputSettings.SEARCH_INDEX_DATA_PROVIDER
+                .getNonIndexableKeys(context);
+        final int xmlId = (new LanguageAndInputSettings()).getPreferenceScreenResId();
+
+        final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
+
+        assertThat(keys).containsAllIn(niks);
+    }
+
+    @Test
+    public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
+        final Context context = RuntimeEnvironment.application;
+        final LanguageAndInputSettings fragment = new LanguageAndInputSettings();
+        final List<String> preferenceScreenKeys = XmlTestUtils.getKeysFromPreferenceXml(context,
+                fragment.getPreferenceScreenResId());
+        final List<String> preferenceKeys = new ArrayList<>();
+
+        for (PreferenceController controller : fragment.getPreferenceControllers(context)) {
+            preferenceKeys.add(controller.getPreferenceKey());
+        }
+
+        assertThat(preferenceScreenKeys).containsAllIn(preferenceKeys);
+    }
+
     /**
      * Test fragment to expose lifecycle and context so we can verify behavior for observables.
      */
diff --git a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
index d1c3207..e7f4968 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
@@ -19,15 +19,18 @@
 import android.provider.SearchIndexableResource;
 import android.view.Menu;
 
+import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
+import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.testutils.XmlTestUtils;
 import com.android.settingslib.drawer.CategoryKey;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
@@ -38,16 +41,23 @@
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class NetworkDashboardFragmentTest {
 
+    @Mock
+    private Context mContext;
+
     private NetworkDashboardFragment mFragment;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         mFragment = new NetworkDashboardFragment();
     }
 
@@ -89,4 +99,58 @@
 
         assertThat(keys).containsAllIn(niks);
     }
-}
+
+    @Test
+    public void testSummaryProvider_hasMobileAndHotspot_shouldReturnMobileSummary() {
+        final MobileNetworkPreferenceController mobileNetworkPreferenceController =
+                mock(MobileNetworkPreferenceController.class);
+        final TetherPreferenceController tetherPreferenceController =
+                mock(TetherPreferenceController.class);
+
+        final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+        final SummaryLoader.SummaryProvider provider =
+                new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader,
+                        mobileNetworkPreferenceController, tetherPreferenceController);
+
+        provider.setListening(false);
+
+        verifyZeroInteractions(summaryLoader);
+
+        when(mobileNetworkPreferenceController.isAvailable()).thenReturn(true);
+        when(tetherPreferenceController.isAvailable()).thenReturn(true);
+
+        provider.setListening(true);
+
+        verify(mContext).getString(R.string.wifi_settings_title);
+        verify(mContext).getString(R.string.network_dashboard_summary_data_usage);
+        verify(mContext).getString(R.string.network_dashboard_summary_hotspot);
+        verify(mContext).getString(R.string.network_dashboard_summary_mobile);
+        verify(mContext, times(3)).getString(R.string.join_many_items_middle, null, null);
+    }
+
+    @Test
+    public void testSummaryProvider_noMobileOrHotspot_shouldReturnSimpleSummary() {
+        final MobileNetworkPreferenceController mobileNetworkPreferenceController =
+                mock(MobileNetworkPreferenceController.class);
+        final TetherPreferenceController tetherPreferenceController =
+                mock(TetherPreferenceController.class);
+
+        final SummaryLoader summaryLoader = mock(SummaryLoader.class);
+        final SummaryLoader.SummaryProvider provider =
+                new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader,
+                        mobileNetworkPreferenceController, tetherPreferenceController);
+
+        provider.setListening(false);
+
+        verifyZeroInteractions(summaryLoader);
+
+        when(mobileNetworkPreferenceController.isAvailable()).thenReturn(false);
+        when(tetherPreferenceController.isAvailable()).thenReturn(false);
+
+        provider.setListening(true);
+
+        verify(mContext).getString(R.string.wifi_settings_title);
+        verify(mContext).getString(R.string.network_dashboard_summary_data_usage);
+        verify(mContext).getString(R.string.join_many_items_middle, null, null);
+    }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java
new file mode 100644
index 0000000..589e2df
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockGenericControllerTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2017 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.password;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+        manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                SettingsShadowResources.class
+        })
+public class ChooseLockGenericControllerTest {
+
+    private ChooseLockGenericController mController;
+
+    @Mock
+    private ManagedLockPasswordProvider mManagedLockPasswordProvider;
+
+    @Mock
+    private DevicePolicyManager mDevicePolicyManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new ChooseLockGenericController(
+                application,
+                0 /* userId */,
+                mDevicePolicyManager,
+                mManagedLockPasswordProvider);
+        SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, false);
+        SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, false);
+    }
+
+    @After
+    public void tearDown() {
+        SettingsShadowResources.reset();
+    }
+
+    @Test
+    public void isScreenLockVisible_shouldRespectResourceConfig() {
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            // All locks except managed defaults to visible
+            assertThat(mController.isScreenLockVisible(lock)).named(lock + " visible")
+                    .isEqualTo(lock != ScreenLockType.MANAGED);
+        }
+
+        SettingsShadowResources.overrideResource(R.bool.config_hide_none_security_option, true);
+        SettingsShadowResources.overrideResource(R.bool.config_hide_swipe_security_option, true);
+        assertThat(mController.isScreenLockVisible(ScreenLockType.NONE)).named("NONE visible")
+                .isFalse();
+        assertThat(mController.isScreenLockVisible(ScreenLockType.SWIPE)).named("SWIPE visible")
+                .isFalse();
+    }
+
+    @Test
+    public void isScreenLockVisible_notCurrentUser_shouldHideSwipe() {
+        mController = new ChooseLockGenericController(application, 1 /* userId */);
+        assertThat(mController.isScreenLockVisible(ScreenLockType.SWIPE)).named("SWIPE visible")
+                .isFalse();
+    }
+
+    @Test
+    public void isScreenLockVisible_managedPasswordChoosable_shouldShowManaged() {
+        doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+
+        assertThat(mController.isScreenLockVisible(ScreenLockType.MANAGED)).named("MANAGED visible")
+                .isTrue();
+    }
+
+    @Test
+    public void isScreenLockEnabled_lowerQuality_shouldReturnFalse() {
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(mController.isScreenLockEnabled(lock, lock.maxQuality + 1))
+                    .named(lock + " enabled")
+                    .isFalse();
+        }
+    }
+
+    @Test
+    public void isScreenLockEnabled_equalQuality_shouldReturnTrue() {
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(mController.isScreenLockEnabled(lock, lock.defaultQuality))
+                    .named(lock + " enabled")
+                    .isTrue();
+        }
+    }
+
+    @Test
+    public void isScreenLockEnabled_higherQuality_shouldReturnTrue() {
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(mController.isScreenLockEnabled(lock, lock.maxQuality - 1))
+                    .named(lock + " enabled")
+                    .isTrue();
+        }
+    }
+
+    @Test
+    public void isScreenLockDisabledByAdmin_lowerQuality_shouldReturnTrue() {
+        doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality + 1))
+                    .named(lock + " disabledByAdmin")
+                    .isTrue();
+        }
+    }
+
+    @Test
+    public void isScreenLockDisabledByAdmin_equalQuality_shouldReturnFalse() {
+        doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality))
+                    .named(lock + " disabledByAdmin")
+                    .isFalse();
+        }
+    }
+
+    @Test
+    public void isScreenLockDisabledByAdmin_higherQuality_shouldReturnFalse() {
+        doReturn(true).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(mController.isScreenLockDisabledByAdmin(lock, lock.maxQuality - 1))
+                    .named(lock + " disabledByAdmin")
+                    .isFalse();
+        }
+    }
+
+    @Test
+    public void isScreenLockDisabledByAdmin_managedNotChoosable_shouldReturnTrue() {
+        doReturn(false).when(mManagedLockPasswordProvider).isManagedPasswordChoosable();
+        assertThat(mController.isScreenLockDisabledByAdmin(
+                ScreenLockType.MANAGED, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
+                .named("MANANGED disabledByAdmin")
+                .isTrue();
+    }
+
+    @Test
+    public void getTitle_shouldContainEnumName() {
+        doReturn("MANAGED").when(mManagedLockPasswordProvider).getPickerOptionTitle(anyBoolean());
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(mController.getTitle(lock).toString())
+                    .containsMatch(Pattern.compile(lock.toString(), Pattern.CASE_INSENSITIVE));
+        }
+    }
+
+    @Test
+    public void getVisibleScreenLockTypes_qualitySomething_shouldReturnPatterPinPassword() {
+        assertThat(mController.getVisibleScreenLockTypes(
+                DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, false))
+                .isEqualTo(Arrays.asList(
+                        ScreenLockType.PATTERN,
+                        ScreenLockType.PIN,
+                        ScreenLockType.PASSWORD));
+    }
+
+    @Test
+    public void getVisibleScreenLockTypes_showDisabled_shouldReturnAllButManaged() {
+        assertThat(mController.getVisibleScreenLockTypes(
+                DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, true))
+                .isEqualTo(Arrays.asList(
+                        ScreenLockType.NONE,
+                        ScreenLockType.SWIPE,
+                        ScreenLockType.PATTERN,
+                        ScreenLockType.PIN,
+                        ScreenLockType.PASSWORD));
+    }
+
+    @Test
+    public void upgradeQuality_noDpmRequirement_shouldReturnQuality() {
+        doReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
+                .when(mDevicePolicyManager).getPasswordQuality(any(ComponentName.class), anyInt());
+
+        int upgradedQuality = mController.upgradeQuality(
+                DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+        assertThat(upgradedQuality).named("upgradedQuality")
+                .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+    }
+
+    @Test
+    public void upgradeQuality_dpmRequirement_shouldReturnRequiredQuality() {
+        doReturn(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC)
+                .when(mDevicePolicyManager).getPasswordQuality(any(ComponentName.class), anyInt());
+
+        int upgradedQuality = mController.upgradeQuality(
+                DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+        assertThat(upgradedQuality).named("upgradedQuality")
+                .isEqualTo(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/password/ScreenLockTypeTest.java b/tests/robotests/src/com/android/settings/password/ScreenLockTypeTest.java
new file mode 100644
index 0000000..96bce00
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/ScreenLockTypeTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 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.password;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.admin.DevicePolicyManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+        manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION)
+public class ScreenLockTypeTest {
+
+    @Test
+    public void fromQuality_shouldReturnLockWithAssociatedQuality() {
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC))
+                .isEqualTo(ScreenLockType.PASSWORD);
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC))
+                .isEqualTo(ScreenLockType.PASSWORD);
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK))
+                .isNull();
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX))
+                .isEqualTo(ScreenLockType.PASSWORD);
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_MANAGED))
+                .isEqualTo(ScreenLockType.MANAGED);
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC))
+                .isEqualTo(ScreenLockType.PIN);
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX))
+                .isEqualTo(ScreenLockType.PIN);
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING))
+                .isEqualTo(ScreenLockType.PATTERN);
+        assertThat(ScreenLockType.fromQuality(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED))
+                .isEqualTo(ScreenLockType.SWIPE);
+    }
+
+    @Test
+    public void fromKey_shouldReturnLockWithGivenKey() {
+        for (ScreenLockType lock : ScreenLockType.values()) {
+            assertThat(ScreenLockType.fromKey(lock.preferenceKey)).isEqualTo(lock);
+        }
+        assertThat(ScreenLockType.fromKey("nonexistent")).isNull();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
new file mode 100644
index 0000000..2436906
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 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.password;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.RuntimeEnvironment.application;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
+import com.android.settings.password.ChooseLockPassword.IntentBuilder;
+import com.android.settings.password.SetupChooseLockPassword.SetupChooseLockPasswordFragment;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
+import com.android.settings.testutils.shadow.ShadowEventLogWriter;
+import com.android.settings.testutils.shadow.ShadowUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowActivity.IntentForResult;
+import org.robolectric.shadows.ShadowDialog;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+        manifest = TestConfig.MANIFEST_PATH,
+        sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                SettingsShadowResources.class,
+                SettingsShadowResources.SettingsShadowTheme.class,
+                ShadowDynamicIndexableContentMonitor.class,
+                ShadowEventLogWriter.class,
+                ShadowUtils.class
+        })
+public class SetupChooseLockPasswordTest {
+
+    @Test
+    public void createActivity_shouldNotCrash() {
+        // Basic sanity test for activity created without crashing
+        Robolectric.buildActivity(SetupChooseLockPassword.class,
+                SetupChooseLockPassword.modifyIntentForSetup(
+                        application,
+                        new IntentBuilder(application).build()))
+                .setup().get();
+    }
+
+    @Test
+    public void createActivity_withShowOptionsButtonExtra_shouldShowButton() {
+        Intent intent = SetupChooseLockPassword.modifyIntentForSetup(
+                application,
+                new IntentBuilder(application).build());
+        intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+        SetupChooseLockPassword activity =
+                Robolectric.buildActivity(SetupChooseLockPassword.class, intent).setup().get();
+
+        Button optionsButton = activity.findViewById(R.id.screen_lock_options);
+        assertThat(optionsButton).isNotNull();
+
+        ShadowActivity shadowActivity = shadowOf(activity);
+        optionsButton.performClick();
+
+        assertThat(ShadowDialog.getLatestDialog()).isNotNull();
+    }
+
+    @Test
+    public void createActivity_clickDifferentOption_extrasShouldBePropagated() {
+        Bundle bundle = new Bundle();
+        bundle.putString("foo", "bar");
+
+        Intent intent = new IntentBuilder(application).build();
+        intent.putExtra(ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS, bundle);
+        intent = SetupChooseLockPassword.modifyIntentForSetup(application, intent);
+        intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+
+        SetupChooseLockPassword activity =
+                Robolectric.buildActivity(SetupChooseLockPassword.class, intent).setup().get();
+
+        SetupChooseLockPasswordFragment fragment =
+                (SetupChooseLockPasswordFragment) activity.getFragmentManager()
+                        .findFragmentById(R.id.main_content);
+        fragment.onLockTypeSelected(ScreenLockType.PATTERN);
+
+        ShadowActivity shadowActivity = shadowOf(activity);
+        IntentForResult chooseLockIntent = shadowActivity.getNextStartedActivityForResult();
+        assertThat(chooseLockIntent).isNotNull();
+        assertThat(chooseLockIntent.requestCode)
+                .isEqualTo(SetupChooseLockPasswordFragment.REQUEST_SCREEN_LOCK_OPTIONS);
+        assertThat(chooseLockIntent.intent.getStringExtra("foo")).named("Foo extra")
+                .isEqualTo("bar");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
index 87eeced..ddbda23 100644
--- a/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
+++ b/tests/robotests/src/com/android/settings/search/BaseSearchIndexProviderTest.java
@@ -108,7 +108,7 @@
             public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
                     boolean enabled) {
                 final SearchIndexableResource sir = new SearchIndexableResource(context);
-                sir.xmlResId = R.xml.language_and_input;
+                sir.xmlResId = R.xml.data_usage;
                 return Arrays.asList(sir);
             }
 
@@ -121,13 +121,7 @@
         final List<String> nonIndexableKeys = provider
                 .getNonIndexableKeys(RuntimeEnvironment.application);
 
-        assertThat(nonIndexableKeys).containsAllOf("phone_language", "spellcheckers_settings",
-                "key_user_dictionary_settings", "gesture_settings_category", "gesture_assist",
-                "gesture_swipe_down_fingerprint", "gesture_double_tap_power",
-                "gesture_double_twist", "gesture_double_tap_screen", "gesture_pick_up",
-                "pointer_speed", "tts_settings",
-                "game_controller_settings_category", "vibrate_input_devices");
+        assertThat(nonIndexableKeys).containsAllOf("status_header", "limit_summary",
+                "restrict_background");
     }
-
-
 }
diff --git a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
index 65b39e6..483dee7 100644
--- a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
@@ -17,11 +17,13 @@
 package com.android.settings.system;
 
 import android.content.Context;
-
 import android.os.UserManager;
+
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.XmlTestUtils;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
@@ -36,7 +38,10 @@
 import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                ShadowUserManager.class
+        })
 public class SystemDashboardFragmentTest {
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 65bb389..6085c1e 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -28,14 +28,13 @@
 import com.android.settings.localepicker.LocaleFeatureProvider;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.overlay.SupportFeatureProvider;
-import com.android.settings.security.SecurityFeatureProvider;
-import com.android.settings.search2.SearchFeatureProvider;
 import com.android.settings.overlay.SurveyFeatureProvider;
+import com.android.settings.search2.SearchFeatureProvider;
+import com.android.settings.security.SecurityFeatureProvider;
 import com.android.settings.users.UserFeatureProvider;
 
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.mockingDetails;
 import static org.mockito.Mockito.when;
 
 /**
@@ -64,7 +63,7 @@
      *
      * @param context The context must be a deep mock.
      */
-    public static void setupForTest(Context context) {
+    public static FakeFeatureFactory setupForTest(Context context) {
         sFactory = null;
         when(context.getString(com.android.settings.R.string.config_featureFactory))
                 .thenReturn(FakeFeatureFactory.class.getName());
@@ -74,6 +73,7 @@
         } catch (ClassNotFoundException e) {
             // Ignore.
         }
+        return (FakeFeatureFactory) FakeFeatureFactory.getFactory(context);
     }
 
     /**
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
index cb02d3e..d4b0ff7 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
@@ -137,6 +137,16 @@
                 realResources, Resources.class, "getInteger", ClassParameter.from(int.class, id));
     }
 
+    @Implementation
+    public boolean getBoolean(int id) {
+        final Object override = sResourceOverrides.get(id);
+        if (override instanceof Boolean) {
+            return (boolean) override;
+        }
+        return Shadow.directlyOn(realResources, Resources.class, "getBoolean",
+                ClassParameter.from(int.class, id));
+    }
+
     @Implements(Theme.class)
     public static class SettingsShadowTheme extends ShadowTheme {
 
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowEntityHeaderController.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowEntityHeaderController.java
new file mode 100644
index 0000000..bccb297
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowEntityHeaderController.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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.testutils.shadow;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.view.View;
+
+import com.android.settings.widget.EntityHeaderController;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(value = EntityHeaderController.class, callThroughByDefault = false)
+public class ShadowEntityHeaderController {
+
+    private static EntityHeaderController sMockController;
+
+    public static void setUseMock(EntityHeaderController mockController) {
+        sMockController = mockController;
+    }
+
+    @Resetter
+    public static void reset() {
+        sMockController = null;
+    }
+
+    @Implementation
+    public static EntityHeaderController newInstance(Context context, Fragment fragment,
+            View header) {
+        return sMockController;
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPowerManagerWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPowerManagerWrapper.java
new file mode 100644
index 0000000..7aa28fa
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPowerManagerWrapper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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.testutils.shadow;
+
+import com.android.settings.display.PowerManagerWrapper;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(PowerManagerWrapper.class)
+public class ShadowPowerManagerWrapper {
+
+    @Implementation
+    public int getMinimumScreenBrightnessSetting() {
+        return 0;
+    }
+
+    @Implementation
+    public int getMaximumScreenBrightnessSetting() {
+        return 0;
+    }
+
+    @Implementation
+    public int getMinimumScreenBrightnessForVrSetting() {
+        return 0;
+    }
+
+    @Implementation
+    public int getMaximumScreenBrightnessForVrSetting() {
+        return 0;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
similarity index 61%
rename from tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
rename to tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
index 8b9b4b4..e6c742a 100644
--- a/tests/robotests/src/com/android/settings/applications/AppHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
@@ -14,17 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.settings.applications;
+package com.android.settings.widget;
 
 
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Fragment;
@@ -43,6 +35,8 @@
 import com.android.settings.R;
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -53,9 +47,17 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class AppHeaderControllerTest {
+public class EntityHeaderControllerTest {
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
@@ -64,16 +66,19 @@
     @Mock
     private Fragment mFragment;
 
+    private FakeFeatureFactory mFeatureFactory;
     private Context mShadowContext;
     private LayoutInflater mLayoutInflater;
     private PackageInfo mInfo;
-    private AppHeaderController mController;
-
+    private EntityHeaderController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
         mShadowContext = RuntimeEnvironment.application;
+        when(mContext.getApplicationContext()).thenReturn(mContext);
         when(mFragment.getContext()).thenReturn(mShadowContext);
         mLayoutInflater = LayoutInflater.from(mShadowContext);
         mInfo = new PackageInfo();
@@ -82,7 +87,7 @@
 
     @Test
     public void testBuildView_constructedWithoutView_shouldCreateNewView() {
-        mController = new AppHeaderController(mShadowContext, mFragment, null);
+        mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
         View view = mController.done(mActivity);
 
         assertThat(view).isNotNull();
@@ -90,7 +95,7 @@
 
     @Test
     public void testBuildView_withContext_shouldBuildPreference() {
-        mController = new AppHeaderController(mShadowContext, mFragment, null);
+        mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
         Preference preference = mController.done(mActivity, mShadowContext);
 
         assertThat(preference instanceof LayoutPreference).isTrue();
@@ -98,8 +103,8 @@
 
     @Test
     public void testBuildView_constructedWithView_shouldReturnSameView() {
-        View inputView = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
-        mController = new AppHeaderController(mShadowContext, mFragment, inputView);
+        View inputView = mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
+        mController = EntityHeaderController.newInstance(mShadowContext, mFragment, inputView);
         View view = mController.done(mActivity);
 
         assertThat(view).isSameAs(inputView);
@@ -108,11 +113,12 @@
     @Test
     public void bindViews_shouldBindAllData() {
         final String testString = "test";
-        final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
-        final TextView label = appHeader.findViewById(R.id.app_detail_title);
-        final TextView version = appHeader.findViewById(R.id.app_detail_summary);
+        final View header = mLayoutInflater.inflate(
+                R.layout.settings_entity_header, null /* root */);
+        final TextView label = header.findViewById(R.id.entity_header_title);
+        final TextView version = header.findViewById(R.id.entity_header_summary);
 
-        mController = new AppHeaderController(mShadowContext, mFragment, appHeader);
+        mController = EntityHeaderController.newInstance(mShadowContext, mFragment, header);
         mController.setLabel(testString);
         mController.setSummary(testString);
         mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
@@ -129,22 +135,22 @@
         info.activityInfo.packageName = "123";
         info.activityInfo.name = "321";
         final View appLinks = mLayoutInflater
-                .inflate(R.layout.app_details, null /* root */);
+                .inflate(R.layout.settings_entity_header, null /* root */);
         when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
                 .thenReturn(info);
 
-        mController = new AppHeaderController(mContext, mFragment, appLinks);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
         mController.setButtonActions(
-                AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
-                AppHeaderController.ActionType.ACTION_NONE);
+                EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
+                EntityHeaderController.ActionType.ACTION_NONE);
         mController.done(mActivity);
 
-        assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
                 .isEqualTo(View.VISIBLE);
-        assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
                 .isEqualTo(View.GONE);
         try {
-            appLinks.findViewById(R.id.left_button).performClick();
+            appLinks.findViewById(android.R.id.button1).performClick();
         } catch (Exception e) {
             // Ignore exception because the launching intent is fake.
         }
@@ -154,94 +160,94 @@
     @Test
     public void bindButton_noAppPref_shouldNotShowButton() {
         final View appLinks = mLayoutInflater
-                .inflate(R.layout.app_details, null /* root */);
+                .inflate(R.layout.settings_entity_header, null /* root */);
         when(mContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
                 .thenReturn(null);
 
-        mController = new AppHeaderController(mContext, mFragment, appLinks);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
         mController.setButtonActions(
-                AppHeaderController.ActionType.ACTION_APP_PREFERENCE,
-                AppHeaderController.ActionType.ACTION_NONE);
+                EntityHeaderController.ActionType.ACTION_APP_PREFERENCE,
+                EntityHeaderController.ActionType.ACTION_NONE);
         mController.done(mActivity);
 
-        assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
                 .isEqualTo(View.GONE);
-        assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
                 .isEqualTo(View.GONE);
     }
 
     @Test
     public void bindButton_noAppInfo_shouldNotShowButton() {
         final View appLinks = mLayoutInflater
-                .inflate(R.layout.app_details, null /* root */);
+                .inflate(R.layout.settings_entity_header, null /* root */);
 
-        mController = new AppHeaderController(mContext, mFragment, appLinks);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
         mController.setPackageName(null)
                 .setButtonActions(
-                        AppHeaderController.ActionType.ACTION_APP_INFO,
-                        AppHeaderController.ActionType.ACTION_NONE);
+                        EntityHeaderController.ActionType.ACTION_APP_INFO,
+                        EntityHeaderController.ActionType.ACTION_NONE);
         mController.done(mActivity);
 
-        assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
                 .isEqualTo(View.GONE);
-        assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
                 .isEqualTo(View.GONE);
     }
 
     @Test
     public void bindButton_hasAppInfo_shouldShowButton() {
         final View appLinks = mLayoutInflater
-                .inflate(R.layout.app_details, null /* root */);
+                .inflate(R.layout.settings_entity_header, null /* root */);
         when(mFragment.getActivity()).thenReturn(mock(Activity.class));
 
-        mController = new AppHeaderController(mContext, mFragment, appLinks);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
         mController.setPackageName("123")
                 .setUid(UserHandle.USER_SYSTEM)
                 .setButtonActions(
-                        AppHeaderController.ActionType.ACTION_APP_INFO,
-                        AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
+                        EntityHeaderController.ActionType.ACTION_APP_INFO,
+                        EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
         mController.done(mActivity);
 
-        assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
                 .isEqualTo(View.VISIBLE);
-        assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
                 .isEqualTo(View.GONE);
     }
 
     @Test
     public void bindButton_hasAppInfo_shouldHaveContentDescription() {
         final View appLinks = mLayoutInflater
-                .inflate(R.layout.app_details, null /* root */);
+                .inflate(R.layout.settings_entity_header, null /* root */);
         when(mFragment.getActivity()).thenReturn(mock(Activity.class));
         when(mContext.getString(eq(R.string.application_info_label))).thenReturn("App Info");
 
-        mController = new AppHeaderController(mContext, mFragment, appLinks);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
         mController.setPackageName("123")
                 .setUid(UserHandle.USER_SYSTEM)
                 .setButtonActions(
-                        AppHeaderController.ActionType.ACTION_APP_INFO,
-                        AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
+                        EntityHeaderController.ActionType.ACTION_APP_INFO,
+                        EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE);
         mController.done(mActivity);
 
-        assertThat(appLinks.findViewById(R.id.left_button).getContentDescription())
+        assertThat(appLinks.findViewById(android.R.id.button1).getContentDescription())
                 .isEqualTo("App Info");
     }
 
     @Test
     public void bindButton_hasAppNotifIntent_shouldShowButton() {
         final View appLinks = mLayoutInflater
-                .inflate(R.layout.app_details, null /* root */);
+                .inflate(R.layout.settings_entity_header, null /* root */);
 
-        mController = new AppHeaderController(mContext, mFragment, appLinks);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, appLinks);
         mController.setAppNotifPrefIntent(new Intent())
                 .setButtonActions(
-                        AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
-                        AppHeaderController.ActionType.ACTION_NONE);
+                        EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
+                        EntityHeaderController.ActionType.ACTION_NONE);
         mController.done(mActivity);
 
-        assertThat(appLinks.findViewById(R.id.left_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button1).getVisibility())
                 .isEqualTo(View.VISIBLE);
-        assertThat(appLinks.findViewById(R.id.right_button).getVisibility())
+        assertThat(appLinks.findViewById(android.R.id.button2).getVisibility())
                 .isEqualTo(View.GONE);
     }
 
@@ -249,31 +255,35 @@
     // app is instant.
     @Test
     public void instantApps_normalAppsDontGetLabel() {
-        final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
-        mController = new AppHeaderController(mContext, mFragment, appHeader);
+        final View header = mLayoutInflater.inflate(
+                R.layout.settings_entity_header, null /* root */);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, header);
         mController.done(mActivity);
-        assertThat(appHeader.findViewById(R.id.install_type).getVisibility())
+
+        assertThat(header.findViewById(R.id.install_type).getVisibility())
                 .isEqualTo(View.GONE);
     }
 
     // Test that the "instant apps" label is present in the header when we have an instant app.
     @Test
     public void instantApps_expectedHeaderItem() {
-        final View appHeader = mLayoutInflater.inflate(R.layout.app_details, null /* root */);
-        mController = new AppHeaderController(mContext, mFragment, appHeader);
+        final View header = mLayoutInflater.inflate(
+                R.layout.settings_entity_header, null /* root */);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, header);
         mController.setIsInstantApp(true);
         mController.done(mActivity);
-        TextView label = appHeader.findViewById(R.id.install_type);
+        TextView label = header.findViewById(R.id.install_type);
+
         assertThat(label.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(label.getText()).isEqualTo(
-                appHeader.getResources().getString(R.string.install_type_instant));
-        assertThat(appHeader.findViewById(R.id.app_detail_summary).getVisibility())
+                header.getResources().getString(R.string.install_type_instant));
+        assertThat(header.findViewById(R.id.entity_header_summary).getVisibility())
                 .isEqualTo(View.GONE);
     }
 
     @Test
     public void styleActionBar_invalidObjects_shouldNotCrash() {
-        mController = new AppHeaderController(mShadowContext, mFragment, null);
+        mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
         mController.styleActionBar(null);
 
         when(mActivity.getActionBar()).thenReturn(null);
@@ -286,7 +296,7 @@
     public void styleActionBar_setElevationAndBackground() {
         final ActionBar actionBar = mActivity.getActionBar();
 
-        mController = new AppHeaderController(mShadowContext, mFragment, null);
+        mController = EntityHeaderController.newInstance(mShadowContext, mFragment, null);
         mController.styleActionBar(mActivity);
 
         verify(actionBar).setElevation(0);
@@ -297,7 +307,7 @@
 
     @Test
     public void initAppHeaderController_appHeaderNull_useFragmentContext() {
-        mController = new AppHeaderController(mContext, mFragment, null);
+        mController = EntityHeaderController.newInstance(mContext, mFragment, null);
 
         // Fragment.getContext() is invoked to inflate the view
         verify(mFragment).getContext();
diff --git a/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java b/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java
new file mode 100644
index 0000000..e074966
--- /dev/null
+++ b/tests/unit/src/com/android/settings/applications/ManageApplicationsLaunchTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.applications;
+
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.allOf;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ManageApplicationsLaunchTest {
+
+    private Instrumentation mInstrumentation;
+
+    @Before
+    public void setUp() {
+        mInstrumentation = InstrumentationRegistry.getInstrumentation();
+    }
+
+    @Test
+    public void launchAppsSettings_shouldShowAppList() throws Exception {
+        final Intent appsSettingsIntent = new
+                Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
+
+        mInstrumentation.startActivitySync(appsSettingsIntent);
+
+        onView(allOf(withText("Calculator"))).check(matches(isDisplayed()));
+    }
+}
diff --git a/tests/unit/src/com/android/settings/applications/ManageApplicationsTest.java b/tests/unit/src/com/android/settings/applications/ManageApplicationsUnitTest.java
similarity index 93%
rename from tests/unit/src/com/android/settings/applications/ManageApplicationsTest.java
rename to tests/unit/src/com/android/settings/applications/ManageApplicationsUnitTest.java
index 92e556e..10c9edb 100644
--- a/tests/unit/src/com/android/settings/applications/ManageApplicationsTest.java
+++ b/tests/unit/src/com/android/settings/applications/ManageApplicationsUnitTest.java
@@ -16,18 +16,22 @@
 
 package com.android.settings.applications;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-
 import android.content.pm.ApplicationInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
 
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppFilter;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
-public class ManageApplicationsTest {
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ManageApplicationsUnitTest {
     @Test
     public void getOverrideFilter_filtersVolumeForAudio() {
         AppFilter filter =