Merge "Input settings: Associate keyboard layouts with device/IME subtype."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dfc6787..9c6b045 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -454,6 +454,17 @@
         <service android:name=".TetherService"
             android:exported="true"
             android:permission="android.permission.TETHER_PRIVILEGED" />
+
+        <activity android:name="TetherProvisioningActivity"
+            android:exported="true"
+            android:permission="android.permission.TETHER_PRIVILEGED"
+            android:theme="@android:style/Theme.Translucent.NoTitleBar">
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.TETHER_PROVISIONING_UI" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <receiver
             android:name=".HotspotOffReceiver" >
             <intent-filter>
@@ -853,30 +864,6 @@
                 android:value="true" />
         </activity>
 
-        <activity android:name="Settings$HomeSettingsActivity"
-                android:label="@string/home_settings"
-                android:icon="@drawable/ic_settings_home"
-                android:taskAffinity="">
-            <intent-filter android:priority="1">
-                <action android:name="android.settings.HOME_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.VOICE_LAUNCH" />
-            </intent-filter>
-            <intent-filter android:priority="10">
-                <action android:name="com.android.settings.action.SETTINGS" />
-            </intent-filter>
-            <meta-data android:name="com.android.settings.category"
-                android:value="com.android.settings.category.device" />
-            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
-                android:value="com.android.settings.HomeSettings" />
-            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
-                android:value="true" />
-        </activity>
-
         <activity android:name="Settings$DisplaySettingsActivity"
                 android:label="@string/display_settings"
                 android:icon="@drawable/ic_settings_display"
@@ -2700,6 +2687,10 @@
                 <action android:name="android.settings.MANAGE_DEFAULT_APPS_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.settings.HOME_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                        android:value="com.android.settings.applications.ManageDefaultApps" />
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
diff --git a/proguard.flags b/proguard.flags
index 578ff4d..448cd72 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -5,6 +5,7 @@
 -keep class com.android.settings.wifi.*Settings
 -keep class com.android.settings.deviceinfo.*
 -keep class com.android.settings.bluetooth.*
+-keep class com.android.settings.datausage.*
 -keep class com.android.settings.applications.*
 -keep class com.android.settings.inputmethod.*
 -keep class com.android.settings.ResetNetwork
diff --git a/res/drawable/ic_data_saver.xml b/res/drawable/ic_data_saver.xml
new file mode 100644
index 0000000..426238c
--- /dev/null
+++ b/res/drawable/ic_data_saver.xml
@@ -0,0 +1,28 @@
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="
+        M9.0,16.0l2.0,0.0L11.0,8.0L9.0,8.0l0.0,8.0z
+        m3.0,-14.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0z
+        m0.0,18.0c-4.41,0.0 -8.0,-3.59 -8.0,-8.0s3.59,-8.0 8.0,-8.0 8.0,3.59 8.0,8.0 -3.59,8.0 -8.0,8.0z
+        m1.0,-4.0l2.0,0.0l0.0,-8.0l-2.0,0.0l0.0,8.0z"/>
+</vector>
diff --git a/res/layout/admin_support_details_content.xml b/res/layout/admin_support_details_content.xml
new file mode 100644
index 0000000..f1c5d6e
--- /dev/null
+++ b/res/layout/admin_support_details_content.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<!-- Layout used for displaying admin support details in empty preference fragments. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/admin_support_details"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:padding="@*android:dimen/preference_fragment_padding_side"
+        android:gravity="center_vertical"
+        android:orientation="vertical"
+        android:visibility="gone">
+    <TextView android:id="@+id/admin_support_msg"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+            android:text="@string/default_admin_support_msg"
+            android:maxLength="200"
+            android:autoLink="email|phone"
+            android:textColor="?android:attr/textColorSecondary" />
+    <TextView android:id="@+id/admins_policies_list"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="@dimen/admin_details_dialog_link_padding_top"
+            android:text="@string/admin_support_more_info"
+            android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+            android:textColor="?android:attr/colorAccent"
+            android:clickable="true"
+            android:background="?android:attr/selectableItemBackground" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/app_header.xml b/res/layout/app_header.xml
index 6c13ae8..2d8a099 100644
--- a/res/layout/app_header.xml
+++ b/res/layout/app_header.xml
@@ -50,7 +50,8 @@
         android:minWidth="0dp"
         android:contentDescription="@string/notification_app_settings_button"
         android:scaleType="center"
-        android:src="@drawable/ic_info"
+        android:src="@drawable/ic_settings_24dp"
+        android:visibility="gone"
         style="?android:attr/borderlessButtonStyle" />
 
 </RelativeLayout>
diff --git a/res/layout/app_preference_item.xml b/res/layout/app_preference_item.xml
index b02f835..0ad08cc 100755
--- a/res/layout/app_preference_item.xml
+++ b/res/layout/app_preference_item.xml
@@ -18,35 +18,55 @@
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
     android:padding="6dip">
     <ImageView
-        android:id="@+id/app_image"
+        android:id="@android:id/icon"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:adjustViewBounds="true"
         android:padding="6dip"
-    />
-    <TextView
-        android:id="@+id/app_label"
+        android:duplicateParentState="true"
+        />
+    <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:minHeight="?android:attr/listPreferredItemHeight"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="?android:attr/textColorAlertDialogListItem"
-        android:gravity="center_vertical"
-        android:paddingEnd="7dip"
-        android:ellipsize="marquee"
-    />
+        android:layout_gravity="center_vertical"
+        android:duplicateParentState="true"
+        android:orientation="vertical">
+        <TextView
+            android:id="@android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textColor="?android:attr/textColorAlertDialogListItem"
+            android:gravity="center_vertical"
+            android:paddingEnd="7dip"
+            android:ellipsize="marquee"
+            android:duplicateParentState="true"
+            />
+        <TextView
+            android:id="@android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:gravity="center_vertical"
+            android:paddingEnd="7dip"
+            android:ellipsize="marquee"
+            android:visibility="gone"
+            android:duplicateParentState="true"
+            />
+    </LinearLayout>
     <TextView
         android:id="@+id/default_label"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:minHeight="?android:attr/listPreferredItemHeight"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:gravity="center_vertical"
+        android:layout_gravity="center_vertical"
         android:text="@string/default_app"
         android:visibility="gone"
         android:paddingEnd="7dip"
-    />
+        android:duplicateParentState="true"
+        />
 </LinearLayout>
diff --git a/res/layout/data_usage_app_header.xml b/res/layout/data_usage_app_header.xml
deleted file mode 100644
index 8ca391a..0000000
--- a/res/layout/data_usage_app_header.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<!--
-     Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <include layout="@layout/app_header" />
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height=".5dp"
-        android:background="@android:color/white" />
-
-    <include layout="@layout/apps_filter_spinner" />
-
-</LinearLayout>
diff --git a/res/layout/data_usage_cycles.xml b/res/layout/data_usage_cycles.xml
index 5267e26..9c6cc31 100644
--- a/res/layout/data_usage_cycles.xml
+++ b/res/layout/data_usage_cycles.xml
@@ -17,7 +17,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:minHeight="?android:attr/listPreferredItemHeight"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:orientation="horizontal">
diff --git a/res/layout/device_admin_add.xml b/res/layout/device_admin_add.xml
index 4e8a6ac..b42b694 100644
--- a/res/layout/device_admin_add.xml
+++ b/res/layout/device_admin_add.xml
@@ -149,6 +149,15 @@
                 android:text="@string/cancel"
                 style="?android:attr/buttonBarButtonStyle"
                 android:layout_height="wrap_content" />
+            <Button android:id="@+id/uninstall_button"
+                android:layout_width="0dip"
+                android:layout_gravity="end"
+                android:layout_weight="1"
+                android:maxLines="2"
+                android:text="@string/uninstall_device_admin"
+                style="?android:attr/buttonBarButtonStyle"
+                android:layout_height="wrap_content"
+                android:visibility="gone" />
             <Button android:id="@+id/action_button"
                 android:layout_width="0dip"
                 android:layout_gravity="start"
diff --git a/res/layout/preference_list_fragment.xml b/res/layout/preference_list_fragment.xml
index f8badcf..d675a19 100644
--- a/res/layout/preference_list_fragment.xml
+++ b/res/layout/preference_list_fragment.xml
@@ -73,6 +73,8 @@
         android:gravity="center"
         android:visibility="gone" />
 
+    <include layout="@layout/admin_support_details_content" />
+
     <RelativeLayout android:id="@+id/button_bar"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
diff --git a/res/layout/preference_settings_icon_widget.xml b/res/layout/preference_settings_icon_widget.xml
new file mode 100644
index 0000000..7160ca7
--- /dev/null
+++ b/res/layout/preference_settings_icon_widget.xml
@@ -0,0 +1,23 @@
+<?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
+  -->
+
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:src="@drawable/ic_settings_24dp"
+    android:tint="@color/material_grey_600"
+    android:contentDescription="@null"/>
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 84d98da..bce8fb0 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -502,6 +502,24 @@
                             android:inputType="textNoSuggestions" />
                 </LinearLayout>
             </LinearLayout>
+
+            <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/wifi_section">
+                <LinearLayout
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        style="@style/wifi_item" >
+                    <CheckBox android:id="@+id/shared"
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            style="@style/wifi_item_content"
+                            android:textSize="14sp"
+                            android:text="@string/wifi_shared"
+                            android:checked="true" />
+                </LinearLayout>
+            </LinearLayout>
         </LinearLayout>
     </LinearLayout>
 </ScrollView>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index e070505..b048b71 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -15,9 +15,6 @@
 -->
 
 <resources>
-    <declare-styleable name="WifiEncryptionState">
-        <attr name="state_encrypted" format="boolean" />
-    </declare-styleable>
     <declare-styleable name="IconPreferenceScreen">
         <attr name="icon" />
     </declare-styleable>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 6140c78..30aa52f 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -207,7 +207,6 @@
 
     <!-- WiFi Preferences -->
     <dimen name="wifi_divider_height">1px</dimen>
-    <dimen name="wifi_preference_badge_padding">8dip</dimen>
 
     <!-- Color picker -->
     <dimen name="color_swatch_size">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 51b2325..89c05ad 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1020,6 +1020,15 @@
     <!-- Summary specifying that this is the current screen lock setting [CHAR LIMIT=45] -->
     <string name="current_screen_lock">Current screen lock</string>
 
+    <!-- Title for preference that guides the user through creating a backup unlock pattern for fingerprint [CHAR LIMIT=45]-->
+    <string name="fingerprint_unlock_set_unlock_pattern">Fingerprint + Pattern</string>
+
+    <!-- Title for preference that guides the user through creating a backup unlock PIN for fingerprint [CHAR LIMIT=45]-->
+    <string name="fingerprint_unlock_set_unlock_pin">Fingerprint + PIN</string>
+
+    <!-- Title for preference that guides the user through creating a backup unlock password for fingerprint [CHAR LIMIT=45]-->
+    <string name="fingerprint_unlock_set_unlock_password">Fingerprint + Password</string>
+
     <!-- Summary for preference that has been disabled by because of the DevicePolicyAdmin, or because device encryption is enabled, or because there are credentials in the credential storage [CHAR LIMIT=50] -->
     <string name="unlock_set_unlock_disabled_summary">Disabled by administrator, encryption policy, or credential storage</string>
 
@@ -1626,6 +1635,8 @@
     <string name="wifi_ap_choose_5G">5 GHz Band</string>
     <!-- Label for the spinner to show ip settings [CHAR LIMIT=25] -->
     <string name="wifi_ip_settings">IP settings</string>
+    <!-- Label for the check box to share a network with other users on the same device -->
+    <string name="wifi_shared">Share with other device users</string>
     <!-- Hint for unchanged fields -->
     <string name="wifi_unchanged">(unchanged)</string>
     <!-- Hint for unspecified fields -->
@@ -2827,8 +2838,6 @@
     <string name="location_title">My Location</string>
     <!-- [CHAR LIMIT=30] Title for managed profile location switch  -->
     <string name="managed_profile_location_switch_title">Location for work profile</string>
-    <!-- [CHAR LIMIT=30] Text to show on managed profile location switch if MDM has locked down location access for managed profile-->
-    <string name="managed_profile_location_switch_lockdown">Turned off by your company</string>
     <!-- [CHAR LIMIT=30] Location settings screen, setting preference screen box label for location mode -->
     <string name="location_mode_title">Mode</string>
     <!-- [CHAR LIMIT=30] Location settings screen, high accuracy location mode -->
@@ -3817,8 +3826,6 @@
     <string name="accessibility_feature_state_on">On</string>
     <!-- Summary for the disabled state of an accessibility feature. [CHAR LIMIT=10] -->
     <string name="accessibility_feature_state_off">Off</string>
-    <!-- Summary when an accessibility feature or ime is not permitted. [CHAR LIMIT=40] -->
-    <string name="accessibility_feature_or_input_method_not_allowed">Not allowed by your organization</string>
 
     <!-- Title for the preference category containing the video caption preview. [CHAR LIMIT=35] -->
     <string name="captioning_preview_title">Preview</string>
@@ -4527,6 +4534,8 @@
     <string name="active_device_admin_msg">Device administrator</string>
     <!-- Label for button to remove the active device admin -->
     <string name="remove_device_admin">Deactivate</string>
+    <!-- Label for button to uninstall the device admin application [CHAR LIMIT=40] -->
+    <string name="uninstall_device_admin">Uninstall</string>
     <!-- Label for screen showing to select device policy -->
     <string name="select_device_admin_msg">Device administrators</string>
     <!-- Message when there are no available device admins to display -->
@@ -4920,9 +4929,9 @@
     <!-- Button title for launching application-specific data usage settings. [CHAR LIMIT=32] -->
     <string name="data_usage_app_settings">App settings</string>
     <!-- Checkbox label that restricts background data usage of a specific application. [CHAR LIMIT=40] -->
-    <string name="data_usage_app_restrict_background">Restrict app background data</string>
-    <!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=64] -->
-    <string name="data_usage_app_restrict_background_summary">Disable background data on cellular networks.</string>
+    <string name="data_usage_app_restrict_background">Background data</string>
+    <!-- Summary message for checkbox that restricts background data usage of a specific application. [CHAR LIMIT=NONE] -->
+    <string name="data_usage_app_restrict_background_summary">Enable usage of cellular data in the background</string>
     <!-- Summary message for checkbox that restricts background data usage of a specific application when no networks have been limited. [CHAR LIMIT=84] -->
     <string name="data_usage_app_restrict_background_summary_disabled">To restrict background data for this app, first set a cellular data limit.</string>
     <!-- Title of dialog shown when user restricts background data usage of a specific application. [CHAR LIMIT=48] -->
@@ -5290,6 +5299,10 @@
     <string name="user_enable_calling_and_sms_confirm_title">Turn on phone calls &amp; SMS?</string>
     <!-- Message for confirmation of turning on calls and SMS [CHAR LIMIT=none] -->
     <string name="user_enable_calling_and_sms_confirm_message">Call and SMS history will be shared with this user.</string>
+    <!-- Title for the emergency info preference [CHAR LIMIT=40] -->
+    <string name="emergency_info_title">Emergency information</string>
+    <!-- Description of the emergency info preference [CHAR LIMIT=80] -->
+    <string name="emergency_info_subtitle">Accessible through lock screen in the emergency dialer</string>
 
     <!-- Application Restrictions screen title [CHAR LIMIT=45] -->
     <string name="application_restrictions">Allow apps and content</string>
@@ -6876,7 +6889,7 @@
     <string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
 
     <!-- Title of condition that background data is off [CHAR LIMIT=30] -->
-    <string name="condition_bg_data_title">Background data is off</string>
+    <string name="condition_bg_data_title">Data Saver is on</string>
 
     <!-- Summary of condition that background data is off [CHAR LIMIT=NONE] -->
     <string name="condition_bg_data_summary">Background data is only available via Wi-Fi. This may affect some apps or services when Wi-Fi is not available.</string>
@@ -6972,4 +6985,34 @@
          the code to do that -->
     <string name="data_usage_other_apps" translatable="false">Other apps included in usage</string>
 
+    <!-- Description of number of apps allowed to ignore data saver [CHAR LIMIT=NONE] -->
+    <plurals name="data_saver_unrestricted_summary">
+        <item quantity="one">1 app allowed to use unrestricted data when Data Saver is on</item>
+        <item quantity="other"><xliff:g id="count" example="10">%1$d</xliff:g> apps allowed to use unrestricted data when Data Saver is on</item>
+    </plurals>
+
+    <!-- Name of Data Saver screens [CHAR LIMIT=30] -->
+    <string name="data_saver_title">Data Saver</string>
+
+    <!-- Button that leads to list of apps with unrestricted data access [CHAR LIMIT=60] -->
+    <string name="unrestricted_data_saver">Unrestricted data access</string>
+
+    <!-- Summary for the data saver feature being on [CHAR LIMIT=NONE] -->
+    <string name="data_saver_on">On</string>
+
+    <!-- Summary for the data saver feature being off [CHAR LIMIT=NONE] -->
+    <string name="data_saver_off">Off</string>
+
+    <!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=30] -->
+    <string name="unrestricted_app_title">Unrestricted data usage</string>
+
+    <!-- Title for switch to allow app unrestricted data usage [CHAR LIMIT=30] -->
+    <string name="unrestricted_app_summary">Allow unrestricted data access when Data Saver is on</string>
+
+    <!-- Button to switch the default home app [CHAR LIMIT=60] -->
+    <string name="home_app">Home app</string>
+
+    <!-- No default home set summary [CHAR LIMIT=NONE] -->
+    <string name="no_default_home">No default Home</string>
+
 </resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index f3a9369..da74348 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -24,7 +24,6 @@
     <attr name="setup_divider_color" format="reference" />
     <attr name="side_margin" format="reference|dimension" />
     <attr name="wifi_signal_color" format="reference" />
-    <attr name="wifi_signal" format="reference" />
 
     <style name="SetupWizardDisableAppStartingTheme">
         <!-- Theme to disable the app starting window. The actual theme of the activity needs to
diff --git a/res/xml/app_data_usage.xml b/res/xml/app_data_usage.xml
index b082b56..520b93b 100644
--- a/res/xml/app_data_usage.xml
+++ b/res/xml/app_data_usage.xml
@@ -17,6 +17,9 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
     android:title="@string/data_usage_summary_title">
 
+    <com.android.settings.datausage.SpinnerPreference
+        android:key="cycle" />
+
     <com.android.settings.applications.SpacePreference
         android:layout_height="8dp" />
 
@@ -50,6 +53,11 @@
         android:title="@string/data_usage_app_restrict_background"
         android:summary="@string/data_usage_app_restrict_background_summary" />
 
+    <SwitchPreference
+        android:key="unrestricted_data_saver"
+        android:title="@string/unrestricted_app_title"
+        android:summary="@string/unrestricted_app_summary" />
+
     <PreferenceCategory
         android:key="app_list"
         android:title="@string/data_usage_other_apps" />
diff --git a/res/xml/data_saver.xml b/res/xml/data_saver.xml
new file mode 100644
index 0000000..5b69cbb
--- /dev/null
+++ b/res/xml/data_saver.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/data_saver_title">
+
+    <Preference
+        android:key="unrestricted_access"
+        android:title="@string/unrestricted_data_saver"
+        android:fragment="com.android.settings.datausage.UnrestrictedDataAccess" />
+
+</PreferenceScreen>
diff --git a/res/xml/data_usage.xml b/res/xml/data_usage.xml
index 378496e..0626da9 100644
--- a/res/xml/data_usage.xml
+++ b/res/xml/data_usage.xml
@@ -29,9 +29,10 @@
             android:key="limit_summary"
             android:selectable="false" />
 
