Merge "Fix App name and icon in Settings Battery details."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5721c74..755c6e3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3327,6 +3327,66 @@
                        android:value="com.android.settings.category.ia.device" />
         </activity-alias>
 
+        <activity-alias android:name="ManageApplicationsDashboardAlias"
+                        android:targetActivity="Settings$ManageApplicationsActivity">
+            <intent-filter android:priority="200">
+                <action android:name="com.android.settings.action.SETTINGS" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.apps" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.applications.ManageApplications" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity-alias>
+
+        <activity-alias android:name="AppNotificationDashboardAlias"
+                        android:targetActivity="Settings$NotificationAppListActivity">
+            <intent-filter android:priority="150">
+                <action android:name="com.android.settings.action.SETTINGS"/>
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.apps"/>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.applications.NotificationApps"/>
+        </activity-alias>
+
+        <activity-alias android:name="ConfigureNotificationDashboardAlias"
+                  android:targetActivity="Settings$ConfigureNotificationSettingsActivity">
+            <intent-filter android:priority="120">
+                <action android:name="com.android.settings.action.SETTINGS"/>
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.apps"/>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.notification.ConfigureNotificationSettings" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity-alias>
+
+        <activity android:name=".Settings$UserAndAccountDashboardActivity"
+                  android:label="@string/account_dashboard_title"
+                  android:icon="@drawable/ic_settings_accounts">
+            <intent-filter android:priority="2">
+                <action android:name="com.android.settings.action.SETTINGS"/>
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.accounts.UserAndAccountDashboardFragment"/>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.homepage"/>
+        </activity>
+
+        <activity-alias android:name="UserDashboardAlias"
+                        android:targetActivity="Settings$UserSettingsActivity">
+            <intent-filter android:priority="8">
+                <action android:name="com.android.settings.action.SETTINGS"/>
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.users.UserSettings" />
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.accounts" />
+        </activity-alias>
+
         <!-- End of information architecture host activities -->
 
         <service
diff --git a/res/color/white_disabled.xml b/res/color/white_disabled.xml
new file mode 100644
index 0000000..17008a8
--- /dev/null
+++ b/res/color/white_disabled.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/white"
+        android:alpha="?android:attr/disabledAlpha" />
+</selector>
diff --git a/res/drawable/enrollment_fingerprint_isolated.xml b/res/drawable/enrollment_fingerprint_isolated.xml
index fc31ff8..de3965e 100644
--- a/res/drawable/enrollment_fingerprint_isolated.xml
+++ b/res/drawable/enrollment_fingerprint_isolated.xml
@@ -17,14 +17,14 @@
 <vector
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:name="enrollment_fingerprint_isolated"
-    android:width="75dp"
-    android:viewportWidth="75"
+    android:width="88dp"
     android:height="88dp"
-    android:viewportHeight="88" >
+    android:viewportWidth="176"
+    android:viewportHeight="176" >
     <group
         android:name="fingerprint_ridges_2"
-        android:translateX="37.5835"
-        android:translateY="43.66685" >
+        android:translateX="88"
+        android:translateY="87.66685" >
         <group
             android:name="ridge_5" >
             <path
diff --git a/res/drawable/fingerprint_progress_ring.xml b/res/drawable/fingerprint_progress_ring.xml
deleted file mode 100644
index 44a69e9..0000000
--- a/res/drawable/fingerprint_progress_ring.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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.
--->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@android:id/background">
-        <shape
-            android:innerRadius="?attr/fingerprint_ring_radius"
-            android:shape="ring"
-            android:thickness="@dimen/fingerprint_ring_thickness"
-            android:useLevel="false">
-            <solid android:color="@color/fingerprint_progress_ring_bg" />
-        </shape>
-    </item>
-    <item android:id="@android:id/progress">
-        <shape
-            android:innerRadius="?attr/fingerprint_ring_radius"
-            android:shape="ring"
-            android:thickness="@dimen/fingerprint_ring_thickness">
-            <gradient
-                android:startColor="@color/fingerprint_progress_ring"
-                android:endColor="@color/fingerprint_progress_ring"
-                android:angle="0"
-            />
-        </shape>
-    </item>
-</layer-list>
diff --git a/res/drawable/fp_illustration.xml b/res/drawable/fp_illustration.xml
new file mode 100644
index 0000000..17ab4d2
--- /dev/null
+++ b/res/drawable/fp_illustration.xml
@@ -0,0 +1,28 @@
+<?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
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:id="@+id/fingerprint_background"
+        android:drawable="@drawable/fp_illustration_enrollment" />
+
+    <item
+        android:id="@+id/fingerprint_animation"
+        android:drawable="@drawable/enrollment_fingerprint_isolated_animation" />
+
+</layer-list>
diff --git a/res/drawable/fp_illustration_enrollment.xml b/res/drawable/fp_illustration_enrollment.xml
index f9b7ed4..630c6bd 100644
--- a/res/drawable/fp_illustration_enrollment.xml
+++ b/res/drawable/fp_illustration_enrollment.xml
@@ -16,21 +16,25 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="88.0dp"
         android:height="88.0dp"
-        android:viewportWidth="88.0"
-        android:viewportHeight="88.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M67.74,11.59c-0.41,0.0 -0.82,-0.1 -1.2,-0.31c-7.44,-4.06 -15.0,-6.04 -23.11,-6.04c-7.92,0.0 -14.67,1.85 -21.88,6.01c-1.2,0.69 -2.73,0.28 -3.42,-0.92s-0.28,-2.72 0.92,-3.41c7.9,-4.55 15.65,-6.68 24.37,-6.68c8.97,0.0 17.32,2.17 25.51,6.65c1.21,0.66 1.66,2.18 1.0,3.39C69.48,11.12 68.62,11.59 67.74,11.59z"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M9.25,34.74c-0.48,0.0 -0.96,-0.14 -1.39,-0.42c-1.15,-0.77 -1.45,-2.32 -0.68,-3.47c4.09,-6.09 9.3,-10.89 15.49,-14.27c6.52,-3.55 13.91,-5.43 21.38,-5.43c7.44,0.0 14.8,1.86 21.3,5.39c6.17,3.35 11.38,8.12 15.47,14.16c0.77,1.14 0.47,2.7 -0.67,3.47c-1.14,0.77 -2.7,0.47 -3.47,-0.67c-3.64,-5.38 -8.25,-9.61 -13.71,-12.57c-5.77,-3.13 -12.31,-4.78 -18.92,-4.78c-6.63,0.0 -13.2,1.67 -18.98,4.82c-5.48,2.99 -10.1,7.25 -13.73,12.66C10.85,34.35 10.06,34.74 9.25,34.74z"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M34.76,86.82c-0.67,0.0 -1.33,-0.27 -1.82,-0.79c-3.49,-3.72 -5.51,-6.25 -8.26,-11.45c-2.84,-5.35 -4.34,-11.88 -4.34,-18.86c0.0,-13.02 10.59,-23.61 23.61,-23.61c13.02,0.0 23.61,10.59 23.61,23.61c0.0,1.38 -1.12,2.5 -2.5,2.5s-2.5,-1.12 -2.5,-2.5c0.0,-10.26 -8.35,-18.61 -18.61,-18.61c-10.26,0.0 -18.61,8.35 -18.61,18.61c0.0,6.17 1.3,11.89 3.76,16.52c2.62,4.94 4.37,7.04 7.49,10.37c0.94,1.01 0.89,2.59 -0.11,3.53C35.99,86.6 35.38,86.82 34.76,86.82z"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M64.28,78.84c-4.99,0.0 -9.35,-1.32 -12.98,-3.92c-6.17,-4.43 -9.86,-11.6 -9.86,-19.19c0.0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5c0.0,5.98 2.91,11.64 7.77,15.13c2.8,2.01 6.09,2.98 10.06,2.98c0.97,0.0 2.57,-0.11 4.17,-0.4c1.36,-0.25 2.66,0.64 2.92,2.0c0.25,1.36 -0.64,2.66 -2.0,2.92C66.93,78.8 64.86,78.84 64.28,78.84z"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M55.92,87.75c-0.23,0.0 -0.46,-0.03 -0.7,-0.1c-6.6,-1.91 -10.92,-4.49 -15.4,-9.2c-5.76,-6.06 -8.94,-14.13 -8.94,-22.72c0.0,-7.2 5.86,-13.05 13.05,-13.05c7.2,0.0 13.05,5.86 13.05,13.05c0.0,4.44 3.61,8.05 8.05,8.05s8.05,-3.61 8.05,-8.05c0.0,-16.08 -13.08,-29.16 -29.16,-29.16c-11.43,0.0 -21.86,6.73 -26.58,17.15c-1.57,3.48 -2.37,7.52 -2.37,12.01c0.0,3.36 0.28,8.62 2.71,15.49c0.46,1.3 -0.22,2.73 -1.52,3.19c-1.3,0.46 -2.73,-0.22 -3.19,-1.52c-2.02,-5.7 -3.0,-11.31 -3.0,-17.16c0.0,-5.21 0.95,-9.94 2.82,-14.07c5.52,-12.2 17.74,-20.09 31.13,-20.09c18.83,0.0 34.16,15.32 34.16,34.16c0.0,7.2 -5.86,13.05 -13.05,13.05S52.0,62.92 52.0,55.73c0.0,-4.44 -3.61,-8.05 -8.05,-8.05s-8.05,3.61 -8.05,8.05c0.0,7.3 2.69,14.15 7.56,19.28c3.86,4.06 7.43,6.18 13.17,7.84c1.33,0.38 2.09,1.77 1.71,3.1C58.01,87.04 57.01,87.75 55.92,87.75z"/>
+        android:viewportWidth="176.0"
+        android:viewportHeight="176.0">
+    <group
+        android:translateX="44"
+        android:translateY="44">
+        <path
+            android:fillColor="#FF000000"
+            android:pathData="M67.74,11.59c-0.41,0.0 -0.82,-0.1 -1.2,-0.31c-7.44,-4.06 -15.0,-6.04 -23.11,-6.04c-7.92,0.0 -14.67,1.85 -21.88,6.01c-1.2,0.69 -2.73,0.28 -3.42,-0.92s-0.28,-2.72 0.92,-3.41c7.9,-4.55 15.65,-6.68 24.37,-6.68c8.97,0.0 17.32,2.17 25.51,6.65c1.21,0.66 1.66,2.18 1.0,3.39C69.48,11.12 68.62,11.59 67.74,11.59z"/>
+        <path
+            android:fillColor="#FF000000"
+            android:pathData="M9.25,34.74c-0.48,0.0 -0.96,-0.14 -1.39,-0.42c-1.15,-0.77 -1.45,-2.32 -0.68,-3.47c4.09,-6.09 9.3,-10.89 15.49,-14.27c6.52,-3.55 13.91,-5.43 21.38,-5.43c7.44,0.0 14.8,1.86 21.3,5.39c6.17,3.35 11.38,8.12 15.47,14.16c0.77,1.14 0.47,2.7 -0.67,3.47c-1.14,0.77 -2.7,0.47 -3.47,-0.67c-3.64,-5.38 -8.25,-9.61 -13.71,-12.57c-5.77,-3.13 -12.31,-4.78 -18.92,-4.78c-6.63,0.0 -13.2,1.67 -18.98,4.82c-5.48,2.99 -10.1,7.25 -13.73,12.66C10.85,34.35 10.06,34.74 9.25,34.74z"/>
+        <path
+            android:fillColor="#FF000000"
+            android:pathData="M34.76,86.82c-0.67,0.0 -1.33,-0.27 -1.82,-0.79c-3.49,-3.72 -5.51,-6.25 -8.26,-11.45c-2.84,-5.35 -4.34,-11.88 -4.34,-18.86c0.0,-13.02 10.59,-23.61 23.61,-23.61c13.02,0.0 23.61,10.59 23.61,23.61c0.0,1.38 -1.12,2.5 -2.5,2.5s-2.5,-1.12 -2.5,-2.5c0.0,-10.26 -8.35,-18.61 -18.61,-18.61c-10.26,0.0 -18.61,8.35 -18.61,18.61c0.0,6.17 1.3,11.89 3.76,16.52c2.62,4.94 4.37,7.04 7.49,10.37c0.94,1.01 0.89,2.59 -0.11,3.53C35.99,86.6 35.38,86.82 34.76,86.82z"/>
+        <path
+            android:fillColor="#FF000000"
+            android:pathData="M64.28,78.84c-4.99,0.0 -9.35,-1.32 -12.98,-3.92c-6.17,-4.43 -9.86,-11.6 -9.86,-19.19c0.0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5c0.0,5.98 2.91,11.64 7.77,15.13c2.8,2.01 6.09,2.98 10.06,2.98c0.97,0.0 2.57,-0.11 4.17,-0.4c1.36,-0.25 2.66,0.64 2.92,2.0c0.25,1.36 -0.64,2.66 -2.0,2.92C66.93,78.8 64.86,78.84 64.28,78.84z"/>
+        <path
+            android:fillColor="#FF000000"
+            android:pathData="M55.92,87.75c-0.23,0.0 -0.46,-0.03 -0.7,-0.1c-6.6,-1.91 -10.92,-4.49 -15.4,-9.2c-5.76,-6.06 -8.94,-14.13 -8.94,-22.72c0.0,-7.2 5.86,-13.05 13.05,-13.05c7.2,0.0 13.05,5.86 13.05,13.05c0.0,4.44 3.61,8.05 8.05,8.05s8.05,-3.61 8.05,-8.05c0.0,-16.08 -13.08,-29.16 -29.16,-29.16c-11.43,0.0 -21.86,6.73 -26.58,17.15c-1.57,3.48 -2.37,7.52 -2.37,12.01c0.0,3.36 0.28,8.62 2.71,15.49c0.46,1.3 -0.22,2.73 -1.52,3.19c-1.3,0.46 -2.73,-0.22 -3.19,-1.52c-2.02,-5.7 -3.0,-11.31 -3.0,-17.16c0.0,-5.21 0.95,-9.94 2.82,-14.07c5.52,-12.2 17.74,-20.09 31.13,-20.09c18.83,0.0 34.16,15.32 34.16,34.16c0.0,7.2 -5.86,13.05 -13.05,13.05S52.0,62.92 52.0,55.73c0.0,-4.44 -3.61,-8.05 -8.05,-8.05s-8.05,3.61 -8.05,8.05c0.0,7.3 2.69,14.15 7.56,19.28c3.86,4.06 7.43,6.18 13.17,7.84c1.33,0.38 2.09,1.77 1.71,3.1C58.01,87.04 57.01,87.75 55.92,87.75z"/>
+    </group>
 </vector>