-        <com.android.settings.datausage.RestrictBackgroundDataPreference
+        <com.android.settings.datausage.DataSaverPreference
             android:key="restrict_background"
-            android:title="@string/data_usage_menu_restrict_background" />
+            android:title="@string/data_saver_title"
+            android:fragment="com.android.settings.datausage.DataSaverSummary" />
 
     </PreferenceCategory>
 
diff --git a/res/xml/default_apps.xml b/res/xml/default_apps.xml
index a38ef4a..76d0e8c 100644
--- a/res/xml/default_apps.xml
+++ b/res/xml/default_apps.xml
@@ -25,6 +25,12 @@
         android:title="@string/assist_and_voice_input_title"
         />
 
+    <com.android.settings.applications.DefaultHomePreference
+            android:key="default_home"
+            android:title="@string/home_app"
+            android:summary="@string/no_default_home"
+            />
+
     <com.android.settings.applications.DefaultBrowserPreference
             android:key="default_browser"
             android:title="@string/default_browser_title"
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 4ccc14a..d22d32a 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -27,10 +27,10 @@
             android:summary="@string/location_mode_location_off_title" />
 
         <!-- This preference category gets removed if there is no managed profile -->
-        <SwitchPreference
+        <com.android.settingslib.RestrictedSwitchPreference
             android:key="managed_profile_location_switch"
             android:title="@string/managed_profile_location_switch_title"
-            android:summary="@string/managed_profile_location_switch_lockdown"
+            settings:useAdminDisabledSummary="true"
             android:persistent="false"
             android:enabled="false"
             android:selectable="true" />
diff --git a/res/xml/privacy_settings.xml b/res/xml/privacy_settings.xml
index f67c837..461d242 100644
--- a/res/xml/privacy_settings.xml
+++ b/res/xml/privacy_settings.xml
@@ -33,6 +33,11 @@
         <intent android:action="dummy" />
     </PreferenceScreen>
 
+    <PreferenceScreen
+        android:key="data_management"
+        android:persistent="false">
+    </PreferenceScreen>
+
     <SwitchPreference
         android:key="auto_restore"
         android:title="@string/auto_restore_title"
@@ -51,6 +56,7 @@
         android:key="network_reset"
         android:title="@string/reset_network_title"
         settings:keywords="@string/keywords_network_reset"
+        settings:useAdminDisabledSummary="true"
         android:fragment="com.android.settings.ResetNetwork" />
 
     <!-- Factory reset -->
@@ -59,6 +65,7 @@
         android:title="@string/master_clear_title"
         settings:keywords="@string/keywords_factory_data_reset"
         settings:userRestriction="no_factory_reset"
+        settings:useAdminDisabledSummary="true"
         android:fragment="com.android.settings.MasterClear" />
 
 </PreferenceScreen>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 2137490..2b8ae13 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -62,6 +62,7 @@
         <com.android.settingslib.RestrictedPreference
                 android:key="zen_mode"
                 android:title="@string/zen_mode_settings_title"
+                settings:useAdminDisabledSummary="true"
                 settings:keywords="@string/keywords_sounds_and_notifications_interruptions"
                 android:fragment="com.android.settings.notification.ZenModeSettings" />
 
@@ -91,7 +92,8 @@
 
         <com.android.settingslib.RestrictedPreference
                 android:key="cell_broadcast_settings"
-                android:title="@string/cell_broadcast_settings" >
+                android:title="@string/cell_broadcast_settings"
+                settings:useAdminDisabledSummary="true">
                 <intent
                         android:action="android.intent.action.MAIN"
                         android:targetPackage="com.android.cellbroadcastreceiver"
diff --git a/res/xml/user_details_settings.xml b/res/xml/user_details_settings.xml
index 96c8ab9..0b0c6d9 100644
--- a/res/xml/user_details_settings.xml
+++ b/res/xml/user_details_settings.xml
@@ -23,6 +23,7 @@
             android:persistent="false" />
     <com.android.settingslib.RestrictedPreference
             android:key="remove_user"
-            android:title="@string/user_remove_user" />
+            android:title="@string/user_remove_user"
+            settings:useAdminDisabledSummary="true" />
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/user_settings.xml b/res/xml/user_settings.xml
index 4fefc10..ac2685f 100644
--- a/res/xml/user_settings.xml
+++ b/res/xml/user_settings.xml
@@ -35,5 +35,9 @@
                 android:key="add_users_when_locked"
                 android:title="@string/user_add_on_lockscreen_menu"
                 android:summary="@string/user_add_on_lockscreen_menu_summary" />
+        <Preference
+                android:key="emergency_info"
+                android:title="@string/emergency_info_title"
+                android:summary="@string/emergency_info_subtitle"/>
     </PreferenceCategory>
 </PreferenceScreen>
diff --git a/res/xml/wifi_settings.xml b/res/xml/wifi_settings.xml
index 99a0c4e..b4ab126 100644
--- a/res/xml/wifi_settings.xml
+++ b/res/xml/wifi_settings.xml
@@ -21,7 +21,7 @@
 
     <!-- Needed so PreferenceGroupAdapter allows AccessPointPreference to be
          recycled. Removed in onResume -->
-    <com.android.settings.wifi.AccessPointPreference
+    <com.android.settings.wifi.LongPressAccessPointPreference
         android:key="dummy" />
 
 </PreferenceScreen>
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index db7e18a..10ec484 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -44,12 +44,14 @@
     <com.android.settingslib.RestrictedPreference
         android:fragment="com.android.settings.TetherSettings"
         android:key="tether_settings"
-        android:title="@string/tether_settings_title_all" />
+        android:title="@string/tether_settings_title_all"
+        settings:useAdminDisabledSummary="true" />
 
     <com.android.settingslib.RestrictedPreference
         android:fragment="com.android.settings.vpn2.VpnSettings"
         android:key="vpn_settings"
-        android:title="@string/vpn_settings_title" />
+        android:title="@string/vpn_settings_title"
+        settings:useAdminDisabledSummary="true" />
 
     <PreferenceScreen
         android:key="mobile_network_settings"
diff --git a/src/com/android/settings/AppHeader.java b/src/com/android/settings/AppHeader.java
index 36026bb..0351ed5 100644
--- a/src/com/android/settings/AppHeader.java
+++ b/src/com/android/settings/AppHeader.java
@@ -58,7 +58,7 @@
     }
 
     public static View setupHeaderView(final Activity activity, Drawable icon, CharSequence label,
-            final String pkgName, final int uid, boolean includeAppInfo, int tintColorRes,
+            final String pkgName, final int uid, final boolean includeAppInfo, int tintColorRes,
             View bar) {
         final ImageView appIcon = (ImageView) bar.findViewById(R.id.app_icon);
         appIcon.setImageDrawable(icon);
@@ -69,19 +69,20 @@
         final TextView appName = (TextView) bar.findViewById(R.id.app_name);
         appName.setText(label);
 
-        final View appSettings = bar.findViewById(R.id.app_settings);
-        if (includeAppInfo && pkgName != null && !pkgName.equals(Utils.OS_PKG)) {
-            appSettings.setClickable(true);
-            appSettings.setOnClickListener(new OnClickListener() {
+        if (pkgName != null && !pkgName.equals(Utils.OS_PKG)) {
+            bar.setClickable(true);
+            bar.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
-                    AppInfoBase.startAppInfoFragment(InstalledAppDetails.class,
-                            R.string.application_info_label, pkgName, uid, activity,
-                            INSTALLED_APP_DETAILS);
+                    if (includeAppInfo) {
+                        AppInfoBase.startAppInfoFragment(InstalledAppDetails.class,
+                                R.string.application_info_label, pkgName, uid, activity,
+                                INSTALLED_APP_DETAILS);
+                    } else {
+                        activity.finish();
+                    }
                 }
             });
-        } else {
-            appSettings.setVisibility(View.GONE);
         }
         return bar;
     }
diff --git a/src/com/android/settings/AppListPreference.java b/src/com/android/settings/AppListPreference.java
index 4d24d7f..1c1ccd7 100644
--- a/src/com/android/settings/AppListPreference.java
+++ b/src/com/android/settings/AppListPreference.java
@@ -16,7 +16,6 @@
 
 package com.android.settings;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.content.ComponentName;
 import android.content.Context;
@@ -50,6 +49,7 @@
 
     private Drawable[] mEntryDrawables;
     private boolean mShowItemNone = false;
+    private CharSequence[] mSummaries;
 
     public class AppArrayAdapter extends ArrayAdapter<CharSequence> {
         private Drawable[] mImageDrawables = null;
@@ -63,16 +63,30 @@
         }
 
         @Override
+        public boolean isEnabled(int position) {
+            return mSummaries == null || mSummaries[position] == null;
+        }
+
+        @Override
         public View getView(int position, View convertView, ViewGroup parent) {
             LayoutInflater inflater = LayoutInflater.from(getContext());
             View view = inflater.inflate(R.layout.app_preference_item, parent, false);
-            TextView textView = (TextView) view.findViewById(R.id.app_label);
+            TextView textView = (TextView) view.findViewById(android.R.id.title);
             textView.setText(getItem(position));
             if (position == mSelectedIndex) {
                 view.findViewById(R.id.default_label).setVisibility(View.VISIBLE);
             }
-            ImageView imageView = (ImageView)view.findViewById(R.id.app_image);
+            ImageView imageView = (ImageView) view.findViewById(android.R.id.icon);
             imageView.setImageDrawable(mImageDrawables[position]);
+            // Summaries are describing why a item is disabled, so anything with a summary
+            // is not enabled.
+            boolean enabled = mSummaries == null || mSummaries[position] == null;
+            view.setEnabled(enabled);
+            if (!enabled) {
+                TextView summary = (TextView) view.findViewById(android.R.id.summary);
+                summary.setText(mSummaries[position]);
+                summary.setVisibility(View.VISIBLE);
+            }
             return view;
         }
     }
@@ -133,6 +147,12 @@
     }
 
     public void setComponentNames(ComponentName[] componentNames, ComponentName defaultCN) {
+        setComponentNames(componentNames, defaultCN, null);
+    }
+
+    public void setComponentNames(ComponentName[] componentNames, ComponentName defaultCN,
+            CharSequence[] summaries) {
+        mSummaries = summaries;
         // Look up all package names in PackageManager. Skip ones we can't find.
         PackageManager pm = getContext().getPackageManager();
         final int entryCount = componentNames.length + (mShowItemNone ? 1 : 0);
@@ -192,7 +212,7 @@
     @Override
     protected Parcelable onSaveInstanceState() {
         Parcelable superState = super.onSaveInstanceState();
-        return new SavedState(getEntryValues(), getValue(), mShowItemNone, superState);
+        return new SavedState(getEntryValues(), getValue(), mSummaries, mShowItemNone, superState);
     }
 
     @Override
@@ -201,6 +221,7 @@
             SavedState savedState = (SavedState) state;
             mShowItemNone = savedState.showItemNone;
             setPackageNames(savedState.entryValues, savedState.value);
+            mSummaries = savedState.summaries;
             super.onRestoreInstanceState(savedState.superState);
         } else {
             super.onRestoreInstanceState(state);
@@ -213,13 +234,15 @@
         public final CharSequence value;
         public final boolean showItemNone;
         public final Parcelable superState;
+        public final CharSequence[] summaries;
 
-        public SavedState(CharSequence[] entryValues, CharSequence value, boolean showItemNone,
-                Parcelable superState) {
+        public SavedState(CharSequence[] entryValues, CharSequence value, CharSequence[] summaries,
+                boolean showItemNone, Parcelable superState) {
             this.entryValues = entryValues;
             this.value = value;
             this.showItemNone = showItemNone;
             this.superState = superState;
+            this.summaries = summaries;
         }
 
         @Override
@@ -233,6 +256,7 @@
             dest.writeCharSequence(value);
             dest.writeInt(showItemNone ? 1 : 0);
             dest.writeParcelable(superState, flags);
+            dest.writeCharSequenceArray(summaries);
         }
 
         public static Creator<SavedState> CREATOR = new Creator<SavedState>() {
@@ -242,7 +266,8 @@
                 CharSequence value = source.readCharSequence();
                 boolean showItemNone = source.readInt() != 0;
                 Parcelable superState = source.readParcelable(getClass().getClassLoader());
-                return new SavedState(entryValues, value, showItemNone, superState);
+                CharSequence[] summaries = source.readCharSequenceArray();
+                return new SavedState(entryValues, value, summaries, showItemNone, superState);
             }
 
             @Override
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 0e6cf3b..6461b93 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -300,6 +300,7 @@
                 }
                 addPreferencesFromResource(R.xml.security_settings_picker);
                 disableUnusablePreferences(quality, hideDisabledPrefs);
+                updatePreferenceText();
                 updateCurrentPreference();
                 updatePreferenceSummaryIfNeeded();
             } else {
@@ -307,6 +308,19 @@
             }
         }
 
+        private void updatePreferenceText() {
+            if (mForFingerprint) {
+                Preference pattern = findPreference(KEY_UNLOCK_SET_PATTERN);
+                pattern.setTitle(R.string.fingerprint_unlock_set_unlock_pattern);
+
+                Preference pin = findPreference(KEY_UNLOCK_SET_PIN);
+                pin.setTitle(R.string.fingerprint_unlock_set_unlock_pin);
+
+                Preference password = findPreference(KEY_UNLOCK_SET_PASSWORD);
+                password.setTitle(R.string.fingerprint_unlock_set_unlock_password);
+            }
+        }
+
         private void updateCurrentPreference() {
             String currentKey = getKeyForCurrent();
             Preference preference = findPreference(currentKey);
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index 70ecdfd..1035ef1 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -150,6 +150,23 @@
                 false, false, true, challenge, Utils.getCredentialOwnerUserId(mActivity));
     }
 
+    /**
+     * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
+     * @param message optional message to display about the action about to be done
+     * @param details optional detail message to display
+     * @param challenge a challenge to be verified against the device credential.
+     *                  This method can only be called internally.
+     * @param userId The userId for whom the lock should be confirmed.
+     * @return true if one exists and we launched an activity to confirm it
+     * @see #onActivityResult(int, int, android.content.Intent)
+     */
+    public boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
+            @Nullable CharSequence header, @Nullable CharSequence description,
+            long challenge, int userId) {
+        return launchConfirmationActivity(request, title, header, description,
+                false, false, true, challenge, Utils.enforceSameOwner(mActivity, userId));
+    }
+
     private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
             @Nullable CharSequence header, @Nullable CharSequence description,
             boolean returnCredentials, boolean external, boolean hasChallenge,
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index 86c9fca..40e3103 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -22,6 +22,7 @@
 import android.app.ActivityOptions;
 import android.app.IActivityManager;
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -63,12 +64,16 @@
     private boolean mAllowFpAuthentication;
     protected Button mCancelButton;
     protected ImageView mFingerprintIcon;
+    protected int mEffectiveUserId;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mAllowFpAuthentication = getActivity().getIntent().getBooleanExtra(
                 ALLOW_FP_AUTHENTICATION, false);
+        // Only take this argument into account if it belongs to the current profile.
+        Intent intent = getActivity().getIntent();
+        mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
     }
 
     @Override
@@ -78,7 +83,7 @@
         mFingerprintIcon = (ImageView) view.findViewById(R.id.fingerprintIcon);
         mFingerprintHelper = new FingerprintUiHelper(
                 mFingerprintIcon,
-                (TextView) view.findViewById(R.id.errorText), this);
+                (TextView) view.findViewById(R.id.errorText), this, mEffectiveUserId);
         boolean showCancelButton = getActivity().getIntent().getBooleanExtra(
                 SHOW_CANCEL_BUTTON, false);
         mCancelButton.setVisibility(showCancelButton ? View.VISIBLE : View.GONE);
@@ -132,7 +137,12 @@
     public void onAuthenticated() {
         // Check whether we are still active.
         if (getActivity() != null && getActivity().isResumed()) {
+            TrustManager trustManager =
+                (TrustManager) getActivity().getSystemService(Context.TRUST_SERVICE);
+            trustManager.setDeviceLockedForUser(mEffectiveUserId, false);
             authenticationSucceeded();
+            authenticationSucceeded();
+            checkForPendingIntent();
         }
     }
 
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index f6347c1..e1362ea 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -99,7 +99,6 @@
         private AppearAnimationUtils mAppearAnimationUtils;
         private DisappearAnimationUtils mDisappearAnimationUtils;
         private boolean mBlockImm;
-        private int mEffectiveUserId;
 
         // required constructor for fragments
         public ConfirmLockPasswordFragment() {
@@ -110,9 +109,6 @@
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             mLockPatternUtils = new LockPatternUtils(getActivity());
-            Intent intent = getActivity().getIntent();
-            // Only take this argument into account if it belongs to the current profile.
-            mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
         }
 
         @Override
@@ -183,14 +179,13 @@
         private int getDefaultDetails() {
             boolean isProfile = Utils.isManagedProfile(
                     UserManager.get(getActivity()), mEffectiveUserId);
-            if (mIsAlpha && !isProfile) {
-                return R.string.lockpassword_confirm_your_password_generic;
-            } else if (mIsAlpha && isProfile) {
-                return R.string.lockpassword_confirm_your_password_generic_profile;
-            } else if (!isProfile) {
-                return R.string.lockpassword_confirm_your_pin_generic;
+            if (mIsAlpha) {
+                return isProfile ? R.string.lockpassword_confirm_your_password_generic_profile
+                        : R.string.lockpassword_confirm_your_password_generic;
+            } else {
+                return isProfile ? R.string.lockpassword_confirm_your_pin_generic_profile
+                        : R.string.lockpassword_confirm_your_pin_generic;
             }
-            return R.string.lockpassword_confirm_your_pin_generic_profile;
         }
 
         private int getErrorMessage() {
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index 5c72bd1..922d1c7 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -104,8 +104,6 @@
         private AppearAnimationUtils mAppearAnimationUtils;
         private DisappearAnimationUtils mDisappearAnimationUtils;
 
-        private int mEffectiveUserId;
-
         // required constructor for fragments
         public ConfirmLockPatternFragment() {
 
@@ -115,9 +113,6 @@
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             mLockPatternUtils = new LockPatternUtils(getActivity());
-            Intent intent = getActivity().getIntent();
-            // Only take this argument into account if it belongs to the current profile.
-            mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
         }
 
         @Override
diff --git a/src/com/android/settings/DeviceAdminAdd.java b/src/com/android/settings/DeviceAdminAdd.java
index 3067ca2..1ce72f9 100644
--- a/src/com/android/settings/DeviceAdminAdd.java
+++ b/src/com/android/settings/DeviceAdminAdd.java
@@ -36,6 +36,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
@@ -74,6 +75,8 @@
     private static final int MAX_ADD_MSG_LINES_LANDSCAPE = 2;
     private static final int MAX_ADD_MSG_LINES = 15;
 
+    private static final int REQUEST_CODE_UNINSTALL = 1;
+
     Handler mHandler;
 
     DevicePolicyManager mDPM;
@@ -93,6 +96,7 @@
     TextView mSupportMessage;
     ViewGroup mAdminPolicies;
     Button mActionButton;
+    Button mUninstallButton;
     Button mCancelButton;
 
     boolean mAdding;
@@ -285,6 +289,7 @@
         mAdminWarning = (TextView) findViewById(R.id.admin_warning);
         mAdminPolicies = (ViewGroup) findViewById(R.id.admin_policies);
         mSupportMessage = (TextView) findViewById(R.id.admin_support_message);
+
         mCancelButton = (Button) findViewById(R.id.cancel_button);
         mCancelButton.setFilterTouchesWhenObscured(true);
         mCancelButton.setOnClickListener(new View.OnClickListener() {
@@ -294,6 +299,17 @@
                 finish();
             }
         });
+
+        mUninstallButton = (Button) findViewById(R.id.uninstall_button);
+        mUninstallButton.setFilterTouchesWhenObscured(true);
+        mUninstallButton.setOnClickListener(new View.OnClickListener() {
+            public void onClick(View v) {
+                EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_UNINSTALLED_BY_USER,
+                        mDeviceAdmin.getActivityInfo().applicationInfo.uid);
+                uninstall();
+            }
+        });
+
         mActionButton = (Button) findViewById(R.id.action_button);
         mActionButton.setFilterTouchesWhenObscured(true);
         mActionButton.setOnClickListener(new View.OnClickListener() {
@@ -448,6 +464,18 @@
         }
     }
 
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case REQUEST_CODE_UNINSTALL:
+                if (resultCode == RESULT_OK) {
+                    finish();
+                }
+                return;
+        }
+        super.onActivityResult(requestCode, resultCode, data);
+    }
+
     void updateInterface() {
         mAdminIcon.setImageDrawable(mDeviceAdmin.loadIcon(getPackageManager()));
         mAdminName.setText(mDeviceAdmin.loadLabel(getPackageManager()));
@@ -516,6 +544,9 @@
                 setTitle(getText(R.string.add_device_admin_msg));
             }
             mActionButton.setText(getText(R.string.add_device_admin));
+            if (isAdminUninstallable()) {
+                mUninstallButton.setVisibility(View.VISIBLE);
+            }
             mSupportMessage.setVisibility(View.GONE);
             mAdding = true;
         }
@@ -564,4 +595,18 @@
                 UserHandle.getUserId(adminInfo.getActivityInfo().applicationInfo.uid));
         return info != null ? info.isManagedProfile() : false;
     }
+
+    private boolean isAdminUninstallable() {
+        // System apps can't be uninstalled.
+        return !mDeviceAdmin.getActivityInfo().applicationInfo.isSystemApp();
+    }
+
+    private void uninstall() {
+        final Uri packageURI = Uri.parse("package:" + mDeviceAdmin.getPackageName());
+        final Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageURI);
+        uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, false);
+        uninstallIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
+
+        startActivityForResult(uninstallIntent, REQUEST_CODE_UNINSTALL);
+    }
 }
diff --git a/src/com/android/settings/DimmableIconPreference.java b/src/com/android/settings/DimmableIconPreference.java
index 98bf551..8f09c53 100644
--- a/src/com/android/settings/DimmableIconPreference.java
+++ b/src/com/android/settings/DimmableIconPreference.java
@@ -44,11 +44,13 @@
     public DimmableIconPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContentDescription = null;
+        useAdminDisabledSummary(true);
     }
 
     public DimmableIconPreference(Context context, @Nullable CharSequence contentDescription) {
         super(context);
         mContentDescription = contentDescription;
+        useAdminDisabledSummary(true);
     }
 
     private void dimIcon(boolean dimmed) {
diff --git a/src/com/android/settings/EventLogTags.logtags b/src/com/android/settings/EventLogTags.logtags
index b21623c..1811866 100644
--- a/src/com/android/settings/EventLogTags.logtags
+++ b/src/com/android/settings/EventLogTags.logtags
@@ -10,3 +10,6 @@
 
 # log whether user declined activation of device admin
 90202 exp_det_device_admin_declined_by_user (app_signature|3)
+
+# log whether user uninstalled device admin on activation screen
+90203 exp_det_device_admin_uninstalled_by_user (app_signature|3)
diff --git a/src/com/android/settings/HotspotOffReceiver.java b/src/com/android/settings/HotspotOffReceiver.java
index f3c3fee..3db0ee9 100644
--- a/src/com/android/settings/HotspotOffReceiver.java
+++ b/src/com/android/settings/HotspotOffReceiver.java
@@ -4,6 +4,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.util.Log;
 
@@ -25,7 +26,8 @@
             if (wifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED) {
                 if (DEBUG) Log.d(TAG, "TetherService.cancelRecheckAlarmIfNecessary called");
                 // The hotspot has been turned off, we don't need to recheck tethering.
-                TetherService.cancelRecheckAlarmIfNecessary(context, TetherUtil.TETHERING_WIFI);
+                TetherService.cancelRecheckAlarmIfNecessary(
+                        context, ConnectivityManager.TETHERING_WIFI);
             }
         }
     }
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index ea39cf3..884e07b 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -41,6 +41,8 @@
     public static final int VIRTUAL_KEYBOARDS = UNDECLARED + 11;
     public static final int PHYSICAL_KEYBOARDS = UNDECLARED + 12;
     public static final int ENABLE_VIRTUAL_KEYBOARDS = UNDECLARED + 13;
+    public static final int DATA_SAVER_SUMMARY = UNDECLARED + 14;
+    public static final int DATA_USAGE_UNRESTRICTED_ACCESS = UNDECLARED + 15;
 
     /**
      * Declare the view of this category.
diff --git a/src/com/android/settings/PrivacySettings.java b/src/com/android/settings/PrivacySettings.java
index dbceb2b..df73fec 100644
--- a/src/com/android/settings/PrivacySettings.java
+++ b/src/com/android/settings/PrivacySettings.java
@@ -56,6 +56,7 @@
     private static final String BACKUP_DATA = "backup_data";
     private static final String AUTO_RESTORE = "auto_restore";
     private static final String CONFIGURE_ACCOUNT = "configure_account";
+    private static final String DATA_MANAGEMENT = "data_management";
     private static final String BACKUP_INACTIVE = "backup_inactive";
     private static final String NETWORK_RESET = "network_reset";
     private static final String FACTORY_RESET = "factory_reset";
@@ -64,6 +65,7 @@
     private PreferenceScreen mBackup;
     private SwitchPreference mAutoRestore;
     private PreferenceScreen mConfigure;
+    private PreferenceScreen mManageData;
     private boolean mEnabled;
 
     @Override
@@ -92,6 +94,7 @@
         mAutoRestore.setOnPreferenceChangeListener(preferenceChangeListener);
 
         mConfigure = (PreferenceScreen) screen.findPreference(CONFIGURE_ACCOUNT);
+        mManageData = (PreferenceScreen) screen.findPreference(DATA_MANAGEMENT);
 
         Set<String> keysToRemove = new HashSet<>();
         getNonVisibleKeys(getActivity(), keysToRemove);
@@ -146,11 +149,15 @@
         boolean backupEnabled = false;
         Intent configIntent = null;
         String configSummary = null;
+        Intent manageIntent = null;
+        String manageLabel = null;
         try {
             backupEnabled = mBackupManager.isBackupEnabled();
             String transport = mBackupManager.getCurrentTransport();
             configIntent = mBackupManager.getConfigurationIntent(transport);
             configSummary = mBackupManager.getDestinationString(transport);
+            manageIntent = mBackupManager.getDataManagementIntent(transport);
+            manageLabel = mBackupManager.getDataManagementLabel(transport);
 
             mBackup.setSummary(backupEnabled
                     ? R.string.accessibility_feature_state_on
@@ -169,6 +176,17 @@
         mConfigure.setIntent(configIntent);
         setConfigureSummary(configSummary);
 
+        final boolean manageEnabled = (manageIntent != null) && backupEnabled;
+        if (manageEnabled) {
+            mManageData.setIntent(manageIntent);
+            if (manageLabel != null) {
+                mManageData.setTitle(manageLabel);
+            }
+        } else {
+            // Hide the item if data management intent is not supported by transport.
+            getPreferenceScreen().removePreference(mManageData);
+        }
+
         RestrictedPreference networkResetPref = (RestrictedPreference) findPreference(
                 NETWORK_RESET);
         if (networkResetPref != null) {
diff --git a/src/com/android/settings/ProfileChallengePreferenceFragment.java b/src/com/android/settings/ProfileChallengePreferenceFragment.java
index 4b57552..5d39641 100644
--- a/src/com/android/settings/ProfileChallengePreferenceFragment.java
+++ b/src/com/android/settings/ProfileChallengePreferenceFragment.java
@@ -25,6 +25,8 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.UserInfo;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -34,12 +36,15 @@
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
 import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.util.Log;
 import android.support.v7.preference.PreferenceCategory;
 import android.support.v7.preference.PreferenceGroup;
 import android.support.v7.preference.PreferenceScreen;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.fingerprint.FingerprintEnrollIntroduction;
+import com.android.settings.fingerprint.FingerprintSettings;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -218,6 +223,7 @@
         PreferenceGroup securityCategory = (PreferenceGroup)
                 root.findPreference(KEY_SECURITY_CATEGORY);
         if (securityCategory != null) {
+            maybeAddFingerprintPreference(securityCategory);
             if (mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileUserId)) {
                 maybeAddUnificationPreference(securityCategory);
             } else {
@@ -241,6 +247,14 @@
         }
     }
 
+    private void maybeAddFingerprintPreference(PreferenceGroup securityCategory) {
+        Preference fingerprintPreference =
+                FingerprintSettings.getFingerprintPreferenceForUser(getActivity(), mProfileUserId);
+        if (fingerprintPreference != null) {
+            securityCategory.addPreference(fingerprintPreference);
+        }
+    }
+
     private void removeNonWhitelistedItems(PreferenceGroup prefScreen) {
         int numPreferences = prefScreen.getPreferenceCount();
         int i = 0;
diff --git a/src/com/android/settings/RestrictedSettingsFragment.java b/src/com/android/settings/RestrictedSettingsFragment.java
index c78d6e2..3642fa6 100644
--- a/src/com/android/settings/RestrictedSettingsFragment.java
+++ b/src/com/android/settings/RestrictedSettingsFragment.java
@@ -17,6 +17,7 @@
 package com.android.settings;
 
 import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -24,10 +25,18 @@
 import android.content.RestrictionsManager;
 import android.os.Bundle;
 import android.os.PersistableBundle;
+import android.os.UserHandle;
 import android.os.UserManager;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 /**
- * Base class for settings screens that should be pin protected when in restricted mode.
+ * Base class for settings screens that should be pin protected when in restricted mode or
+ * that will display an admin support message in case an admin has disabled the options.
  * The constructor for this class will take the restriction key that this screen should be
  * locked by.  If {@link RestrictionsManager.hasRestrictionsProvider()} and
  * {@link UserManager.hasUserRestriction()}, then the user will have to enter the restrictions
@@ -37,7 +46,8 @@
  * {@link RestrictionsManager.hasRestrictionsProvider()} returns true, pass in
  * {@link RESTRICT_IF_OVERRIDABLE} to the constructor instead of a restrictions key.
  */
-public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragment {
+public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragment
+            implements View.OnClickListener {
 
     protected static final String RESTRICT_IF_OVERRIDABLE = "restrict_if_overridable";
 
@@ -55,6 +65,9 @@
     private RestrictionsManager mRestrictionsManager;
 
     private final String mRestrictionKey;
+    private View mAdminSupportDetails;
+    private EnforcedAdmin mEnforcedAdmin;
+    private TextView mEmptyTextView;
 
     // Receiver to clear pin status when the screen is turned off.
     private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
@@ -95,6 +108,13 @@
     }
 
     @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mAdminSupportDetails = initAdminSupportDetailsView();
+        mEmptyTextView = initEmptyTextView();
+    }
+
+    @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
 
@@ -178,6 +198,68 @@
         return restricted && mRestrictionsManager.hasRestrictionsProvider();
     }
 
+    protected View initAdminSupportDetailsView() {
+        return null;
+    }
+
+    protected TextView initEmptyTextView() {
+        return null;
+    }
+
+    private void updateAdminSupportDetailsView() {
+        mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
+                mRestrictionKey, UserHandle.myUserId());
+        if (mEnforcedAdmin != null) {
+            final Activity activity = getActivity();
+            DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService(
+                    Context.DEVICE_POLICY_SERVICE);
+            if (mEnforcedAdmin.userId == UserHandle.USER_NULL) {
+                mEnforcedAdmin.userId = UserHandle.myUserId();
+            }
+            CharSequence supportMessage = dpm.getShortSupportMessageForUser(
+                    mEnforcedAdmin.component, mEnforcedAdmin.userId);
+            if (supportMessage != null) {
+                TextView textView = (TextView) activity.findViewById(R.id.admin_support_msg);
+                textView.setText(supportMessage);
+            }
+            activity.findViewById(R.id.admins_policies_list).setOnClickListener(this);
+        }
+    }
+
+    @Override
+    public void onClick(View view) {
+        Intent intent = new Intent();
+        if (view.getId() == R.id.admins_policies_list && mEnforcedAdmin != null) {
+            if (mEnforcedAdmin.component != null) {
+                intent.setClass(getActivity(), DeviceAdminAdd.class);
+                intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mEnforcedAdmin.component);
+                // DeviceAdminAdd class may need to run as managed profile.
+                getActivity().startActivityAsUser(intent, UserHandle.of(mEnforcedAdmin.userId));
+            } else {
+                intent.setClass(getActivity(), Settings.DeviceAdminSettingsActivity.class);
+                // Activity merges both managed profile and parent users
+                // admins so show as same user as this activity.
+                getActivity().startActivity(intent);
+            }
+        }
+    }
+
+    public TextView getEmptyTextView() {
+        return mEmptyTextView;
+    }
+
+    @Override
+    protected void onDataSetChanged() {
+        highlightPreferenceIfNeeded();
+        if (mAdminSupportDetails != null && isUiRestricted()) {
+            updateAdminSupportDetailsView();
+            setEmptyView(mAdminSupportDetails);
+        } else if (mEmptyTextView != null) {
+            setEmptyView(mEmptyTextView);
+        }
+        super.onDataSetChanged();
+    }
+
     /**
      * Returns whether restricted or actionable UI elements should be removed or disabled.
      */
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index d39203d..a324d9c 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -90,7 +90,6 @@
     private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
     private static final String KEY_ADVANCED_SECURITY = "advanced_security";
     private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
-    private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings";
 
     private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
     private static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
@@ -375,32 +374,12 @@
     }
 
     private void maybeAddFingerprintPreference(PreferenceGroup securityCategory) {
-        FingerprintManager fpm = (FingerprintManager) getActivity().getSystemService(
-                Context.FINGERPRINT_SERVICE);
-        if (!fpm.isHardwareDetected()) {
-            Log.v(TAG, "No fingerprint hardware detected!!");
-            return;
+        Preference fingerprintPreference =
+                FingerprintSettings.getFingerprintPreferenceForUser(
+                        securityCategory.getContext(), UserHandle.myUserId());
+        if (fingerprintPreference != null) {
+            securityCategory.addPreference(fingerprintPreference);
         }
-        Preference fingerprintPreference = new Preference(securityCategory.getContext());
-        fingerprintPreference.setKey(KEY_FINGERPRINT_SETTINGS);
-        fingerprintPreference.setTitle(R.string.security_settings_fingerprint_preference_title);
-        Intent intent = new Intent();
-        final List<Fingerprint> items = fpm.getEnrolledFingerprints();
-        final int fingerprintCount = items != null ? items.size() : 0;
-        final String clazz;
-        if (fingerprintCount > 0) {
-            fingerprintPreference.setSummary(getResources().getQuantityString(
-                    R.plurals.security_settings_fingerprint_preference_summary,
-                    fingerprintCount, fingerprintCount));
-            clazz = FingerprintSettings.class.getName();
-        } else {
-            fingerprintPreference.setSummary(
-                    R.string.security_settings_fingerprint_preference_summary_none);
-            clazz = FingerprintEnrollIntroduction.class.getName();
-        }
-        intent.setClassName("com.android.settings", clazz);
-        fingerprintPreference.setIntent(intent);
-        securityCategory.addPreference(fingerprintPreference);
     }
 
     private void addTrustAgentSettings(PreferenceGroup securityCategory) {
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index bcb1ce9..da9f2fd 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -29,7 +29,6 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.nfc.NfcAdapter;
 import android.os.AsyncTask;
@@ -115,8 +114,8 @@
 import com.android.settings.wifi.WifiSettings;
 import com.android.settings.wifi.p2p.WifiP2pSettings;
 import com.android.settingslib.drawer.DashboardCategory;
-import com.android.settingslib.drawer.Tile;
 import com.android.settingslib.drawer.SettingsDrawerActivity;
+import com.android.settingslib.drawer.Tile;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -382,7 +381,6 @@
     private static final String MSG_DATA_FORCE_REFRESH = "msg_data_force_refresh";
 
     private boolean mNeedToRevertToInitialFragment = false;
-    private int mHomeActivitiesCount = 1;
 
     private Intent mResultIntentData;
     private ComponentName mCurrentSuggestion;
@@ -563,8 +561,6 @@
 
             mDisplayHomeAsUpEnabled = savedState.getBoolean(SAVE_KEY_SHOW_HOME_AS_UP);
             mDisplaySearch = savedState.getBoolean(SAVE_KEY_SHOW_SEARCH);
-            mHomeActivitiesCount = savedState.getInt(SAVE_KEY_HOME_ACTIVITIES_COUNT,
-                    1 /* one home activity by default */);
         } else {
             if (!mIsShowingDashboard) {
                 mDisplaySearch = false;
@@ -653,17 +649,10 @@
             }
         }
 
-        mHomeActivitiesCount = getHomeActivitiesCount();
         if (DEBUG_TIMING) Log.d(LOG_TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
                 + " ms");
     }
 
-    private int getHomeActivitiesCount() {
-        final ArrayList<ResolveInfo> homeApps = new ArrayList<ResolveInfo>();
-        getPackageManager().getHomeActivities(homeApps);
-        return homeApps.size();
-    }
-
     private void setTitleFromIntent(Intent intent) {
         final int initialTitleResId = intent.getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
         if (initialTitleResId > 0) {
@@ -753,8 +742,6 @@
             String query = (mSearchView != null) ? mSearchView.getQuery().toString() : EMPTY_QUERY;
             outState.putString(SAVE_KEY_SEARCH_QUERY, query);
         }
-
-        outState.putInt(SAVE_KEY_HOME_ACTIVITIES_COUNT, mHomeActivitiesCount);
     }
 
     @Override
@@ -780,6 +767,9 @@
             onQueryTextSubmit(mSearchQuery);
         }
         updateTilesList();
+        if (mIsShowingDashboard) {
+            showMenuIcon();
+        }
     }
 
     @Override
@@ -1024,10 +1014,6 @@
                 mBatteryPresent, isAdmin, pm);
 
         setTileEnabled(new ComponentName(packageName,
-                Settings.HomeSettingsActivity.class.getName()),
-                updateHomeSettingTiles(), isAdmin, pm);
-
-        setTileEnabled(new ComponentName(packageName,
                 Settings.UserSettingsActivity.class.getName()),
                 UserHandle.MU_ENABLED && UserManager.supportsMultipleUsers()
                 && !Utils.isMonkeyRunning(), isAdmin, pm);
@@ -1083,27 +1069,6 @@
         }
     }
 