diff --git a/res/drawable/ring_progress.xml b/res/drawable/ring_progress.xml
new file mode 100644
index 0000000..02fcd5b
--- /dev/null
+++ b/res/drawable/ring_progress.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background">
+        <shape
+            android:innerRadiusRatio="2.2"
+            android:shape="ring"
+            android:thickness="@dimen/ring_progress_bar_thickness"
+            android:useLevel="false"
+            android:tint="?android:colorControlNormal">
+            <solid android:color="@color/white_disabled" />
+        </shape>
+    </item>
+    <item android:id="@android:id/progress">
+        <rotate
+            android:fromDegrees="270"
+            android:pivotX="50%"
+            android:pivotY="50%"
+            android:toDegrees="270">
+            <shape
+                android:innerRadiusRatio="2.2"
+                android:shape="ring"
+                android:thickness="@dimen/ring_progress_bar_thickness"
+                android:tint="?android:attr/colorControlActivated">
+                <solid android:color="@android:color/white" />
+            </shape>
+        </rotate>
+    </item>
+</layer-list>
diff --git a/res/layout-land/fingerprint_enroll_enrolling.xml b/res/layout-land/fingerprint_enroll_enrolling.xml
index ba0f803..27af681 100644
--- a/res/layout-land/fingerprint_enroll_enrolling.xml
+++ b/res/layout-land/fingerprint_enroll_enrolling.xml
@@ -49,7 +49,7 @@
                 android:layout_height="wrap_content"
                 android:layout_marginStart="0dp"
                 android:layout_marginEnd="0dp"
-                android:src="@drawable/ic_lock" />
+                android:src="@drawable/ic_fingerprint_header" />
 
             <TextView
                 android:id="@+id/suw_layout_title"
@@ -97,8 +97,8 @@
             android:layout_height="match_parent">
 
             <include layout="@layout/fingerprint_enroll_enrolling_content"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
                 android:layout_gravity="center"/>
 
             <TextView
diff --git a/res/layout-land/fingerprint_enroll_find_sensor.xml b/res/layout-land/fingerprint_enroll_find_sensor.xml
index 0a3a33f..b64b27f 100644
--- a/res/layout-land/fingerprint_enroll_find_sensor.xml
+++ b/res/layout-land/fingerprint_enroll_find_sensor.xml
@@ -50,7 +50,7 @@
                     android:layout_height="wrap_content"
                     android:layout_marginStart="0dp"
                     android:layout_marginEnd="0dp"
-                    android:src="@drawable/ic_lock" />
+                    android:src="@drawable/ic_fingerprint_header" />
 
                 <TextView
                     android:id="@+id/suw_layout_title"
diff --git a/res/layout/fingerprint_enroll_enrolling_base.xml b/res/layout/fingerprint_enroll_enrolling_base.xml
index e9e3385..33a5acf 100644
--- a/res/layout/fingerprint_enroll_enrolling_base.xml
+++ b/res/layout/fingerprint_enroll_enrolling_base.xml
@@ -55,8 +55,9 @@
         </FrameLayout>
 
         <include layout="@layout/fingerprint_enroll_enrolling_content"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
+            android:layout_width="@dimen/fingerprint_progress_bar_max_size"
+            android:layout_height="0dp"
+            android:layout_weight="1"
             android:layout_gravity="center_horizontal"
             android:layout_marginTop="@dimen/fingerprint_enrolling_content_margin_top"/>
 
diff --git a/res/layout/fingerprint_enroll_enrolling_content.xml b/res/layout/fingerprint_enroll_enrolling_content.xml
index 42769d1..1622f3f 100644
--- a/res/layout/fingerprint_enroll_enrolling_content.xml
+++ b/res/layout/fingerprint_enroll_enrolling_content.xml
@@ -15,32 +15,11 @@
   ~ limitations under the License
   -->
 
-<RelativeLayout
+<com.android.settings.widget.RingProgressBar
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/fingerprint_progress_bar"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_gravity="center_horizontal">
-
-    <ImageView
-        android:id="@+id/fingerprint_animator"
-        android:layout_width="@dimen/fingerprint_animation_size"
-        android:layout_height="@dimen/fingerprint_animation_size"
-        android:layout_centerInParent="true"
-        android:background="@drawable/fp_illustration_enrollment"
-        android:backgroundTint="@color/fingerprint_indicator_background_resting"
-        android:src="@drawable/enrollment_fingerprint_isolated_animation"/>
-
-    <ProgressBar
-        android:id="@+id/fingerprint_progress_bar"
-        android:layout_width="?attr/fingerprint_progress_bar_size"
-        android:layout_height="?attr/fingerprint_progress_bar_size"
-        android:layout_centerInParent="true"
-        style="?android:attr/progressBarStyleHorizontal"
-        android:max="10000"
-        android:mirrorForRtl="false"
-        android:progress="0"
-        android:indeterminate="false"
-        android:progressDrawable="@drawable/fingerprint_progress_ring"
-        android:rotation="-90"/>
-
-</RelativeLayout>
+    android:background="@drawable/fp_illustration"
+    android:minHeight="@dimen/fingerprint_progress_bar_min_size"
+    android:progress="0" />
diff --git a/res/layout/see_all.xml b/res/layout/see_all.xml
deleted file mode 100644
index 44b263c..0000000
--- a/res/layout/see_all.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 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:background="?android:attr/selectableItemBackground"
-        android:gravity="center_vertical"
-        android:minHeight="@dimen/dashboard_tile_minimum_height"
-        android:clickable="true"
-        android:focusable="true">
-
-    <View
-            android:layout_width="@dimen/dashboard_tile_image_size"
-            android:layout_height="@dimen/dashboard_tile_image_size"
-            android:layout_marginStart="@dimen/dashboard_tile_image_margin_start"
-            android:layout_marginEnd="@dimen/dashboard_tile_image_margin_end"
-            android:visibility="invisible" />
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="vertical">
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="0dip"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-            android:layout_weight="1">
-
-            <RelativeLayout
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content">
-
-                <TextView android:id="@android:id/title"
-                          android:layout_width="wrap_content"
-                          android:layout_height="wrap_content"
-                          android:singleLine="true"
-                          android:textAppearance="@android:style/TextAppearance.Material.Widget.Button.Inverse"
-                          android:textColor="?android:attr/colorAccent"
-                          android:ellipsize="marquee"
-                          android:fadingEdge="horizontal" />
-
-            </RelativeLayout>
-
-        </LinearLayout>
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/res/values-sw400dp/dimens.xml b/res/values-sw400dp/dimens.xml
index da58a9c..7ae4061 100755
--- a/res/values-sw400dp/dimens.xml
+++ b/res/values-sw400dp/dimens.xml
@@ -16,16 +16,10 @@
   -->
 
 <resources>
-    <dimen name="fingerprint_ring_radius">106dp</dimen>
-    <dimen name="fingerprint_animation_size">100dp</dimen>
-    <dimen name="fingerprint_progress_bar_size">220dp</dimen>
     <dimen name="fingerprint_enrolling_content_margin_top">56dp</dimen>
     <dimen name="fingerprint_in_app_indicator_size">176dp</dimen>
     <dimen name="fingerprint_find_sensor_graphic_size">240dp</dimen>
 
-    <dimen name="setup_fingerprint_ring_radius">92dp</dimen>
-    <dimen name="setup_fingerprint_progress_bar_size">192dp</dimen>
-
     <dimen name="support_escalation_card_padding_start">56dp</dimen>
     <dimen name="support_escalation_card_padding_end">56dp</dimen>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 9f3dd5b..3be4038 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -53,8 +53,6 @@
     <color name="fingerprint_title_area_bg">?android:attr/colorAccent</color>
     <color name="fingerprint_title_color">#ffffffff</color>
     <color name="fingerprint_message_color">#de000000</color>
-    <color name="fingerprint_progress_ring">?android:attr/colorAccent</color>
-    <color name="fingerprint_progress_ring_bg">#20000000</color>
     <color name="fingerprint_indicator_background_resting">#12000000</color>
 
     <color name="running_processes_system_ram">#ff384248</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index b266f9c..40f3f71 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -67,6 +67,7 @@
 
     <dimen name="captioning_preview_height">200dp</dimen>
 
+    <dimen name="ring_progress_bar_thickness">4dp</dimen>
     <dimen name="settings_side_margin">0dip</dimen>
 
     <!-- Weight of the left pane in a multi-pane preference layout. -->
@@ -221,8 +222,6 @@
     <dimen name="redaction_vertical_margins">8dp</dimen>
 
     <!-- Fingerprint -->
-    <dimen name="fingerprint_ring_radius">92dip</dimen>
-    <dimen name="fingerprint_ring_thickness">4dip</dimen>
     <dimen name="fingerprint_dot_radius">8dp</dimen>
     <dimen name="fingerprint_pulse_radius">50dp</dimen>
     <item name="fingerprint_sensor_location_fraction_x" type="fraction">50%</item>
@@ -233,15 +232,13 @@
     <dimen name="fingerprint_error_text_appear_distance">16dp</dimen>
     <dimen name="fingerprint_error_text_disappear_distance">-8dp</dimen>
     <dimen name="fingerprint_animation_size">88dp</dimen>