-    private boolean updateHomeSettingTiles() {
-        // Once we decide to show Home settings, keep showing it forever
-        SharedPreferences sp = getSharedPreferences(HomeSettings.HOME_PREFS, Context.MODE_PRIVATE);
-        if (sp.getBoolean(HomeSettings.HOME_PREFS_DO_SHOW, false)) {
-            return true;
-        }
-
-        try {
-            mHomeActivitiesCount = getHomeActivitiesCount();
-            if (mHomeActivitiesCount < 2) {
-                return false;
-            }
-        } catch (Exception e) {
-            // Can't look up the home activity; bail on configuring the icon
-            Log.w(LOG_TAG, "Problem looking up home activity!", e);
-        }
-
-        sp.edit().putBoolean(HomeSettings.HOME_PREFS_DO_SHOW, true).apply();
-        return true;
-    }
-
     private void getMetaData() {
         try {
             ActivityInfo ai = getPackageManager().getActivityInfo(getComponentName(),
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 4f81a38..d8b9b91 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -176,13 +176,6 @@
         unregisterObserverIfNeeded();
     }
 
-    @Override
-    public void onStop() {
-        super.onStop();
-
-        unregisterObserverIfNeeded();
-    }
-
     public void showLoadingWhenEmpty() {
         View loading = getView().findViewById(R.id.loading_container);
         setEmptyView(loading);
@@ -220,7 +213,7 @@
         }
     }
 
-    private void onDataSetChanged() {
+    protected void onDataSetChanged() {
         highlightPreferenceIfNeeded();
         updateEmptyView();
     }
@@ -290,6 +283,9 @@
     }
 
     public void setEmptyView(View v) {
+        if (mEmptyView != null) {
+            mEmptyView.setVisibility(View.GONE);
+        }
         mEmptyView = v;
         updateEmptyView();
     }
diff --git a/src/com/android/settings/SmsDefaultDialog.java b/src/com/android/settings/SmsDefaultDialog.java
index a1af021..e38c9b8 100644
--- a/src/com/android/settings/SmsDefaultDialog.java
+++ b/src/com/android/settings/SmsDefaultDialog.java
@@ -187,14 +187,14 @@
             Item item = ((Item) getItem(position));
             LayoutInflater inflater = getLayoutInflater();
             View view = inflater.inflate(R.layout.app_preference_item, parent, false);
-            TextView textView = (TextView) view.findViewById(R.id.app_label);
+            TextView textView = (TextView) view.findViewById(android.R.id.title);
             textView.setText(item.label);
             if (position == mSelectedIndex) {
                 view.findViewById(R.id.default_label).setVisibility(View.VISIBLE);
             } else {
                 view.findViewById(R.id.default_label).setVisibility(View.GONE);
             }
-            ImageView imageView = (ImageView)view.findViewById(R.id.app_image);
+            ImageView imageView = (ImageView)view.findViewById(android.R.id.icon);
             imageView.setImageDrawable(item.icon);
             return view;
         }
diff --git a/src/com/android/settings/TetherProvisioningActivity.java b/src/com/android/settings/TetherProvisioningActivity.java
new file mode 100644
index 0000000..408e001
--- /dev/null
+++ b/src/com/android/settings/TetherProvisioningActivity.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+ * Activity which acts as a proxy to the tether provisioning app for sanity checks and permission
+ * restrictions. Specifically, the provisioning apps require
+ * {@link android.permission.CONNECTIVITY_INTERNAL}, while this activity can be started by a caller
+ * with {@link android.permission.TETHER_PRIVILEGED}.
+ */
+public class TetherProvisioningActivity extends Activity {
+    private static final int PROVISION_REQUEST = 0;
+    private static final String TAG = "TetherProvisioningAct";
+    private static final String EXTRA_TETHER_TYPE = "TETHER_TYPE";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private ResultReceiver mResultReceiver;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mResultReceiver = (ResultReceiver)getIntent().getParcelableExtra(
+                ConnectivityManager.EXTRA_PROVISION_CALLBACK);
+
+        // TODO: Move isProvisioningNeededButUnavailable into ConnectivityManager and check
+        // it here to short-circuit and fail.
+
+        int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
+                ConnectivityManager.TETHERING_INVALID);
+        String[] provisionApp = getResources().getStringArray(
+                com.android.internal.R.array.config_mobile_hotspot_provision_app);
+
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClassName(provisionApp[0], provisionApp[1]);
+        intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
+        if (DEBUG) {
+            Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]);
+        }
+        startActivityForResultAsUser(intent, PROVISION_REQUEST, UserHandle.CURRENT);
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
+        super.onActivityResult(requestCode, resultCode, intent);
+        if (requestCode == PROVISION_REQUEST) {
+            if (DEBUG) Log.d(TAG, "Got result from app: " + resultCode);
+            int result = resultCode == Activity.RESULT_OK ?
+                    ConnectivityManager.TETHER_ERROR_NO_ERROR :
+                    ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+            mResultReceiver.send(result, null);
+            finish();
+        }
+    }
+}
diff --git a/src/com/android/settings/TetherService.java b/src/com/android/settings/TetherService.java
index 346a175..d4944ef 100644
--- a/src/com/android/settings/TetherService.java
+++ b/src/com/android/settings/TetherService.java
@@ -31,13 +31,16 @@
 import android.content.SharedPreferences;
 import android.net.ConnectivityManager;
 import android.os.IBinder;
+import android.os.ResultReceiver;
 import android.os.SystemClock;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.settingslib.TetherUtil;
 
 import java.util.ArrayList;
+import java.util.List;
 
 public class TetherService extends Service {
     private static final String TAG = "TetherService";
@@ -57,9 +60,9 @@
     private static final String KEY_TETHERS = "currentTethers";
 
     private int mCurrentTypeIndex;
-    private boolean mEnableWifiAfterCheck;
     private boolean mInProvisionCheck;
     private ArrayList<Integer> mCurrentTethers;
+    private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
 
     @Override
     public IBinder onBind(Intent intent) {
@@ -77,23 +80,42 @@
         SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
         mCurrentTethers = stringToTethers(prefs.getString(KEY_TETHERS, ""));
         mCurrentTypeIndex = 0;
+        mPendingCallbacks = new ArrayMap<>(3);
+        mPendingCallbacks.put(ConnectivityManager.TETHERING_WIFI, new ArrayList<ResultReceiver>());
+        mPendingCallbacks.put(ConnectivityManager.TETHERING_USB, new ArrayList<ResultReceiver>());
+        mPendingCallbacks.put(
+                ConnectivityManager.TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
     }
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        if (intent.hasExtra(TetherUtil.EXTRA_ADD_TETHER_TYPE)) {
-            int type = intent.getIntExtra(TetherUtil.EXTRA_ADD_TETHER_TYPE,
-                    TetherUtil.TETHERING_INVALID);
+        if (intent.hasExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE)) {
+            int type = intent.getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
+                    ConnectivityManager.TETHERING_INVALID);
+            ResultReceiver callback =
+                    intent.getParcelableExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK);
+            if (callback != null) {
+                List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
+                if (callbacksForType != null) {
+                    callbacksForType.add(callback);
+                } else {
+                    // Invalid tether type. Just ignore this request and report failure.
+                    callback.send(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE, null);
+                    stopSelf();
+                    return START_NOT_STICKY;
+                }
+            }
+
             if (!mCurrentTethers.contains(type)) {
                 if (DEBUG) Log.d(TAG, "Adding tether " + type);
                 mCurrentTethers.add(type);
             }
         }
 
-        if (intent.hasExtra(TetherUtil.EXTRA_REM_TETHER_TYPE)) {
+        if (intent.hasExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE)) {
             if (!mInProvisionCheck) {
-                int type = intent.getIntExtra(TetherUtil.EXTRA_REM_TETHER_TYPE,
-                        TetherUtil.TETHERING_INVALID);
+                int type = intent.getIntExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE,
+                        ConnectivityManager.TETHERING_INVALID);
                 int index = mCurrentTethers.indexOf(type);
                 if (DEBUG) Log.d(TAG, "Removing tether " + type + ", index " + index);
                 if (index >= 0) {
@@ -114,19 +136,16 @@
         // Only set the alarm if we have one tether, meaning the one just added,
         // to avoid setting it when it was already set previously for another
         // type.
-        if (intent.getBooleanExtra(TetherUtil.EXTRA_SET_ALARM, false)
+        if (intent.getBooleanExtra(ConnectivityManager.EXTRA_SET_ALARM, false)
                 && mCurrentTethers.size() == 1) {
             scheduleAlarm();
         }
 
-        if (intent.getBooleanExtra(TetherUtil.EXTRA_ENABLE_WIFI_TETHER, false)) {
-            mEnableWifiAfterCheck = true;
-        }
-
-        if (intent.getBooleanExtra(TetherUtil.EXTRA_RUN_PROVISION, false)) {
+        if (intent.getBooleanExtra(ConnectivityManager.EXTRA_RUN_PROVISION, false)) {
             startProvisioning(mCurrentTypeIndex);
         } else if (!mInProvisionCheck) {
             // If we aren't running any provisioning, no reason to stay alive.
+            if (DEBUG) Log.d(TAG, "Stopping self.  startid: " + startId);
             stopSelf();
             return START_NOT_STICKY;
         }
@@ -173,12 +192,6 @@
         return buffer.toString();
     }
 
-    private void enableWifiTetheringIfNeeded() {
-        if (!TetherUtil.isWifiTetherEnabled(this)) {
-            TetherUtil.setWifiTethering(true, this);
-        }
-    }
-
     private void disableWifiTethering() {
         TetherUtil.setWifiTethering(false, this);
     }
@@ -221,14 +234,14 @@
 
     public static void scheduleRecheckAlarm(Context context, int type) {
         Intent intent = new Intent(context, TetherService.class);
-        intent.putExtra(TetherUtil.EXTRA_ADD_TETHER_TYPE, type);
-        intent.putExtra(TetherUtil.EXTRA_SET_ALARM, true);
+        intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
+        intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true);
         context.startService(intent);
     }
 
     private void scheduleAlarm() {
         Intent intent = new Intent(this, TetherService.class);
-        intent.putExtra(TetherUtil.EXTRA_RUN_PROVISION, true);
+        intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
 
         PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
         AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
@@ -248,7 +261,7 @@
      */
     public static void cancelRecheckAlarmIfNecessary(final Context context, int type) {
         Intent intent = new Intent(context, TetherService.class);
-        intent.putExtra(TetherUtil.EXTRA_REM_TETHER_TYPE, type);
+        intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
         context.startService(intent);
     }
 
@@ -264,6 +277,20 @@
         if (DEBUG) Log.d(TAG, "Tethering no longer active, canceling recheck");
     }
 
+    private void fireCallbacksForType(int type, int result) {
+        List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
+        if (callbacksForType == null) {
+            return;
+        }
+        int errorCode = result == RESULT_OK ? ConnectivityManager.TETHER_ERROR_NO_ERROR :
+                ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+        for (ResultReceiver callback : callbacksForType) {
+          if (DEBUG) Log.d(TAG, "Firing result: " + errorCode + " to callback");
+          callback.send(errorCode, null);
+        }
+        callbacksForType.clear();
+    }
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -278,24 +305,21 @@
                 }
                 int checkType = mCurrentTethers.get(mCurrentTypeIndex);
                 mInProvisionCheck = false;
-                if (intent.getIntExtra(EXTRA_RESULT, RESULT_DEFAULT) == RESULT_OK) {
-                    if (checkType == TetherUtil.TETHERING_WIFI && mEnableWifiAfterCheck) {
-                        enableWifiTetheringIfNeeded();
-                        mEnableWifiAfterCheck = false;
-                    }
-                } else {
+                int result = intent.getIntExtra(EXTRA_RESULT, RESULT_DEFAULT);
+                if (result != RESULT_OK) {
                     switch (checkType) {
-                        case TetherUtil.TETHERING_WIFI:
+                        case ConnectivityManager.TETHERING_WIFI:
                             disableWifiTethering();
                             break;
-                        case TetherUtil.TETHERING_BLUETOOTH:
+                        case ConnectivityManager.TETHERING_BLUETOOTH:
                             disableBtTethering();
                             break;
-                        case TetherUtil.TETHERING_USB:
+                        case ConnectivityManager.TETHERING_USB:
                             disableUsbTethering();
                             break;
                     }
                 }
+                fireCallbacksForType(checkType, result);
 
                 if (++mCurrentTypeIndex >= mCurrentTethers.size()) {
                     // We are done with all checks, time to die.
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index ee8900e..4b5f23d 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -47,10 +47,10 @@
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicReference;
 
-import static com.android.settingslib.TetherUtil.TETHERING_BLUETOOTH;
-import static com.android.settingslib.TetherUtil.TETHERING_INVALID;
-import static com.android.settingslib.TetherUtil.TETHERING_USB;
-import static com.android.settingslib.TetherUtil.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
+import static android.net.ConnectivityManager.TETHERING_INVALID;
+import static android.net.ConnectivityManager.TETHERING_USB;
+import static android.net.ConnectivityManager.TETHERING_WIFI;
 
 /*
  * Displays preferences for Tethering.
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index f56ebe0..411256c 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -481,6 +481,7 @@
             AccessibilityServiceInfo info = installedServices.get(i);
 
             RestrictedPreference preference = new RestrictedPreference(getActivity());
+            preference.useAdminDisabledSummary(true);
             String title = info.getResolveInfo().loadLabel(getPackageManager()).toString();
 
             ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
@@ -515,13 +516,9 @@
                 preference.setEnabled(true);
             }
 
-            String summaryString;
             if (serviceAllowed) {
-                summaryString = serviceEnabledString;
-            } else  {
-                summaryString = getString(R.string.accessibility_feature_or_input_method_not_allowed);
+                preference.setSummary(serviceEnabledString);
             }
-            preference.setSummary(summaryString);
 
             preference.setOrder(i);
             preference.setFragment(ToggleAccessibilityServicePreferenceFragment.class.getName());
diff --git a/src/com/android/settings/accounts/ProviderPreference.java b/src/com/android/settings/accounts/ProviderPreference.java
index 863fef4..31f0c8e 100644
--- a/src/com/android/settings/accounts/ProviderPreference.java
+++ b/src/com/android/settings/accounts/ProviderPreference.java
@@ -39,6 +39,7 @@
         setIcon(icon);
         setPersistent(false);
         setTitle(providerName);
+        useAdminDisabledSummary(true);
     }
 
     public String getAccountType() {
diff --git a/src/com/android/settings/applications/DefaultHomePreference.java b/src/com/android/settings/applications/DefaultHomePreference.java
new file mode 100644
index 0000000..7426ce6
--- /dev/null
+++ b/src/com/android/settings/applications/DefaultHomePreference.java
@@ -0,0 +1,118 @@
+/*
+ * 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.applications;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.os.Build;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import com.android.settings.AppListPreference;
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultHomePreference extends AppListPreference {
+
+    private final ArrayList<ComponentName> mAllHomeComponents = new ArrayList<>();
+    private final IntentFilter mHomeFilter;
+
+    public DefaultHomePreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mHomeFilter = new IntentFilter(Intent.ACTION_MAIN);
+        mHomeFilter.addCategory(Intent.CATEGORY_HOME);
+        mHomeFilter.addCategory(Intent.CATEGORY_DEFAULT);
+        refreshHomeOptions();
+    }
+
+    @Override
+    public void performClick() {
+        refreshHomeOptions();
+        super.performClick();
+    }
+
+    @Override
+    protected boolean persistString(String value) {
+        if (value != null) {
+            ComponentName component = ComponentName.unflattenFromString(value);
+            getContext().getPackageManager().replacePreferredActivity(mHomeFilter,
+                    IntentFilter.MATCH_CATEGORY_EMPTY,
+                    mAllHomeComponents.toArray(new ComponentName[0]), component);
+            setSummary(getEntry());
+        }
+        return super.persistString(value);
+    }
+
+    public void refreshHomeOptions() {
+        final String myPkg = getContext().getPackageName();
+        ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
+        PackageManager pm = getContext().getPackageManager();
+        ComponentName currentDefaultHome  = pm.getHomeActivities(homeActivities);
+        ArrayList<ComponentName> components = new ArrayList<>();
+        mAllHomeComponents.clear();
+        List<CharSequence> summaries = new ArrayList<>();
+
+        boolean mustSupportManagedProfile = hasManagedProfile();
+        for (int i = 0; i < homeActivities.size(); i++) {
+            final ResolveInfo candidate = homeActivities.get(i);
+            final ActivityInfo info = candidate.activityInfo;
+            ComponentName activityName = new ComponentName(info.packageName, info.name);
+            mAllHomeComponents.add(activityName);
+            if (info.packageName.equals(myPkg)) {
+                continue;
+            }
+            components.add(activityName);
+            if (mustSupportManagedProfile && !launcherHasManagedProfilesFeature(candidate, pm)) {
+                summaries.add(getContext().getString(R.string.home_work_profile_not_supported));
+            } else {
+                summaries.add(null);
+            }
+        }
+        setComponentNames(components.toArray(new ComponentName[0]), currentDefaultHome,
+                summaries.toArray(new CharSequence[0]));
+    }
+
+    private boolean launcherHasManagedProfilesFeature(ResolveInfo resolveInfo, PackageManager pm) {
+        try {
+            ApplicationInfo appInfo = pm.getApplicationInfo(
+                    resolveInfo.activityInfo.packageName, 0 /* default flags */);
+            return versionNumberAtLeastL(appInfo.targetSdkVersion);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    private boolean versionNumberAtLeastL(int versionNumber) {
+        return versionNumber >= Build.VERSION_CODES.LOLLIPOP;
+    }
+
+    private boolean hasManagedProfile() {
+        UserManager userManager = getContext().getSystemService(UserManager.class);
+        List<UserInfo> profiles = userManager.getProfiles(getContext().getUserId());
+        for (UserInfo userInfo : profiles) {
+            if (userInfo.isManagedProfile()) return true;
+        }
+        return false;
+    }
+
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index eac89b1..f71dd0a 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -87,7 +87,6 @@
     private boolean mInitialScanStarted;
     private boolean mInitiateDiscoverable;
 
-    private TextView mEmptyView;
     private SwitchBar mSwitchBar;
 
     private final IntentFilter mIntentFilter;
@@ -136,10 +135,6 @@
         mInitialScanStarted = false;
         mInitiateDiscoverable = true;
 
-        mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
-        setEmptyView(mEmptyView);
-        mEmptyView.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
-
         final SettingsActivity activity = (SettingsActivity) getActivity();
         mSwitchBar = activity.getSwitchBar();
 
@@ -175,7 +170,6 @@
         if (isUiRestricted()) {
             setDeviceListGroup(getPreferenceScreen());
             removeAllDevices();
-            mEmptyView.setText(R.string.bluetooth_empty_list_user_restricted);
             return;
         }
 
@@ -298,7 +292,6 @@
                 mDevicePreferenceMap.clear();
 
                 if (isUiRestricted()) {
-                    messageId = R.string.bluetooth_empty_list_user_restricted;
                     break;
                 }
 
@@ -360,7 +353,7 @@
             case BluetoothAdapter.STATE_OFF:
                 setOffMessage();
                 if (isUiRestricted()) {
-                    messageId = R.string.bluetooth_empty_list_user_restricted;
+                    messageId = 0;
                 }
                 break;
 
@@ -373,15 +366,28 @@
         setDeviceListGroup(preferenceScreen);
         removeAllDevices();
         if (messageId != 0) {
-            mEmptyView.setText(messageId);
+            getEmptyTextView().setText(messageId);
         }
         if (!isUiRestricted()) {
             getActivity().invalidateOptionsMenu();
         }
     }
 
+    @Override
+    protected TextView initEmptyTextView() {
+        TextView textView = (TextView) getView().findViewById(android.R.id.empty);
+        textView.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
+        return textView;
+    }
+
+    @Override
+    protected View initAdminSupportDetailsView() {
+        return getActivity().findViewById(R.id.admin_support_details);
+    }
+
     private void setOffMessage() {
-        if (mEmptyView == null) {
+        final TextView emptyView = getEmptyTextView();
+        if (emptyView == null) {
             return;
         }
         final CharSequence briefText = getText(R.string.bluetooth_empty_list_bluetooth_off);
@@ -392,13 +398,13 @@
 
         if (!bleScanningMode) {
             // Show only the brief text if the scanning mode has been turned off.
-            mEmptyView.setText(briefText, TextView.BufferType.SPANNABLE);
+            emptyView.setText(briefText, TextView.BufferType.SPANNABLE);
         } else {
             final StringBuilder contentBuilder = new StringBuilder();
             contentBuilder.append(briefText);
             contentBuilder.append("\n\n");
             contentBuilder.append(getText(R.string.ble_scan_notify_text));
-            LinkifyUtils.linkify(mEmptyView, contentBuilder, new LinkifyUtils.OnClickListener() {
+            LinkifyUtils.linkify(emptyView, contentBuilder, new LinkifyUtils.OnClickListener() {
                 @Override
                 public void onClick() {
                     final SettingsActivity activity =
@@ -409,7 +415,7 @@
             });
         }
         getPreferenceScreen().removeAll();
-        Spannable boldSpan = (Spannable) mEmptyView.getText();
+        Spannable boldSpan = (Spannable) emptyView.getText();
         boldSpan.setSpan(
                 new TextAppearanceSpan(getActivity(), android.R.style.TextAppearance_Medium), 0,
                 briefText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index b564a27..0d92c62 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -33,6 +33,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.dashboard.conditional.Condition;
 import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
+import com.android.settingslib.SuggestionParser;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.Tile;
 
@@ -66,6 +67,7 @@
     private int mSuggestionMode = SUGGESTION_MODE_DEFAULT;
 
     private Condition mExpandedCondition = null;
+    private SuggestionParser mSuggestionParser;
 
     public DashboardAdapter(Context context) {
         mContext = context;
@@ -73,8 +75,9 @@
         setHasStableIds(true);
     }
 
-    public void setSuggestions(List<Tile> suggestions) {
-        mSuggestions = suggestions;
+    public void setSuggestions(SuggestionParser suggestionParser) {
+        mSuggestions = suggestionParser.getSuggestions();
+        mSuggestionParser = suggestionParser;
         recountItems();
     }
 
@@ -235,10 +238,12 @@
                 new MenuItem.OnMenuItemClickListener() {
             @Override
             public boolean onMenuItemClick(MenuItem item) {
-                mContext.getPackageManager().setComponentEnabledSetting(
-                        suggestion.intent.getComponent(),
-                        PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
-                        PackageManager.DONT_KILL_APP);
+                if (mSuggestionParser.dismissSuggestion(suggestion)) {
+                    mContext.getPackageManager().setComponentEnabledSetting(
+                            suggestion.intent.getComponent(),
+                            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                            PackageManager.DONT_KILL_APP);
+                }
                 mSuggestions.remove(suggestion);
                 recountItems();
                 return true;
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index cbb1549..8dffffa 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.dashboard;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.support.v7.widget.LinearLayoutManager;
 import android.util.Log;
@@ -55,6 +56,8 @@
             Settings.StorageSettingsActivity.class.getName(),
     };
 
+    private static final String SUGGESTIONS = "suggestions";
+
     private FocusRecyclerView mDashboard;
     private DashboardAdapter mAdapter;
     private SummaryLoader mSummaryLoader;
@@ -77,8 +80,10 @@
         setHasOptionsMenu(true);
         if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
                 + " ms");
-        mConditionManager = ConditionManager.get(getContext());
-        mSuggestionParser = new SuggestionParser(getContext(), R.xml.suggestion_ordering);
+        Context context = getContext();
+        mConditionManager = ConditionManager.get(context);
+        mSuggestionParser = new SuggestionParser(context,
+                context.getSharedPreferences(SUGGESTIONS, 0), R.xml.suggestion_ordering);
     }
 
     @Override
@@ -138,7 +143,7 @@
         mDashboard.setListener(this);
         mAdapter = new DashboardAdapter(getContext());
         mAdapter.setConditions(mConditionManager.getConditions());
-        mAdapter.setSuggestions(mSuggestionParser.getSuggestions());
+        mAdapter.setSuggestions(mSuggestionParser);
         mSummaryLoader.setAdapter(mAdapter);
         ConditionAdapterUtils.addDismiss(mDashboard);
 
diff --git a/src/com/android/settings/dashboard/conditional/BackgroundDataCondition.java b/src/com/android/settings/dashboard/conditional/BackgroundDataCondition.java
index d1bcb12..6bfc538 100644
--- a/src/com/android/settings/dashboard/conditional/BackgroundDataCondition.java
+++ b/src/com/android/settings/dashboard/conditional/BackgroundDataCondition.java
@@ -34,7 +34,7 @@
 
     @Override
     public Icon getIcon() {
-        return Icon.createWithResource(mManager.getContext(), R.drawable.ic_cellular_off);
+        return Icon.createWithResource(mManager.getContext(), R.drawable.ic_data_saver);
     }
 
     @Override
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 9ca066f..a65f007 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -14,14 +14,6 @@
 
 package com.android.settings.datausage;
 
-import com.android.settings.AppHeader;
-import com.android.settings.InstrumentedFragment;
-import com.android.settings.R;
-import com.android.settings.applications.AppInfoBase;
-import com.android.settingslib.AppItem;
-import com.android.settingslib.net.ChartData;
-import com.android.settingslib.net.ChartDataLoader;
-
 import android.app.LoaderManager;
 import android.content.Context;
 import android.content.Intent;
@@ -43,10 +35,15 @@
 import android.support.v7.preference.PreferenceCategory;
 import android.text.format.Formatter;
 import android.util.ArraySet;
-import android.util.Log;
 import android.view.View;
 import android.widget.AdapterView;
-import android.widget.Spinner;
+import com.android.settings.AppHeader;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settingslib.AppItem;
+import com.android.settingslib.net.ChartData;
+import com.android.settingslib.net.ChartDataLoader;
 
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -62,6 +59,8 @@
     private static final String KEY_APP_SETTINGS = "app_settings";
     private static final String KEY_RESTRICT_BACKGROUND = "restrict_background";
     private static final String KEY_APP_LIST = "app_list";
+    private static final String KEY_CYCLE = "cycle";
+    private static final String KEY_UNRESTRICTED_DATA = "unrestricted_data_saver";
 
     private static final int LOADER_CHART_DATA = 2;
 
@@ -76,7 +75,6 @@
     private Drawable mIcon;
     private CharSequence mLabel;
     private INetworkStatsSession mStatsSession;
-    private Spinner mCycleSpinner;
     private CycleAdapter mCycleAdapter;
 
     private long mStart;
@@ -86,6 +84,9 @@
     private NetworkPolicy mPolicy;
     private AppItem mAppItem;
     private Intent mAppSettingsIntent;
+    private SpinnerPreference mCycle;
+    private SwitchPreference mUnrestrictedData;
+    private DataSaverBackend mDataSaverBackend;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -137,9 +138,15 @@
         mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE);
         mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE);
 
+        mCycle = (SpinnerPreference) findPreference(KEY_CYCLE);
+        mCycleAdapter = new CycleAdapter(getContext(), mCycle, mCycleListener, false);
+
         if (UserHandle.isApp(mAppItem.key)) {
             mRestrictBackground = (SwitchPreference) findPreference(KEY_RESTRICT_BACKGROUND);
             mRestrictBackground.setOnPreferenceChangeListener(this);
+            mUnrestrictedData = (SwitchPreference) findPreference(KEY_UNRESTRICTED_DATA);
+            mUnrestrictedData.setOnPreferenceChangeListener(this);
+            mDataSaverBackend = new DataSaverBackend(getContext());
             mAppSettings = findPreference(KEY_APP_SETTINGS);
 
             mAppSettingsIntent = new Intent(Intent.ACTION_MANAGE_NETWORK_USAGE);
@@ -169,6 +176,7 @@
                 removePreference(KEY_APP_LIST);
             }
         } else {
+            removePreference(KEY_UNRESTRICTED_DATA);
             removePreference(KEY_APP_SETTINGS);
             removePreference(KEY_RESTRICT_BACKGROUND);
             removePreference(KEY_APP_LIST);
@@ -195,6 +203,9 @@
         if (preference == mRestrictBackground) {
             setAppRestrictBackground((Boolean) newValue);
             return true;
+        } else if (preference == mUnrestrictedData) {
+            mDataSaverBackend.setIsWhitelisted(mAppItem.key, (Boolean) newValue);
+            return true;
         }
         return false;
     }
@@ -214,6 +225,9 @@
         if (mRestrictBackground != null) {
             mRestrictBackground.setChecked(getAppRestrictBackground());
         }
+        if (mUnrestrictedData != null) {
+            mUnrestrictedData.setChecked(mDataSaverBackend.isWhitelisted(mAppItem.key));
+        }
     }
 
     private void addUid(int uid) {
@@ -260,7 +274,7 @@
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
 
-        View header = setPinnedHeaderView(R.layout.data_usage_app_header);
+        View header = setPinnedHeaderView(R.layout.app_header);
         String pkg = mPackages.size() != 0 ? mPackages.valueAt(0) : null;
         int uid = 0;
         try {
@@ -269,9 +283,6 @@
         }
         AppHeader.setupHeaderView(getActivity(), mIcon, mLabel,
                 pkg, uid, AppHeader.includeAppInfo(this), 0, header);
-
-        mCycleSpinner = (Spinner) header.findViewById(R.id.filter_spinner);
-        mCycleAdapter = new CycleAdapter(getContext(), mCycleSpinner, mCycleListener);
     }
 
     @Override
@@ -283,8 +294,7 @@
             new AdapterView.OnItemSelectedListener() {
         @Override
         public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-            final CycleAdapter.CycleItem cycle =
-                    (CycleAdapter.CycleItem) parent.getItemAtPosition(position);
+            final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem) mCycle.getSelectedItem();
 
             mStart = cycle.start;
             mEnd = cycle.end;
diff --git a/src/com/android/settings/datausage/AppStateDataUsageBridge.java b/src/com/android/settings/datausage/AppStateDataUsageBridge.java
new file mode 100644
index 0000000..1aff496
--- /dev/null
+++ b/src/com/android/settings/datausage/AppStateDataUsageBridge.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.datausage;
+
+import com.android.settings.applications.AppStateBaseBridge;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+
+import java.util.ArrayList;
+
+public class AppStateDataUsageBridge extends AppStateBaseBridge {
+
+    private static final String TAG = "AppStateDataUsageBridge";
+
+    private final DataSaverBackend mDataSaverBackend;
+
+    public AppStateDataUsageBridge(ApplicationsState appState, Callback callback,
+            DataSaverBackend backend) {
+        super(appState, callback);
+        mDataSaverBackend = backend;
+    }
+
+    @Override
+    protected void loadAllExtraInfo() {
+        ArrayList<AppEntry> apps = mAppSession.getAllApps();
+        final int N = apps.size();
+        for (int i = 0; i < N; i++) {
+            AppEntry app = apps.get(i);
+            app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(app.info.uid));
+        }
+    }
+
+    @Override
+    protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
+        app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(uid));
+    }
+
+    public static class DataUsageState {
+        public boolean isDataSaverWhitelisted;
+
+        public DataUsageState(boolean isDataSaverWhitelisted) {
+            this.isDataSaverWhitelisted = isDataSaverWhitelisted;
+        }
+    }
+}
diff --git a/src/com/android/settings/datausage/CycleAdapter.java b/src/com/android/settings/datausage/CycleAdapter.java
index 682cc8a..67e62cb 100644
--- a/src/com/android/settings/datausage/CycleAdapter.java
+++ b/src/com/android/settings/datausage/CycleAdapter.java
@@ -13,17 +13,15 @@
  */
 package com.android.settings.datausage;
 
-import com.android.settings.Utils;
-import com.android.settingslib.net.ChartData;
-
 import android.content.Context;
 import android.net.NetworkPolicy;
 import android.net.NetworkStatsHistory;
 import android.text.format.DateUtils;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settingslib.net.ChartData;
 import libcore.util.Objects;
 
 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
@@ -31,12 +29,13 @@
 
 public class CycleAdapter extends ArrayAdapter<CycleAdapter.CycleItem> {
 
-    private final Spinner mSpinner;
+    private final SpinnerInterface mSpinner;
     private final AdapterView.OnItemSelectedListener mListener;
 
-    public CycleAdapter(Context context, Spinner spinner,
-            AdapterView.OnItemSelectedListener listener) {
-        super(context, com.android.settings.R.layout.filter_spinner_item);
+    public CycleAdapter(Context context, SpinnerInterface spinner,
+            AdapterView.OnItemSelectedListener listener, boolean isHeader) {
+        super(context, isHeader ? R.layout.filter_spinner_item
+                : R.layout.data_usage_cycle_item);
         setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         mSpinner = spinner;
         mListener = listener;
@@ -72,7 +71,7 @@
                 mSpinner.getSelectedItem();
         clear();
 
-        final Context context = mSpinner.getContext();
+        final Context context = getContext();
         NetworkStatsHistory.Entry entry = null;
 
         long historyStart = Long.MAX_VALUE;
@@ -141,7 +140,7 @@
             // user-defined inspection region.
             final CycleAdapter.CycleItem selectedItem = getItem(position);
             if (!Objects.equal(selectedItem, previousItem)) {
-                mListener.onItemSelected(mSpinner, null, position, 0);
+                mListener.onItemSelected(null, null, position, 0);
                 return false;
             }
         }
@@ -185,4 +184,11 @@
             return Long.compare(start, another.start);
         }
     }
+
+    public interface SpinnerInterface {
+        void setAdapter(CycleAdapter cycleAdapter);
+        void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener);
+        Object getSelectedItem();
+        void setSelection(int position);
+    }
 }