-    <dimen name="fingerprint_progress_bar_size">192dp</dimen>
+    <dimen name="fingerprint_progress_bar_max_size">220dp</dimen>
+    <dimen name="fingerprint_progress_bar_min_size">120dp</dimen>
     <dimen name="fingerprint_enrolling_content_margin_top">36dp</dimen>
     <dimen name="fingerprint_in_app_indicator_size">124dp</dimen>
     <dimen name="fingerprint_in_app_indicator_min_size">124dp</dimen>
     <dimen name="fingerprint_in_app_indicator_max_size">264dp</dimen>
 
-    <dimen name="setup_fingerprint_ring_radius">80dip</dimen>
-    <dimen name="setup_fingerprint_progress_bar_size">168dp</dimen>
-
     <dimen name="confirm_credentials_security_method_margin">48dp</dimen>
     <dimen name="confirm_credentials_layout_width">@dimen/match_parent</dimen>
     <dimen name="confirm_credentials_top_padding">0dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c5e45c03..b0e7b6b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5931,6 +5931,8 @@
     <string name="connected_devices_dashboard_title">Connected devices</string>
     <!-- Title for setting tile leading to Apps & Notification settings [CHAR LIMIT=40]-->
     <string name="app_and_notification_dashboard_title">Apps &amp; notifications</string>
+    <!-- Title for setting tile leading to User and accounts settings [CHAR LIMIT=40]-->
+    <string name="account_dashboard_title">User &amp; accounts</string>
     <!-- Summary text for system preference tile, showing current display language of device [CHAR LIMIT=NONE]-->
     <string name="system_dashboard_summary">Language: <xliff:g id="language">%1$s</xliff:g></string>
 
@@ -7283,11 +7285,6 @@
     <!-- Conversation message timestamp of the messaging app preview screen. [CHAR LIMIT=20] -->
     <string name="screen_zoom_conversation_timestamp_4">Tue 6:03PM</string>
 
-    <!-- Button to show all top-level settings items [CHAR LIMIT=20] -->
-    <string name="see_all">See all</string>
-    <!-- Button to show less top-level settings items [CHAR LIMIT=20] -->
-    <string name="see_less">See less</string>
-
     <!-- Wi-Fi state - Disconnected [CHAR LIMIT=NONE] -->
     <string name="disconnected">Disconnected</string>
 
diff --git a/res/values/styles.xml b/res/values/styles.xml
index fc37bb0..0f957a8 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -445,4 +445,11 @@
         <item name="android:lineSpacingMultiplier">1.2</item>
     </style>
 
+    <style name="RingProgressBarStyle" parent="android:style/Widget.Material.ProgressBar.Horizontal">
+        <item name="android:indeterminate">false</item>
+        <item name="android:max">10000</item>
+        <item name="android:mirrorForRtl">false</item>
+        <item name="android:progressDrawable">@drawable/ring_progress</item>
+    </style>
+
 </resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 35d05fb..a5ff54a 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -16,8 +16,6 @@
 
 <resources>
     <attr name="fingerprint_layout_theme" format="reference" />
-    <attr name="fingerprint_progress_bar_size" format="reference|dimension" />
-    <attr name="fingerprint_ring_radius" format="reference|dimension" />
     <attr name="ic_menu_moreoverflow" format="reference" />
     <attr name="ic_wps" format="reference" />
     <attr name="setup_divider_color" format="reference" />
@@ -38,8 +36,6 @@
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
-        <item name="fingerprint_progress_bar_size">@dimen/setup_fingerprint_progress_bar_size</item>
-        <item name="fingerprint_ring_radius">@dimen/setup_fingerprint_ring_radius</item>
         <item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_material</item>
         <item name="ic_wps">@drawable/ic_wps_dark</item>
         <item name="setup_divider_color">@color/setup_divider_color_dark</item>
@@ -62,8 +58,6 @@
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
-        <item name="fingerprint_progress_bar_size">@dimen/setup_fingerprint_progress_bar_size</item>
-        <item name="fingerprint_ring_radius">@dimen/setup_fingerprint_ring_radius</item>
         <item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_material</item>
         <item name="ic_wps">@drawable/ic_wps_light</item>
         <item name="setup_divider_color">@color/setup_divider_color_light</item>
@@ -141,8 +135,6 @@
         <item name="*android:preferenceFragmentPaddingSide">@dimen/settings_side_margin</item>
 
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
-        <item name="fingerprint_progress_bar_size">@dimen/fingerprint_progress_bar_size</item>
-        <item name="fingerprint_ring_radius">@dimen/fingerprint_ring_radius</item>
         <item name="ic_menu_moreoverflow">@*android:drawable/ic_menu_moreoverflow_holo_dark</item>
         <item name="ic_wps">@drawable/ic_wps_light</item>
         <item name="wifi_signal">@drawable/wifi_signal</item>
diff --git a/res/xml/advanced_apps.xml b/res/xml/advanced_apps.xml
index 405d5af..7b1af10 100644
--- a/res/xml/advanced_apps.xml
+++ b/res/xml/advanced_apps.xml
@@ -19,10 +19,12 @@
     xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
     android:key="applications_settings">
 
-    <PreferenceScreen
+    <Preference
         android:key="manage_perms"
         android:title="@string/app_permissions"
-        settings:keywords="@string/keywords_app_permissions" />
+        settings:keywords="@string/keywords_app_permissions">
+        <intent android:action="android.intent.action.MANAGE_PERMISSIONS"/>
+    </Preference>
 
     <PreferenceCategory
         android:title="@string/default_apps_title">
diff --git a/res/xml/app_and_notification.xml b/res/xml/app_and_notification.xml
index 5da902f..4aa109e 100644
--- a/res/xml/app_and_notification.xml
+++ b/res/xml/app_and_notification.xml
@@ -15,6 +15,16 @@
   limitations under the License.
   -->
 
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+    <Preference
+        android:key="manage_perms"
+        android:title="@string/app_permissions"
+        android:order="-130"
+        settings:keywords="@string/keywords_app_permissions">
+        <intent android:action="android.intent.action.MANAGE_PERMISSIONS"/>
+    </Preference>
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index bfecbbf..451c7e3 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -168,6 +168,7 @@
     public static class ConnectedDeviceDashboardActivity extends SettingsActivity {}
     public static class AppAndNotificationDashboardActivity extends SettingsActivity {}
     public static class StorageDashboardActivity extends SettingsActivity {}
+    public static class UserAndAccountDashboardActivity extends SettingsActivity {}
     public static class SystemDashboardActivity extends SettingsActivity {}
     public static class SupportDashboardActivity extends SettingsActivity {}
 
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 5452f91..34dd095 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -61,6 +61,7 @@
 import com.android.settings.accounts.AccountSyncSettings;
 import com.android.settings.accounts.ChooseAccountActivity;
 import com.android.settings.accounts.ManagedProfileSettings;
+import com.android.settings.accounts.UserAndAccountDashboardFragment;
 import com.android.settings.applications.AppAndNotificationDashboardFragment;
 import com.android.settings.applications.AdvancedAppSettings;
 import com.android.settings.applications.DrawOverlayDetails;
@@ -279,8 +280,11 @@
             "com.android.settings.Settings.DisplayDashboardAlias",
             "com.android.settings.Settings.SoundDashboardAlias",
             "com.android.settings.Settings.SecurityDashboardAlias",
+            Settings.UserAndAccountDashboardActivity.class.getName(),
             Settings.SystemDashboardActivity.class.getName(),
             Settings.SupportDashboardActivity.class.getName(),
+            // Home page > Apps & Notifications
+            "com.android.settings.Settings.ManageApplicationsDashboardAlias",
             // Home page > Network & Internet
             "com.android.settings.Settings.WifiDashboardAlias",
             "com.android.settings.Settings.DataUsageDashboardAlias",
@@ -289,7 +293,6 @@
             "com.android.settings.Settings.DateTimeDashboardAlias",
             "com.android.settings.Settings.AccessibilityDashboardAlias",
             "com.android.settings.Settings.AboutDeviceDashboardAlias",
-
     };
 
     private static final String[] ENTRY_FRAGMENTS = {
@@ -395,6 +398,7 @@
             NetworkDashboardFragment.class.getName(),
             ConnectedDeviceDashboardFragment.class.getName(),
             AppAndNotificationDashboardFragment.class.getName(),
+            UserAndAccountDashboardFragment.class.getName(),
     };
 
 
diff --git a/src/com/android/settings/accounts/UserAndAccountDashboardFragment.java b/src/com/android/settings/accounts/UserAndAccountDashboardFragment.java
new file mode 100644
index 0000000..34d6dc4
--- /dev/null
+++ b/src/com/android/settings/accounts/UserAndAccountDashboardFragment.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.accounts;
+
+import android.content.Context;
+
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.drawer.CategoryKey;
+
+import java.util.List;
+
+public class UserAndAccountDashboardFragment extends DashboardFragment {
+
+    private static final String TAG = "UserAndAccountDashboard";
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsEvent.ACCOUNT;
+    }
+
+    @Override
+    protected String getCategoryKey() {
+        return CategoryKey.CATEGORY_ACCOUNT;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.account_settings;
+    }
+
+    @Override
+    protected List<PreferenceController> getPreferenceControllers(Context context) {
+        return null;
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/settings/applications/AdvancedAppSettings.java b/src/com/android/settings/applications/AdvancedAppSettings.java
index db9d8de..59c1fbe 100644
--- a/src/com/android/settings/applications/AdvancedAppSettings.java
+++ b/src/com/android/settings/applications/AdvancedAppSettings.java
@@ -15,57 +15,48 @@
  */
 package com.android.settings.applications;
 
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.provider.SearchIndexableResource;
-import android.support.v7.preference.Preference;
+
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
-import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-public class AdvancedAppSettings extends SettingsPreferenceFragment implements
-        Indexable {
+public class AdvancedAppSettings extends DashboardFragment {
 
     static final String TAG = "AdvancedAppSettings";
 
-    private static final String KEY_APP_PERM = "manage_perms";
-    private static final String KEY_APP_DOMAIN_URLS = "domain_urls";
-    private static final String KEY_HIGH_POWER_APPS = "high_power_apps";
-    private static final String KEY_SYSTEM_ALERT_WINDOW = "system_alert_window";
-    private static final String KEY_WRITE_SETTINGS_APPS = "write_settings_apps";
-
-    private Preference mAppPermsPreference;
-    private Preference mAppDomainURLsPreference;
-    private Preference mHighPowerPreference;
-    private Preference mSystemAlertWindowPreference;
-    private Preference mWriteSettingsPreference;
-
-    private BroadcastReceiver mPermissionReceiver;
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        addPreferencesFromResource(R.xml.advanced_apps);
+    }
 
-        Preference permissions = getPreferenceScreen().findPreference(KEY_APP_PERM);
-        permissions.setIntent(new Intent(Intent.ACTION_MANAGE_PERMISSIONS));
+    @Override
+    protected String getCategoryKey() {
+        return "";
+    }
 
-        mAppPermsPreference = findPreference(KEY_APP_PERM);
-        mAppDomainURLsPreference = findPreference(KEY_APP_DOMAIN_URLS);
-        mHighPowerPreference = findPreference(KEY_HIGH_POWER_APPS);
-        mSystemAlertWindowPreference = findPreference(KEY_SYSTEM_ALERT_WINDOW);
-        mWriteSettingsPreference = findPreference(KEY_WRITE_SETTINGS_APPS);
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.advanced_apps;
+    }
+
+    @Override
+    protected List<PreferenceController> getPreferenceControllers(Context context) {
+        return null;
     }
 
     @Override
@@ -73,25 +64,6 @@
         return MetricsEvent.APPLICATIONS_ADVANCED;
     }
 