diff --git a/src/com/android/settings/datausage/DataSaverBackend.java b/src/com/android/settings/datausage/DataSaverBackend.java
new file mode 100644
index 0000000..c38a05c
--- /dev/null
+++ b/src/com/android/settings/datausage/DataSaverBackend.java
@@ -0,0 +1,148 @@
+/*
+ * 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.datausage;
+
+import android.content.Context;
+import android.net.INetworkPolicyListener;
+import android.net.INetworkPolicyManager;
+import android.net.NetworkPolicyManager;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.util.SparseBooleanArray;
+
+import java.util.ArrayList;
+
+public class DataSaverBackend {
+
+    private static final String TAG = "DataSaverBackend";
+
+    private final Context mContext;
+
+    private final Handler mHandler = new Handler();
+    private final NetworkPolicyManager mPolicyManager;
+    private final INetworkPolicyManager mIPolicyManager;
+    private final ArrayList<Listener> mListeners = new ArrayList<>();
+    private SparseBooleanArray mWhitelist;
+
+    // TODO: Staticize into only one.
+    public DataSaverBackend(Context context) {
+        mContext = context;
+        mIPolicyManager = INetworkPolicyManager.Stub.asInterface(
+                        ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
+        mPolicyManager = NetworkPolicyManager.from(context);
+    }
+
+    public void addListener(Listener listener) {
+        mListeners.add(listener);
+        if (mListeners.size() == 1) {
+            mPolicyManager.registerListener(mPolicyListener);
+        }
+        listener.onDataSaverChanged(isDataSaverEnabled());
+    }
+
+    public void remListener(Listener listener) {
+        mListeners.remove(listener);
+        if (mListeners.size() == 0) {
+            mPolicyManager.unregisterListener(mPolicyListener);
+        }
+    }
+
+    public boolean isDataSaverEnabled() {
+        return mPolicyManager.getRestrictBackground();
+    }
+
+    public void setDataSaverEnabled(boolean enabled) {
+        mPolicyManager.setRestrictBackground(enabled);
+    }
+
+    public void refreshWhitelist() {
+        loadWhitelist();
+    }
+
+    public void setIsWhitelisted(int uid, boolean whitelisted) {
+        mWhitelist.put(uid, whitelisted);
+        try {
+            if (whitelisted) {
+                mIPolicyManager.addRestrictBackgroundWhitelistedUid(uid);
+            } else {
+                mIPolicyManager.removeRestrictBackgroundWhitelistedUid(uid);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Can't reach policy manager", e);
+        }
+    }
+
+    public boolean isWhitelisted(int uid) {
+        if (mWhitelist == null) {
+            loadWhitelist();
+        }
+        return mWhitelist.get(uid);
+    }
+
+    public int getWhitelistedCount() {
+        int count = 0;
+        if (mWhitelist == null) {
+            loadWhitelist();
+        }
+        for (int i = 0; i < mWhitelist.size(); i++) {
+            if (mWhitelist.valueAt(i)) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    private void loadWhitelist() {
+        mWhitelist = new SparseBooleanArray();
+        try {
+            for (int uid : mIPolicyManager.getRestrictBackgroundWhitelistedUids()) {
+                mWhitelist.put(uid, true);
+            }
+        } catch (RemoteException e) {
+        }
+    }
+
+    private void handleRestrictBackgroundChanged(boolean isDataSaving) {
+        for (int i = 0; i < mListeners.size(); i++) {
+            mListeners.get(i).onDataSaverChanged(isDataSaving);
+        }
+    }
+
+    private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+        @Override
+        public void onUidRulesChanged(int i, int i1) throws RemoteException {
+        }
+
+        @Override
+        public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
+        }
+
+        @Override
+        public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    handleRestrictBackgroundChanged(isDataSaving);
+                }
+            });
+        }
+    };
+
+    public interface Listener {
+        void onDataSaverChanged(boolean isDataSaving);
+    }
+}
diff --git a/src/com/android/settings/datausage/DataSaverPreference.java b/src/com/android/settings/datausage/DataSaverPreference.java
new file mode 100644
index 0000000..c286d95
--- /dev/null
+++ b/src/com/android/settings/datausage/DataSaverPreference.java
@@ -0,0 +1,47 @@
+/*
+ * 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.datausage;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.util.AttributeSet;
+import com.android.settings.R;
+
+public class DataSaverPreference extends Preference implements DataSaverBackend.Listener {
+
+    private final DataSaverBackend mDataSaverBackend;
+
+    public DataSaverPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mDataSaverBackend = new DataSaverBackend(context);
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+        mDataSaverBackend.addListener(this);
+    }
+
+    @Override
+    public void onDetached() {
+        super.onDetached();
+        mDataSaverBackend.addListener(this);
+    }
+
+    @Override
+    public void onDataSaverChanged(boolean isDataSaving) {
+        setSummary(isDataSaving ? R.string.data_saver_on : R.string.data_saver_off);
+    }
+}
diff --git a/src/com/android/settings/datausage/DataSaverSummary.java b/src/com/android/settings/datausage/DataSaverSummary.java
new file mode 100644
index 0000000..fa24fa3
--- /dev/null
+++ b/src/com/android/settings/datausage/DataSaverSummary.java
@@ -0,0 +1,83 @@
+/*
+ * 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.datausage;
+
+import android.os.Bundle;
+import android.support.v7.preference.Preference;
+import android.util.Log;
+import android.widget.Switch;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.widget.SwitchBar;
+
+public class DataSaverSummary extends SettingsPreferenceFragment
+        implements SwitchBar.OnSwitchChangeListener, DataSaverBackend.Listener {
+
+    private static final String KEY_UNRESTRICTED_ACCESS = "unrestricted_access";
+
+    private SwitchBar mSwitchBar;
+    private DataSaverBackend mDataSaverBackend;
+    private Preference mUnrestrictedAccess;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        addPreferencesFromResource(R.xml.data_saver);
+        mUnrestrictedAccess = findPreference(KEY_UNRESTRICTED_ACCESS);
+        mDataSaverBackend = new DataSaverBackend(getContext());
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar();
+        mSwitchBar.show();
+        mSwitchBar.addOnSwitchChangeListener(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mDataSaverBackend.addListener(this);
+        mDataSaverBackend.refreshWhitelist();
+        int count = mDataSaverBackend.getWhitelistedCount();
+        mUnrestrictedAccess.setSummary(getResources().getQuantityString(
+                R.plurals.data_saver_unrestricted_summary, count, count));
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mDataSaverBackend.remListener(this);
+    }
+
+    @Override
+    public void onSwitchChanged(Switch switchView, boolean isChecked) {
+        mDataSaverBackend.setDataSaverEnabled(isChecked);
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.DATA_SAVER_SUMMARY;
+    }
+
+    @Override
+    public void onDataSaverChanged(boolean isDataSaving) {
+        mSwitchBar.setChecked(isDataSaving);
+    }
+}
diff --git a/src/com/android/settings/datausage/DataUsageList.java b/src/com/android/settings/datausage/DataUsageList.java
index 4aa52ba..bb24aef 100644
--- a/src/com/android/settings/datausage/DataUsageList.java
+++ b/src/com/android/settings/datausage/DataUsageList.java
@@ -147,7 +147,27 @@
 
         mHeader = setPinnedHeaderView(R.layout.apps_filter_spinner);
         mCycleSpinner = (Spinner) mHeader.findViewById(R.id.filter_spinner);
-        mCycleAdapter = new CycleAdapter(getContext(), mCycleSpinner, mCycleListener);
+        mCycleAdapter = new CycleAdapter(getContext(), new CycleAdapter.SpinnerInterface() {
+            @Override
+            public void setAdapter(CycleAdapter cycleAdapter) {
+                mCycleSpinner.setAdapter(cycleAdapter);
+            }
+
+            @Override
+            public void setOnItemSelectedListener(OnItemSelectedListener listener) {
+                mCycleSpinner.setOnItemSelectedListener(listener);
+            }
+
+            @Override
+            public Object getSelectedItem() {
+                return mCycleSpinner.getSelectedItem();
+            }
+
+            @Override
+            public void setSelection(int position) {
+                mCycleSpinner.setSelection(position);
+            }
+        }, mCycleListener, true);
         setLoading(true, false);
     }
 
@@ -470,7 +490,7 @@
         @Override
         public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
             final CycleAdapter.CycleItem cycle = (CycleAdapter.CycleItem)
-                    parent.getItemAtPosition(position);
+                    mCycleSpinner.getSelectedItem();
 
             if (LOGD) {
                 Log.d(TAG, "showing cycle " + cycle + ", start=" + cycle.start + ", end="
diff --git a/src/com/android/settings/datausage/SpinnerPreference.java b/src/com/android/settings/datausage/SpinnerPreference.java
new file mode 100644
index 0000000..8372883
--- /dev/null
+++ b/src/com/android/settings/datausage/SpinnerPreference.java
@@ -0,0 +1,90 @@
+/*
+ * 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.datausage;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Spinner;
+import com.android.settings.R;
+
+public class SpinnerPreference extends Preference implements CycleAdapter.SpinnerInterface {
+
+    private CycleAdapter mAdapter;
+    private AdapterView.OnItemSelectedListener mListener;
+    private Object mCurrentObject;
+    private int mPosition;
+
+    public SpinnerPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLayoutResource(R.layout.data_usage_cycles);
+    }
+
+    @Override
+    public void setAdapter(CycleAdapter cycleAdapter) {
+        mAdapter = cycleAdapter;
+        notifyChanged();
+    }
+
+    @Override
+    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public Object getSelectedItem() {
+        return mCurrentObject;
+    }
+
+    @Override
+    public void setSelection(int position) {
+        mPosition = position;
+        mCurrentObject = mAdapter.getItem(mPosition);
+        notifyChanged();
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        Spinner spinner = (Spinner) holder.findViewById(R.id.cycles_spinner);
+        spinner.setAdapter(mAdapter);
+        spinner.setSelection(mPosition);
+        spinner.setOnItemSelectedListener(mOnSelectedListener);
+    }
+
+    @Override
+    protected void performClick(View view) {
+        view.findViewById(R.id.cycles_spinner).performClick();
+    }
+
+    private final AdapterView.OnItemSelectedListener mOnSelectedListener
+            = new AdapterView.OnItemSelectedListener() {
+        @Override
+        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+            if (mPosition == position) return;
+            mPosition = position;
+            mCurrentObject = mAdapter.getItem(position);
+            mListener.onItemSelected(parent, view, position, id);
+        }
+
+        @Override
+        public void onNothingSelected(AdapterView<?> parent) {
+            mListener.onNothingSelected(parent);
+        }
+    };
+}
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccess.java b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
new file mode 100644
index 0000000..a88da88
--- /dev/null
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
@@ -0,0 +1,184 @@
+/*
+ * 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.datausage;
+
+import android.app.Application;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.view.View;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.applications.AppStateBaseBridge;
+import com.android.settingslib.applications.ApplicationsState;
+
+import java.util.ArrayList;
+
+public class UnrestrictedDataAccess extends SettingsPreferenceFragment
+        implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback, Preference.OnPreferenceChangeListener {
+
+    private ApplicationsState mApplicationsState;
+    private AppStateDataUsageBridge mDataUsageBridge;
+    private ApplicationsState.Session mSession;
+    private DataSaverBackend mDataSaverBackend;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
+        getPreferenceScreen().setOrderingAsAdded(false);
+        mApplicationsState = ApplicationsState.getInstance(
+                (Application) getContext().getApplicationContext());
+        mDataSaverBackend = new DataSaverBackend(getContext());
+        mDataUsageBridge = new AppStateDataUsageBridge(mApplicationsState, this, mDataSaverBackend);
+        mSession = mApplicationsState.newSession(this);
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        setLoading(true, false);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mSession.resume();
+        mDataUsageBridge.resume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mDataUsageBridge.pause();
+        mSession.pause();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mSession.release();
+        mDataUsageBridge.release();
+    }
+
+    @Override
+    public void onExtraInfoUpdated() {
+        ArrayList<ApplicationsState.AppEntry> apps = mSession.getAllApps();
+        final int N = apps.size();
+        for (int i = 0; i < N; i++) {
+            ApplicationsState.AppEntry entry = apps.get(i);
+            String key = entry.info.packageName + "|" + entry.info.uid;
+            AccessPreference preference = (AccessPreference) findPreference(key);
+            if (preference == null) {
+                preference = new AccessPreference(getContext(), entry);
+                preference.setKey(key);
+                preference.setOnPreferenceChangeListener(this);
+                getPreferenceScreen().addPreference(preference);
+            }
+            AppStateDataUsageBridge.DataUsageState state =
+                    (AppStateDataUsageBridge.DataUsageState) entry.extraInfo;
+            preference.setChecked(state.isDataSaverWhitelisted);
+        }
+        setLoading(false, true);
+    }
+
+    @Override
+    public void onRunningStateChanged(boolean running) {
+
+    }
+
+    @Override
+    public void onPackageListChanged() {
+
+    }
+
+    @Override
+    public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
+
+    }
+
+    @Override
+    public void onPackageIconChanged() {
+
+    }
+
+    @Override
+    public void onPackageSizeChanged(String packageName) {
+
+    }
+
+    @Override
+    public void onAllSizesComputed() {
+
+    }
+
+    @Override
+    public void onLauncherInfoChanged() {
+
+    }
+
+    @Override
+    public void onLoadEntriesCompleted() {
+
+    }
+
+    @Override
+    protected int getMetricsCategory() {
+        return InstrumentedFragment.DATA_USAGE_UNRESTRICTED_ACCESS;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        if (preference instanceof AccessPreference) {
+            AccessPreference accessPreference = (AccessPreference) preference;
+            boolean whitelisted = newValue == Boolean.TRUE;
+            mDataSaverBackend.setIsWhitelisted(accessPreference.mEntry.info.uid, whitelisted);
+            ((AppStateDataUsageBridge.DataUsageState) accessPreference.mEntry.extraInfo)
+                    .isDataSaverWhitelisted = whitelisted;
+            return true;
+        }
+        return false;
+    }
+
+    private class AccessPreference extends SwitchPreference {
+        private final ApplicationsState.AppEntry mEntry;
+
+        public AccessPreference(Context context, ApplicationsState.AppEntry entry) {
+            super(context);
+            mEntry = entry;
+            mEntry.ensureLabel(getContext());
+            setTitle(entry.label);
+            setChecked(((AppStateDataUsageBridge.DataUsageState) entry.extraInfo)
+                    .isDataSaverWhitelisted);
+        }
+
+        @Override
+        public void onBindViewHolder(PreferenceViewHolder holder) {
+            holder.itemView.post(new Runnable() {
+                @Override
+                public void run() {
+                    // Ensure we have an icon before binding.
+                    mApplicationsState.ensureIcon(mEntry);
+                    // This might trigger us to bind again, but it gives an easy way to only load the icon
+                    // once its needed, so its probably worth it.
+                    setIcon(mEntry.icon);
+                }
+            });
+            super.onBindViewHolder(holder);
+        }
+    }
+}
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollBase.java b/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
index 2843040..20bbadc 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.graphics.Color;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.WindowManager;
@@ -42,6 +43,7 @@
     static final int RESULT_TIMEOUT = FingerprintSettings.RESULT_TIMEOUT;
 
     protected byte[] mToken;
+    protected int mUserId;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -53,6 +55,7 @@
             mToken = savedInstanceState.getByteArray(
                     ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
         }
+        mUserId = getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId());
     }
 
     @Override
@@ -127,6 +130,9 @@
         Intent intent = new Intent();
         intent.setClassName("com.android.settings", FingerprintEnrollEnrolling.class.getName());
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
+        if (mUserId != UserHandle.USER_NULL) {
+            intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+        }
         return intent;
     }
 }
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
index 322a92c..36dfbfe 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollEnrolling.java
@@ -32,6 +32,7 @@
 import android.graphics.drawable.Drawable;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.AnimationUtils;
@@ -221,6 +222,9 @@
         Intent intent = getFinishIntent();
         intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+        if (mUserId != UserHandle.USER_NULL) {
+            intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+        }
         startActivity(intent);
         finish();
     }
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
index c17dc70..b858950 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -19,6 +19,7 @@
 import android.content.Intent;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
+import android.os.UserHandle;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.ChooseLockSettingsHelper;
@@ -173,10 +174,17 @@
     private void launchConfirmLock() {
         long challenge = getSystemService(FingerprintManager.class).preEnroll();
         ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
-        if (!helper.launchConfirmationActivity(CONFIRM_REQUEST,
+        boolean launchedConfirmationActivity = false;
+        if (mUserId == UserHandle.USER_NULL) {
+            launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
                 getString(R.string.security_settings_fingerprint_preference_title),
-                null, null, challenge)) {
-
+                null, null, challenge);
+        } else {
+            launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
+                    getString(R.string.security_settings_fingerprint_preference_title),
+                    null, null, challenge, mUserId);
+        }
+        if (!launchedConfirmationActivity) {
             // This shouldn't happen, as we should only end up at this step if a lock thingy is
             // already set.
             finish();
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFinish.java b/src/com/android/settings/fingerprint/FingerprintEnrollFinish.java
index 80124e0..8ec4ec0 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFinish.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFinish.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.view.View;
 import android.widget.Button;
 
@@ -39,7 +40,7 @@
         Button addButton = (Button) findViewById(R.id.add_another_button);
 
         FingerprintManager fpm = (FingerprintManager) getSystemService(Context.FINGERPRINT_SERVICE);
-        int enrolled = fpm.getEnrolledFingerprints().size();
+        int enrolled = fpm.getEnrolledFingerprints(mUserId).size();
         int max = getResources().getInteger(
                 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
         if (enrolled >= max) {
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
index beb1a8f..c1347f5 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
@@ -18,11 +18,13 @@
 
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.view.View;
 
 import com.android.internal.logging.MetricsLogger;
+import com.android.settings.ChooseLockGeneric;
 import com.android.settings.ChooseLockSettingsHelper;
 import com.android.settings.HelpUtils;
 import com.android.settings.R;
@@ -32,6 +34,9 @@
  */
 public class FingerprintEnrollIntroduction extends FingerprintEnrollBase {
 
+    private static final int CHOOSE_LOCK_GENERIC_REQUEST = 1;
+    private static final int FINGERPRINT_FIND_SENSOR_REQUEST = 2;
+
     private boolean mHasPassword;
 
     @Override
@@ -41,37 +46,73 @@
         setHeaderText(R.string.security_settings_fingerprint_enroll_introduction_title);
         findViewById(R.id.cancel_button).setOnClickListener(this);
         findViewById(R.id.learn_more_button).setOnClickListener(this);
+        updatePasswordQuality();
+    }
+
+    private void updatePasswordQuality() {
         final int passwordQuality = new ChooseLockSettingsHelper(this).utils()
-                .getActivePasswordQuality(UserHandle.myUserId());
+                .getActivePasswordQuality(mUserId);
         mHasPassword = passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
     }
 
     @Override
     protected void onNextButtonClick() {
-        Intent intent;
         if (!mHasPassword) {
             // No fingerprints registered, launch into enrollment wizard.
-            intent = getOnboardIntent();
+            launchChooseLock();
         } else {
             // Lock thingy is already set up, launch directly into find sensor step from wizard.
-            intent = getFindSensorIntent();
+            launchFindSensor(null);
         }
-        startActivityForResult(intent, 0);
     }
 
-    protected Intent getOnboardIntent() {
-        return new Intent(this, FingerprintEnrollOnboard.class);
+    private void launchChooseLock() {
+        Intent intent = getChooseLockIntent();
+        long challenge = getSystemService(FingerprintManager.class).preEnroll();
+        intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
+                DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+        intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.HIDE_DISABLED_PREFS, true);
+        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
+        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
+        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
+        if (mUserId != UserHandle.USER_NULL) {
+            intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+        }
+        startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
+    }
+
+    private void launchFindSensor(byte[] token) {
+        Intent intent = getFindSensorIntent();
+        if (token != null) {
+            intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+        }
+        startActivityForResult(intent, FINGERPRINT_FIND_SENSOR_REQUEST);
+    }
+
+    protected Intent getChooseLockIntent() {
+        return new Intent(this, ChooseLockGeneric.class);
     }
 
     protected Intent getFindSensorIntent() {
-        return new Intent(this, FingerprintEnrollFindSensor.class);
+        Intent intent = new Intent(this, FingerprintEnrollFindSensor.class);
+        if (mUserId != UserHandle.USER_NULL) {
+            intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+        }
+        return intent;
     }
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (resultCode == RESULT_FINISHED) {
-            setResult(RESULT_OK);
-            finish();
+            if (requestCode == FINGERPRINT_FIND_SENSOR_REQUEST) {
+                setResult(RESULT_OK);
+                finish();
+            } else if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST) {
+                updatePasswordQuality();
+                byte[] token = data.getByteArrayExtra(
+                        ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
+                launchFindSensor(token);
+            }
         } else {
             super.onActivityResult(requestCode, resultCode, data);
         }
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollOnboard.java b/src/com/android/settings/fingerprint/FingerprintEnrollOnboard.java
index 0990459..1b80589 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollOnboard.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollOnboard.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
+import android.os.UserHandle;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.ChooseLockGeneric;
@@ -66,6 +67,9 @@
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, true);
+        if (mUserId != UserHandle.USER_NULL) {
+            intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+        }
         startActivityForResult(intent, CHOOSE_LOCK_GENERIC_REQUEST);
     }
 
@@ -76,6 +80,9 @@
     private void launchFindSensor(byte[] token) {
         Intent intent = getFindSensorIntent();
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+        if (mUserId != UserHandle.USER_NULL) {
+            intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+        }
         startActivity(intent);
         finish();
     }
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
index 72c06db..d0fcda0 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollSidecar.java
@@ -18,10 +18,12 @@
 
 import android.annotation.Nullable;
 import android.app.Activity;
+import android.content.Intent;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.Handler;
+import android.os.UserHandle;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.ChooseLockSettingsHelper;
@@ -40,6 +42,8 @@
     private Handler mHandler = new Handler();
     private byte[] mToken;
     private boolean mDone;
+    private int mUserId;
+    private FingerprintManager mFingerprintManager;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -50,8 +54,10 @@
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
+        mFingerprintManager = activity.getSystemService(FingerprintManager.class);
         mToken = activity.getIntent().getByteArrayExtra(
                 ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
+        mUserId = activity.getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
     }
 
     @Override
@@ -74,8 +80,11 @@
         mHandler.removeCallbacks(mTimeoutRunnable);
         mEnrollmentSteps = -1;
         mEnrollmentCancel = new CancellationSignal();
-        getActivity().getSystemService(FingerprintManager.class).enroll(mToken, mEnrollmentCancel,
-                0 /* flags */, mEnrollmentCallback);
+        if (mUserId != UserHandle.USER_NULL) {
+            mFingerprintManager.setActiveUser(mUserId);
+        }
+        mFingerprintManager.enroll(mToken, mEnrollmentCancel,
+                0 /* flags */, mEnrollmentCallback, mUserId);
         mEnrolling = true;
     }
 
diff --git a/src/com/android/settings/fingerprint/FingerprintSettings.java b/src/com/android/settings/fingerprint/FingerprintSettings.java
index 9e90c00..56e9b12 100644
--- a/src/com/android/settings/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/fingerprint/FingerprintSettings.java
@@ -72,6 +72,8 @@
  */
 public class FingerprintSettings extends SubSettings {
 
+    private static final String TAG = "FingerprintSettings";
+
     /**
      * Used by the choose fingerprint wizard to indicate the wizard is
      * finished, and each activity in the wizard should finish.
@@ -98,6 +100,8 @@
 
     private static final long LOCKOUT_DURATION = 30000; // time we have to wait for fp to reset, ms
 
+    public static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings";
+
     @Override
     public Intent getIntent() {
         Intent modIntent = new Intent(super.getIntent());
@@ -765,4 +769,34 @@
             return builder;
         }
     }
+
+    public static Preference getFingerprintPreferenceForUser(Context context, int userId) {
+        FingerprintManager fpm = (FingerprintManager) context.getSystemService(
+                Context.FINGERPRINT_SERVICE);
+        if (!fpm.isHardwareDetected()) {
+            Log.v(TAG, "No fingerprint hardware detected!!");
+            return null;
+        }
+        Preference fingerprintPreference = new Preference(context);
+        fingerprintPreference.setKey(KEY_FINGERPRINT_SETTINGS);
+        fingerprintPreference.setTitle(R.string.security_settings_fingerprint_preference_title);
+        Intent intent = new Intent();
+        final List<Fingerprint> items = fpm.getEnrolledFingerprints(userId);
+        final int fingerprintCount = items != null ? items.size() : 0;
+        final String clazz;
+        if (fingerprintCount > 0) {
+            fingerprintPreference.setSummary(context.getResources().getQuantityString(
+                    R.plurals.security_settings_fingerprint_preference_summary,
+                    fingerprintCount, fingerprintCount));
+            clazz = FingerprintSettings.class.getName();
+        } else {
+            fingerprintPreference.setSummary(
+                    R.string.security_settings_fingerprint_preference_summary_none);
+            clazz = FingerprintEnrollIntroduction.class.getName();
+        }
+        intent.setClassName("com.android.settings", clazz);
+        intent.putExtra(Intent.EXTRA_USER_ID, userId);
+        fingerprintPreference.setIntent(intent);
+        return fingerprintPreference;
+    }
 }
diff --git a/src/com/android/settings/fingerprint/FingerprintUiHelper.java b/src/com/android/settings/fingerprint/FingerprintUiHelper.java
index 245cbb4..cf37050 100644
--- a/src/com/android/settings/fingerprint/FingerprintUiHelper.java
+++ b/src/com/android/settings/fingerprint/FingerprintUiHelper.java
@@ -34,21 +34,26 @@
     private ImageView mIcon;
     private TextView mErrorTextView;
     private CancellationSignal mCancellationSignal;
+    private int mUserId;
 
     private Callback mCallback;
     private FingerprintManager mFingerprintManager;
 
-    public FingerprintUiHelper(ImageView icon, TextView errorTextView, Callback callback) {
+    public FingerprintUiHelper(ImageView icon, TextView errorTextView, Callback callback,
+            int userId) {
         mFingerprintManager = icon.getContext().getSystemService(FingerprintManager.class);
         mIcon = icon;
         mErrorTextView = errorTextView;
         mCallback = callback;
+        mUserId = userId;
     }
 
     public void startListening() {
-        if (mFingerprintManager.getEnrolledFingerprints().size() > 0) {
+        if (mFingerprintManager.getEnrolledFingerprints(mUserId).size() > 0) {
             mCancellationSignal = new CancellationSignal();
-            mFingerprintManager.authenticate(null, mCancellationSignal, 0 /* flags */, this, null);
+            mFingerprintManager.setActiveUser(mUserId);
+            mFingerprintManager.authenticate(
+                    null, mCancellationSignal, 0 /* flags */, this, null, mUserId);
             setFingerprintIconVisibility(true);
             mIcon.setImageResource(R.drawable.ic_fingerprint);
         }
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
index c7e39e5..0f0d35f 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -23,6 +23,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.R;
+import com.android.settings.SetupChooseLockGeneric;
 import com.android.settings.SetupWizardUtils;
 import com.android.setupwizardlib.view.NavigationBar;
 
@@ -30,8 +31,8 @@
         implements NavigationBar.NavigationBarListener {
 
     @Override
-    protected Intent getOnboardIntent() {
-        final Intent intent = new Intent(this, SetupFingerprintEnrollOnboard.class);
+    protected Intent getChooseLockIntent() {
+        Intent intent = new Intent(this, SetupChooseLockGeneric.class);
         SetupWizardUtils.copySetupExtras(getIntent(), intent);
         return intent;
     }
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index 2e4242a..a8a7086 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -20,6 +20,9 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.support.v7.preference.PreferenceScreen;
 import android.view.inputmethod.InputMethodInfo;
@@ -38,6 +41,8 @@
 public final class AvailableVirtualKeyboardFragment extends SettingsPreferenceFragment
         implements InputMethodPreference.OnSavePreferenceListener {
 
+    private static final Drawable NO_ICON = new ColorDrawable(Color.TRANSPARENT);
+
     private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = new ArrayList<>();
     private InputMethodSettingValuesWrapper mInputMethodSettingValues;
     private InputMethodManager mImm;
@@ -93,8 +98,15 @@
             final InputMethodInfo imi = imis.get(i);
             final boolean isAllowedByOrganization = permittedList == null
                     || permittedList.contains(imi.getPackageName());
+            Drawable icon;
+            try {
+                icon = getActivity().getPackageManager().getApplicationIcon(imi.getPackageName());
+            } catch (Exception e) {
+                icon = NO_ICON;
+            }
             final InputMethodPreference pref = new InputMethodPreference(
                     context, imi, true, isAllowedByOrganization, this);
+            pref.setIcon(icon);
             mInputMethodPreferenceList.add(pref);
         }
         final Collator collator = Collator.getInstance();
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
index 8c87080..c807e8a 100755
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ b/src/com/android/settings/inputmethod/InputMethodPreference.java
@@ -54,6 +54,7 @@
         OnPreferenceChangeListener {
     private static final String TAG = InputMethodPreference.class.getSimpleName();
     private static final String EMPTY_TEXT = "";
+    private static final int SETTINGS_ICON_LAYOUT = R.layout.preference_settings_icon_widget;
 
     interface OnSavePreferenceListener {
         /**
@@ -97,8 +98,8 @@
         mIsAllowedByOrganization = isAllowedByOrganization;
         mOnSaveListener = onSaveListener;
         if (!isImeEnabler) {
-            // Hide switch widget.
-            setWidgetLayoutResource(0 /* widgetLayoutResId */);
+            // Replace switch widget with settings icon.
+            setWidgetLayoutResource(SETTINGS_ICON_LAYOUT);
         }
         // Disable on/off switch texts.
         setSwitchTextOn(EMPTY_TEXT);
@@ -119,6 +120,7 @@
                 && mInputMethodSettingValues.isValidSystemNonAuxAsciiCapableIme(imi, context);
         setOnPreferenceClickListener(this);
         setOnPreferenceChangeListener(this);
+        useAdminDisabledSummary(true);
         if (!isAllowedByOrganization) {
             EnforcedAdmin admin =
                     RestrictedLockUtils.getProfileOrDeviceOwnerOnCallingUser(context);
@@ -133,7 +135,7 @@
     private boolean isImeEnabler() {
         // If this {@link SwitchPreference} doesn't have a widget layout, we explicitly hide the
         // switch widget at constructor.
-        return getWidgetLayoutResource() != 0;
+        return getWidgetLayoutResource() != SETTINGS_ICON_LAYOUT;
     }
 
     @Override
@@ -194,7 +196,9 @@
         // this preference should be disabled to prevent accidentally disabling an input method.
         setEnabled(!((isAlwaysChecked && isImeEnabler()) || (!mIsAllowedByOrganization)));
         setChecked(mInputMethodSettingValues.isEnabledImi(mImi));
-        setSummary(getSummaryString());
+        if (mIsAllowedByOrganization) {
+            setSummary(getSummaryString());
+        }
     }
 
     private InputMethodManager getInputMethodManager() {
@@ -203,9 +207,6 @@
 
     private String getSummaryString() {
         final Context context = getContext();
-        if (!mIsAllowedByOrganization) {
-            return context.getString(R.string.accessibility_feature_or_input_method_not_allowed);
-        }
         final InputMethodManager imm = getInputMethodManager();
         final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(mImi, true);
         final ArrayList<CharSequence> subtypeLabels = new ArrayList<>();
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
index 541c686..b6ca9f2 100644
--- a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -19,6 +19,9 @@
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.support.v7.preference.Preference;
 import android.view.inputmethod.InputMethodInfo;
@@ -38,6 +41,7 @@
 public final class VirtualKeyboardFragment extends SettingsPreferenceFragment {
 
     private static final String ADD_VIRTUAL_KEYBOARD_SCREEN = "add_virtual_keyboard_screen";
+    private static final Drawable NO_ICON = new ColorDrawable(Color.TRANSPARENT);
 
     private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = new ArrayList<>();
     private InputMethodManager mImm;
@@ -78,12 +82,21 @@
             final InputMethodInfo imi = imis.get(i);
             final boolean isAllowedByOrganization = permittedList == null
                     || permittedList.contains(imi.getPackageName());
+            Drawable icon;
+            try {
+                // TODO: Consider other ways to retrieve an icon to show here.
+                icon = getActivity().getPackageManager().getApplicationIcon(imi.getPackageName());
+            } catch (Exception e) {
+                // TODO: Consider handling the error differently perhaps by showing default icons.
+                icon = NO_ICON;
+            }
             final InputMethodPreference pref = new InputMethodPreference(
                     context,
                     imi,
                     false,  /* isImeEnabler */
                     isAllowedByOrganization,
                     null  /* this can be null since isImeEnabler is false */);
+            pref.setIcon(icon);
             mInputMethodPreferenceList.add(pref);
         }
         final Collator collator = Collator.getInstance();
@@ -101,6 +114,7 @@
             InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(pref);
             pref.updatePreferenceViews();
         }
+        mAddVirtualKeyboardScreen.setIcon(R.drawable.ic_add);
         mAddVirtualKeyboardScreen.setOrder(N);
         getPreferenceScreen().addPreference(mAddVirtualKeyboardScreen);
     }
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 047fcbb..c45de16 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -32,7 +32,6 @@
 import android.support.v7.preference.PreferenceCategory;
 import android.support.v7.preference.PreferenceGroup;
 import android.support.v7.preference.PreferenceScreen;
-import android.support.v14.preference.SwitchPreference;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -47,6 +46,7 @@
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.location.RecentLocationApps;
 
 import java.util.ArrayList;
@@ -104,7 +104,7 @@
     private Switch mSwitch;
     private boolean mValidListener = false;
     private UserHandle mManagedProfile;
-    private SwitchPreference mManagedProfileSwitch;
+    private RestrictedSwitchPreference mManagedProfileSwitch;
     private Preference mLocationMode;
     private PreferenceCategory mCategoryRecentLocationRequests;
     /** Receives UPDATE_INTENT  */
@@ -253,7 +253,7 @@
             root.removePreference(root.findPreference(KEY_MANAGED_PROFILE_SWITCH));
             mManagedProfileSwitch = null;
         } else {
-            mManagedProfileSwitch = (SwitchPreference)root
+            mManagedProfileSwitch = (RestrictedSwitchPreference)root
                     .findPreference(KEY_MANAGED_PROFILE_SWITCH);
             mManagedProfileSwitch.setOnPreferenceClickListener(null);
         }
@@ -263,26 +263,30 @@
         if (mManagedProfileSwitch == null) {
             return;
         }
-        boolean enabled = mainSwitchOn;
-        int summaryResId = R.string.switch_off_text;
-        if (mUm.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile)
-                && getAdminRestrictingManagedProfile() != null) {
-                    summaryResId = R.string.managed_profile_location_switch_lockdown;
-                    enabled = false;
-        }
-
-        mManagedProfileSwitch.setEnabled(enabled);
         mManagedProfileSwitch.setOnPreferenceClickListener(null);
-        if (!enabled) {
+        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(),
+                UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile.getIdentifier());
+        if (mUm.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile)
+                && admin != null) {
+            mManagedProfileSwitch.setDisabledByAdmin(admin);
             mManagedProfileSwitch.setChecked(false);
         } else {
-            final boolean isRestricted = isManagedProfileRestrictedByBase();
-            mManagedProfileSwitch.setChecked(!isRestricted);
-            summaryResId = (isRestricted ?
-                    R.string.switch_off_text : R.string.switch_on_text);
-            mManagedProfileSwitch.setOnPreferenceClickListener(mManagedProfileSwitchClickListener);
+            boolean enabled = mainSwitchOn;
+            mManagedProfileSwitch.setEnabled(enabled);
+
+            int summaryResId = R.string.switch_off_text;
+            if (!enabled) {
+                mManagedProfileSwitch.setChecked(false);
+            } else {
+                final boolean isRestricted = isManagedProfileRestrictedByBase();
+                mManagedProfileSwitch.setChecked(!isRestricted);
+                summaryResId = (isRestricted ?
+                        R.string.switch_off_text : R.string.switch_on_text);
+                mManagedProfileSwitch.setOnPreferenceClickListener(
+                        mManagedProfileSwitchClickListener);
+            }
+            mManagedProfileSwitch.setSummary(summaryResId);
         }
-        mManagedProfileSwitch.setSummary(summaryResId);
     }
 
     /**
@@ -418,27 +422,6 @@
         }
     }
 
-    private ComponentName getAdminRestrictingManagedProfile() {
-        if (mManagedProfile == null) {
-            return null;
-        }
-        DevicePolicyManager dpm = (DevicePolicyManager)getActivity().getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-        if (dpm == null) {
-            return null;
-        }
-        List<ComponentName> admins = dpm.getActiveAdminsAsUser(mManagedProfile.getIdentifier());
-        for (int i = 0; i < admins.size(); ++i) {
-            final ComponentName admin = admins.get(i);
-            Bundle restrictions = dpm.getUserRestrictions(admin, mManagedProfile.getIdentifier());
-            if (restrictions != null && restrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION,
-                    false)) {
-                return admin;
-            }
-        }
-        return null;
-    }
-
     private boolean isManagedProfileRestrictedByBase() {
         if (mManagedProfile == null) {
             return false;
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 33cff53..1bdb46a 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -81,6 +81,9 @@
     @Override
     public void onResume() {
         super.onResume();
+        if (isUiRestricted()) {
+            return;
+        }
         updateControls();
     }
 
diff --git a/src/com/android/settings/notification/ZenModeEventRuleSettings.java b/src/com/android/settings/notification/ZenModeEventRuleSettings.java
index c5691d4..69c870a 100644
--- a/src/com/android/settings/notification/ZenModeEventRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeEventRuleSettings.java
@@ -72,6 +72,9 @@
     @Override
     public void onResume() {
         super.onResume();
+        if (isUiRestricted()) {
+            return;
+        }
         if (!mCreate) {
             reloadCalendar();
         }
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index b0f12f8..19514ab 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -133,6 +133,9 @@
     @Override
     public void onResume() {
         super.onResume();
+        if (isUiRestricted()) {
+            return;
+        }
         updateControls();
     }
 
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 3743396..99fd198 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -47,6 +47,9 @@
     @Override
     public void onResume() {
         super.onResume();
+        if (isUiRestricted()) {
+            return;
+        }
         updateControls();
     }
 
diff --git a/src/com/android/settings/notification/ZenModeSettingsBase.java b/src/com/android/settings/notification/ZenModeSettingsBase.java
index 4c8663f..f1b5edf 100644
--- a/src/com/android/settings/notification/ZenModeSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeSettingsBase.java
@@ -28,7 +28,9 @@
 import android.provider.Settings.Global;
 import android.service.notification.ZenModeConfig;
 import android.util.Log;
+import android.view.View;
 
+import com.android.settings.R;
 import com.android.settings.RestrictedSettingsFragment;
 
 import java.util.List;
@@ -67,11 +69,17 @@
         maybeRefreshRules(true, true /*fireChanged*/);
         mSettingsObserver.register();
         if (isUiRestricted()) {
-            finish();
+            getPreferenceScreen().removeAll();
+            return;
         }
     }
 
     @Override
+    protected View initAdminSupportDetailsView() {
+        return getActivity().findViewById(R.id.admin_support_details);
+    }
+
+    @Override
     public void onPause() {
         super.onPause();
         mSettingsObserver.unregister();
diff --git a/src/com/android/settings/print/PrintJobSettingsFragment.java b/src/com/android/settings/print/PrintJobSettingsFragment.java
index 80bf166..11b4ba2 100644
--- a/src/com/android/settings/print/PrintJobSettingsFragment.java
+++ b/src/com/android/settings/print/PrintJobSettingsFragment.java
@@ -153,9 +153,10 @@
 
     private void processArguments() {
         String printJobId = getArguments().getString(EXTRA_PRINT_JOB_ID);
-        mPrintJobId = PrintJobId.unflattenFromString(printJobId);
-        if (mPrintJobId == null) {
+        if (printJobId == null) {
             finish();
+        } else {
+            mPrintJobId = PrintJobId.unflattenFromString(printJobId);
         }
     }
 
diff --git a/src/com/android/settings/print/PrintServiceSettingsFragment.java b/src/com/android/settings/print/PrintServiceSettingsFragment.java
index 5d20f65..2ac84f4 100644
--- a/src/com/android/settings/print/PrintServiceSettingsFragment.java
+++ b/src/com/android/settings/print/PrintServiceSettingsFragment.java
@@ -481,7 +481,8 @@
                         final int printerCount = mPrinters.size();
                         for (int i = 0; i < printerCount; i++) {
                             PrinterInfo printer = mPrinters.get(i);
-                            if (printer.getName().toLowerCase().contains(constraintLowerCase)) {
+                            String name = printer.getName();
+                            if (name != null && name.toLowerCase().contains(constraintLowerCase)) {
                                 filteredPrinters.add(printer);
                             }
                         }
diff --git a/src/com/android/settings/users/UserPreference.java b/src/com/android/settings/users/UserPreference.java
index 61ad6df..eff8b9a 100644
--- a/src/com/android/settings/users/UserPreference.java
+++ b/src/com/android/settings/users/UserPreference.java
@@ -76,6 +76,7 @@
         mDeleteClickListener = deleteListener;
         mSettingsClickListener = settingsListener;
         mUserId = userId;
+        useAdminDisabledSummary(true);
     }
 
     private void dimIcon(boolean dimmed) {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 06ec966..8229464 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -101,6 +101,7 @@
     private static final String KEY_USER_LIST = "user_list";
     private static final String KEY_USER_ME = "user_me";
     private static final String KEY_ADD_USER = "user_add";
+    private static final String KEY_EMERGENCY_INFO = "emergency_info";
 
     private static final int MENU_REMOVE_USER = Menu.FIRST;
 
@@ -134,6 +135,7 @@
     private DimmableIconPreference mAddUser;
     private PreferenceGroup mLockScreenSettings;
     private RestrictedSwitchPreference mAddUserWhenLocked;
+    private Preference mEmergencyInfoPreference;
     private int mRemovingUserId = -1;
     private int mAddedUserId = 0;
     private boolean mAddingUser;
@@ -229,6 +231,8 @@
         }
         mLockScreenSettings = (PreferenceGroup) findPreference("lock_screen_settings");
         mAddUserWhenLocked = (RestrictedSwitchPreference) findPreference("add_users_when_locked");
+        mEmergencyInfoPreference = findPreference(KEY_EMERGENCY_INFO);
+        mEmergencyInfoPreference.setOnPreferenceClickListener(this);
         loadProfile();
         setHasOptionsMenu(true);
         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
@@ -917,6 +921,9 @@
             } else {
                 onAddUserClicked(USER_TYPE_USER);
             }
+        } else if (pref == mEmergencyInfoPreference) {
+            Intent intent = new Intent("com.android.emergency.EDIT_EMERGENGY_INFO");
+            startActivity(intent);
         }
         return false;
     }