-    private final PermissionsResultCallback mPermissionCallback = new PermissionsResultCallback() {
-        @Override
-        public void onAppWithPermissionsCountsResult(int standardGrantedPermissionAppCount,
-                int standardUsedPermissionAppCount) {
-            if (getActivity() == null) {
-                return;
-            }
-            mPermissionReceiver = null;
-            if (standardUsedPermissionAppCount != 0) {
-                mAppPermsPreference.setSummary(getContext().getString(
-                        R.string.app_permissions_summary,
-                        standardGrantedPermissionAppCount,
-                        standardUsedPermissionAppCount));
-            } else {
-                mAppPermsPreference.setSummary(null);
-            }
-        }
-    };
-
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider() {
                 @Override
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index f501dfa..9ea48b0 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -20,6 +20,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
+import android.support.v7.util.DiffUtil;
 import android.support.v7.widget.PopupMenu;
 import android.support.v7.widget.RecyclerView;
 import android.text.TextUtils;
@@ -34,7 +35,6 @@
 import android.widget.TextView;
 
 import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.internal.util.ArrayUtils;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.instrumentation.MetricsFeatureProvider;
@@ -48,82 +48,92 @@
 import java.util.List;
 
 public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.DashboardItemHolder>
-        implements View.OnClickListener, SummaryLoader.SummaryConsumer {
+        implements SummaryLoader.SummaryConsumer {
     public static final String TAG = "DashboardAdapter";
     private static final String STATE_SUGGESTION_LIST = "suggestion_list";
     private static final String STATE_CATEGORY_LIST = "category_list";
-    private static final String STATE_IS_SHOWING_ALL = "is_showing_all";
     private static final String STATE_SUGGESTION_MODE = "suggestion_mode";
-    private static final int NS_SPACER = 0;
-    private static final int NS_SUGGESTION = 1000;
-    private static final int NS_ITEMS = 2000;
-    private static final int NS_CONDITION = 3000;
 
-    private static int SUGGESTION_MODE_DEFAULT = 0;
-    private static int SUGGESTION_MODE_COLLAPSED = 1;
-    private static int SUGGESTION_MODE_EXPANDED = 2;
-
-    private static final int DEFAULT_SUGGESTION_COUNT = 2;
-
-    private final List<Object> mItems = new ArrayList<>();
-    private final List<Integer> mTypes = new ArrayList<>();
-    private final List<Integer> mIds = new ArrayList<>();
     private final IconCache mCache;
-
     private final Context mContext;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
-
-    private List<DashboardCategory> mCategories;
-    private List<Condition> mConditions;
-    private List<Tile> mSuggestions;
-
-    private boolean mIsShowingAll;
-    // Used for counting items;
-    private int mId;
-
-    private int mSuggestionMode = SUGGESTION_MODE_DEFAULT;
-
-    private Condition mExpandedCondition = null;
+    private DashboardData mDashboardData;
     private SuggestionParser mSuggestionParser;
 
+    private View.OnClickListener mTileClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            //TODO: get rid of setTag/getTag
+            final Tile tile = (Tile) mDashboardData.getItemEntityByPosition((int) v.getTag());
+            ((SettingsActivity) mContext).openTile(tile);
+        }
+    };
+
+    private View.OnClickListener mConditionClickListener = new View.OnClickListener() {
+
+        @Override
+        public void onClick(View v) {
+            Condition expandedCondition = mDashboardData.getExpandedCondition();
+
+            //TODO: get rid of setTag/getTag
+            if (v.getTag() == expandedCondition) {
+                mMetricsFeatureProvider.action(mContext,
+                        MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK,
+                        expandedCondition.getMetricsConstant());
+                expandedCondition.onPrimaryClick();
+            } else {
+                expandedCondition = (Condition) v.getTag();
+                mMetricsFeatureProvider.action(mContext,
+                        MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
+                        expandedCondition.getMetricsConstant());
+
+                updateExpandedCondition(expandedCondition);
+            }
+        }
+    };
+
     public DashboardAdapter(Context context, SuggestionParser parser,
             MetricsFeatureProvider metricsFeatureProvider, Bundle savedInstanceState,
             List<Condition> conditions) {
+        List<Tile> suggestions = null;
+        List<DashboardCategory> categories = null;
+        int suggestionMode = DashboardData.SUGGESTION_MODE_DEFAULT;
+
         mContext = context;
         mMetricsFeatureProvider = metricsFeatureProvider;
         mCache = new IconCache(context);
         mSuggestionParser = parser;
-        mConditions = conditions;
 
         setHasStableIds(true);
 
-        boolean showAll = true;
         if (savedInstanceState != null) {
-            mSuggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
-            mCategories = savedInstanceState.getParcelableArrayList(STATE_CATEGORY_LIST);
-            showAll = savedInstanceState.getBoolean(STATE_IS_SHOWING_ALL, true);
-            mSuggestionMode = savedInstanceState.getInt(
-                    STATE_SUGGESTION_MODE, SUGGESTION_MODE_DEFAULT);
+            suggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
+            categories = savedInstanceState.getParcelableArrayList(STATE_CATEGORY_LIST);
+            suggestionMode = savedInstanceState.getInt(
+                    STATE_SUGGESTION_MODE, DashboardData.SUGGESTION_MODE_DEFAULT);
         }
-        setShowingAll(showAll);
+
+        mDashboardData = new DashboardData.Builder()
+                .setConditions(conditions)
+                .setSuggestions(suggestions)
+                .setCategories(categories)
+                .setSuggestionMode(suggestionMode)
+                .build();
     }
 
     public List<Tile> getSuggestions() {
-        return mSuggestions;
+        return mDashboardData.getSuggestions();
     }
 
     public void setCategoriesAndSuggestions(List<DashboardCategory> categories,
             List<Tile> suggestions) {
-        mSuggestions = suggestions;
-        mCategories = categories;
-
         // TODO: Better place for tinting?
         TypedValue tintColor = new TypedValue();
         mContext.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent,
                 tintColor, true);
         for (int i = 0; i < categories.size(); i++) {
             for (int j = 0; j < categories.get(i).tiles.size(); j++) {
-                Tile tile = categories.get(i).tiles.get(j);
+                final Tile tile = categories.get(i).tiles.get(j);
 
                 if (!mContext.getPackageName().equals(
                         tile.intent.getComponent().getPackageName())) {
@@ -133,85 +143,49 @@
                 }
             }
         }
-        recountItems();
+
+        final DashboardData prevData = mDashboardData;
+        mDashboardData = new DashboardData.Builder(prevData)
+                .setSuggestions(suggestions)
+                .setCategories(categories)
+                .build();
+        notifyDashboardDataChanged(prevData);
     }
 
     public void setConditions(List<Condition> conditions) {
-        mConditions = conditions;
-        recountItems();
+        final DashboardData prevData = mDashboardData;
+        mDashboardData = new DashboardData.Builder(prevData)
+                .setConditions(conditions)
+                .build();
+        notifyDashboardDataChanged(prevData);
     }
 
     @Override
     public void notifySummaryChanged(Tile tile) {
-        notifyDataSetChanged();
-    }
+        final int position = mDashboardData.getPositionByTile(tile);
+        if (position != DashboardData.POSITION_NOT_FOUND) {
+            final Tile targetTile = (Tile) mDashboardData.getItemEntityByPosition(position);
+            if (!TextUtils.equals(tile.summary, targetTile.summary)) {
 
-    public void setShowingAll(boolean showingAll) {
-        mIsShowingAll = showingAll;
-        recountItems();
-    }
-
-    private void recountItems() {
-        reset();
-        boolean hasConditions = false;
-        for (int i = 0; mConditions != null && i < mConditions.size(); i++) {
-            boolean shouldShow = mConditions.get(i).shouldShow();
-            hasConditions |= shouldShow;
-            countItem(mConditions.get(i), R.layout.condition_card, shouldShow, NS_CONDITION);
-        }
-        boolean hasSuggestions = mSuggestions != null && mSuggestions.size() != 0;
-        countItem(null, R.layout.dashboard_spacer, hasConditions && hasSuggestions, NS_SPACER);
-        countItem(null, R.layout.suggestion_header, hasSuggestions, NS_SPACER);
-        resetCount();
-        if (mSuggestions != null) {
-            int maxSuggestions = getDisplayableSuggestionCount();
-            for (int i = 0; i < mSuggestions.size(); i++) {
-                countItem(mSuggestions.get(i), R.layout.suggestion_tile, i < maxSuggestions,
-                        NS_SUGGESTION);
+                // Since usually tile in parameter and tile in mCategories are same instance,
+                // which is hard to be detected by DiffUtil, so we notifyItemChanged directly.
+                notifyItemChanged(position);
             }
         }
-        resetCount();
-        for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
-            DashboardCategory category = mCategories.get(i);
-            countItem(category, R.layout.dashboard_category, mIsShowingAll
-                    && !TextUtils.isEmpty(category.title), NS_ITEMS);
-            for (int j = 0; j < category.tiles.size(); j++) {
-                Tile tile = category.tiles.get(j);
-                countItem(tile, R.layout.dashboard_tile, mIsShowingAll
-                        || ArrayUtils.contains(DashboardSummary.INITIAL_ITEMS,
-                        tile.intent.getComponent().getClassName()), NS_ITEMS);
-            }
+    }
+
+    // TODO: move this method to SuggestionParser or some other util class
+    public void disableSuggestion(Tile suggestion) {
+        if (mSuggestionParser == null) {
+            return;
         }
-        notifyDataSetChanged();
-    }
-
-    private void resetCount() {
-        mId = 0;
-    }
-
-    private void reset() {
-        mItems.clear();
-        mTypes.clear();
-        mIds.clear();
-        mId = 0;
-    }
-
-    private void countItem(Object object, int type, boolean add, int nameSpace) {
-        if (add) {
-            mItems.add(object);
-            mTypes.add(type);
-            // TODO: Counting namespaces for handling of suggestions/conds appearing/disappearing.
-            mIds.add(mId + nameSpace);
+        if (mSuggestionParser.dismissSuggestion(suggestion)) {
+            mContext.getPackageManager().setComponentEnabledSetting(
+                    suggestion.intent.getComponent(),
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                    PackageManager.DONT_KILL_APP);
+            mSuggestionParser.markCategoryDone(suggestion.category);
         }
-        mId++;
-    }
-
-    private int getDisplayableSuggestionCount() {
-        final int suggestionSize = mSuggestions.size();
-        return mSuggestionMode == SUGGESTION_MODE_DEFAULT
-                ? Math.min(DEFAULT_SUGGESTION_COUNT, suggestionSize)
-                : mSuggestionMode == SUGGESTION_MODE_EXPANDED
-                        ? suggestionSize : 0;
     }
 
     @Override
@@ -222,21 +196,24 @@
 
     @Override
     public void onBindViewHolder(DashboardItemHolder holder, int position) {
-        switch (mTypes.get(position)) {
+        final int type = mDashboardData.getItemTypeByPosition(position);
+        switch (type) {
             case R.layout.dashboard_category:
-                onBindCategory(holder, (DashboardCategory) mItems.get(position));
+                onBindCategory(holder,
+                        (DashboardCategory) mDashboardData.getItemEntityByPosition(position));
                 break;
             case R.layout.dashboard_tile:
-                final Tile tile = (Tile) mItems.get(position);
+                final Tile tile = (Tile) mDashboardData.getItemEntityByPosition(position);
                 onBindTile(holder, tile);
-                holder.itemView.setTag(tile);
-                holder.itemView.setOnClickListener(this);
+                holder.itemView.setTag(position);
+                holder.itemView.setOnClickListener(mTileClickListener);
                 break;
             case R.layout.suggestion_header:
-                onBindSuggestionHeader(holder);
+                onBindSuggestionHeader(holder, (DashboardData.SuggestionHeaderData)
+                        mDashboardData.getItemEntityByPosition(position));
                 break;
             case R.layout.suggestion_tile:
-                final Tile suggestion = (Tile) mItems.get(position);
+                final Tile suggestion = (Tile) mDashboardData.getItemEntityByPosition(position);
                 onBindTile(holder, suggestion);
                 holder.itemView.setOnClickListener(new View.OnClickListener() {
                     @Override
@@ -255,12 +232,12 @@
                             }
                         });
                 break;
-            case R.layout.see_all:
-                onBindSeeAll(holder);
-                break;
             case R.layout.condition_card:
-                ConditionAdapterUtils.bindViews((Condition) mItems.get(position), holder,
-                        mItems.get(position) == mExpandedCondition, this,
+                final boolean isExpanded = mDashboardData.getItemEntityByPosition(position)
+                        == mDashboardData.getExpandedCondition();
+                ConditionAdapterUtils.bindViews(
+                        (Condition) mDashboardData.getItemEntityByPosition(position),
+                        holder, isExpanded, mConditionClickListener,
                         new View.OnClickListener() {
                             @Override
                             public void onClick(View v) {
@@ -271,45 +248,103 @@
         }
     }
 
+    @Override
+    public long getItemId(int position) {
+        return mDashboardData.getItemIdByPosition(position);
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return mDashboardData.getItemTypeByPosition(position);
+    }
+
+    @Override
+    public int getItemCount() {
+        return mDashboardData.size();
+    }
+
+    public void onExpandClick(View v) {
+        Condition expandedCondition = mDashboardData.getExpandedCondition();
+        if (v.getTag() == expandedCondition) {
+            mMetricsFeatureProvider.action(mContext,
+                    MetricsEvent.ACTION_SETTINGS_CONDITION_COLLAPSE,
+                    expandedCondition.getMetricsConstant());
+            expandedCondition = null;
+        } else {
+            expandedCondition = (Condition) v.getTag();
+            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
+                    expandedCondition.getMetricsConstant());
+        }
+
+        updateExpandedCondition(expandedCondition);
+    }
+
+    public Object getItem(long itemId) {
+        return mDashboardData.getItemEntityById(itemId);
+    }
+
+    public static String getSuggestionIdentifier(Context context, Tile suggestion) {
+        String packageName = suggestion.intent.getComponent().getPackageName();
+        if (packageName.equals(context.getPackageName())) {
+            // Since Settings provides several suggestions, fill in the class instead of the
+            // package for these.
+            packageName = suggestion.intent.getComponent().getClassName();
+        }
+        return packageName;
+    }
+
+    private void notifyDashboardDataChanged(DashboardData prevData) {
+        if (prevData != null) {
+            final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DashboardData
+                    .ItemsDataDiffCallback(prevData.getItemList(), mDashboardData.getItemList()));
+            diffResult.dispatchUpdatesTo(this);
+        } else {
+            notifyDataSetChanged();
+        }
+    }
+
+    private void updateExpandedCondition(Condition condition) {
+        final DashboardData prevData = mDashboardData;
+        mDashboardData = new DashboardData.Builder(prevData)
+                .setExpandedCondition(condition)
+                .build();
+        notifyDashboardDataChanged(prevData);
+    }
+
     private void showRemoveOption(View v, final Tile suggestion) {
-        PopupMenu popup = new PopupMenu(
+        final PopupMenu popup = new PopupMenu(
                 new ContextThemeWrapper(mContext, R.style.Theme_AppCompat_DayNight), v);
         popup.getMenu().add(R.string.suggestion_remove).setOnMenuItemClickListener(
                 new MenuItem.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                mMetricsFeatureProvider.action(
-                        mContext, MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION,
-                        DashboardAdapter.getSuggestionIdentifier(mContext, suggestion));
-                disableSuggestion(suggestion);
-                mSuggestions.remove(suggestion);
-                recountItems();
-                return true;
-            }
-        });
+                    @Override
+                    public boolean onMenuItemClick(MenuItem item) {
+                        mMetricsFeatureProvider.action(
+                                mContext, MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION,
+                                DashboardAdapter.getSuggestionIdentifier(mContext, suggestion));
+                        disableSuggestion(suggestion);
+                        List<Tile> suggestions = mDashboardData.getSuggestions();
+                        suggestions.remove(suggestion);
+
+                        DashboardData prevData = mDashboardData;
+                        mDashboardData = new DashboardData.Builder(prevData)
+                                .setSuggestions(suggestions)
+                                .build();
+                        notifyDashboardDataChanged(prevData);
+
+                        return true;
+                    }
+                });
         popup.show();
     }
 
-    public void disableSuggestion(Tile suggestion) {
-        if (mSuggestionParser == null) {
-            return;
-        }
-        if (mSuggestionParser.dismissSuggestion(suggestion)) {
-            mContext.getPackageManager().setComponentEnabledSetting(
-                    suggestion.intent.getComponent(),
-                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                    PackageManager.DONT_KILL_APP);
-            mSuggestionParser.markCategoryDone(suggestion.category);
-        }
-    }
+    private void onBindSuggestionHeader(final DashboardItemHolder holder, DashboardData
+            .SuggestionHeaderData data) {
+        final boolean moreSuggestions = data.hasMoreSuggestions;
+        final int undisplayedSuggestionCount = data.undisplayedSuggestionCount;
 
-    private void onBindSuggestionHeader(final DashboardItemHolder holder) {
-        final boolean moreSuggestions = hasMoreSuggestions();
-        final int undisplayedSuggestionCount =
-                mSuggestions.size() - getDisplayableSuggestionCount();
         holder.icon.setImageResource(moreSuggestions ? R.drawable.ic_expand_more
                 : R.drawable.ic_expand_less);
-        holder.title.setText(mContext.getString(R.string.suggestions_title, mSuggestions.size()));
+        holder.title.setText(mContext.getString(R.string.suggestions_title, data.suggestionSize));
         String summaryContentDescription;
         if (moreSuggestions) {
             summaryContentDescription = mContext.getResources().getQuantityString(
@@ -329,22 +364,22 @@
         holder.itemView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                if (hasMoreSuggestions()) {
-                    mSuggestionMode = SUGGESTION_MODE_EXPANDED;
+                final int suggestionMode;
+                if (moreSuggestions) {
+                    suggestionMode = DashboardData.SUGGESTION_MODE_EXPANDED;
                 } else {
-                    mSuggestionMode = SUGGESTION_MODE_COLLAPSED;
+                    suggestionMode = DashboardData.SUGGESTION_MODE_COLLAPSED;
                 }
-                recountItems();
+
+                DashboardData prevData = mDashboardData;
+                mDashboardData = new DashboardData.Builder(prevData)
+                        .setSuggestionMode(suggestionMode)
+                        .build();
+                notifyDashboardDataChanged(prevData);
             }
         });
     }
 
-    private boolean hasMoreSuggestions() {
-        return mSuggestionMode == SUGGESTION_MODE_COLLAPSED
-                || (mSuggestionMode == SUGGESTION_MODE_DEFAULT
-                && mSuggestions.size() > DEFAULT_SUGGESTION_COUNT);
-    }
-
     private void onBindTile(DashboardItemHolder holder, Tile tile) {
         holder.icon.setImageDrawable(mCache.getIcon(tile.icon));
         holder.title.setText(tile.title);
@@ -360,98 +395,21 @@
         holder.title.setText(category.title);
     }
 
-    private void onBindSeeAll(DashboardItemHolder holder) {
-        holder.title.setText(mIsShowingAll ? R.string.see_less
-                : R.string.see_all);
-        holder.itemView.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                setShowingAll(!mIsShowingAll);
-            }
-        });
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return mIds.get(position);
-    }
-
-    @Override
-    public int getItemViewType(int position) {
-        return mTypes.get(position);
-    }
-
-    @Override
-    public int getItemCount() {
-        return mIds.size();
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (v.getId() == R.id.dashboard_tile) {
-            ((SettingsActivity) mContext).openTile((Tile) v.getTag());
-            return;
-        }
-        if (v.getTag() == mExpandedCondition) {
-            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK,
-                    mExpandedCondition.getMetricsConstant());
-            mExpandedCondition.onPrimaryClick();
-        } else {
-            mExpandedCondition = (Condition) v.getTag();
-            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
-                    mExpandedCondition.getMetricsConstant());
-            notifyDataSetChanged();
-        }
-    }
-
-    public void onExpandClick(View v) {
-        if (v.getTag() == mExpandedCondition) {
-            mMetricsFeatureProvider.action(mContext,
-                    MetricsEvent.ACTION_SETTINGS_CONDITION_COLLAPSE,
-                    mExpandedCondition.getMetricsConstant());
-            mExpandedCondition = null;
-        } else {
-            mExpandedCondition = (Condition) v.getTag();
-            mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND,
-                    mExpandedCondition.getMetricsConstant());
-        }
-        notifyDataSetChanged();
-    }
-
-    public Object getItem(long itemId) {
-        for (int i = 0; i < mIds.size(); i++) {
-            if (mIds.get(i) == itemId) {
-                return mItems.get(i);
-            }
-        }
-        return null;
-    }
-
-    public static String getSuggestionIdentifier(Context context, Tile suggestion) {
-        String packageName = suggestion.intent.getComponent().getPackageName();
-        if (packageName.equals(context.getPackageName())) {
-            // Since Settings provides several suggestions, fill in the class instead of the
-            // package for these.
-            packageName = suggestion.intent.getComponent().getClassName();
-        }
-        return packageName;
-    }
-
     void onSaveInstanceState(Bundle outState) {
-        if (mSuggestions != null) {
+        final List<Tile> suggestions = mDashboardData.getSuggestions();
+        final List<DashboardCategory> categories = mDashboardData.getCategories();
+        if (suggestions != null) {
             outState.putParcelableArrayList(STATE_SUGGESTION_LIST,
-                    new ArrayList<Tile>(mSuggestions));
+                    new ArrayList<Tile>(suggestions));
         }
-        if (mCategories != null) {
+        if (categories != null) {
             outState.putParcelableArrayList(STATE_CATEGORY_LIST,
-                    new ArrayList<DashboardCategory>(mCategories));
+                    new ArrayList<DashboardCategory>(categories));
         }
-        outState.putBoolean(STATE_IS_SHOWING_ALL, mIsShowingAll);
-        outState.putInt(STATE_SUGGESTION_MODE, mSuggestionMode);
+        outState.putInt(STATE_SUGGESTION_MODE, mDashboardData.getSuggestionMode());
     }
 
     private static class IconCache {
-
         private final Context mContext;
         private final ArrayMap<Icon, Drawable> mMap = new ArrayMap<>();
 
diff --git a/src/com/android/settings/dashboard/DashboardData.java b/src/com/android/settings/dashboard/DashboardData.java
new file mode 100644
index 0000000..0fc994b
--- /dev/null
+++ b/src/com/android/settings/dashboard/DashboardData.java
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.dashboard;
+
+import android.annotation.IntDef;
+import android.support.v7.util.DiffUtil;
+import android.text.TextUtils;
+import com.android.settings.dashboard.conditional.Condition;
+import com.android.settingslib.drawer.DashboardCategory;
+import com.android.settingslib.drawer.Tile;
+import com.android.settings.R;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Description about data list used in the DashboardAdapter. In the data list each item can be
+ * Condition, suggestion or category tile.
+ * <p>
+ * ItemsData has inner class Item, which represents the Item in data list.
+ */
+public class DashboardData {
+    public static final int SUGGESTION_MODE_DEFAULT = 0;
+    public static final int SUGGESTION_MODE_COLLAPSED = 1;
+    public static final int SUGGESTION_MODE_EXPANDED = 2;
+    public static final int POSITION_NOT_FOUND = -1;
+    public static final int DEFAULT_SUGGESTION_COUNT = 2;
+
+    // id namespace for different type of items.
+    private static final int NS_SPACER = 0;
+    private static final int NS_SUGGESTION = 1000;
+    private static final int NS_ITEMS = 2000;
+    private static final int NS_CONDITION = 3000;
+
+    private final List<Item> mItems;
+    private final List<DashboardCategory> mCategories;
+    private final List<Condition> mConditions;
+    private final List<Tile> mSuggestions;
+    private final int mSuggestionMode;
+    private final Condition mExpandedCondition;
+    private int mId;
+
+    private DashboardData(Builder builder) {
+        mCategories = builder.mCategories;
+        mConditions = builder.mConditions;
+        mSuggestions = builder.mSuggestions;
+        mSuggestionMode = builder.mSuggestionMode;
+        mExpandedCondition = builder.mExpandedCondition;
+
+        mItems = new ArrayList<>();
+        mId = 0;
+
+        buildItemsData();
+    }
+
+    public int getItemIdByPosition(int position) {
+        return mItems.get(position).id;
+    }
+
+    public int getItemTypeByPosition(int position) {
+        return mItems.get(position).type;
+    }
+
+    public Object getItemEntityByPosition(int position) {
+        return mItems.get(position).entity;
+    }
+
+    public List<Item> getItemList() {
+        return mItems;
+    }
+
+    public int size() {
+        return mItems.size();
+    }
+
+    public Object getItemEntityById(long id) {
+        for (final Item item : mItems) {
+            if (item.id == id) {
+                return item.entity;
+            }
+        }
+        return null;
+    }
+
+    public List<DashboardCategory> getCategories() {
+        return mCategories;
+    }
+
+    public List<Condition> getConditions() {
+        return mConditions;
+    }
+
+    public List<Tile> getSuggestions() {
+        return mSuggestions;
+    }
+
+    public int getSuggestionMode() {
+        return mSuggestionMode;
+    }
+
+    public Condition getExpandedCondition() {
+        return mExpandedCondition;
+    }
+
+    /**
+     * Find the position of the object in mItems list, using the equals method to compare
+     *
+     * @param entity the object that need to be found in list
+     * @return position of the object, return POSITION_NOT_FOUND if object isn't in the list
+     */
+    public int getPositionByEntity(Object entity) {
+        if (entity == null) return POSITION_NOT_FOUND;
+
+        final int size = mItems.size();
+        for (int i = 0; i < size; i++) {
+            final Object item = mItems.get(i).entity;
+            if (entity.equals(item)) {
+                return i;
+            }
+        }
+
+        return POSITION_NOT_FOUND;
+    }
+
+    /**
+     * Find the position of the Tile object.
+     * <p>
+     * First, try to find the exact identical instance of the tile object, if not found,
+     * then try to find a tile has the same title.
+     *
+     * @param tile tile that need to be found
+     * @return position of the object, return INDEX_NOT_FOUND if object isn't in the list
+     */
+    public int getPositionByTile(Tile tile) {
+        final int size = mItems.size();
+        for (int i = 0; i < size; i++) {
+            final Object entity = mItems.get(i).entity;
+            if (entity == tile) {
+                return i;
+            } else if (entity instanceof Tile && tile.title.equals(((Tile) entity).title)) {
+                return i;
+            }
+        }
+
+        return POSITION_NOT_FOUND;
+    }
+
+    /**
+     * Get the count of suggestions to display
+     *
+     * The displayable count mainly depends on the {@link #mSuggestionMode}
+     * and the size of suggestions list.
+     *
+     * When in default mode, displayable count couldn't larger than
+     * {@link #DEFAULT_SUGGESTION_COUNT}.
+     *
+     * When in expanded mode, display all the suggestions.
+     * @return the count of suggestions to display
+     */
+    public int getDisplayableSuggestionCount() {
+        final int suggestionSize = mSuggestions.size();
+        return mSuggestionMode == SUGGESTION_MODE_DEFAULT
+                ? Math.min(DEFAULT_SUGGESTION_COUNT, suggestionSize)
+                : mSuggestionMode == SUGGESTION_MODE_EXPANDED
+                ? suggestionSize : 0;
+    }
+
+    public boolean hasMoreSuggestions() {
+        return mSuggestionMode == SUGGESTION_MODE_COLLAPSED
+                || (mSuggestionMode == SUGGESTION_MODE_DEFAULT
+                && mSuggestions.size() > DEFAULT_SUGGESTION_COUNT);
+    }
+
+    private void resetCount() {
+        mId = 0;
+    }
+
+    /**
+     * Count the item and add it into list when {@paramref add} is true.
+     *
+     * Note that {@link #mId} will increment automatically and the real
+     * id stored in {@link Item} is shifted by {@paramref nameSpace}. This is a
+     * simple way to keep the id stable.
+     *
+     * @param object maybe {@link Condition}, {@link Tile}, {@link DashboardCategory} or null
+     * @param type type of the item, and value is the layout id
+     * @param add  flag about whether to add item into list
+     * @param nameSpace namespace based on the type
+     */
+    private void countItem(Object object, int type, boolean add, int nameSpace) {
+        if (add) {
+            mItems.add(new Item(object, type, mId + nameSpace, object == mExpandedCondition));
+        }
+        mId++;
+    }
+
+    /**
+     * Build the mItems list using mConditions, mSuggestions, mCategories data
+     * and mIsShowingAll, mSuggestionMode flag.
+     */
+    private void buildItemsData() {
+        boolean hasConditions = false;
+        for (int i = 0; mConditions != null && i < mConditions.size(); i++) {
+            boolean shouldShow = mConditions.get(i).shouldShow();
+            hasConditions |= shouldShow;
+            countItem(mConditions.get(i), R.layout.condition_card, shouldShow, NS_CONDITION);
+        }
+
+        resetCount();
+        final boolean hasSuggestions = mSuggestions != null && mSuggestions.size() != 0;
+        countItem(null, R.layout.dashboard_spacer, hasConditions && hasSuggestions, NS_SPACER);
+        countItem(buildSuggestionHeaderData(), R.layout.suggestion_header, hasSuggestions,
+                NS_SPACER);
+
+        resetCount();
+        if (mSuggestions != null) {
+            int maxSuggestions = getDisplayableSuggestionCount();
+            for (int i = 0; i < mSuggestions.size(); i++) {
+                countItem(mSuggestions.get(i), R.layout.suggestion_tile, i < maxSuggestions,
+                        NS_SUGGESTION);
+            }
+        }
+        resetCount();
+        for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
+            DashboardCategory category = mCategories.get(i);
+            countItem(category, R.layout.dashboard_category,
+                    !TextUtils.isEmpty(category.title), NS_ITEMS);
+            for (int j = 0; j < category.tiles.size(); j++) {
+                Tile tile = category.tiles.get(j);
+                countItem(tile, R.layout.dashboard_tile, true, NS_ITEMS);
+            }
+        }
+    }
+
+    private SuggestionHeaderData buildSuggestionHeaderData() {
+        SuggestionHeaderData data;
+        if (mSuggestions == null) {
+            data = new SuggestionHeaderData();
+        } else {
+            final boolean hasMoreSuggestions = hasMoreSuggestions();
+            final int suggestionSize = mSuggestions.size();
+            final int undisplayedSuggestionCount = suggestionSize - getDisplayableSuggestionCount();
+            data = new SuggestionHeaderData(hasMoreSuggestions, suggestionSize,
+                    undisplayedSuggestionCount);
+        }
+
+        return data;
+    }
+
+    /**
+     * Builder used to build the ItemsData
+     * <p>
+     * {@link #mExpandedCondition} and {@link #mSuggestionMode} have default value
+     * while others are not.
+     */
+    public static class Builder {
+        private int mSuggestionMode = SUGGESTION_MODE_DEFAULT;
+        private Condition mExpandedCondition = null;
+
+        private List<DashboardCategory> mCategories;
+        private List<Condition> mConditions;
+        private List<Tile> mSuggestions;
+
+
+        public Builder() {
+        }
+
+        public Builder(DashboardData dashboardData) {
+            mCategories = dashboardData.mCategories;
+            mConditions = dashboardData.mConditions;
+            mSuggestions = dashboardData.mSuggestions;
+            mSuggestionMode = dashboardData.mSuggestionMode;
+            mExpandedCondition = dashboardData.mExpandedCondition;
+        }
+
+        public Builder setCategories(List<DashboardCategory> categories) {
+            this.mCategories = categories;
+            return this;
+        }
+
+        public Builder setConditions(List<Condition> conditions) {
+            this.mConditions = conditions;
+            return this;
+        }
+
+        public Builder setSuggestions(List<Tile> suggestions) {
+            this.mSuggestions = suggestions;
+            return this;
+        }
+
+        public Builder setSuggestionMode(int suggestionMode) {
+            this.mSuggestionMode = suggestionMode;
+            return this;
+        }
+
+        public Builder setExpandedCondition(Condition expandedCondition) {
+            this.mExpandedCondition = expandedCondition;
+            return this;
+        }
+
+        public DashboardData build() {
+            return new DashboardData(this);
+        }
+    }
+
+    /**
+     * A DiffCallback to calculate the difference between old and new Item
+     * List in DashboardData
+     */
+    public static class ItemsDataDiffCallback extends DiffUtil.Callback {
+        final private List<Item> mOldItems;
+        final private List<Item> mNewItems;
+
+        public ItemsDataDiffCallback(List<Item> oldItems, List<Item> newItems) {
+            mOldItems = oldItems;
+            mNewItems = newItems;
+        }
+
+        @Override
+        public int getOldListSize() {
+            return mOldItems.size();
+        }
+
+        @Override
+        public int getNewListSize() {
+            return mNewItems.size();
+        }
+
+        @Override
+        public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
+            return mOldItems.get(oldItemPosition).id == mNewItems.get(newItemPosition).id;
+        }
+
+        @Override
+        public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
+            return mOldItems.get(oldItemPosition).equals(mNewItems.get(newItemPosition));
+        }
+    }
+
+    /**
+     * An item contains the data needed in the DashboardData.
+     */
+    private static class Item {
+        // valid types in field type
+        private static final int TYPE_DASHBOARD_CATEGORY = R.layout.dashboard_category;
+        private static final int TYPE_DASHBOARD_TILE = R.layout.dashboard_tile;
+        private static final int TYPE_SUGGESTION_HEADER = R.layout.suggestion_header;
+        private static final int TYPE_SUGGESTION_TILE = R.layout.suggestion_tile;
+        private static final int TYPE_CONDITION_CARD = R.layout.condition_card;
+        private static final int TYPE_DASHBOARD_SPACER = R.layout.dashboard_spacer;
+
+        @IntDef({TYPE_DASHBOARD_CATEGORY, TYPE_DASHBOARD_TILE, TYPE_SUGGESTION_HEADER,
+                TYPE_SUGGESTION_TILE, TYPE_CONDITION_CARD, TYPE_DASHBOARD_SPACER})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface ItemTypes{}
+
+        /**
+         * The main data object in item, usually is a {@link Tile}, {@link Condition} or
+         * {@link DashboardCategory} object. This object can also be null when the
+         * item is an divider line. Please refer to {@link #buildItemsData()} for
+         * detail usage of the Item.
+         */
+        public final Object entity;
+
+        /**
+         * The type of item, value inside is the layout id(e.g. R.layout.dashboard_tile)
+         */
+        public final @ItemTypes int type;
+
+        /**
+         * Id of this item, used in the {@link ItemsDataDiffCallback} to identify the same item.
+         */
+        public final int id;
+
+        /**
+         * To store whether the condition is expanded, useless when {@link #type} is not
+         * {@link #TYPE_CONDITION_CARD}
+         */
+        public final boolean conditionExpanded;
+
+        public Item(Object entity, @ItemTypes int type, int id, boolean conditionExpanded) {
+            this.entity = entity;
+            this.type = type;
+            this.id = id;
+            this.conditionExpanded = conditionExpanded;
+        }
+
+        /**
+         * Override it to make comparision in the {@link ItemsDataDiffCallback}
+         * @param obj object to compared with
+         * @return true if the same object or has equal value.
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            if (!(obj instanceof Item)) {
+                return false;
+            }
+
+            final Item targetItem = (Item) obj;
+            if (type != targetItem.type || id != targetItem.id) {
+                return false;
+            }
+
+            switch (type) {
+                case TYPE_DASHBOARD_CATEGORY:
+                    // Only check title for dashboard category
+                    return TextUtils.equals(((DashboardCategory)entity).title,
+                            ((DashboardCategory) targetItem.entity).title);
+                case TYPE_DASHBOARD_TILE:
+                    final Tile localTile = (Tile)entity;
+                    final Tile targetTile = (Tile)targetItem.entity;
+
+                    // Only check title and summary for dashboard tile
+                    return TextUtils.equals(localTile.title, targetTile.title)
+                            && TextUtils.equals(localTile.summary, targetTile.summary);
+                case TYPE_CONDITION_CARD:
+                    // First check conditionExpanded for quick return
+                    if (conditionExpanded != targetItem.conditionExpanded) {
+                        return false;
+                    }
+                    // After that, go to default to do final check
+                default:
+                    return entity == null ? targetItem.entity == null
+                            : entity.equals(targetItem.entity);
+            }
+        }
+    }
+
+    /**
+     * This class contains the data needed to build the header. The data can also be
+     * used to check the diff in DiffUtil.Callback
+     */
+    public static class SuggestionHeaderData {
+        public final boolean hasMoreSuggestions;
+        public final int suggestionSize;
+        public final int undisplayedSuggestionCount;
+
+        public SuggestionHeaderData(boolean moreSuggestions, int suggestionSize, int
+                undisplayedSuggestionCount) {
+            this.hasMoreSuggestions = moreSuggestions;
+            this.suggestionSize = suggestionSize;
+            this.undisplayedSuggestionCount = undisplayedSuggestionCount;
+        }
+
+        public SuggestionHeaderData() {
+            hasMoreSuggestions = false;
+            suggestionSize = 0;
+            undisplayedSuggestionCount = 0;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            if (!(obj instanceof SuggestionHeaderData)) {
+                return false;
+            }
+
+            SuggestionHeaderData targetData = (SuggestionHeaderData) obj;
+
+            return hasMoreSuggestions == targetData.hasMoreSuggestions
+                    && suggestionSize == targetData.suggestionSize
+                    && undisplayedSuggestionCount == targetData.undisplayedSuggestionCount;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 9ab8cf4..fd125af 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -277,11 +277,6 @@
         displayResourceTiles();
 
         refreshDashboardTiles(TAG);
-
-        if (!mProgressiveDisclosureMixin.isCollapsed()
-                && mProgressiveDisclosureMixin.shouldCollapse(getPreferenceScreen())) {
-            mProgressiveDisclosureMixin.collapse(getPreferenceScreen());
-        }
     }
 
     /**
@@ -349,11 +344,12 @@
             pref.setIcon(tile.icon.loadDrawable(context));
         }
         final Bundle metadata = tile.metaData;
+        String clsName = null;
         if (metadata != null) {
-            String clsName = metadata.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS);
-            if (!TextUtils.isEmpty(clsName)) {
-                pref.setFragment(clsName);
-            }
+            clsName = metadata.getString(SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS);
+        }
+        if (!TextUtils.isEmpty(clsName)) {
+            pref.setFragment(clsName);
         } else if (tile.intent != null) {
             final Intent intent = new Intent(tile.intent);
             pref.setOnPreferenceClickListener(preference -> {
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
index cd56458..fa108bb 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
@@ -23,13 +23,12 @@
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
-import android.app.DialogFragment;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.res.ColorStateList;
 import android.graphics.drawable.Animatable2;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -37,7 +36,6 @@
 import android.view.View;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
-import android.widget.ImageView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
@@ -75,7 +73,6 @@
     private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
 
     private ProgressBar mProgressBar;
-    private ImageView mFingerprintAnimator;
     private ObjectAnimator mProgressAnim;
     private TextView mStartMessage;
     private TextView mRepeatMessage;
@@ -87,6 +84,7 @@
     private FingerprintEnrollSidecar mSidecar;
     private boolean mAnimationCancelled;
     private AnimatedVectorDrawable mIconAnimationDrawable;
+    private Drawable mIconBackgroundDrawable;
     private int mIndicatorBackgroundRestingColor;
     private int mIndicatorBackgroundActivatedColor;
     private boolean mRestoring;
@@ -100,8 +98,11 @@
         mRepeatMessage = (TextView) findViewById(R.id.repeat_message);
         mErrorText = (TextView) findViewById(R.id.error_text);
         mProgressBar = (ProgressBar) findViewById(R.id.fingerprint_progress_bar);
-        mFingerprintAnimator = (ImageView) findViewById(R.id.fingerprint_animator);
-        mIconAnimationDrawable = (AnimatedVectorDrawable) mFingerprintAnimator.getDrawable();
+        final LayerDrawable fingerprintDrawable = (LayerDrawable) mProgressBar.getBackground();
+        mIconAnimationDrawable = (AnimatedVectorDrawable)
+                fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_animation);
+        mIconBackgroundDrawable =
+                fingerprintDrawable.findDrawableByLayerId(R.id.fingerprint_background);
         mIconAnimationDrawable.registerAnimationCallback(mIconAnimationCallback);
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
                 this, android.R.interpolator.fast_out_slow_in);
@@ -109,7 +110,7 @@
                 this, android.R.interpolator.linear_out_slow_in);
         mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
                 this, android.R.interpolator.fast_out_linear_in);
-        mFingerprintAnimator.setOnTouchListener(new View.OnTouchListener() {
+        mProgressBar.setOnTouchListener(new View.OnTouchListener() {
             @Override
             public boolean onTouch(View v, MotionEvent event) {
                 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
@@ -117,12 +118,12 @@
                     if (mIconTouchCount == ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN) {
                         showIconTouchDialog();
                     } else {
-                        mFingerprintAnimator.postDelayed(mShowDialogRunnable,
+                        mProgressBar.postDelayed(mShowDialogRunnable,
                                 ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN);
                     }
                 } else if (event.getActionMasked() == MotionEvent.ACTION_CANCEL
                         || event.getActionMasked() == MotionEvent.ACTION_UP) {
-                    mFingerprintAnimator.removeCallbacks(mShowDialogRunnable);
+                    mProgressBar.removeCallbacks(mShowDialogRunnable);
                 }
                 return true;
             }
@@ -131,6 +132,7 @@
                 = getColor(R.color.fingerprint_indicator_background_resting);
         mIndicatorBackgroundActivatedColor
                 = getColor(R.color.fingerprint_indicator_background_activated);
+        mIconBackgroundDrawable.setTint(mIndicatorBackgroundRestingColor);
         mRestoring = savedInstanceState != null;
     }
 
@@ -213,8 +215,7 @@
                 new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
-                mFingerprintAnimator.setBackgroundTintList(ColorStateList.valueOf(
-                        (Integer) animation.getAnimatedValue()));
+                mIconBackgroundDrawable.setTint((Integer) animation.getAnimatedValue());
             }
         };
         anim.addUpdateListener(listener);
@@ -400,7 +401,7 @@
             }
 
             // Start animation after it has ended.
-            mFingerprintAnimator.post(new Runnable() {
+            mProgressBar.post(new Runnable() {
                 @Override
                 public void run() {
                     startIconAnimation();
diff --git a/src/com/android/settings/gestures/GesturePreference.java b/src/com/android/settings/gestures/GesturePreference.java
index 1909dcd..5a64a5a 100644
--- a/src/com/android/settings/gestures/GesturePreference.java
+++ b/src/com/android/settings/gestures/GesturePreference.java
@@ -150,6 +150,10 @@
                         playButton.setVisibility(View.VISIBLE);
                     }
                 }
+                if (mMediaPlayer != null && !mMediaPlayer.isPlaying() &&
+                        playButton.getVisibility() != View.VISIBLE) {
+                    playButton.setVisibility(View.VISIBLE);
+                }
             }
         });
 
@@ -175,4 +179,10 @@
         }
     }
 
+    void onViewInvisible() {
+        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
+            mMediaPlayer.pause();
+        }
+    }
+
 }
diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java
index a8f70d9..6fc7abe 100644
--- a/src/com/android/settings/gestures/GestureSettings.java
+++ b/src/com/android/settings/gestures/GestureSettings.java
@@ -145,6 +145,14 @@
     }
 
     @Override
+    public void onStop() {
+        super.onStop();
+        for (GesturePreference preference : mPreferences) {
+            preference.onViewInvisible();
+        }
+    }
+
+    @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         boolean enabled = (boolean) newValue;
         String key = preference.getKey();
diff --git a/src/com/android/settings/widget/RingProgressBar.java b/src/com/android/settings/widget/RingProgressBar.java
new file mode 100644
index 0000000..605e4e9
--- /dev/null
+++ b/src/com/android/settings/widget/RingProgressBar.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ProgressBar;
+
+import com.android.settings.R;
+
+/**
+ * A (determinate) progress bar in the form of a ring. The progress bar goes clockwise starting
+ * from the 12 o'clock position. This view maintain equal width and height using a strategy similar
+ * to "centerInside" for ImageView.
+ */
+public class RingProgressBar extends ProgressBar {
+
+    public RingProgressBar(Context context) {
+        this(context, null);
+    }
+
+    public RingProgressBar(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public RingProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, R.style.RingProgressBarStyle);
+    }
+
+    public RingProgressBar(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        final int measuredHeight = getMeasuredHeight();
+        final int measuredWidth = getMeasuredWidth();
+        final int shortSide = Math.min(measuredHeight, measuredWidth);
+        setMeasuredDimension(shortSide, shortSide);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accounts/UserAndAccountDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/UserAndAccountDashboardFragmentTest.java
new file mode 100644
index 0000000..2d266b6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accounts/UserAndAccountDashboardFragmentTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.settings.accounts;
+
+import android.content.Context;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.drawer.CategoryKey;
+
+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.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UserAndAccountDashboardFragmentTest {
+
+  @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+  private Context mContext;
+
+  private UserAndAccountDashboardFragment mFragment;
+
+  @Before
+  public void setUp() {
+    MockitoAnnotations.initMocks(this);
+    FakeFeatureFactory.setupForTest(mContext);
+    mFragment = new UserAndAccountDashboardFragment();
+  }
+
+  @Test
+  public void testCategory_isConnectedDevice() {
+    assertThat(mFragment.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_ACCOUNT);
+  }
+
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
new file mode 100644
index 0000000..52c2103
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.dashboard;
+
+import android.support.annotation.NonNull;
+import android.support.v7.util.DiffUtil;
+import android.support.v7.util.ListUpdateCallback;
+import com.android.settings.TestConfig;
+import com.android.settings.dashboard.conditional.AirplaneModeCondition;
+import com.android.settings.dashboard.conditional.Condition;
+import com.android.settingslib.drawer.DashboardCategory;
+import com.android.settingslib.drawer.Tile;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class DashboardDataTest {
+    private static final String TEST_SUGGESTION_TITLE = "Use fingerprint";
+    private static final String TEST_CATEGORY_TILE_TITLE = "Display";
+
+    private DashboardData mDashboardDataWithOneConditions;
+    private DashboardData mDashboardDataWithTwoConditions;
+    private DashboardData mDashboardDataWithNoItems;
+    @Mock
+    private Tile mTestCategoryTile;
+    @Mock
+    private Tile mTestSuggestion;
+    @Mock
+    private DashboardCategory mDashboardCategory;
+    @Mock
+    private Condition mTestCondition;
+    @Mock
+    private Condition mSecondCondition; // condition used to test insert in DiffUtil
+
+    @Before
+    public void SetUp() {
+        MockitoAnnotations.initMocks(this);
+
+        // Build suggestions
+        final List<Tile> suggestions = new ArrayList<>();
+        mTestSuggestion.title = TEST_SUGGESTION_TITLE;
+        suggestions.add(mTestSuggestion);
+
+        // Build oneItemConditions
+        final List<Condition> oneItemConditions = new ArrayList<>();
+        when(mTestCondition.shouldShow()).thenReturn(true);
+        oneItemConditions.add(mTestCondition);
+
+        // Build twoItemConditions
+        final List<Condition> twoItemsConditions = new ArrayList<>();
+        when(mSecondCondition.shouldShow()).thenReturn(true);
+        twoItemsConditions.add(mTestCondition);
+        twoItemsConditions.add(mSecondCondition);
+
+        // Build categories
+        final List<DashboardCategory> categories = new ArrayList<>();
+        mTestCategoryTile.title = TEST_CATEGORY_TILE_TITLE;
+        mDashboardCategory.title = "test";
+        mDashboardCategory.tiles = new ArrayList<>();
+        mDashboardCategory.tiles.add(mTestCategoryTile);
+        categories.add(mDashboardCategory);
+
+        // Build DashboardData 
+        mDashboardDataWithOneConditions = new DashboardData.Builder()
+                .setConditions(oneItemConditions)
+                .setCategories(categories)
+                .setSuggestions(suggestions)
+                .build();
+
+        mDashboardDataWithTwoConditions = new DashboardData.Builder()
+                .setConditions(twoItemsConditions)
+                .setCategories(categories)
+                .setSuggestions(suggestions)
+                .build();
+
+        mDashboardDataWithNoItems = new DashboardData.Builder()
+                .setConditions(null)
+                .setCategories(null)
+                .setSuggestions(null)
+                .build();
+    }
+
+    @Test
+    public void testBuildItemsData_containsAllData() {
+        final DashboardData.SuggestionHeaderData data =
+                new DashboardData.SuggestionHeaderData(false, 1, 0);
+        final Object[] expectedObjects = {mTestCondition, null, data, mTestSuggestion,
+                mDashboardCategory, mTestCategoryTile};
+        final int expectedSize = expectedObjects.length;
+
+        assertThat(mDashboardDataWithOneConditions.getItemList().size())
+                .isEqualTo(expectedSize);
+        for (int i = 0; i < expectedSize; i++) {
+            if (mDashboardDataWithOneConditions.getItemEntityByPosition(i)
+                    instanceof DashboardData.SuggestionHeaderData) {
+                // SuggestionHeaderData is created inside when build, we can only use isEqualTo
+                assertThat(mDashboardDataWithOneConditions.getItemEntityByPosition(i))
+                        .isEqualTo(expectedObjects[i]);
+            } else {
+                assertThat(mDashboardDataWithOneConditions.getItemEntityByPosition(i))
+                        .isSameAs(expectedObjects[i]);
+            }
+        }
+    }
+
+    @Test
+    public void testGetPositionByEntity_selfInstance_returnPositionFound() {
+        final int position = mDashboardDataWithOneConditions
+                .getPositionByEntity(mTestCondition);
+        assertThat(position).isNotEqualTo(DashboardData.POSITION_NOT_FOUND);
+    }
+
+    @Test
+    public void testGetPositionByEntity_notExisted_returnNotFound() {
+        final Condition condition = mock(AirplaneModeCondition.class);
+        final int position = mDashboardDataWithOneConditions.getPositionByEntity(condition);
+        assertThat(position).isEqualTo(DashboardData.POSITION_NOT_FOUND);
+    }
+
+    @Test
+    public void testGetPositionByTile_selfInstance_returnPositionFound() {
+        final int position = mDashboardDataWithOneConditions
+                .getPositionByTile(mTestCategoryTile);
+        assertThat(position).isNotEqualTo(DashboardData.POSITION_NOT_FOUND);
+    }
+
+    @Test
+    public void testGetPositionByTile_equalTitle_returnPositionFound() {
+        final Tile tile = mock(Tile.class);
+        tile.title = TEST_CATEGORY_TILE_TITLE;
+        final int position = mDashboardDataWithOneConditions.getPositionByTile(tile);
+        assertThat(position).isNotEqualTo(DashboardData.POSITION_NOT_FOUND);
+    }
+
+    @Test
+    public void testGetPositionByTile_notExisted_returnNotFound() {
+        final Tile tile = mock(Tile.class);
+        tile.title = "";
+        final int position = mDashboardDataWithOneConditions.getPositionByTile(tile);
+        assertThat(position).isEqualTo(DashboardData.POSITION_NOT_FOUND);
+    }
+
+    @Test
+    public void testDiffUtil_DataEqual_noResultData() {
+        List<ListUpdateResult.ResultData> testResultData = new ArrayList<>();
+        testDiffUtil(mDashboardDataWithOneConditions, 
+                mDashboardDataWithOneConditions, testResultData);
+    }
+
+    @Test
+    public void testDiffUtil_InsertOneCondition_ResultDataOneInserted() {
+        //Build testResultData
+        final List<ListUpdateResult.ResultData> testResultData = new ArrayList<>();
+        testResultData.add(new ListUpdateResult.ResultData(
+                ListUpdateResult.ResultData.TYPE_OPERATION_INSERT, 1, 1));
+
+        testDiffUtil(mDashboardDataWithOneConditions,
+                mDashboardDataWithTwoConditions, testResultData);
+    }
+
+    @Test
+    public void testDiffUtil_DeleteAllData_ResultDataOneDeleted() {
+        //Build testResultData
+        final List<ListUpdateResult.ResultData> testResultData = new ArrayList<>();
+        testResultData.add(new ListUpdateResult.ResultData(
+                ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 6));
+
+        testDiffUtil(mDashboardDataWithOneConditions, mDashboardDataWithNoItems, testResultData);
+    }
+
+    /**
+     * Test when using the
+     * {@link com.android.settings.dashboard.DashboardData.ItemsDataDiffCallback}
+     * to transfer List from {@paramref baseDashboardData} to {@paramref diffDashboardData}, whether
+     * the transform data result is equals to {@paramref testResultData}
+     * <p>
+     * The steps are described below:
+     * 1. Calculate a {@link android.support.v7.util.DiffUtil.DiffResult} from
+     * {@paramref baseDashboardData} to {@paramref diffDashboardData}
+     * <p>
+     * 2. Dispatch the {@link android.support.v7.util.DiffUtil.DiffResult} calculated from step 1
+     * into {@link ListUpdateResult}
+     * <p>
+     * 3. Get result data(a.k.a. baseResultData) from {@link ListUpdateResult} and compare it to
+     * {@paramref testResultData}
+     * <p>
+     * Because baseResultData and {@paramref testResultData} don't have sequence. When do the
+     * comparison, we will sort them first and then compare the inside data from them one by one.
+     *
+     * @param baseDashboardData
+     * @param diffDashboardData
+     * @param testResultData
+     */
+    private void testDiffUtil(DashboardData baseDashboardData, DashboardData diffDashboardData,
+            List<ListUpdateResult.ResultData> testResultData) {
+        final DiffUtil.DiffResult diffUtilResult = DiffUtil.calculateDiff(
+                new DashboardData.ItemsDataDiffCallback(
+                        baseDashboardData.getItemList(), diffDashboardData.getItemList()));
+
+        // Dispatch to listUpdateResult, then listUpdateResult will have result data
+        final ListUpdateResult listUpdateResult = new ListUpdateResult();
+        diffUtilResult.dispatchUpdatesTo(listUpdateResult);
+
+        final List<ListUpdateResult.ResultData> baseResultData = listUpdateResult.getResultData();
+        assertThat(testResultData.size()).isEqualTo(baseResultData.size());
+
+        // Sort them so we can compare them one by one using a for loop
+        Collections.sort(baseResultData);
+        Collections.sort(testResultData);
+        final int size = baseResultData.size();
+        for (int i = 0; i < size; i++) {
+            // Refer to equals method in ResultData
+            assertThat(baseResultData.get(i)).isEqualTo(testResultData.get(i));
+        }
+    }
+
+    /**
+     * This class contains the result about how the changes made to convert one
+     * list to another list. It implements ListUpdateCallback to record the result data.
+     */
+    private static class ListUpdateResult implements ListUpdateCallback {
+        final private List<ResultData> mResultData;
+
+        public ListUpdateResult() {
+            mResultData = new ArrayList<>();
+        }
+
+        public List<ResultData> getResultData() {
+            return mResultData;
+        }
+
+        @Override
+        public void onInserted(int position, int count) {
+            mResultData.add(new ResultData(ResultData.TYPE_OPERATION_INSERT, position, count));
+        }
+
+        @Override
+        public void onRemoved(int position, int count) {
+            mResultData.add(new ResultData(ResultData.TYPE_OPERATION_REMOVE, position, count));
+        }
+
+        @Override
+        public void onMoved(int fromPosition, int toPosition) {
+            mResultData.add(
+                    new ResultData(ResultData.TYPE_OPERATION_MOVE, fromPosition, toPosition));
+        }
+
+        @Override
+        public void onChanged(int position, int count, Object payload) {
+            mResultData.add(new ResultData(ResultData.TYPE_OPERATION_CHANGE, position, count));
+        }
+
+        /**
+         * This class contains general type and field to record the operation data generated
+         * in {@link ListUpdateCallback}. Please refer to {@link ListUpdateCallback} for more info.
+         * <p>
+         * The following are examples about the data stored in this class:
+         * <p>
+         * "The data starts from position(arg1) with count number(arg2) is changed(operation)"
+         * or "The data is moved(operation) from position1(arg1) to position2(arg2)"
+         */
+        private static class ResultData implements Comparable<ResultData> {
+            public static final int TYPE_OPERATION_INSERT = 0;
+            public static final int TYPE_OPERATION_REMOVE = 1;
+            public static final int TYPE_OPERATION_MOVE = 2;
+            public static final int TYPE_OPERATION_CHANGE = 3;
+
+            public final int operation;
+            public final int arg1;
+            public final int arg2;
+
+            public ResultData(int operation, int arg1, int arg2) {
+                this.operation = operation;
+                this.arg1 = arg1;
+                this.arg2 = arg2;
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                if (this == obj) {
+                    return true;
+                }
+
+                if (!(obj instanceof ResultData)) {
+                    return false;
+                }
+
+                ResultData targetData = (ResultData) obj;
+
+                return operation == targetData.operation && arg1 == targetData.arg1
+                        && arg2 == targetData.arg2;
+            }
+
+            @Override
+            public int compareTo(@NonNull ResultData resultData) {
+                if (this.operation != resultData.operation) {
+                    return operation - resultData.operation;
+                }
+
+                if (arg1 != resultData.arg1) {
+                    return arg1 - resultData.arg1;
+                }
+
+                return arg2 - resultData.arg2;
+            }
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index e4222ce..8fc290e 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -16,6 +16,7 @@
 package com.android.settings.dashboard;
 
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
@@ -142,6 +143,21 @@
         assertThat(preference.getOrder()).isEqualTo(-tile.priority);
     }
 
+    @Test
+    public void bindPreference_noFragmentMetadata_shouldBindIntent() {
+        final Preference preference = new Preference(
+                ShadowApplication.getInstance().getApplicationContext());
+        final Tile tile = new Tile();
+        tile.metaData = new Bundle();
+        tile.priority = 10;
+        tile.intent = new Intent();
+        mTestFragment.bindPreferenceToTile(mContext, preference, tile, "123");
+
+        assertThat(preference.getFragment()).isNull();
+        assertThat(preference.getIntent()).isNotNull();
+        assertThat(preference.getOrder()).isEqualTo(-tile.priority);
+    }
+
     public static class TestPreferenceController extends PreferenceController {
 
         public TestPreferenceController(Context context) {
diff --git a/tests/robotests/src/com/android/settings/widget/RingProgressBarTest.java b/tests/robotests/src/com/android/settings/widget/RingProgressBarTest.java
new file mode 100644
index 0000000..b7a5fd9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/RingProgressBarTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import static junit.framework.Assert.assertEquals;
+
+import android.content.Context;
+import android.view.View.MeasureSpec;
+
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class RingProgressBarTest {
+
+    private Context mContext = RuntimeEnvironment.application;
+
+    private RingProgressBar mProgressBar;
+
+    @Before
+    public void setUp() {
+        mProgressBar = new RingProgressBar(mContext);
+    }
+
+    @Test
+    public void testMeasurePortrait() {
+        mProgressBar.measure(
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(200, MeasureSpec.EXACTLY));
+        assertEquals(100, mProgressBar.getMeasuredHeight());
+        assertEquals(100, mProgressBar.getMeasuredWidth());
+    }
+
+    @Test
+    public void testMeasureLandscape() {
+        mProgressBar.measure(
+                MeasureSpec.makeMeasureSpec(200, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY));
+        assertEquals(100, mProgressBar.getMeasuredHeight());
+        assertEquals(100, mProgressBar.getMeasuredWidth());
+    }
+
+    @Test
+    public void testDefaultAttributes() {
+        assertEquals(false, mProgressBar.isIndeterminate());
+        assertEquals(0, mProgressBar.getProgress());
+        assertEquals(10000, mProgressBar.getMax());
+    }
+}