diff --git a/src/com/android/settings/wifi/AccessPointPreference.java b/src/com/android/settings/wifi/AccessPointPreference.java
deleted file mode 100644
index 061055a..0000000
--- a/src/com/android/settings/wifi/AccessPointPreference.java
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * 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.
- */
-package com.android.settings.wifi;
-
-import android.app.Fragment;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.net.wifi.WifiConfiguration;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.view.View;
-import android.widget.TextView;
-
-import com.android.settings.R;
-import com.android.settingslib.wifi.AccessPoint;
-
-public class AccessPointPreference extends Preference {
-
-    private static final int[] STATE_SECURED = {
-        R.attr.state_encrypted
-    };
-    private static final int[] STATE_NONE = {};
-
-    private static int[] wifi_signal_attributes = { R.attr.wifi_signal };
-
-    private final StateListDrawable mWifiSld;
-    private final int mBadgePadding;
-    private final UserBadgeCache mBadgeCache;
-
-    private final Fragment mFragment;
-
-    private TextView mTitleView;
-    private boolean mForSavedNetworks = false;
-    private AccessPoint mAccessPoint;
-    private Drawable mBadge;
-    private int mLevel;
-    private CharSequence mContentDescription;
-
-    static final int[] WIFI_CONNECTION_STRENGTH = {
-        R.string.accessibility_wifi_one_bar,
-        R.string.accessibility_wifi_two_bars,
-        R.string.accessibility_wifi_three_bars,
-        R.string.accessibility_wifi_signal_full
-    };
-
-    // Used for dummy pref.
-    public AccessPointPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mWifiSld = null;
-        mBadgePadding = 0;
-        mBadgeCache = null;
-        mFragment = null;
-    }
-
-    public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache,
-            boolean forSavedNetworks, Fragment fragment) {
-        super(context);
-        mFragment = fragment;
-        mBadgeCache = cache;
-        mAccessPoint = accessPoint;
-        mForSavedNetworks = forSavedNetworks;
-        mAccessPoint.setTag(this);
-        mLevel = -1;
-
-        mWifiSld = (StateListDrawable) context.getTheme()
-                .obtainStyledAttributes(wifi_signal_attributes).getDrawable(0);
-
-        // Distance from the end of the title at which this AP's user badge should sit.
-        mBadgePadding = context.getResources()
-                .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding);
-        refresh();
-    }
-
-    public AccessPoint getAccessPoint() {
-        return mAccessPoint;
-    }
-
-    @Override
-    public void onBindViewHolder(final PreferenceViewHolder view) {
-        super.onBindViewHolder(view);
-        if (mFragment != null) {
-            view.itemView.setOnCreateContextMenuListener(mFragment);
-            view.itemView.setTag(this);
-            view.itemView.setLongClickable(true);
-        }
-        if (mAccessPoint == null) {
-            // Used for dummy pref.
-            return;
-        }
-        Drawable drawable = getIcon();
-        if (drawable != null) {
-            drawable.setLevel(mLevel);
-        }
-
-        mTitleView = (TextView) view.findViewById(com.android.internal.R.id.title);
-        if (mTitleView != null) {
-            // Attach to the end of the title view
-            mTitleView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, mBadge, null);
-            mTitleView.setCompoundDrawablePadding(mBadgePadding);
-        }
-        view.itemView.setContentDescription(mContentDescription);
-    }
-
-    protected void updateIcon(int level, Context context) {
-        if (level == -1) {
-            setIcon(null);
-        } else {
-            if (getIcon() == null) {
-                // To avoid a drawing race condition, we first set the state (SECURE/NONE) and then
-                // set the icon (drawable) to that state's drawable.
-                // If sld is null then we are indexing and therefore do not have access to
-                // (nor need to display) the drawable.
-                if (mWifiSld != null) {
-                    mWifiSld.setState((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE)
-                            ? STATE_SECURED
-                            : STATE_NONE);
-                    Drawable drawable = mWifiSld.getCurrent();
-                    if (!mForSavedNetworks) {
-                        setIcon(drawable);
-                    } else {
-                        setIcon(null);
-                    }
-                }
-            }
-        }
-    }
-
-    protected void updateBadge(Context context) {
-        WifiConfiguration config = mAccessPoint.getConfig();
-        if (config != null) {
-            // Fetch badge (may be null)
-            // Get the badge using a cache since the PM will ask the UserManager for the list
-            // of profiles every time otherwise.
-            mBadge = mBadgeCache.getUserBadge(config.creatorUid);
-        }
-    }
-
-    /**
-     * Updates the title and summary; may indirectly call notifyChanged().
-     */
-    public void refresh() {
-        if (mForSavedNetworks) {
-            setTitle(mAccessPoint.getConfigName());
-        } else {
-            setTitle(mAccessPoint.getSsid());
-        }
-
-        final Context context = getContext();
-        int level = mAccessPoint.getLevel();
-        if (level != mLevel) {
-            mLevel = level;
-            updateIcon(mLevel, context);
-            notifyChanged();
-        }
-        updateBadge(context);
-
-        setSummary(mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary()
-                : mAccessPoint.getSettingsSummary());
-
-        mContentDescription = getTitle();
-        if (getSummary() != null) {
-            mContentDescription = TextUtils.concat(mContentDescription, ",", getSummary());
-        }
-        if (level >= 0 && level < WIFI_CONNECTION_STRENGTH.length) {
-            mContentDescription = TextUtils.concat(mContentDescription, ",",
-                    getContext().getString(WIFI_CONNECTION_STRENGTH[level]));
-        }
-    }
-
-    @Override
-    protected void notifyChanged() {
-        if (Looper.getMainLooper() != Looper.myLooper()) {
-            // Let our BG thread callbacks call setTitle/setSummary.
-            postNotifyChanged();
-        } else {
-            super.notifyChanged();
-        }
-    }
-
-    public void onLevelChanged() {
-        postNotifyChanged();
-    }
-
-    private void postNotifyChanged() {
-        if (mTitleView != null) {
-            mTitleView.post(mNotifyChanged);
-        } // Otherwise we haven't been bound yet, and don't need to update.
-    }
-
-    private final Runnable mNotifyChanged = new Runnable() {
-        @Override
-        public void run() {
-            notifyChanged();
-        }
-    };
-
-    public static class UserBadgeCache {
-        private final SparseArray<Drawable> mBadges = new SparseArray<>();
-        private final PackageManager mPm;
-
-        UserBadgeCache(PackageManager pm) {
-            mPm = pm;
-        }
-
-        private Drawable getUserBadge(int userId) {
-            int index = mBadges.indexOfKey(userId);
-            if (index < 0) {
-                Drawable badge = mPm.getUserBadgeForDensity(new UserHandle(userId), 0 /* dpi */);
-                mBadges.put(userId, badge);
-                return badge;
-            }
-            return mBadges.valueAt(index);
-        }
-    }
-}
diff --git a/src/com/android/settings/wifi/LongPressAccessPointPreference.java b/src/com/android/settings/wifi/LongPressAccessPointPreference.java
new file mode 100644
index 0000000..46746cb
--- /dev/null
+++ b/src/com/android/settings/wifi/LongPressAccessPointPreference.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+package com.android.settings.wifi;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
+import android.net.wifi.WifiConfiguration;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.AccessPointPreference;
+
+public class LongPressAccessPointPreference extends AccessPointPreference {
+
+    private final Fragment mFragment;
+
+    // Used for dummy pref.
+    public LongPressAccessPointPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mFragment = null;
+    }
+
+    public LongPressAccessPointPreference(AccessPoint accessPoint, Context context,
+            UserBadgeCache cache, boolean forSavedNetworks, Fragment fragment) {
+        super(accessPoint, context, cache, forSavedNetworks);
+        mFragment = fragment;
+    }
+
+    @Override
+    public void onBindViewHolder(final PreferenceViewHolder view) {
+        super.onBindViewHolder(view);
+        if (mFragment != null) {
+            view.itemView.setOnCreateContextMenuListener(mFragment);
+            view.itemView.setTag(this);
+            view.itemView.setLongClickable(true);
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index e0ea23a..c5aca20 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -31,8 +31,8 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
-import com.android.settings.wifi.AccessPointPreference.UserBadgeCache;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.AccessPointPreference;
 import com.android.settingslib.wifi.WifiTracker;
 
 import java.util.ArrayList;
@@ -53,7 +53,7 @@
     private Bundle mAccessPointSavedState;
     private AccessPoint mSelectedAccessPoint;
 
-    private UserBadgeCache mUserBadgeCache;
+    private AccessPointPreference.UserBadgeCache mUserBadgeCache;
 
     // Instance state key
     private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state";
@@ -67,7 +67,7 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         addPreferencesFromResource(R.xml.wifi_display_saved_access_points);
-        mUserBadgeCache = new UserBadgeCache(getPackageManager());
+        mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
     }
 
     @Override
@@ -108,8 +108,9 @@
 
         final int accessPointsSize = accessPoints.size();
         for (int i = 0; i < accessPointsSize; ++i){
-            AccessPointPreference preference = new AccessPointPreference(accessPoints.get(i),
-                    context, mUserBadgeCache, true, this);
+            LongPressAccessPointPreference preference =
+                    new LongPressAccessPointPreference(accessPoints.get(i), context,
+                            mUserBadgeCache, true, this);
             preference.setIcon(null);
             preferenceScreen.addPreference(preference);
         }
@@ -119,7 +120,7 @@
         }
     }
 
-    private void showDialog(AccessPointPreference accessPoint, boolean edit) {
+    private void showDialog(LongPressAccessPointPreference accessPoint, boolean edit) {
         if (mDialog != null) {
             removeDialog(WifiSettings.WIFI_DIALOG_ID);
             mDialog = null;
@@ -184,8 +185,8 @@
 
     @Override
     public boolean onPreferenceTreeClick(Preference preference) {
-        if (preference instanceof AccessPointPreference) {
-            showDialog((AccessPointPreference) preference, false);
+        if (preference instanceof LongPressAccessPointPreference) {
+            showDialog((LongPressAccessPointPreference) preference, false);
             return true;
         } else{
             return super.onPreferenceTreeClick(preference);
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index abe700e..a7cb18d 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -35,6 +35,7 @@
 import android.net.wifi.WifiEnterpriseConfig.Phase2;
 import android.net.wifi.WifiInfo;
 import android.os.Handler;
+import android.os.UserManager;
 import android.security.Credentials;
 import android.security.KeyStore;
 import android.text.Editable;
@@ -138,6 +139,8 @@
     private TextView mProxyExclusionListView;
     private TextView mProxyPacView;
 
+    private CheckBox mSharedCheckBox;
+
     private IpAssignment mIpAssignment = IpAssignment.UNASSIGNED;
     private ProxySettings mProxySettings = ProxySettings.UNASSIGNED;
     private ProxyInfo mHttpProxy = null;
@@ -179,6 +182,7 @@
         mIpSettingsSpinner.setOnItemSelectedListener(this);
         mProxySettingsSpinner = (Spinner) mView.findViewById(R.id.proxy_settings);
         mProxySettingsSpinner.setOnItemSelectedListener(this);
+        mSharedCheckBox = (CheckBox) mView.findViewById(R.id.shared);
 
         if (mAccessPoint == null) { // new network
             mConfigUi.setTitle(R.string.wifi_add_network);
@@ -218,6 +222,10 @@
                     mIpSettingsSpinner.setSelection(DHCP);
                 }
 
+                mSharedCheckBox.setEnabled(config.shared);
+                if (!config.shared) {
+                    showAdvancedFields = true;
+                }
 
                 if (config.getProxySettings() == ProxySettings.STATIC) {
                     mProxySettingsSpinner.setSelection(PROXY_STATIC);
@@ -308,6 +316,12 @@
             }
         }
 
+        final UserManager userManager =
+                (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        if (!userManager.isSplitSystemUser()) {
+            mSharedCheckBox.setVisibility(View.GONE);
+        }
+
         mConfigUi.setCancelButton(res.getString(R.string.wifi_cancel));
         if (mConfigUi.getSubmitButton() != null) {
             enableSubmitIfAppropriate();
@@ -393,6 +407,8 @@
             config.networkId = mAccessPoint.getConfig().networkId;
         }
 
+        config.shared = mSharedCheckBox.isChecked();
+
         switch (mAccessPointSecurity) {
             case AccessPoint.SECURITY_NONE:
                 config.allowedKeyManagement.set(KeyMgmt.NONE);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 403d12a..67f1c43 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -63,6 +63,7 @@
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
 import android.widget.Toast;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.LinkifyUtils;
 import com.android.settings.R;
@@ -73,9 +74,9 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
-import com.android.settings.wifi.AccessPointPreference.UserBadgeCache;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.settingslib.wifi.AccessPoint.AccessPointListener;
+import com.android.settingslib.wifi.AccessPointPreference;
 import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.settingslib.wifi.WifiTracker;
 
@@ -131,7 +132,6 @@
     private WifiDialog mDialog;
     private WriteWifiConfigToNfcDialog mWifiToNfcDialog;
 
-    private TextView mEmptyView;
     private ProgressBar mProgressHeader;
 
     // this boolean extra specifies whether to disable the Next button when not connected. Used by
@@ -155,7 +155,7 @@
 
     private HandlerThread mBgThread;
 
-    private UserBadgeCache mUserBadgeCache;
+    private AccessPointPreference.UserBadgeCache mUserBadgeCache;
     private Preference mAddPreference;
 
     /* End of "used in Wifi Setup context" */
@@ -185,7 +185,7 @@
         mAddPreference.setIcon(ic_add);
         mAddPreference.setTitle(R.string.wifi_add_network);
 
-        mUserBadgeCache = new UserBadgeCache(getPackageManager());
+        mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
 
         mBgThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
         mBgThread.start();
@@ -280,7 +280,6 @@
             }
         }
 
-        mEmptyView = initEmptyView();
         registerForContextMenu(getListView());
         setHasOptionsMenu(true);
 
@@ -448,8 +447,9 @@
     public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
             Preference preference = (Preference) view.getTag();
 
-            if (preference instanceof AccessPointPreference) {
-                mSelectedAccessPoint = ((AccessPointPreference) preference).getAccessPoint();
+            if (preference instanceof LongPressAccessPointPreference) {
+                mSelectedAccessPoint =
+                        ((LongPressAccessPointPreference) preference).getAccessPoint();
                 menu.setHeaderTitle(mSelectedAccessPoint.getSsid());
                 if (mSelectedAccessPoint.isConnectable()) {
                     menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect);
@@ -515,8 +515,8 @@
 
     @Override
     public boolean onPreferenceTreeClick(Preference preference) {
-        if (preference instanceof AccessPointPreference) {
-            mSelectedAccessPoint = ((AccessPointPreference) preference).getAccessPoint();
+        if (preference instanceof LongPressAccessPointPreference) {
+            mSelectedAccessPoint = ((LongPressAccessPointPreference) preference).getAccessPoint();
             if (mSelectedAccessPoint == null) {
                 return false;
             }
@@ -628,9 +628,8 @@
     public void onAccessPointsChanged() {
         // Safeguard from some delayed event handling
         if (getActivity() == null) return;
-
         if (isUiRestricted()) {
-            addMessagePreference(R.string.wifi_empty_list_user_restricted);
+            getPreferenceScreen().removeAll();
             return;
         }
         final int wifiState = mWifiManager.getWifiState();
@@ -654,7 +653,8 @@
                             getPreferenceScreen().addPreference(pref);
                             continue;
                         }
-                        AccessPointPreference preference = new AccessPointPreference(accessPoint,
+                        LongPressAccessPointPreference
+                                preference = new LongPressAccessPointPreference(accessPoint,
                                 getPrefContext(), mUserBadgeCache, false, this);
                         preference.setOrder(index++);
 
@@ -708,15 +708,26 @@
         }
     }
 
-    protected TextView initEmptyView() {
+    @Override
+    protected TextView initEmptyTextView() {
         TextView emptyView = (TextView) getActivity().findViewById(android.R.id.empty);
         emptyView.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
-        setEmptyView(emptyView);
         return emptyView;
     }
 
+    @Override
+    protected View initAdminSupportDetailsView() {
+        return getActivity().findViewById(R.id.admin_support_details);
+    }
+
     private void setOffMessage() {
-        if (mEmptyView == null) {
+        if (isUiRestricted()) {
+            getPreferenceScreen().removeAll();
+            return;
+        }
+
+        TextView emptyTextView = getEmptyTextView();
+        if (emptyTextView == null) {
             return;
         }
 
@@ -729,17 +740,17 @@
         final boolean wifiScanningMode = Settings.Global.getInt(
                 resolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1;
 
-        if (isUiRestricted() || !wifiScanningMode) {
+        if (!wifiScanningMode) {
             // Show only the brief text if the user is not allowed to configure scanning settings,
             // or the scanning mode has been turned off.
-            mEmptyView.setText(briefText, BufferType.SPANNABLE);
+            emptyTextView.setText(briefText, BufferType.SPANNABLE);
         } else {
             // Append the description of scanning settings with link.
             final StringBuilder contentBuilder = new StringBuilder();
             contentBuilder.append(briefText);
             contentBuilder.append("\n\n");
             contentBuilder.append(getText(R.string.wifi_scan_notify_text));
-            LinkifyUtils.linkify(mEmptyView, contentBuilder, new LinkifyUtils.OnClickListener() {
+            LinkifyUtils.linkify(emptyTextView, contentBuilder, new LinkifyUtils.OnClickListener() {
                 @Override
                 public void onClick() {
                     final SettingsActivity activity =
@@ -750,7 +761,7 @@
             });
         }
         // Embolden and enlarge the brief description anyway.
-        Spannable boldSpan = (Spannable) mEmptyView.getText();
+        Spannable boldSpan = (Spannable) emptyTextView.getText();
         boldSpan.setSpan(
                 new TextAppearanceSpan(getActivity(), android.R.style.TextAppearance_Medium), 0,
                 briefText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -758,7 +769,8 @@
     }
 
     private void addMessagePreference(int messageId) {
-        if (mEmptyView != null) mEmptyView.setText(messageId);
+        TextView emptyTextView = getEmptyTextView();
+        if (emptyTextView != null) emptyTextView.setText(messageId);
         getPreferenceScreen().removeAll();
     }
 
@@ -867,15 +879,6 @@
     }
 
     /**
-     * Refreshes acccess points and ask Wifi module to scan networks again.
-     */
-    /* package */ void refreshAccessPoints() {
-        mWifiTracker.resumeScanning();
-
-        getPreferenceScreen().removeAll();
-    }
-
-    /**
      * Called when "add network" button is pressed.
      */
     /* package */ void onAddNetworkPressed() {
@@ -885,29 +888,6 @@
         showDialog(null, WifiConfigUiBase.MODE_CONNECT);
     }
 
-    /* package */ int getAccessPointsCount() {
-        final boolean wifiIsEnabled = mWifiTracker.isWifiEnabled();
-        if (wifiIsEnabled) {
-            return getPreferenceScreen().getPreferenceCount();
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     * Requests wifi module to pause wifi scan. May be ignored when the module is disabled.
-     */
-    /* package */ void pauseWifiScan() {
-        mWifiTracker.pauseScanning();
-    }
-
-    /**
-     * Requests wifi module to resume wifi scan. May be ignored when the module is disabled.
-     */
-    /* package */ void resumeWifiScan() {
-        mWifiTracker.resumeScanning();
-    }
-
     @Override
     protected int getHelpResource() {
         return R.string.help_url_wifi;
@@ -915,19 +895,19 @@
 
     @Override
     public void onAccessPointChanged(AccessPoint accessPoint) {
-        ((AccessPointPreference) accessPoint.getTag()).refresh();
+        ((LongPressAccessPointPreference) accessPoint.getTag()).refresh();
     }
 
     @Override
     public void onLevelChanged(AccessPoint accessPoint) {
-        ((AccessPointPreference) accessPoint.getTag()).onLevelChanged();
+        ((LongPressAccessPointPreference) accessPoint.getTag()).onLevelChanged();
     }
 
     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
         new BaseSearchIndexProvider() {
             @Override
             public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
-                final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
+                final List<SearchIndexableRaw> result = new ArrayList<>();
                 final Resources res = context.getResources();
 
                 // Add fragment title
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
index 096847d..2f35478 100644
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
@@ -144,7 +144,7 @@
     }
 
     @Override
-    protected TextView initEmptyView() {
+    protected TextView initEmptyTextView() {
         final LayoutInflater inflater = LayoutInflater.from(getActivity());
         mEmptyFooter = (TextView) inflater.inflate(R.layout.setup_wifi_empty, getListView(), false);
         return mEmptyFooter;
diff --git a/tests/unit/src/com/android/settings/UserCredentialsTests.java b/tests/unit/src/com/android/settings/UserCredentialsTest.java
similarity index 81%
rename from tests/unit/src/com/android/settings/UserCredentialsTests.java
rename to tests/unit/src/com/android/settings/UserCredentialsTest.java
index da1e58b..6de252e 100644
--- a/tests/unit/src/com/android/settings/UserCredentialsTests.java
+++ b/tests/unit/src/com/android/settings/UserCredentialsTest.java
@@ -18,8 +18,7 @@
 
 import android.os.Parcel;
 import android.test.InstrumentationTestCase;
-import android.test.InstrumentationTestRunner;
-import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
 
 import static com.android.settings.UserCredentialsSettings.Credential;
 
@@ -27,13 +26,14 @@
  * User credentials settings fragment tests
  *
  * To run the test, use command:
- * adb shell am instrument -e class com.android.settings.security.UserCredentialsTests
- * -w com.android.settings.tests/android.test.InstrumentationTestRunner
+ * adb shell am instrument -e class com.android.settings.UserCredentialsTest
+ * -w com.android.settings.tests.unit/android.support.test.runner.AndroidJUnitRunner
  *
  */
-public class UserCredentialsTests extends InstrumentationTestCase {
+public class UserCredentialsTest extends InstrumentationTestCase {
     private static final String TAG = "UserCredentialsTests";
 
+    @SmallTest
     public void testCredentialIsParcelable() {
         final String alias = "credential-test-alias";
         Credential c = new Credential(alias);