Merge "Fix disabled WebView packages being shown as enabled in Dev Setting."
diff --git a/res/layout/dialog_hardware_info.xml b/res/layout/dialog_hardware_info.xml
new file mode 100644
index 0000000..f9d52b8
--- /dev/null
+++ b/res/layout/dialog_hardware_info.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2017 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:padding="24dp">
+
+        <TextView
+            android:id="@+id/model_label"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary"
+            android:text="@string/model_info" />
+        <TextView
+            android:id="@+id/model_value"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="24dp"
+            android:textAppearance="@android:style/TextAppearance.Material.Body2" />
+
+        <TextView
+            android:id="@+id/hardware_rev_label"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary"
+            android:text="@string/hardware_revision" />
+        <TextView
+            android:id="@+id/hardware_rev_value"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="24dp"
+            android:textAppearance="@android:style/TextAppearance.Material.Body2" />
+
+    </LinearLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/res/layout/installed_app_details.xml b/res/layout/installed_app_details.xml
deleted file mode 100644
index c84936a..0000000
--- a/res/layout/installed_app_details.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2008, 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:id="@+id/all_details"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:orientation="vertical">
-
-    <!-- App snippet with buttons -->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:paddingTop="5dip"
-        android:paddingBottom="10dip"
-        android:orientation="vertical">
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <FrameLayout
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1">
-                <!-- Application snippet label, version and icon -->
-                <include
-                    layout="@layout/app_item"
-                    android:id="@+id/app_snippet" />
-            </FrameLayout>
-
-            <ImageView
-                android:id="@+id/gear"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:layout_gravity="center_vertical"
-                android:padding="12dp"
-                android:src="@drawable/ic_settings_24dp"
-                android:tint="?android:attr/colorAccent"
-                android:clickable="true"
-                android:background="?android:attr/selectableItemBackground" />
-
-        </LinearLayout>
-
-        <Space
-            android:layout_width="match_parent"
-            android:layout_height="5dp" />
-
-        <!-- Force stop and uninstall buttons -->
-        <include
-            layout="@layout/two_buttons_panel"
-            android:id="@+id/control_buttons_panel"/>
-
-    </LinearLayout>
-</LinearLayout>
-
diff --git a/res/layout/vpn_dialog.xml b/res/layout/vpn_dialog.xml
index 6822e95..61b0861 100644
--- a/res/layout/vpn_dialog.xml
+++ b/res/layout/vpn_dialog.xml
@@ -20,7 +20,7 @@
     <LinearLayout android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:padding="8dp">
+            android:padding="24dp">
 
         <LinearLayout android:id="@+id/editor"
                 android:layout_width="match_parent"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8673359..c9a1bf7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2364,6 +2364,10 @@
     <string name="security_patch">Android security patch level</string>
     <!-- About phone screen, status item label  [CHAR LIMIT=40] -->
     <string name="model_info">Model</string>
+    <!-- About phone screen, dialog title for showing hardware information such as model, serial number, etc.[CHAR LIMIT=60] -->
+    <string name="hardware_info">Model &amp; hardware</string>
+    <!-- Label for device's hardware revision value [CHAR LIMIT=40] -->
+    <string name="hardware_revision">Hardware version</string>
     <!-- About phone screen, fcc equipment id label  [CHAR LIMIT=40] -->
     <string name="fcc_equipment_id">Equipment ID</string>
     <!-- About phone screen,  setting option name  [CHAR LIMIT=40] -->
@@ -3755,7 +3759,9 @@
     <!-- On Text & language settings screen, setting summary for the Auto-punctuate setting. -->
     <string name="auto_punctuate_summary">Press Space key twice to insert \u0022.\u0022</string>
     <!-- On Security & location settings screen, setting check box name. Title of the checkbox to set whether password edit fields will show the most recent character typed and then hide it, or just hide it right away.  By hide, I mean mask it out. -->
-    <string name="show_password">Make passwords visible</string>
+    <string name="show_password">Show passwords</string>
+    <!-- On Security & location settings screen. This is a short summary text describing what "Show passwords" setting does -->
+    <string name="show_password_summary">Display characters briefly as you type</string>
     <!-- Warning message about security implications of enabling an input method, displayed as a dialog
          message when the user selects to enable an IME. -->
     <string name="ime_security_warning">This input method may be able to collect
@@ -8164,6 +8170,8 @@
         <item quantity="one"><xliff:g id="count">%d</xliff:g> default app set by your admin</item>
         <item quantity="other"><xliff:g id="count">%d</xliff:g> default apps set by your admin</item>
     </plurals>
+    <!-- Label explaining that the current input method was set by the admin. [CHAR LIMIT=NONE] -->
+    <string name="enterprise_privacy_input_method">Default keyboard set to <xliff:g id="app_label" example="Example Keyboard">%s</xliff:g> by your admin</string>
     <!-- Label explaining that an always-on VPN was set by the admin for the entire device. [CHAR LIMIT=NONE] -->
     <string name="enterprise_privacy_always_on_vpn_device">Always-on VPN turned on</string>
     <!-- Label explaining that an always-on VPN was set by the admin in the personal profile. [CHAR LIMIT=NONE] -->
diff --git a/res/values/themes.xml b/res/values/themes.xml
index c961cce..d6df2ab 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -216,7 +216,6 @@
     </style>
 
     <style name="Theme.ConfirmDeviceCredentials" parent="Theme.SubSettings">
-        <item name="android:windowLightStatusBar">false</item>
         <item name="confirmDeviceCredentialsSideMargin">@dimen/confirm_credentials_side_margin</item>
         <item name="confirmDeviceCredentialsTopMargin">@dimen/confirm_credentials_top_margin</item>
     </style>
diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml
index 0254b13..6bd8ae3 100644
--- a/res/xml/app_storage_settings.xml
+++ b/res/xml/app_storage_settings.xml
@@ -51,23 +51,11 @@
             android:layout="@layout/horizontal_preference" />
 
         <Preference
-            android:key="external_code_size"
-            android:title="@string/external_code_size_label"
-            android:selectable="false"
-            android:layout="@layout/horizontal_preference" />
-
-        <Preference
             android:key="data_size"
             android:title="@string/data_size_label"
             android:selectable="false"
             android:layout="@layout/horizontal_preference" />
 
-        <Preference
-            android:key="external_data_size"
-            android:title="@string/external_data_size_label"
-            android:selectable="false"
-            android:layout="@layout/horizontal_preference" />
-
         <com.android.settings.applications.LayoutPreference
             android:key="clear_data_button"
             android:selectable="false"
diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml
index bfb1247..992c753 100644
--- a/res/xml/enterprise_privacy_settings.xml
+++ b/res/xml/enterprise_privacy_settings.xml
@@ -89,6 +89,10 @@
                 settings:allowDividerBelow="true"
                 settings:multiLine="true"/>
         <com.android.settings.DividerPreference
+                android:key="input_method"
+                settings:allowDividerBelow="true"
+                settings:multiLine="true"/>
+        <com.android.settings.DividerPreference
                 android:key="global_http_proxy"
                 android:title="@string/enterprise_privacy_global_http_proxy"
                 settings:allowDividerBelow="true"
diff --git a/res/xml/installed_app_details.xml b/res/xml/installed_app_details.xml
deleted file mode 100644
index 7ebdaf7..0000000
--- a/res/xml/installed_app_details.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-                  android:title="@string/application_info_label">
-    <com.android.settings.applications.LayoutPreference
-        android:key="header_view"
-        android:layout="@layout/installed_app_details"
-        android:selectable="false" />
-
-    <Preference
-        android:key="storage_settings"
-        android:title="@string/storage_settings"
-        android:selectable="true" />
-
-    <Preference
-        android:key="data_settings"
-        android:title="@string/data_usage_summary_title"
-        android:selectable="true" />
-
-    <Preference
-        android:key="permission_settings"
-        android:title="@string/permissions_label"
-        android:selectable="true" />
-
-    <Preference
-        android:key="notification_settings"
-        android:title="@string/notifications_label"
-        android:selectable="true" />
-
-    <Preference
-        android:key="preferred_settings"
-        android:title="@string/launch_by_default"
-        android:selectable="true" />
-
-    <Preference
-        android:key="battery"
-        android:title="@string/power_usage_summary_title"
-        android:selectable="true" />
-
-    <Preference
-        android:key="memory"
-        android:title="@string/memory_settings_title"
-        android:enabled="false"
-        android:selectable="true" />
-
-</PreferenceScreen>
diff --git a/res/xml/installed_app_details_ia.xml b/res/xml/installed_app_details_ia.xml
index 5b9bdc7..3e06e39 100644
--- a/res/xml/installed_app_details_ia.xml
+++ b/res/xml/installed_app_details_ia.xml
@@ -23,6 +23,12 @@
         android:selectable="false"
         android:order="-10000"/>
 
+    <com.android.settings.applications.LayoutPreference
+      android:key="action_buttons"
+      android:layout="@layout/app_action_buttons"
+      android:selectable="false"
+      android:order="-9999"/>
+
     <Preference
         android:key="notification_settings"
         android:title="@string/notifications_label"
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index 544769d..04272df 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -26,8 +26,10 @@
             <intent android:action="android.settings.LOCATION_SOURCE_SETTINGS"/>
         </Preference>
 
-        <SwitchPreference android:key="show_password"
-                android:title="@string/show_password"/>
+        <SwitchPreference
+            android:key="show_password"
+            android:title="@string/show_password"
+            android:summary="@string/show_password_summary"/>
 
     </PreferenceCategory>
 
diff --git a/src/com/android/settings/AppHeader.java b/src/com/android/settings/AppHeader.java
index f5700b5..45902d8 100644
--- a/src/com/android/settings/AppHeader.java
+++ b/src/com/android/settings/AppHeader.java
@@ -16,21 +16,9 @@
 
 package com.android.settings;
 
-import android.app.Activity;
 import android.app.Fragment;
 import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.applications.AppInfoBase;
-import com.android.settings.applications.InstalledAppDetails;
 
 public class AppHeader {
 
@@ -38,77 +26,6 @@
     // constant value that can be used to check return code from sub activity.
     private static final int INSTALLED_APP_DETAILS = 1;
 
-    public static void createAppHeader(SettingsPreferenceFragment fragment, Drawable icon,
-            CharSequence label, String pkgName, int uid) {
-        createAppHeader(fragment, icon, label, pkgName, uid, 0, null);
-    }
-
-    public static void createAppHeader(SettingsPreferenceFragment fragment, Drawable icon,
-            CharSequence label, String pkgName, int uid, Intent externalSettings) {
-        createAppHeader(fragment, icon, label, pkgName, uid, 0, externalSettings);
-    }
-
-    public static void createAppHeader(Activity activity, Drawable icon, CharSequence label,
-            String pkgName, int uid, ViewGroup pinnedHeader) {
-        final View bar = activity.getLayoutInflater().inflate(R.layout.app_header,
-                pinnedHeader, false);
-        setupHeaderView(activity, icon, label, pkgName, uid, false, 0, bar, null);
-        pinnedHeader.addView(bar);
-    }
-
-    public static void createAppHeader(SettingsPreferenceFragment fragment, Drawable icon,
-            CharSequence label, String pkgName, int uid, int tintColorRes) {
-        createAppHeader(fragment, icon, label, pkgName, uid, tintColorRes, null);
-    }
-
-    public static void createAppHeader(SettingsPreferenceFragment fragment, Drawable icon,
-            CharSequence label, String pkgName, int uid, int tintColorRes,
-            Intent externalSettings) {
-        View bar = fragment.setPinnedHeaderView(R.layout.app_header);
-        setupHeaderView(fragment.getActivity(), icon, label, pkgName, uid, includeAppInfo(fragment),
-                tintColorRes, bar, externalSettings);
-    }
-
-    public static View setupHeaderView(final Activity activity, Drawable icon, CharSequence label,
-            final String pkgName, final int uid, final boolean includeAppInfo, int tintColorRes,
-            View bar, final Intent externalSettings) {
-        final ImageView appIcon = (ImageView) bar.findViewById(R.id.app_icon);
-        appIcon.setImageDrawable(icon);
-        if (tintColorRes != 0) {
-            appIcon.setImageTintList(ColorStateList.valueOf(activity.getColor(tintColorRes)));
-        }
-
-        final TextView appName = (TextView) bar.findViewById(R.id.app_name);
-        appName.setText(label);
-
-        if (pkgName != null && !pkgName.equals(Utils.OS_PKG)) {
-            bar.setClickable(true);
-            bar.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    if (includeAppInfo) {
-                        AppInfoBase.startAppInfoFragment(InstalledAppDetails.class,
-                                R.string.application_info_label, pkgName, uid, activity,
-                                INSTALLED_APP_DETAILS, MetricsProto.MetricsEvent.VIEW_UNKNOWN);
-                    } else {
-                        activity.finish();
-                    }
-                }
-            });
-            if (externalSettings != null) {
-                final View appSettings = bar.findViewById(R.id.app_settings);
-                appSettings.setVisibility(View.VISIBLE);
-                appSettings.setOnClickListener(new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        activity.startActivity(externalSettings);
-                    }
-                });
-            }
-        }
-        return bar;
-    }
-
     public static boolean includeAppInfo(final Fragment fragment) {
         Bundle args = fragment.getArguments();
         boolean showInfo = true;
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 017a348..3e9304d 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -166,16 +166,6 @@
                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
             mForChangeCredRequiredForBoot = getArguments() != null && getArguments().getBoolean(
                     ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT);
-            if (mIsSetNewPassword) {
-                // In ACTION_SET_NEW_PARENT_PROFILE_PASSWORD or ACTION_SET_NEW_PASSWORD, the user
-                // will be asked to confirm the password if one has been set.
-                // On fingerprint supported device, fingerprint options are represented in the
-                // options. If the user chooses to skip fingerprint setup, ChooseLockGeneric is
-                // relaunched to only show options without fingerprint. In this case, we shouldn't
-                // ask the user to confirm the password again.
-                mPasswordConfirmed = getActivity().getIntent().getBooleanExtra(
-                        PASSWORD_CONFIRMED, false);
-            }
 
             if (savedInstanceState != null) {
                 mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
@@ -246,11 +236,12 @@
                 showFactoryResetProtectionWarningDialog(key);
                 return true;
             } else if (KEY_SKIP_FINGERPRINT.equals(key)) {
-                Intent chooseLockGenericIntent = new Intent(getActivity(), ChooseLockGeneric.class);
+                Intent chooseLockGenericIntent = new Intent(getActivity(),
+                    ChooseLockGeneric.InternalActivity.class);
                 chooseLockGenericIntent.setAction(getIntent().getAction());
                 // Forward the target user id to  ChooseLockGeneric.
                 chooseLockGenericIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
-                chooseLockGenericIntent.putExtra(PASSWORD_CONFIRMED, mPasswordConfirmed);
+                chooseLockGenericIntent.putExtra(CONFIRM_CREDENTIALS, !mPasswordConfirmed);
                 startActivityForResult(chooseLockGenericIntent, SKIP_FINGERPRINT_REQUEST);
                 return true;
             } else {
diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java
index 89ba999..e9d3f86 100644
--- a/src/com/android/settings/DeviceInfoSettings.java
+++ b/src/com/android/settings/DeviceInfoSettings.java
@@ -128,7 +128,7 @@
         controllers.add(new BasebandVersionPreferenceController(context));
         controllers.add(new FirmwareVersionPreferenceController(context, lifecycle));
         controllers.add(new RegulatoryInfoPreferenceController(context));
-        controllers.add(new DeviceModelPreferenceController(context));
+        controllers.add(new DeviceModelPreferenceController(context, fragment));
         controllers.add(new SecurityPatchPreferenceController(context));
         controllers.add(new FccEquipmentIdPreferenceController(context));
         controllers.add(new SELinuxStatusPreferenceController(context));
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 7417516..1bd7416 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -359,37 +359,33 @@
 
         PreferenceGroup securityStatusPreferenceGroup =
                 (PreferenceGroup) root.findPreference(KEY_SECURITY_STATUS);
-        if (mDashboardFeatureProvider.isEnabled()) {
-            final List<Preference> tilePrefs = mDashboardFeatureProvider.getPreferencesForCategory(
-                    getActivity(), getPrefContext(), getMetricsCategory(),
-                    CategoryKey.CATEGORY_SECURITY);
-            int numSecurityStatusPrefs = 0;
-            if (tilePrefs != null && !tilePrefs.isEmpty()) {
-                for (Preference preference : tilePrefs) {
-                    if (!TextUtils.isEmpty(preference.getKey())
-                            && preference.getKey().startsWith(SECURITY_STATUS_KEY_PREFIX)) {
-                        // Injected security status settings are placed under the Security status
-                        // category.
-                        securityStatusPreferenceGroup.addPreference(preference);
-                        numSecurityStatusPrefs++;
-                    } else {
-                        // Other injected settings are placed under the Security preference screen.
-                        root.addPreference(preference);
-                    }
+        final List<Preference> tilePrefs = mDashboardFeatureProvider.getPreferencesForCategory(
+            getActivity(), getPrefContext(), getMetricsCategory(),
+            CategoryKey.CATEGORY_SECURITY);
+        int numSecurityStatusPrefs = 0;
+        if (tilePrefs != null && !tilePrefs.isEmpty()) {
+            for (Preference preference : tilePrefs) {
+                if (!TextUtils.isEmpty(preference.getKey())
+                    && preference.getKey().startsWith(SECURITY_STATUS_KEY_PREFIX)) {
+                    // Injected security status settings are placed under the Security status
+                    // category.
+                    securityStatusPreferenceGroup.addPreference(preference);
+                    numSecurityStatusPrefs++;
+                } else {
+                    // Other injected settings are placed under the Security preference screen.
+                    root.addPreference(preference);
                 }
             }
+        }
 
-            if (numSecurityStatusPrefs == 0) {
-                root.removePreference(securityStatusPreferenceGroup);
-            } else if (numSecurityStatusPrefs > 0) {
-                // Update preference data with tile data. Security feature provider only updates the
-                // data if it actually needs to be changed.
-                mSecurityFeatureProvider.updatePreferences(getActivity(), root,
-                        mDashboardFeatureProvider.getTilesForCategory(
-                                CategoryKey.CATEGORY_SECURITY));
-            }
-        } else {
-            root.removePreference(root.findPreference(KEY_SECURITY_STATUS));
+        if (numSecurityStatusPrefs == 0) {
+            root.removePreference(securityStatusPreferenceGroup);
+        } else if (numSecurityStatusPrefs > 0) {
+            // Update preference data with tile data. Security feature provider only updates the
+            // data if it actually needs to be changed.
+            mSecurityFeatureProvider.updatePreferences(getActivity(), root,
+                mDashboardFeatureProvider.getTilesForCategory(
+                    CategoryKey.CATEGORY_SECURITY));
         }
 
         for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
@@ -1202,8 +1198,7 @@
                     Settings.Secure.PACKAGE_VERIFIER_STATE, 0);
             DashboardFeatureProvider dashboardFeatureProvider =
                     FeatureFactory.getFactory(mContext).getDashboardFeatureProvider(mContext);
-            if (dashboardFeatureProvider.isEnabled()
-                    && (packageVerifierState == PACKAGE_VERIFIER_STATE_ENABLED)) {
+            if (packageVerifierState == PACKAGE_VERIFIER_STATE_ENABLED) {
                 // Calling the feature provider could potentially be slow, so do this on a separate
                 // thread so as to not block the loading of Settings.
                 Executors.newSingleThreadExecutor().execute(new Runnable() {
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index 801a20b..65959b4 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -76,7 +76,7 @@
             }
         }
         mAccountSynController.init(mAccount, userHandle);
-        mRemoveAccountController.setAccount(mAccount);
+        mRemoveAccountController.init(mAccount, userHandle);
     }
 
     @Override
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index c54a2d1..85e09d1 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -49,9 +49,7 @@
 import com.android.settings.core.lifecycle.LifecycleObserver;
 import com.android.settings.core.lifecycle.events.OnPause;
 import com.android.settings.core.lifecycle.events.OnResume;
-import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.Index;
 import com.android.settings.search.SearchIndexableRaw;
 import com.android.settings.search2.SearchFeatureProviderImpl;
 import com.android.settingslib.RestrictedPreference;
@@ -89,7 +87,6 @@
     private SettingsPreferenceFragment mParent;
     private int mAccountProfileOrder = ORDER_ACCOUNT_PROFILES;
     private AccountRestrictionHelper mHelper;
-    private DashboardFeatureProvider mDashboardFeatureProvider;
     private MetricsFeatureProvider mMetricsFeatureProvider;
 
     /**
@@ -138,7 +135,6 @@
             mAuthoritiesCount = mAuthorities.length;
         }
         final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
-        mDashboardFeatureProvider = featureFactory.getDashboardFeatureProvider(mContext);
         mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
         mHelper = helper;
     }
diff --git a/src/com/android/settings/accounts/ChooseAccountActivity.java b/src/com/android/settings/accounts/ChooseAccountActivity.java
index 6f0c110..fce88aa 100644
--- a/src/com/android/settings/accounts/ChooseAccountActivity.java
+++ b/src/com/android/settings/accounts/ChooseAccountActivity.java
@@ -216,7 +216,7 @@
     }
 
     private void addEnterpriseDisclosure() {
-        final CharSequence disclosure = mFeatureProvider.getDeviceOwnerDisclosure(getActivity());
+        final CharSequence disclosure = mFeatureProvider.getDeviceOwnerDisclosure();
         if (disclosure == null) {
             return;
         }
diff --git a/src/com/android/settings/accounts/RemoveAccountPreferenceController.java b/src/com/android/settings/accounts/RemoveAccountPreferenceController.java
index c8dbe4c..f331144 100644
--- a/src/com/android/settings/accounts/RemoveAccountPreferenceController.java
+++ b/src/com/android/settings/accounts/RemoveAccountPreferenceController.java
@@ -27,8 +27,10 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
 import android.os.Bundle;
 import android.os.Process;
+import android.os.UserHandle;
 import android.support.v7.preference.PreferenceScreen;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -49,6 +51,7 @@
 
     private Account mAccount;
     private Fragment mParentFragment;
+    private UserHandle mUserHandle;
 
     public RemoveAccountPreferenceController(Context context, Fragment parent) {
         super(context);
@@ -76,11 +79,12 @@
 
     @Override
     public void onClick(View v) {
-        ConfirmRemoveAccountDialog.show(mParentFragment, mAccount);
+        ConfirmRemoveAccountDialog.show(mParentFragment, mAccount, mUserHandle);
     }
 
-    public void setAccount(Account account) {
+    public void init(Account account, UserHandle userHandle) {
         mAccount = account;
+        mUserHandle = userHandle;
     }
 
     /**
@@ -88,27 +92,37 @@
      */
     public static class ConfirmRemoveAccountDialog extends InstrumentedDialogFragment implements
             DialogInterface.OnClickListener {
-        private static final String SAVE_ACCOUNT = "account";
+        private static final String KEY_ACCOUNT = "account";
         private static final String REMOVE_ACCOUNT_DIALOG = "confirmRemoveAccount";
         private Account mAccount;
+        private UserHandle mUserHandle;
 
-        public static ConfirmRemoveAccountDialog show(Fragment parent, Account account) {
+        public static ConfirmRemoveAccountDialog show(
+                Fragment parent, Account account, UserHandle userHandle) {
             if (!parent.isAdded()) {
                 return null;
             }
             final ConfirmRemoveAccountDialog dialog = new ConfirmRemoveAccountDialog();
-            dialog.mAccount = account;
+            Bundle bundle = new Bundle();
+            bundle.putParcelable(KEY_ACCOUNT, account);
+            bundle.putParcelable(Intent.EXTRA_USER, userHandle);
+            dialog.setArguments(bundle);
             dialog.setTargetFragment(parent, 0);
             dialog.show(parent.getFragmentManager(), REMOVE_ACCOUNT_DIALOG);
             return dialog;
         }
 
         @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            final Bundle arguments = getArguments();
+            mAccount = arguments.getParcelable(KEY_ACCOUNT);
+            mUserHandle = arguments.getParcelable(Intent.EXTRA_USER);
+        }
+
+        @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
             final Context context = getActivity();
-            if (savedInstanceState != null) {
-                mAccount = (Account) savedInstanceState.getParcelable(SAVE_ACCOUNT);
-            }
             return new AlertDialog.Builder(context)
                 .setTitle(R.string.really_remove_account_title)
                 .setMessage(R.string.really_remove_account_message)
@@ -118,12 +132,6 @@
         }
 
         @Override
-        public void onSaveInstanceState(Bundle outState) {
-            super.onSaveInstanceState(outState);
-            outState.putParcelable(SAVE_ACCOUNT, mAccount);
-        }
-
-        @Override
         public int getMetricsCategory() {
             return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_REMOVE;
         }
@@ -159,7 +167,7 @@
                                 activity.finish();
                             }
                         }
-                    }, null, Process.myUserHandle());
+                    }, null, mUserHandle);
         }
     }
 
diff --git a/src/com/android/settings/accounts/UserAndAccountDashboardFragment.java b/src/com/android/settings/accounts/UserAndAccountDashboardFragment.java
index 66fd85a..1b0282f 100644
--- a/src/com/android/settings/accounts/UserAndAccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/UserAndAccountDashboardFragment.java
@@ -28,7 +28,6 @@
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.SummaryLoader;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.drawer.Tile;
 
@@ -121,10 +120,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.user_and_accounts_settings;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java b/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
index 5dda9c1..bdf6cc4 100644
--- a/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
+++ b/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
@@ -23,7 +23,6 @@
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.Arrays;
@@ -58,10 +57,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.app_and_notification;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/applications/AppInfoWithHeader.java b/src/com/android/settings/applications/AppInfoWithHeader.java
index 4f3e8fa..768a726 100644
--- a/src/com/android/settings/applications/AppInfoWithHeader.java
+++ b/src/com/android/settings/applications/AppInfoWithHeader.java
@@ -21,7 +21,6 @@
 import android.support.v7.preference.Preference;
 import android.util.Log;
 
-import com.android.settings.AppHeader;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.applications.AppUtils;
 
@@ -41,24 +40,17 @@
         mCreated = true;
         if (mPackageInfo == null) return;
         final Activity activity = getActivity();
-        if (!FeatureFactory.getFactory(activity)
-                .getDashboardFeatureProvider(activity).isEnabled()) {
-            AppHeader.createAppHeader(this, mPackageInfo.applicationInfo.loadIcon(mPm),
-                    mPackageInfo.applicationInfo.loadLabel(mPm), mPackageName,
-                    mPackageInfo.applicationInfo.uid, 0);
-        } else {
-            final Preference pref = FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this, null /* appHeader */)
-                    .setIcon(mPackageInfo.applicationInfo.loadIcon(mPm))
-                    .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
-                    .setSummary(mPackageInfo)
-                    .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
-                    .setPackageName(mPackageName)
-                    .setUid(mPackageInfo.applicationInfo.uid)
-                    .setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
-                    .done(getPrefContext());
-            getPreferenceScreen().addPreference(pref);
-        }
+        final Preference pref = FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this, null /* appHeader */)
+            .setIcon(mPackageInfo.applicationInfo.loadIcon(mPm))
+            .setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
+            .setSummary(mPackageInfo)
+            .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
+            .setPackageName(mPackageName)
+            .setUid(mPackageInfo.applicationInfo.uid)
+            .setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
+            .done(getPrefContext());
+        getPreferenceScreen().addPreference(pref);
     }
 }
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index b4d7526..0ea9515 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -105,12 +105,6 @@
     private static final String KEY_URI_CATEGORY = "uri_category";
     private static final String KEY_CLEAR_URI = "clear_uri_button";
 
-    private Preference mTotalSize;
-    private Preference mAppSize;
-    private Preference mDataSize;
-    private Preference mExternalCodeSize;
-    private Preference mExternalDataSize;
-
     // Views related to cache info
     private Preference mCacheSize;
     private Button mClearDataButton;
@@ -125,15 +119,9 @@
     private PreferenceCategory mUri;
 
     private boolean mCanClearData = true;
-    private boolean mHaveSizes = false;
 
     private AppStorageStats mLastResult;
-    private long mLastCodeSize = -1;
-    private long mLastDataSize = -1;
-    private long mLastExternalCodeSize = -1;
-    private long mLastExternalDataSize = -1;
-    private long mLastCacheSize = -1;
-    private long mLastTotalSize = -1;
+    private AppStorageSizesController mSizeController;
 
     private ClearCacheObserver mClearCacheObserver;
     private ClearUserDataObserver mClearDataObserver;
@@ -166,17 +154,15 @@
         mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
 
         // Set default values on sizes
-        mTotalSize = findPreference(KEY_TOTAL_SIZE);
-        mAppSize =  findPreference(KEY_APP_SIZE);
-        mDataSize =  findPreference(KEY_DATA_SIZE);
-        mExternalCodeSize = findPreference(KEY_EXTERNAL_CODE_SIZE);
-        mExternalDataSize = findPreference(KEY_EXTERNAL_DATA_SIZE);
+        mSizeController = new AppStorageSizesController.Builder()
+                .setTotalSizePreference(findPreference(KEY_TOTAL_SIZE))
+                .setAppSizePreference(findPreference(KEY_APP_SIZE))
+                .setDataSizePreference(findPreference(KEY_DATA_SIZE))
+                .setCacheSizePreference(findPreference(KEY_CACHE_SIZE))
+                .setComputingString(R.string.computing_size)
+                .setErrorString(R.string.invalid_size_value)
+                .build();
 
-        if (Environment.isExternalStorageEmulated()) {
-            PreferenceCategory category = (PreferenceCategory) findPreference(KEY_STORAGE_CATEGORY);
-            category.removePreference(mExternalCodeSize);
-            category.removePreference(mExternalDataSize);
-        }
         mClearDataButton = (Button) ((LayoutPreference) findPreference(KEY_CLEAR_DATA))
                 .findViewById(R.id.button);
 
@@ -265,13 +251,6 @@
         dialog.dismiss();
     }
 
-    private String getSizeStr(long size) {
-        if (size == SIZE_INVALID) {
-            return mInvalidSizeStr.toString();
-        }
-        return Formatter.formatFileSize(getActivity(), size);
-    }
-
     @Override
     protected boolean refreshUi() {
         retrieveAppEntry();
@@ -521,7 +500,7 @@
 
     @Override
     public void onLoadFinished(Loader<AppStorageStats> loader, AppStorageStats result) {
-        mLastResult = result;
+        mSizeController.setResult(result);
         updateUiWithSize(result);
     }
 
@@ -545,39 +524,15 @@
     }
 
     private void updateUiWithSize(AppStorageStats result) {
+        mSizeController.updateUi(getContext());
+
         if (result == null) {
-            mLastCodeSize = mLastDataSize = mLastCacheSize = mLastTotalSize = -1;
-            if (!mHaveSizes) {
-                mAppSize.setSummary(mComputingStr);
-                mDataSize.setSummary(mComputingStr);
-                mCacheSize.setSummary(mComputingStr);
-                mTotalSize.setSummary(mComputingStr);
-            }
             mClearDataButton.setEnabled(false);
             mClearCacheButton.setEnabled(false);
         } else {
-            mHaveSizes = true;
             long codeSize = result.getCodeBytes();
             long dataSize = result.getDataBytes();
-            if (mLastCodeSize != codeSize) {
-                mLastCodeSize = codeSize;
-                mAppSize.setSummary(getSizeStr(codeSize));
-            }
-            if (mLastDataSize != dataSize) {
-                mLastDataSize = dataSize;
-                mDataSize.setSummary(getSizeStr(dataSize));
-            }
             long cacheSize = result.getCacheBytes();
-            if (mLastCacheSize != cacheSize) {
-                mLastCacheSize = cacheSize;
-                mCacheSize.setSummary(getSizeStr(cacheSize));
-            }
-
-            long totalSize = codeSize + dataSize + cacheSize;
-            if (mLastTotalSize != totalSize) {
-                mLastTotalSize = totalSize;
-                mTotalSize.setSummary(getSizeStr(totalSize));
-            }
 
             if (dataSize <= 0 || !mCanClearData) {
                 mClearDataButton.setEnabled(false);
@@ -615,28 +570,6 @@
         }
     };
 
-    public static CharSequence getSummary(AppEntry appEntry, Context context) {
-        if (appEntry.size == ApplicationsState.SIZE_INVALID
-                || appEntry.size == ApplicationsState.SIZE_UNKNOWN) {
-            return context.getText(R.string.computing_size);
-        } else {
-            CharSequence storageType = context.getString(
-                    (appEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0
-                    ? R.string.storage_type_external
-                    : R.string.storage_type_internal);
-            return context.getString(R.string.storage_summary_format,
-                    getSize(appEntry, context), storageType);
-        }
-    }
-
-    private static CharSequence getSize(AppEntry appEntry, Context context) {
-        long size = appEntry.size;
-        if (size == SIZE_INVALID) {
-            return context.getText(R.string.invalid_size_value);
-        }
-        return Formatter.formatFileSize(context, size);
-    }
-
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.APPLICATIONS_APP_STORAGE;
diff --git a/src/com/android/settings/applications/AppStorageSizesController.java b/src/com/android/settings/applications/AppStorageSizesController.java
new file mode 100644
index 0000000..bc8f680
--- /dev/null
+++ b/src/com/android/settings/applications/AppStorageSizesController.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.applications;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.v7.preference.Preference;
+import android.text.format.Formatter;
+
+import com.android.internal.util.Preconditions;
+import com.android.settingslib.applications.StorageStatsSource;
+
+/**
+ * Handles setting the sizes for the app info screen.
+ */
+public class AppStorageSizesController {
+    private final Preference mTotalSize;
+    private final Preference mAppSize;
+    private final Preference mDataSize;
+    private final Preference mCacheSize;
+    private final @StringRes int mComputing;
+    private final @StringRes int mError;
+
+    @Nullable
+    private StorageStatsSource.AppStorageStats mLastResult;
+    private boolean mLastResultFailed;
+    private long mLastCodeSize = -1;
+    private long mLastDataSize = -1;
+    private long mLastCacheSize = -1;
+    private long mLastTotalSize = -1;
+
+    private AppStorageSizesController(Preference total, Preference app,
+            Preference data, Preference cache, @StringRes int computing, @StringRes int error) {
+        mTotalSize = total;
+        mAppSize = app;
+        mDataSize = data;
+        mCacheSize = cache;
+        mComputing = computing;
+        mError = error;
+    }
+
+    /**
+     * Updates the UI using storage stats.
+     * @param context Context to use to fetch strings
+     */
+    public void updateUi(Context context) {
+        if (mLastResult == null) {
+            int errorRes = mLastResultFailed ? mError : mComputing;
+
+            mAppSize.setSummary(errorRes);
+            mDataSize.setSummary(errorRes);
+            mCacheSize.setSummary(errorRes);
+            mTotalSize.setSummary(errorRes);
+        } else {
+            long codeSize = mLastResult.getCodeBytes();
+            long dataSize = mLastResult.getDataBytes();
+            if (mLastCodeSize != codeSize) {
+                mLastCodeSize = codeSize;
+                mAppSize.setSummary(getSizeStr(context, codeSize));
+            }
+            if (mLastDataSize != dataSize) {
+                mLastDataSize = dataSize;
+                mDataSize.setSummary(getSizeStr(context, dataSize));
+            }
+            long cacheSize = mLastResult.getCacheBytes();
+            if (mLastCacheSize != cacheSize) {
+                mLastCacheSize = cacheSize;
+                mCacheSize.setSummary(getSizeStr(context, cacheSize));
+            }
+
+            long totalSize = codeSize + dataSize + cacheSize;
+            if (mLastTotalSize != totalSize) {
+                mLastTotalSize = totalSize;
+                mTotalSize.setSummary(getSizeStr(context, totalSize));
+            }
+        }
+    }
+
+    /**
+     * Sets a result for the controller to use to update the UI.
+     * @param result A result for the UI. If null, count as a failed calculation.
+     */
+    public void setResult(StorageStatsSource.AppStorageStats result) {
+        mLastResult = result;
+        mLastResultFailed = result == null;
+    }
+
+    private String getSizeStr(Context context, long size) {
+        return Formatter.formatFileSize(context, size);
+    }
+
+    public static class Builder {
+        private Preference mTotalSize;
+        private Preference mAppSize;
+        private Preference mDataSize;
+        private Preference mCacheSize;
+        private @StringRes int mComputing;
+        private @StringRes int mError;
+
+        public Builder setAppSizePreference(Preference preference) {
+            mAppSize = preference;
+            return this;
+        }
+
+        public Builder setDataSizePreference(Preference preference) {
+            mDataSize = preference;
+            return this;
+        }
+
+        public Builder setCacheSizePreference(Preference preference) {
+            mCacheSize = preference;
+            return this;
+        }
+
+        public Builder setTotalSizePreference(Preference preference) {
+            mTotalSize = preference;
+            return this;
+        }
+
+        public Builder setComputingString(@StringRes int sequence) {
+            mComputing = sequence;
+            return this;
+        }
+
+        public Builder setErrorString(@StringRes int sequence) {
+            mError = sequence;
+            return this;
+        }
+
+        public AppStorageSizesController build() {
+            return new AppStorageSizesController(
+                    Preconditions.checkNotNull(mTotalSize),
+                    Preconditions.checkNotNull(mAppSize),
+                    Preconditions.checkNotNull(mDataSize),
+                    Preconditions.checkNotNull(mCacheSize),
+                    mComputing,
+                    mError);
+        }
+    }
+}
diff --git a/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java b/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java
index 3477299..97e5b7b 100644
--- a/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java
+++ b/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.os.UserHandle;
+import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 import com.android.settings.utils.AsyncLoader;
@@ -30,6 +31,7 @@
  * Fetches the storage stats using the StorageStatsManager for a given package and user tuple.
  */
 public class FetchPackageStorageAsyncLoader extends AsyncLoader<AppStorageStats> {
+    private static final String TAG = "FetchPackageStorage";
     private final StorageStatsSource mSource;
     private final ApplicationInfo mInfo;
     private final UserHandle mUser;
@@ -44,7 +46,13 @@
 
     @Override
     public AppStorageStats loadInBackground() {
-        return mSource.getStatsForPackage(mInfo.volumeUuid, mInfo.packageName, mUser);
+        AppStorageStats result = null;
+        try {
+            result = mSource.getStatsForPackage(mInfo.volumeUuid, mInfo.packageName, mUser);
+        } catch (IllegalStateException e) {
+            Log.w(TAG, "Package may have been removed during query, failing gracefully", e);
+        }
+        return result;
     }
 
     @Override
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 3427d9e..da6bbc0 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -20,6 +20,7 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AlertDialog;
+import android.app.LoaderManager;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.app.admin.DevicePolicyManager;
 import android.content.ActivityNotFoundException;
@@ -65,7 +66,6 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.webkit.IWebViewUpdateService;
 import android.widget.Button;
@@ -86,7 +86,6 @@
 import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
 import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
 import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
-import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.datausage.AppDataUsage;
 import com.android.settings.datausage.DataUsageList;
 import com.android.settings.datausage.DataUsageSummary;
@@ -103,6 +102,8 @@
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 import com.android.settingslib.applications.PermissionsSummaryHelper;
 import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback;
+import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
 import com.android.settingslib.net.ChartData;
 import com.android.settingslib.net.ChartDataLoader;
 
@@ -123,7 +124,8 @@
  * uninstall the application.
  */
 public class InstalledAppDetails extends AppInfoBase
-        implements View.OnClickListener, OnPreferenceClickListener {
+        implements View.OnClickListener, OnPreferenceClickListener,
+        LoaderManager.LoaderCallbacks<AppStorageStats> {
 
     private static final String LOG_TAG = "InstalledAppDetails";
 
@@ -138,13 +140,14 @@
     private static final int SUB_INFO_FRAGMENT = 1;
 
     private static final int LOADER_CHART_DATA = 2;
+    private static final int LOADER_STORAGE = 3;
 
     private static final int DLG_FORCE_STOP = DLG_BASE + 1;
     private static final int DLG_DISABLE = DLG_BASE + 2;
     private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
 
     private static final String KEY_HEADER = "header_view";
-    private static final String KEY_FOOTER = "header_footer";
+    private static final String KEY_ACTION_BUTTONS = "action_buttons";
     private static final String KEY_NOTIFICATION = "notification_settings";
     private static final String KEY_STORAGE = "storage_settings";
     private static final String KEY_PERMISSION = "permission_settings";
@@ -158,12 +161,10 @@
 
     private final HashSet<String> mHomePackages = new HashSet<>();
 
-    private DashboardFeatureProvider mDashboardFeatureProvider;
-
     private boolean mInitialized;
     private boolean mShowUninstalled;
     private LayoutPreference mHeader;
-    private LayoutPreference mFooter;
+    private LayoutPreference mActionButtons;
     private Button mUninstallButton;
     private boolean mUpdatedSysApp = false;
     private Button mForceStopButton;
@@ -191,6 +192,8 @@
     protected ProcStatsData mStatsManager;
     protected ProcStatsPackageEntry mStats;
 
+    private AppStorageStats mLastResult;
+
     private boolean handleDisableable(Button button) {
         boolean disableable = false;
         // Try to prevent the user from bricking their phone
@@ -320,20 +323,14 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         final Activity activity = getActivity();
-        mDashboardFeatureProvider =
-                FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
+
+        if (!ensurePackageInfoAvailable(activity)) {
+            return;
+        }
 
         setHasOptionsMenu(true);
-        addPreferencesFromResource(mDashboardFeatureProvider.isEnabled()
-                ? R.xml.installed_app_details_ia
-                : R.xml.installed_app_details);
+        addPreferencesFromResource(R.xml.installed_app_details_ia);
         addDynamicPrefs();
-        if (mDashboardFeatureProvider.isEnabled()) {
-            mFooter = new LayoutPreference(getPrefContext(), R.layout.app_action_buttons);
-            mFooter.setOrder(-9999);
-            mFooter.setKey(KEY_FOOTER);
-            getPreferenceScreen().addPreference(mFooter);
-        }
         if (Utils.isBandwidthControlEnabled()) {
             INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
                     ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
@@ -359,13 +356,14 @@
         if (mFinishing) {
             return;
         }
-        mState.requestSize(mPackageName, mUserId);
         AppItem app = new AppItem(mAppEntry.info.uid);
         app.addUid(mAppEntry.info.uid);
         if (mStatsSession != null) {
-            getLoaderManager().restartLoader(LOADER_CHART_DATA,
+            LoaderManager loaderManager = getLoaderManager();
+            loaderManager.restartLoader(LOADER_CHART_DATA,
                     ChartDataLoader.buildArgs(getTemplate(getContext()), app),
                     mDataCallbacks);
+            loaderManager.restartLoader(LOADER_STORAGE, Bundle.EMPTY, this);
         }
         new BatteryUpdater().execute();
         new MemoryUpdater().execute();
@@ -389,20 +387,17 @@
         if (mFinishing) {
             return;
         }
-        if (!mDashboardFeatureProvider.isEnabled()) {
-            handleHeader();
-        } else {
-            final Activity activity = getActivity();
-            mHeader = (LayoutPreference) findPreference(KEY_HEADER);
-            FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this, mHeader.findViewById(R.id.app_snippet))
-                    .setPackageName(mPackageName)
-                    .setButtonActions(AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK,
-                            AppHeaderController.ActionType.ACTION_APP_PREFERENCE)
-                    .bindAppHeaderButtons();
-            prepareUninstallAndStop();
-        }
+        final Activity activity = getActivity();
+        mHeader = (LayoutPreference) findPreference(KEY_HEADER);
+        mActionButtons = (LayoutPreference) findPreference(KEY_ACTION_BUTTONS);
+        FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this, mHeader.findViewById(R.id.app_snippet))
+            .setPackageName(mPackageName)
+            .setButtonActions(AppHeaderController.ActionType.ACTION_STORE_DEEP_LINK,
+                AppHeaderController.ActionType.ACTION_APP_PREFERENCE)
+            .bindAppHeaderButtons();
+        prepareUninstallAndStop();
 
         mNotificationPreference = findPreference(KEY_NOTIFICATION);
         mNotificationPreference.setOnPreferenceClickListener(this);
@@ -439,36 +434,27 @@
         refreshUi();
     }
 
-    private void handleHeader() {
-        mHeader = (LayoutPreference) findPreference(KEY_HEADER);
-        // Get Control button panel
-        View btnPanel = mHeader.findViewById(R.id.control_buttons_panel);
-        mForceStopButton = (Button) btnPanel.findViewById(R.id.right_button);
-        mForceStopButton.setText(R.string.force_stop);
-        mUninstallButton = (Button) btnPanel.findViewById(R.id.left_button);
-        mForceStopButton.setEnabled(false);
-
-        View gear = mHeader.findViewById(R.id.gear);
-        Intent i = new Intent(Intent.ACTION_APPLICATION_PREFERENCES);
-        i.setPackage(mPackageName);
-        final Intent intent = resolveIntent(i);
-        if (intent != null) {
-            gear.setVisibility(View.VISIBLE);
-            gear.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    startActivity(intent);
-                }
-            });
-        } else {
-            gear.setVisibility(View.GONE);
+    /**
+     * Ensures the {@link PackageInfo} is available to proceed. If it's not available, the fragment
+     * will finish.
+     *
+     * @return true if packageInfo is available.
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    boolean ensurePackageInfoAvailable(Activity activity) {
+        if (mPackageInfo == null) {
+            mFinishing = true;
+            Log.w(LOG_TAG, "Package info not available. Is this package already uninstalled?");
+            activity.finishAndRemoveTask();
+            return false;
         }
+        return true;
     }
 
     private void prepareUninstallAndStop() {
-        mForceStopButton = (Button) mFooter.findViewById(R.id.right_button);
+        mForceStopButton = (Button) mActionButtons.findViewById(R.id.right_button);
         mForceStopButton.setText(R.string.force_stop);
-        mUninstallButton = (Button) mFooter.findViewById(R.id.left_button);
+        mUninstallButton = (Button) mActionButtons.findViewById(R.id.left_button);
         mForceStopButton.setEnabled(false);
     }
 
@@ -536,25 +522,37 @@
         }
     }
 
+    @Override
+    public Loader<AppStorageStats> onCreateLoader(int id, Bundle args) {
+        Context context = getContext();
+        return new FetchPackageStorageAsyncLoader(
+                context, new StorageStatsSource(context), mAppEntry.info, UserHandle.of(mUserId));
+    }
+
+    @Override
+    public void onLoadFinished(Loader<AppStorageStats> loader, AppStorageStats result) {
+        mLastResult = result;
+        refreshUi();
+    }
+
+    @Override
+    public void onLoaderReset(Loader<AppStorageStats> loader) {
+    }
+
     // Utility method to set application label and icon.
     private void setAppLabelAndIcon(PackageInfo pkgInfo) {
         final View appSnippet = mHeader.findViewById(R.id.app_snippet);
         mState.ensureIcon(mAppEntry);
-        if (mDashboardFeatureProvider.isEnabled()) {
-            final Activity activity = getActivity();
-            FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this, appSnippet)
-                    .setLabel(mAppEntry)
-                    .setIcon(mAppEntry)
-                    .setSummary(getString(getInstallationStatus(mAppEntry.info)))
-                    .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
-                    .done(false /* rebindActions */);
-            mVersionPreference.setSummary(getString(R.string.version_text, pkgInfo.versionName));
-        } else {
-            setupAppSnippet(appSnippet, mAppEntry.label, mAppEntry.icon,
-                    pkgInfo != null ? pkgInfo.versionName : null);
-        }
+        final Activity activity = getActivity();
+        FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this, appSnippet)
+            .setLabel(mAppEntry)
+            .setIcon(mAppEntry)
+            .setSummary(getString(getInstallationStatus(mAppEntry.info)))
+            .setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
+            .done(false /* rebindActions */);
+        mVersionPreference.setSummary(getString(R.string.version_text, pkgInfo.versionName));
     }
 
     @VisibleForTesting
@@ -638,7 +636,8 @@
 
         // Update the preference summaries.
         Activity context = getActivity();
-        mStoragePreference.setSummary(AppStorageSettings.getSummary(mAppEntry, context));
+        boolean isExternal = ((mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+        mStoragePreference.setSummary(getStorageSummary(context, mLastResult, isExternal));
 
         PermissionsSummaryHelper.getPermissionSummary(getContext(),
                 mPackageName, mPermissionCallback);
@@ -707,6 +706,25 @@
         return getString(R.string.computing_size);
     }
 
+    @VisibleForTesting
+    static CharSequence getStorageSummary(
+            Context context, AppStorageStats stats, boolean isExternal) {
+        if (stats == null) {
+            return context.getText(R.string.computing_size);
+        } else {
+            CharSequence storageType = context.getString(isExternal
+                    ? R.string.storage_type_external
+                    : R.string.storage_type_internal);
+            return context.getString(R.string.storage_summary_format,
+                    getSize(context, stats), storageType);
+        }
+    }
+
+    private static CharSequence getSize(Context context, AppStorageStats stats) {
+        return Formatter.formatFileSize(context, stats.getTotalBytes());
+    }
+
+
     @Override
     protected AlertDialog createDialog(int id, int errorCode) {
         switch (id) {
@@ -1146,6 +1164,9 @@
         }
     }
 
+    /**
+     * @deprecated app info pages should use {@link AppHeaderController} to show the app header.
+     */
     public static void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon,
             CharSequence versionName) {
         LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views,
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index ab99c9b..826e5db 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -56,7 +56,6 @@
 
 import android.widget.TextView;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.AppHeader;
 import com.android.settings.R;
 import com.android.settings.Settings.AllApplicationsActivity;
 import com.android.settings.Settings.GamesStorageActivity;
@@ -80,7 +79,6 @@
 import com.android.settings.notification.ConfigureNotificationSettings;
 import com.android.settings.notification.NotificationBackend;
 import com.android.settings.notification.NotificationBackend.AppRow;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.HelpUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -265,7 +263,6 @@
     private NotificationBackend mNotifBackend;
     private ResetAppsHelper mResetAppsHelper;
     private String mVolumeUuid;
-    private String mVolumeName;
     private int mStorageType;
 
     @Override
@@ -289,7 +286,6 @@
         } else if (className.equals(StorageUseActivity.class.getName())) {
             if (args != null && args.containsKey(EXTRA_VOLUME_UUID)) {
                 mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
-                mVolumeName = args.getString(EXTRA_VOLUME_NAME);
                 mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
                 mListType = LIST_TYPE_STORAGE;
             } else {
@@ -423,22 +419,6 @@
         }
     }
 
-    @Override
-    public void onViewCreated(View view, Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-
-        if (mListType == LIST_TYPE_STORAGE) {
-            final Activity activity = getActivity();
-            final boolean isNewIAEnabled = FeatureFactory.getFactory(activity)
-                    .getDashboardFeatureProvider(activity)
-                    .isEnabled();
-            if (!isNewIAEnabled) {
-                FrameLayout pinnedHeader = (FrameLayout) mRootView.findViewById(R.id.pinned_header);
-                AppHeader.createAppHeader(getActivity(), null, mVolumeName, null, -1, pinnedHeader);
-            }
-        }
-    }
-
     private int getDefaultFilter() {
         switch (mListType) {
             case LIST_TYPE_USAGE_ACCESS:
@@ -627,12 +607,7 @@
             return;
         }
         final Context context = getActivity();
-        if (FeatureFactory.getFactory(context).getDashboardFeatureProvider(context).isEnabled()) {
-            mOptionsMenu.findItem(R.id.advanced).setVisible(false);
-        } else {
-            mOptionsMenu.findItem(R.id.advanced).setVisible(
-                    mListType == LIST_TYPE_MAIN || mListType == LIST_TYPE_NOTIFICATION);
-        }
+        mOptionsMenu.findItem(R.id.advanced).setVisible(false);
 
         mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE
                 && mSortOrder != R.id.sort_order_alpha);
diff --git a/src/com/android/settings/applications/ProcessStatsDetail.java b/src/com/android/settings/applications/ProcessStatsDetail.java
index 89c6ade..9b6f41e 100644
--- a/src/com/android/settings/applications/ProcessStatsDetail.java
+++ b/src/com/android/settings/applications/ProcessStatsDetail.java
@@ -44,7 +44,6 @@
 import android.view.View;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.AppHeader;
 import com.android.settings.CancellablePreference;
 import com.android.settings.CancellablePreference.OnCancelListener;
 import com.android.settings.R;
@@ -126,28 +125,20 @@
             return;
         }
         final Activity activity = getActivity();
-        if (!FeatureFactory.getFactory(activity)
-                .getDashboardFeatureProvider(activity).isEnabled()) {
-            AppHeader.createAppHeader(this, mApp.mUiTargetApp != null
-                            ? mApp.mUiTargetApp.loadIcon(mPm)
-                            : new ColorDrawable(0),
-                    mApp.mUiLabel, mApp.mPackage, mApp.mUiTargetApp.uid);
-        } else {
-            final Preference pref = FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this, null /* appHeader */)
-                    .setIcon(mApp.mUiTargetApp != null
-                            ? mApp.mUiTargetApp.loadIcon(mPm)
-                            : new ColorDrawable(0))
-                    .setLabel(mApp.mUiLabel)
-                    .setPackageName(mApp.mPackage)
-                    .setUid(mApp.mUiTargetApp != null
-                            ? mApp.mUiTargetApp.uid
-                            : UserHandle.USER_NULL)
-                    .setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
-                    .done(getPrefContext());
-            getPreferenceScreen().addPreference(pref);
-        }
+        final Preference pref = FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this, null /* appHeader */)
+            .setIcon(mApp.mUiTargetApp != null
+                ? mApp.mUiTargetApp.loadIcon(mPm)
+                : new ColorDrawable(0))
+            .setLabel(mApp.mUiLabel)
+            .setPackageName(mApp.mPackage)
+            .setUid(mApp.mUiTargetApp != null
+                ? mApp.mUiTargetApp.uid
+                : UserHandle.USER_NULL)
+            .setButtonActions(ActionType.ACTION_APP_INFO, ActionType.ACTION_NONE)
+            .done(getPrefContext());
+        getPreferenceScreen().addPreference(pref);
     }
 
     @Override
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index 786b9d3..b12e849 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -27,7 +27,6 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.deviceinfo.UsbBackend;
 import com.android.settings.nfc.NfcPreferenceController;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 
@@ -82,10 +81,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.connected_devices;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index d9cef65..07d4806 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -146,8 +146,7 @@
             List<Tile> suggestions) {
         // TODO: Better place for tinting?
         final TypedArray a = mContext.obtainStyledAttributes(new int[]{
-                mDashboardFeatureProvider.isEnabled()
-                        ? android.R.attr.colorControlNormal : android.R.attr.colorAccent});
+                android.R.attr.colorControlNormal});
         int tintColor = a.getColor(0, mContext.getColor(android.R.color.white));
         a.recycle();
         for (int i = 0; i < categories.size(); i++) {
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProvider.java b/src/com/android/settings/dashboard/DashboardFeatureProvider.java
index 7845829..20bcd3d 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProvider.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProvider.java
@@ -31,11 +31,6 @@
 public interface DashboardFeatureProvider {
 
     /**
-     * Whether or not this feature is enabled.
-     */
-    boolean isEnabled();
-
-    /**
      * Get tiles (wrapped in {@link DashboardCategory}) for key defined in CategoryKey.
      */
     DashboardCategory getTilesForCategory(String key);
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 1184e89..9c21720 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -69,11 +69,6 @@
     }
 
     @Override
-    public boolean isEnabled() {
-        return true;
-    }
-
-    @Override
     public DashboardCategory getTilesForCategory(String key) {
         return mCategoryManager.getTilesByCategory(mContext, key);
     }
@@ -81,9 +76,6 @@
     @Override
     public List<Preference> getPreferencesForCategory(Activity activity, Context context,
             int sourceMetricsCategory, String key) {
-        if (!isEnabled()) {
-            return null;
-        }
         final DashboardCategory category = getTilesForCategory(key);
         if (category == null) {
             Log.d(TAG, "NO dashboard tiles for " + TAG);
@@ -177,7 +169,7 @@
     @Override
     public ProgressiveDisclosureMixin getProgressiveDisclosureMixin(Context context,
             DashboardFragment fragment) {
-        return new ProgressiveDisclosureMixin(context, this, mMetricsFeatureProvider, fragment);
+        return new ProgressiveDisclosureMixin(context, mMetricsFeatureProvider, fragment);
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 29cee5e..e3845cd 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -309,8 +309,7 @@
         mSummaryLoader = new SummaryLoader(getActivity(), getCategoryKey());
         mSummaryLoader.setSummaryConsumer(this);
         final TypedArray a = context.obtainStyledAttributes(new int[]{
-                mDashboardFeatureProvider.isEnabled() ? android.R.attr.colorControlNormal
-                        : android.R.attr.colorAccent});
+                android.R.attr.colorControlNormal});
         final int tintColor = a.getColor(0, context.getColor(android.R.color.white));
         a.recycle();
         final String pkgName = context.getPackageName();
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index 5206336..6482672 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -30,7 +30,6 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
-import com.android.settings.SettingsActivity;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.dashboard.conditional.Condition;
 import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
@@ -87,12 +86,7 @@
         mSuggestionFeatureProvider = FeatureFactory.getFactory(activity)
                 .getSuggestionFeatureProvider(activity);
 
-        if (mDashboardFeatureProvider.isEnabled()) {
-            mSummaryLoader = new SummaryLoader(activity, CategoryKey.CATEGORY_HOMEPAGE);
-        } else {
-            mSummaryLoader = new SummaryLoader(activity,
-                    ((SettingsActivity) getActivity()).getDashboardCategories());
-        }
+        mSummaryLoader = new SummaryLoader(activity, CategoryKey.CATEGORY_HOMEPAGE);
 
         mConditionManager = ConditionManager.get(activity, false);
         mSuggestionParser = new SuggestionParser(activity,
@@ -279,20 +273,15 @@
             return;
         }
 
-        if (mDashboardFeatureProvider.isEnabled()) {
-            // Temporary hack to wrap homepage category into a list. Soon we will create adapter
-            // API that takes a single category.
-            List<DashboardCategory> categories = new ArrayList<>();
-            categories.add(mDashboardFeatureProvider.getTilesForCategory(
-                    CategoryKey.CATEGORY_HOMEPAGE));
-            if (suggestions != null) {
-                mAdapter.setCategoriesAndSuggestions(categories, suggestions);
-            } else {
-                mAdapter.setCategory(categories);
-            }
+        // Temporary hack to wrap homepage category into a list. Soon we will create adapter
+        // API that takes a single category.
+        List<DashboardCategory> categories = new ArrayList<>();
+        categories.add(mDashboardFeatureProvider.getTilesForCategory(
+            CategoryKey.CATEGORY_HOMEPAGE));
+        if (suggestions != null) {
+            mAdapter.setCategoriesAndSuggestions(categories, suggestions);
         } else {
-            mAdapter.setCategoriesAndSuggestions(
-                    ((SettingsActivity) activity).getDashboardCategories(), suggestions);
+            mAdapter.setCategory(categories);
         }
     }
 }
diff --git a/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java b/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java
index 90c3d25..be5e21b 100644
--- a/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java
+++ b/src/com/android/settings/dashboard/ProgressiveDisclosureMixin.java
@@ -46,7 +46,6 @@
     private static final int DEFAULT_TILE_LIMIT = 300;
 
     private final Context mContext;
-    private final DashboardFeatureProvider mDashboardFeatureProvider;
     // Collapsed preference sorted by order.
     private final List<Preference> mCollapsedPrefs = new ArrayList<>();
     private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -57,14 +56,12 @@
     private boolean mUserExpanded;
 
     public ProgressiveDisclosureMixin(Context context,
-            DashboardFeatureProvider dashboardFeatureProvider,
             MetricsFeatureProvider metricsFeatureProvider,
             PreferenceFragment fragment) {
         mContext = context;
         mFragment = fragment;
         mExpandButton = new ExpandPreference(context);
         mExpandButton.setOnPreferenceClickListener(this);
-        mDashboardFeatureProvider = dashboardFeatureProvider;
         mMetricsFeatureProvider = metricsFeatureProvider;
     }
 
@@ -122,8 +119,7 @@
      * Whether the screen should be collapsed.
      */
     public boolean shouldCollapse(PreferenceScreen screen) {
-        return mDashboardFeatureProvider.isEnabled() && screen.getPreferenceCount() >= mTileLimit
-                && !mUserExpanded;
+        return screen.getPreferenceCount() >= mTileLimit && !mUserExpanded;
     }
 
     /**
diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java
index 2f0d8b6..df21168 100644
--- a/src/com/android/settings/dashboard/SummaryLoader.java
+++ b/src/com/android/settings/dashboard/SummaryLoader.java
@@ -116,23 +116,8 @@
             @Override
             public void run() {
 
-                final Tile tile;
-                if (mDashboardFeatureProvider.isEnabled()) {
-                    tile = getTileFromCategory(
-                            mDashboardFeatureProvider.getTilesForCategory(mCategoryKey), component);
-                } else {
-                    // Since tiles are not always cached (like on locale change for instance),
-                    // we need to always get the latest one.
-                    if (!(mActivity instanceof SettingsDrawerActivity)) {
-                        if (DEBUG) {
-                            Log.d(TAG, "Can't get category list.");
-                        }
-                        return;
-                    }
-                    tile = getTileFromCategory(
-                            ((SettingsDrawerActivity) mActivity).getDashboardCategories(),
-                            component);
-                }
+                final Tile tile = getTileFromCategory(
+                    mDashboardFeatureProvider.getTilesForCategory(mCategoryKey), component);
 
                 if (tile == null) {
                     if (DEBUG) {
diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java
index 29bd509..0431ce5 100644
--- a/src/com/android/settings/datausage/AppDataUsage.java
+++ b/src/com/android/settings/datausage/AppDataUsage.java
@@ -42,7 +42,6 @@
 import android.widget.AdapterView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.AppHeader;
 import com.android.settings.R;
 import com.android.settings.applications.AppHeaderController;
 import com.android.settings.applications.AppInfoBase;
@@ -354,24 +353,17 @@
         }
 
         final Activity activity = getActivity();
-        if (!FeatureFactory.getFactory(activity)
-                .getDashboardFeatureProvider(activity).isEnabled()) {
-            View header = setPinnedHeaderView(R.layout.app_header);
-            AppHeader.setupHeaderView(getActivity(), mIcon, mLabel,
-                    pkg, uid, AppHeader.includeAppInfo(this), 0, header, null);
-        } else {
-            final Preference pref = FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this, null /* appHeader */)
-                    .setIcon(mIcon)
-                    .setLabel(mLabel)
-                    .setPackageName(pkg)
-                    .setUid(uid)
-                    .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
-                            AppHeaderController.ActionType.ACTION_NONE)
-                    .done(getPrefContext());
-            getPreferenceScreen().addPreference(pref);
-        }
+        final Preference pref = FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this, null /* appHeader */)
+            .setIcon(mIcon)
+            .setLabel(mLabel)
+            .setPackageName(pkg)
+            .setUid(uid)
+            .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
+                AppHeaderController.ActionType.ACTION_NONE)
+            .done(getPrefContext());
+        getPreferenceScreen().addPreference(pref);
     }
 
     @Override
diff --git a/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java b/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java
index 1b47561..a2c4302 100644
--- a/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/DeviceModelPreferenceController.java
@@ -15,10 +15,12 @@
  */
 package com.android.settings.deviceinfo;
 
+import android.app.Fragment;
 import android.content.Context;
 import android.os.Build;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
 
 import com.android.settings.core.PreferenceController;
 import com.android.settingslib.DeviceInfoUtils;
@@ -27,8 +29,11 @@
 
     private static final String KEY_DEVICE_MODEL = "device_model";
 
-    public DeviceModelPreferenceController(Context context) {
+    private final Fragment mHost;
+
+    public DeviceModelPreferenceController(Context context, Fragment host) {
         super(context);
+        mHost = host;
     }
 
     @Override
@@ -49,4 +54,14 @@
     public String getPreferenceKey() {
         return KEY_DEVICE_MODEL;
     }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(preference.getKey(), KEY_DEVICE_MODEL)) {
+            return false;
+        }
+        final HardwareInfoDialogFragment fragment = HardwareInfoDialogFragment.newInstance();
+        fragment.show(mHost.getFragmentManager(), HardwareInfoDialogFragment.TAG);
+        return true;
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java b/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java
new file mode 100644
index 0000000..d68b47a
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/HardwareInfoDialogFragment.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.SystemProperties;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settingslib.DeviceInfoUtils;
+
+public class HardwareInfoDialogFragment extends InstrumentedDialogFragment {
+
+    public static final String TAG = "HardwareInfo";
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.DIALOG_SETTINGS_HARDWARE_INFO;
+    }
+
+    public static HardwareInfoDialogFragment newInstance() {
+        final HardwareInfoDialogFragment fragment = new HardwareInfoDialogFragment();
+        return fragment;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+                .setTitle(R.string.hardware_info)
+                .setPositiveButton(android.R.string.ok, null);
+        final View content = LayoutInflater.from(builder.getContext())
+                .inflate(R.layout.dialog_hardware_info, null /* parent */);
+        // Model
+        setText(content, R.id.model_label, R.id.model_value,
+                Build.MODEL + DeviceInfoUtils.getMsvSuffix());
+        // Hardware rev
+        setText(content, R.id.hardware_rev_label, R.id.hardware_rev_value,
+                SystemProperties.get("ro.boot.hardware.revision"));
+
+        return builder.setView(content).create();
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    void setText(View content, int labelViewId, int valueViewId, String value) {
+        if (content == null) {
+            return;
+        }
+        final View labelView = content.findViewById(labelViewId);
+        final TextView valueView = content.findViewById(valueViewId);
+        if (!TextUtils.isEmpty(value)) {
+            labelView.setVisibility(View.VISIBLE);
+            valueView.setVisibility(View.VISIBLE);
+            valueView.setText(value);
+        } else {
+            labelView.setVisibility(View.GONE);
+            valueView.setVisibility(View.GONE);
+        }
+    }
+}
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 298a7ad..92703e3 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -39,7 +39,6 @@
 import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
 import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
 import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settingslib.applications.StorageStatsSource;
@@ -174,10 +173,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.storage_dashboard_fragment;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/deviceinfo/StorageProfileFragment.java b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
index 6ae03da..d6071c7 100644
--- a/src/com/android/settings/deviceinfo/StorageProfileFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
@@ -24,6 +24,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
+import android.support.annotation.VisibleForTesting;
 import android.util.SparseArray;
 
 import com.android.internal.logging.nano.MetricsProto;
@@ -119,10 +120,26 @@
     @Override
     public void onLoadFinished(Loader<SparseArray<AppsStorageResult>> loader,
             SparseArray<AppsStorageResult> result) {
-        mPreferenceController.onLoadFinished(result.get(mUserId));
+        mPreferenceController.onLoadFinished(scrubAppsFromResult(result.get(mUserId)));
     }
 
     @Override
     public void onLoaderReset(Loader<SparseArray<AppsStorageResult>> loader) {
     }
+
+    @VisibleForTesting
+    void setPreferenceController(StorageItemPreferenceController controller) {
+        mPreferenceController = controller;
+    }
+
+    private AppsStorageResult scrubAppsFromResult(AppsStorageResult result) {
+        if (result == null) {
+            return null;
+        }
+
+        result.gamesSize = 0;
+        result.musicAppsSize = 0;
+        result.otherAppsSize = 0;
+        return result;
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
index a5e8373..41800a2 100644
--- a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
+++ b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
@@ -97,7 +97,7 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         if (mStoragePreference == null) {
-            mStoragePreference = new StorageItemPreferenceAlternate(mContext);
+            mStoragePreference = new StorageItemPreferenceAlternate(screen.getContext());
 
             PreferenceGroup group =
                     (PreferenceGroup) screen.findPreference(TARGET_PREFERENCE_GROUP_KEY);
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 7487b28..2fa1b18 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -173,6 +173,8 @@
     }
 
     public void onLoadFinished(StorageAsyncLoader.AppsStorageResult data) {
+        // TODO(b/35927909): Figure out how to split out apps which are only installed for work
+        //       profiles in order to attribute those app's code bytes only to that profile.
         mPhotoPreference.setStorageSize(
                 data.externalStats.imageBytes + data.externalStats.videoBytes);
         mAudioPreference.setStorageSize(data.musicAppsSize + data.externalStats.audioBytes);
diff --git a/src/com/android/settings/deviceinfo/storage/UserProfileController.java b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
index 5da9fec..963784d 100644
--- a/src/com/android/settings/deviceinfo/storage/UserProfileController.java
+++ b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
@@ -60,7 +60,7 @@
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
-        mStoragePreference = new StorageItemPreferenceAlternate(mContext);
+        mStoragePreference = new StorageItemPreferenceAlternate(screen.getContext());
         mStoragePreference.setOrder(mPreferenceOrder);
         mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
         mStoragePreference.setTitle(mUser.name);
diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
index 014092f..29f315c 100644
--- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
+++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
@@ -17,6 +17,7 @@
 package com.android.settings.enterprise;
 
 import android.content.ComponentName;
+import android.os.UserHandle;
 import android.support.annotation.Nullable;
 
 /**
@@ -89,4 +90,11 @@
      * @see android.app.admin.DevicePolicyManager#getLastNetworkLogRetrievalTime
      */
     long getLastNetworkLogRetrievalTime();
+
+    /**
+     * Calls {@code DevicePolicyManager.isCurrentInputMethodSetByOwner()}.
+     *
+     * @see android.app.admin.DevicePolicyManager#isCurrentInputMethodSetByOwner
+     */
+    boolean isCurrentInputMethodSetByOwner();
 }
diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
index 210faec..0fdcb9c 100644
--- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
+++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
@@ -18,6 +18,7 @@
 
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
+import android.os.UserHandle;
 import android.support.annotation.Nullable;
 
 public class DevicePolicyManagerWrapperImpl implements DevicePolicyManagerWrapper {
@@ -72,4 +73,9 @@
     public long getLastNetworkLogRetrievalTime() {
         return mDpm.getLastNetworkLogRetrievalTime();
     }
+
+    @Override
+    public boolean isCurrentInputMethodSetByOwner() {
+        return mDpm.isCurrentInputMethodSetByOwner();
+    }
 }
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
index 79b12e6..30b74f5 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.enterprise;
 
-import android.content.Context;
-
 import java.util.Date;
 
 public interface EnterprisePrivacyFeatureProvider {
@@ -37,10 +35,8 @@
      * Returns a message informing the user that the device is managed by a Device Owner app. The
      * message includes a Learn More link that takes the user to the enterprise privacy section of
      * Settings. If the device is not managed by a Device Owner app, returns {@code null}.
-     *
-     * @param context The context in which to show the enterprise privacy section of Settings
      */
-    CharSequence getDeviceOwnerDisclosure(Context context);
+    CharSequence getDeviceOwnerDisclosure();
 
     /**
      * Returns the time at which the Device Owner last retrieved security logs, or {@code null} if
@@ -86,4 +82,10 @@
      * user's managed profile (if any) is wiped, or zero if no such limit is set.
      */
     int getMaximumFailedPasswordsBeforeWipeInManagedProfile();
+
+    /**
+     * Returns the label of the current user's input method if that input method was set by a Device
+     * Owner or Profile Owner in that user. Otherwise, returns {@code null}.
+     */
+    String getImeLabelIfOwnerSet();
 }
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index 645a1f5..49d87a5 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -17,8 +17,10 @@
 package com.android.settings.enterprise;
 
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
@@ -39,6 +41,7 @@
 
 public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFeatureProvider {
 
+    private final Context mContext;
     private final DevicePolicyManagerWrapper mDpm;
     private final PackageManagerWrapper mPm;
     private final UserManager mUm;
@@ -47,9 +50,10 @@
 
     private static final int MY_USER_ID = UserHandle.myUserId();
 
-    public EnterprisePrivacyFeatureProviderImpl(DevicePolicyManagerWrapper dpm,
+    public EnterprisePrivacyFeatureProviderImpl(Context context, DevicePolicyManagerWrapper dpm,
             PackageManagerWrapper pm, UserManager um, ConnectivityManagerWrapper cm,
             Resources resources) {
+        mContext = context.getApplicationContext();
         mDpm = dpm;
         mPm = pm;
         mUm = um;
@@ -80,7 +84,7 @@
     }
 
     @Override
-    public CharSequence getDeviceOwnerDisclosure(Context context) {
+    public CharSequence getDeviceOwnerDisclosure() {
         if (!hasDeviceOwner()) {
             return null;
         }
@@ -95,7 +99,7 @@
         }
         disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
         disclosure.append(mResources.getString(R.string.do_disclosure_learn_more),
-                new EnterprisePrivacySpan(context), 0);
+                new EnterprisePrivacySpan(mContext), 0);
         return disclosure;
     }
 
@@ -156,6 +160,24 @@
         return mDpm.getMaximumFailedPasswordsForWipe(profileOwner, userId);
     }
 
+    @Override
+    public String getImeLabelIfOwnerSet() {
+        if (!mDpm.isCurrentInputMethodSetByOwner()) {
+            return null;
+        }
+        final String packageName = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+                Settings.Secure.DEFAULT_INPUT_METHOD, MY_USER_ID);
+        if (packageName == null) {
+            return null;
+        }
+        try {
+            return mPm.getApplicationInfoAsUser(packageName, 0 /* flags */, MY_USER_ID)
+                    .loadLabel(mPm.getPackageManager()).toString();
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
+        }
+    }
+
     protected static class EnterprisePrivacySpan extends ClickableSpan {
         private final Context mContext;
 
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
index 821b7ff..3929bbd 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
@@ -65,6 +65,7 @@
         controllers.add(new GlobalHttpProxyPreferenceController(context));
         controllers.add(new FailedPasswordWipePrimaryUserPreferenceController(context));
         controllers.add(new FailedPasswordWipeManagedProfilePreferenceController(context));
+        controllers.add(new ImePreferenceController(context));
         return controllers;
     }
 
diff --git a/src/com/android/settings/enterprise/ImePreferenceController.java b/src/com/android/settings/enterprise/ImePreferenceController.java
new file mode 100644
index 0000000..18dfac7
--- /dev/null
+++ b/src/com/android/settings/enterprise/ImePreferenceController.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.enterprise;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+public class ImePreferenceController extends PreferenceController {
+
+    private static final String KEY_INPUT_METHOD = "input_method";
+    private final EnterprisePrivacyFeatureProvider mFeatureProvider;
+
+    public ImePreferenceController(Context context) {
+        super(context);
+        mFeatureProvider = FeatureFactory.getFactory(context)
+                .getEnterprisePrivacyFeatureProvider(context);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        final String ownerSetIme = mFeatureProvider.getImeLabelIfOwnerSet();
+        if (ownerSetIme == null) {
+            preference.setVisible(false);
+            return;
+        }
+        preference.setTitle(mContext.getResources().getString(
+            R.string.enterprise_privacy_input_method, ownerSetIme));
+        preference.setVisible(true);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_INPUT_METHOD;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
index f18ae65..96ac042 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -16,7 +16,6 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Bundle;
-import android.os.Process;
 import android.provider.SearchIndexableResource;
 import android.support.annotation.ColorInt;
 import android.support.annotation.IntDef;
@@ -40,10 +39,8 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 public class PowerUsageAdvanced extends PowerUsageBase {
     private static final String TAG = "AdvancedBatteryUsage";
@@ -274,10 +271,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.power_usage_advanced;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index 1598011..94fc3b5 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -62,7 +62,6 @@
 import com.android.settings.location.LocationSettings;
 import com.android.settings.network.NetworkDashboardFragment;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.wifi.WifiSettings;
 
 import java.io.PrintWriter;
@@ -327,13 +326,11 @@
 
     private PackageManager mPm;
     private DevicePolicyManager mDpm;
-    private int mUsageSince;
     private int[] mTypes;
     private int mUid;
     private double[] mValues;
     private Button mForceStopButton;
     private Button mReportButton;
-    private long mStartTime;
     private BatterySipper.DrainType mDrainType;
     private double mNoCoverage; // Percentage of time that there was no coverage
     private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
@@ -379,7 +376,6 @@
     @Override
     public void onResume() {
         super.onResume();
-        mStartTime = android.os.Process.getElapsedCpuTime();
         checkForceStop();
         if (mHighPower != null) {
             mHighPower.setSummary(HighPowerDetail.getSummary(getActivity(), mApp.packageName));
@@ -414,7 +410,6 @@
     private void createDetails() {
         final Bundle args = getArguments();
         Context context = getActivity();
-        mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
         mUid = args.getInt(EXTRA_UID, 0);
         mPackages = context.getPackageManager().getPackagesForUid(mUid);
         mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
@@ -514,29 +509,23 @@
         if (pkg == null && mPackages != null) {
             pkg = mPackages[0];
         }
-        if (!FeatureFactory.getFactory(activity)
-                .getDashboardFeatureProvider(activity).isEnabled()) {
-            AppHeader.createAppHeader(this, appIcon, title, pkg, uid,
-                    mDrainType != DrainType.APP ? android.R.color.white : 0);
-        } else {
-            final PreferenceScreen screen = getPreferenceScreen();
-            final Preference appHeaderPref =
-                    findPreference(AppHeaderController.PREF_KEY_APP_HEADER);
-            if (appHeaderPref != null) {
-                return;
-            }
-            final Preference pref = FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this, null /* appHeader */)
-                    .setIcon(appIcon)
-                    .setLabel(title)
-                    .setPackageName(pkg)
-                    .setUid(uid)
-                    .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
-                            AppHeaderController.ActionType.ACTION_NONE)
-                    .done(getPrefContext());
-            screen.addPreference(pref);
+        final PreferenceScreen screen = getPreferenceScreen();
+        final Preference appHeaderPref =
+            findPreference(AppHeaderController.PREF_KEY_APP_HEADER);
+        if (appHeaderPref != null) {
+            return;
         }
+        final Preference pref = FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this, null /* appHeader */)
+            .setIcon(appIcon)
+            .setLabel(title)
+            .setPackageName(pkg)
+            .setUid(uid)
+            .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
+                AppHeaderController.ActionType.ACTION_NONE)
+            .done(getPrefContext());
+        screen.addPreference(pref);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 55fcaf8..44f61c1 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -733,10 +733,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.power_usage_summary;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/gestures/AssistGestureSettings.java b/src/com/android/settings/gestures/AssistGestureSettings.java
index 1d82720..7778720 100644
--- a/src/com/android/settings/gestures/AssistGestureSettings.java
+++ b/src/com/android/settings/gestures/AssistGestureSettings.java
@@ -24,7 +24,6 @@
 import com.android.settings.core.PreferenceController;
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -67,10 +66,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.assist_gesture_settings;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/gestures/DoubleTapPowerSettings.java b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
index b17341a..467cec8 100644
--- a/src/com/android/settings/gestures/DoubleTapPowerSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
@@ -24,7 +24,6 @@
 import com.android.settings.core.PreferenceController;
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -67,10 +66,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.double_tap_power_settings;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/gestures/DoubleTapScreenSettings.java b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
index a215dae..887ac80 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
@@ -26,7 +26,6 @@
 import com.android.settings.core.PreferenceController;
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -70,10 +69,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.double_tap_screen_settings;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
index bee9474..46a8cbb 100644
--- a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
+++ b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
@@ -24,7 +24,6 @@
 import com.android.settings.core.PreferenceController;
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -67,10 +66,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.double_twist_gesture_settings;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/gestures/PickupGestureSettings.java b/src/com/android/settings/gestures/PickupGestureSettings.java
index e4d12f2..0fe6097 100644
--- a/src/com/android/settings/gestures/PickupGestureSettings.java
+++ b/src/com/android/settings/gestures/PickupGestureSettings.java
@@ -26,7 +26,6 @@
 import com.android.settings.core.PreferenceController;
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -70,10 +69,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.pick_up_gesture_settings;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/gestures/SwipeToNotificationSettings.java b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
index d948e55..6c136c2 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationSettings.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
@@ -24,7 +24,6 @@
 import com.android.settings.core.PreferenceController;
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -67,10 +66,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.swipe_to_notification_settings;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java
index 3987252..ef9f84b 100644
--- a/src/com/android/settings/language/LanguageAndInputSettings.java
+++ b/src/com/android/settings/language/LanguageAndInputSettings.java
@@ -36,7 +36,6 @@
 import com.android.settings.inputmethod.GameControllerPreferenceController;
 import com.android.settings.inputmethod.SpellCheckerPreferenceController;
 import com.android.settings.gestures.SwipeToNotificationPreferenceController;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 
 import java.util.ArrayList;
@@ -110,10 +109,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.language_and_input;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index 6add786..a0ccf20 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -138,10 +138,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.network_and_internet;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java
index a5e5c3e..11e3e09 100644
--- a/src/com/android/settings/nfc/NfcPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPreferenceController.java
@@ -68,17 +68,10 @@
         mNfcEnabler = new NfcEnabler(mContext, mNfcPreference, mBeamPreference);
         String toggleable = Settings.Global.getString(mContext.getContentResolver(),
                 Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
-        final boolean useNewIA = FeatureFactory.getFactory(mContext)
-                .getDashboardFeatureProvider(mContext).isEnabled();
         // Manually set dependencies for NFC when not toggleable.
         if (toggleable == null || !toggleable.contains(Settings.Global.RADIO_NFC)) {
-            if (useNewIA) {
-                mAirplaneModeObserver = new AirplaneModeObserver();
-                updateNfcPreference();
-            } else {
-                mNfcPreference.setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
-                mBeamPreference.setDependency(AirplaneModePreferenceController.KEY_TOGGLE_AIRPLANE);
-            }
+            mAirplaneModeObserver = new AirplaneModeObserver();
+            updateNfcPreference();
         }
     }
 
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 34745a7..a451786 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -20,13 +20,9 @@
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 
 import android.app.Activity;
-import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ResolveInfo;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -42,11 +38,9 @@
 import com.android.settings.Utils;
 import com.android.settings.applications.AppHeaderController;
 import com.android.settings.applications.AppInfoBase;
-import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.notification.NotificationBackend.AppRow;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.MasterSwitchPreference;
-import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.RestrictedSwitchPreference;
 
 import java.text.Collator;
@@ -63,21 +57,10 @@
 
     private static final String KEY_BLOCK = "block";
 
-    private DashboardFeatureProvider mDashboardFeatureProvider;
     private List<NotificationChannelGroup> mChannelGroupList;
     private List<PreferenceCategory> mChannelGroups = new ArrayList();
 
     @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        if (mAppRow == null) return;
-        if (!mDashboardFeatureProvider.isEnabled()) {
-            AppHeader.createAppHeader(this, mAppRow.icon, mAppRow.label, mAppRow.pkg, mAppRow.uid,
-                    mAppRow.settingsIntent);
-        }
-    }
-
-    @Override
     public int getMetricsCategory() {
         return MetricsEvent.NOTIFICATION_APP_NOTIFICATION;
     }
@@ -91,8 +74,6 @@
             return;
         }
         final Activity activity = getActivity();
-        mDashboardFeatureProvider =
-                FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
 
         addPreferencesFromResource(R.xml.app_notification_settings);
         getPreferenceScreen().setOrderingAsAdded(true);
@@ -121,20 +102,18 @@
                 }
             }.execute();
         }
-        if (mDashboardFeatureProvider.isEnabled()) {
-            final Preference pref = FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this /* fragment */, null /* appHeader */)
-                    .setIcon(mAppRow.icon)
-                    .setLabel(mAppRow.label)
-                    .setPackageName(mAppRow.pkg)
-                    .setUid(mAppRow.uid)
-                    .setAppNotifPrefIntent(mAppRow.settingsIntent)
-                    .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
-                            AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
-                    .done(getPrefContext());
-            getPreferenceScreen().addPreference(pref);
-        }
+        final Preference pref = FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this /* fragment */, null /* appHeader */)
+            .setIcon(mAppRow.icon)
+            .setLabel(mAppRow.label)
+            .setPackageName(mAppRow.pkg)
+            .setUid(mAppRow.uid)
+            .setAppNotifPrefIntent(mAppRow.settingsIntent)
+            .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
+                AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
+            .done(getPrefContext());
+        getPreferenceScreen().addPreference(pref);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index 7be98c1..1cb2154 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -40,11 +40,9 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.AppHeader;
 import com.android.settings.R;
 import com.android.settings.RingtonePreference;
 import com.android.settings.applications.AppHeaderController;
-import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedSwitchPreference;
@@ -69,18 +67,6 @@
     protected RestrictedSwitchPreference mPriority;
     protected RestrictedDropDownPreference mVisibilityOverride;
 
-    private DashboardFeatureProvider mDashboardFeatureProvider;
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        if (mAppRow == null || mChannel == null) return;
-        if (!mDashboardFeatureProvider.isEnabled()) {
-            AppHeader.createAppHeader(
-                    this, mAppRow.icon, mChannel.getName(), mAppRow.pkg, mAppRow.uid);
-        }
-    }
-
     @Override
     public int getMetricsCategory() {
         return MetricsEvent.NOTIFICATION_TOPIC_NOTIFICATION;
@@ -95,8 +81,6 @@
             return;
         }
         final Activity activity = getActivity();
-        mDashboardFeatureProvider =
-                FeatureFactory.getFactory(activity).getDashboardFeatureProvider(activity);
         addPreferencesFromResource(R.xml.channel_notification_settings);
 
         // load settings intent
@@ -125,21 +109,19 @@
             setupBlockAndImportance();
             updateDependents();
         }
-        if (mDashboardFeatureProvider.isEnabled()) {
-            final Preference pref = FeatureFactory.getFactory(activity)
-                    .getApplicationFeatureProvider(activity)
-                    .newAppHeaderController(this /* fragment */, null /* appHeader */)
-                    .setIcon(mAppRow.icon)
-                    .setLabel(getNotificationChannelLabel(mChannel))
-                    .setSummary(mAppRow.label)
-                    .setPackageName(mAppRow.pkg)
-                    .setUid(mAppRow.uid)
-                    .setAppNotifPrefIntent(mAppRow.settingsIntent)
-                    .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
-                            AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
-                    .done(getPrefContext());
-            getPreferenceScreen().addPreference(pref);
-        }
+        final Preference pref = FeatureFactory.getFactory(activity)
+            .getApplicationFeatureProvider(activity)
+            .newAppHeaderController(this /* fragment */, null /* appHeader */)
+            .setIcon(mAppRow.icon)
+            .setLabel(getNotificationChannelLabel(mChannel))
+            .setSummary(mAppRow.label)
+            .setPackageName(mAppRow.pkg)
+            .setUid(mAppRow.uid)
+            .setAppNotifPrefIntent(mAppRow.settingsIntent)
+            .setButtonActions(AppHeaderController.ActionType.ACTION_APP_INFO,
+                AppHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
+            .done(getPrefContext());
+        getPreferenceScreen().addPreference(pref);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index 2a737d4..aee9dc2 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -17,14 +17,12 @@
 package com.android.settings.notification;
 
 import android.content.Context;
-import android.os.Bundle;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.gestures.SwipeToNotificationPreferenceController;
-import com.android.settings.overlay.FeatureFactory;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -62,16 +60,4 @@
         controllers.add(mLockScreenNotificationController);
         return controllers;
     }
-
-    @Override
-    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
-        super.onCreatePreferences(savedInstanceState, rootKey);
-        final Context context = getContext();
-        if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context).isEnabled()) {
-            final String prefKey = getPreferenceController(
-                    SwipeToNotificationPreferenceController.class)
-                    .getPreferenceKey();
-            removePreference(prefKey);
-        }
-    }
 }
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index e72ee03..5b039b2 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -116,7 +116,7 @@
     @Override
     public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) {
         if (mEnterprisePrivacyFeatureProvider == null) {
-            mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl(
+            mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl(context,
                     new DevicePolicyManagerWrapperImpl((DevicePolicyManager) context
                             .getSystemService(Context.DEVICE_POLICY_SERVICE)),
                     new PackageManagerWrapperImpl(context.getPackageManager()),
diff --git a/src/com/android/settings/system/SystemDashboardFragment.java b/src/com/android/settings/system/SystemDashboardFragment.java
index c4bf0da..76ac4a6 100644
--- a/src/com/android/settings/system/SystemDashboardFragment.java
+++ b/src/com/android/settings/system/SystemDashboardFragment.java
@@ -25,7 +25,6 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.deviceinfo.AdditionalSystemUpdatePreferenceController;
 import com.android.settings.deviceinfo.SystemUpdatePreferenceController;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 
@@ -33,7 +32,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-
 public class SystemDashboardFragment extends DashboardFragment {
 
     private static final String TAG = "SystemDashboardFrag";
@@ -73,10 +71,6 @@
                 @Override
                 public List<SearchIndexableResource> getXmlResourcesToIndex(
                         Context context, boolean enabled) {
-                    if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
-                            .isEnabled()) {
-                        return null;
-                    }
                     final SearchIndexableResource sir = new SearchIndexableResource(context);
                     sir.xmlResId = R.xml.system_dashboard_fragment;
                     return Arrays.asList(sir);
diff --git a/src/com/android/settings/vpn2/LegacyVpnPreference.java b/src/com/android/settings/vpn2/LegacyVpnPreference.java
index c1550e2..a4d7221 100644
--- a/src/com/android/settings/vpn2/LegacyVpnPreference.java
+++ b/src/com/android/settings/vpn2/LegacyVpnPreference.java
@@ -34,7 +34,7 @@
 
     LegacyVpnPreference(Context context) {
         super(context, null /* attrs */);
-        setIcon(R.mipmap.ic_launcher_settings);
+        setIcon(R.drawable.ic_settings_24dp);
     }
 
     public VpnProfile getProfile() {
diff --git a/src/com/android/settings/widget/VideoPreference.java b/src/com/android/settings/widget/VideoPreference.java
index c8786dc..e06ef56 100644
--- a/src/com/android/settings/widget/VideoPreference.java
+++ b/src/com/android/settings/widget/VideoPreference.java
@@ -62,6 +62,7 @@
                     .build();
             mMediaPlayer = MediaPlayer.create(mContext, mVideoPath);
             if (mMediaPlayer != null && mMediaPlayer.getDuration() > 0) {
+                setVisible(true);
                 setLayoutResource(R.layout.video_preference);
 
                 mPreviewResource = attributes.getResourceId(
@@ -71,6 +72,8 @@
 
                 mMediaPlayer.setOnPreparedListener(mediaPlayer -> mediaPlayer.setLooping(true));
                 mAnimationAvailable = true;
+            } else {
+                setVisible(false);
             }
         } catch (Exception e) {
             Log.w(TAG, "Animation resource not found. Will not show animation.");
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
index 381006a..c0c0ccf 100644
--- a/tests/app/Android.mk
+++ b/tests/app/Android.mk
@@ -14,6 +14,7 @@
     espresso-contrib-nodep \
     espresso-intents-nodep \
     ub-uiautomator \
+    truth-prebuilt \
     legacy-android-test
 
 # Include all test java files.
diff --git a/tests/app/src/com/android/settings/ChooseLockGenericTest.java b/tests/app/src/com/android/settings/ChooseLockGenericTest.java
new file mode 100644
index 0000000..dee6697
--- /dev/null
+++ b/tests/app/src/com/android/settings/ChooseLockGenericTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
+import android.support.test.runner.lifecycle.Stage;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+
+import android.text.format.DateUtils;
+import android.view.KeyEvent;
+
+import com.android.settings.R;
+
+import java.util.Collection;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link ChooseLockGenericTest}
+ *
+ * m SettingsTests &&
+ * adb install \
+ * -r -g  ${ANDROID_PRODUCT_OUT}/data/app/SettingsTests/SettingsTests.apk &&
+ * adb shell am instrument -e class com.android.settings.ChooseLockGenericTest \
+ * -w com.android.settings.tests/android.support.test.runner.AndroidJUnitRunner
+ */
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class ChooseLockGenericTest {
+    private static final long TIMEOUT = 5 * DateUtils.SECOND_IN_MILLIS;
+    private static final Intent PHISHING_ATTACK_INTENT = new Intent()
+            .putExtra("confirm_credentials", false)
+            .putExtra("password_confirmed", true);
+
+    private UiDevice mDevice;
+    private Context mTargetContext;
+    private String mSettingPackage;
+    private PackageManager mPackageManager;
+    @Rule
+    public ActivityTestRule<ChooseLockGeneric> mChooseLockGenericActivityRule =
+            new ActivityTestRule<>(
+                    ChooseLockGeneric.class,
+                    true /* enable touch at launch */,
+                    false /* don't launch at every test */);
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mTargetContext = getInstrumentation().getTargetContext();
+        mSettingPackage = mTargetContext.getPackageName();
+        mPackageManager = mTargetContext.getPackageManager();
+
+        setPassword();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        clearPassword();
+    }
+
+    @Test
+    public void testConfirmLockPasswordShown_deviceWithPassword() throws Exception, Throwable {
+        // GIVEN a PIN password is set on this device at set up.
+        // WHEN ChooseLockGeneric is launched with no extras.
+        mChooseLockGenericActivityRule.launchActivity(null /* No extras */);
+        // THEN ConfirmLockPassword.InternalActivity is shown.
+        assertThat(getCurrentActivity()).isInstanceOf(ConfirmLockPassword.InternalActivity.class);
+    }
+
+    @Test
+    public void testConfirmLockPasswordShown_deviceWithPassword_phishingAttack()
+            throws Exception, Throwable {
+        // GIVEN a PIN password is set on this device at set up.
+        // WHEN ChooseLockGeneric is launched with extras to by-pass lock password confirmation.
+        mChooseLockGenericActivityRule.launchActivity(PHISHING_ATTACK_INTENT);
+        // THEN ConfirmLockPassword.InternalActivity is still shown.
+        assertThat(getCurrentActivity()).isInstanceOf(ConfirmLockPassword.InternalActivity.class);
+    }
+
+    private Activity getCurrentActivity() throws Throwable {
+        getInstrumentation().waitForIdleSync();
+        final Activity[] activity = new Activity[1];
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance()
+                        .getActivitiesInStage(Stage.RESUMED);
+                activity[0] = activities.iterator().next();
+            }
+        });
+        return activity[0];
+    }
+
+    private void launchNewPassword() throws Exception {
+        Intent newPasswordIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD)
+                .setPackage(mSettingPackage)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getInstrumentation().getContext().startActivity(newPasswordIntent);
+        mDevice.waitForIdle();
+    }
+
+    /** Sets a PIN password, 12345, for testing. */
+    private void setPassword() throws Exception {
+        launchNewPassword();
+
+        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
+            // Set "lock_none", but it actually means we don't want to enroll a fingerprint.
+            UiObject view = new UiObject(
+                    new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
+            assertTrue("lock_none", view.waitForExists(TIMEOUT));
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Pick PIN from the option list
+        UiObject view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/lock_pin"));
+        assertTrue("lock_pin", view.waitForExists(TIMEOUT));
+        view.click();
+        mDevice.waitForIdle();
+
+        // Ignore any interstitial options
+        view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/encrypt_dont_require_password"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Yes, we really want to
+        view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/next_button"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Set our PIN
+        view = new UiObject(new UiSelector()
+                .resourceId(mSettingPackage + ":id/password_entry"));
+        assertTrue("password_entry", view.waitForExists(TIMEOUT));
+
+        // Enter it twice to confirm
+        enterTestPin();
+        enterTestPin();
+
+        mDevice.pressBack();
+    }
+
+    /** Clears the previous set PIN password. */
+    private void clearPassword() throws Exception {
+        launchNewPassword();
+
+        // Enter current PIN
+        UiObject view = new UiObject(
+                new UiSelector().resourceId(mSettingPackage + ":id/password_entry"));
+        if (!view.waitForExists(TIMEOUT)) {
+            // Odd, maybe there is a crash dialog showing; try dismissing it
+            mDevice.pressBack();
+            mDevice.waitForIdle();
+
+            assertTrue("password_entry", view.waitForExists(TIMEOUT));
+        }
+
+        enterTestPin();
+
+        // Set back to "none"
+        view = new UiObject(new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
+        assertTrue("lock_none", view.waitForExists(TIMEOUT));
+        view.click();
+        mDevice.waitForIdle();
+
+        // Yes, we really want "none" if prompted again
+        view = new UiObject(new UiSelector().resourceId(mSettingPackage + ":id/lock_none"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        // Yes, we really want to
+        view = new UiObject(new UiSelector()
+                .resourceId("android:id/button1"));
+        if (view.waitForExists(TIMEOUT)) {
+            view.click();
+            mDevice.waitForIdle();
+        }
+
+        mDevice.pressBack();
+    }
+
+    private void enterTestPin() throws Exception {
+        mDevice.waitForIdle();
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_1);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_2);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_3);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_4);
+        mDevice.pressKeyCode(KeyEvent.KEYCODE_5);
+        mDevice.waitForIdle();
+        mDevice.pressEnter();
+        mDevice.waitForIdle();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index 6a5b935..68ca890 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -19,14 +19,11 @@
 import android.app.ActivityManager;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
-import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
-import com.android.settings.testutils.FakeFeatureFactory;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
@@ -45,8 +42,6 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SettingsActivityTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
     @Mock
     private FragmentManager mFragmentManager;
     @Mock
@@ -58,10 +53,6 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
 
         mActivity = spy(new SettingsActivity());
         doReturn(mBitmap).when(mActivity).getBitmapFromXmlResource(anyInt());
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
index 2b861e2..d2ded86 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountPreferenceControllerTest.java
@@ -33,7 +33,6 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.search.SearchIndexableRaw;
-import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowAccountManager;
 import com.android.settings.testutils.shadow.ShadowContentResolver;
 
@@ -55,7 +54,6 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -76,7 +74,6 @@
     @Mock(answer = RETURNS_DEEP_STUBS)
     private AccountRestrictionHelper mAccountHelper;
 
-    private FakeFeatureFactory mFactory;
     private Context mContext;
     private AccountPreferenceController mController;
 
@@ -86,11 +83,8 @@
         ShadowApplication shadowContext = ShadowApplication.getInstance();
         shadowContext.setSystemService(Context.USER_SERVICE, mUserManager);
         shadowContext.setSystemService(Context.ACCOUNT_SERVICE, mAccountManager);
-        mContext = spy(shadowContext.getApplicationContext());
-        FakeFeatureFactory.setupForTest(mContext);
-        mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+        mContext = shadowContext.getApplicationContext();
 
-        when(mFactory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
         when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
         when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(
diff --git a/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java
index 50f3ac6..033465b 100644
--- a/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/RemoveAccountPreferenceControllerTest.java
@@ -23,6 +23,7 @@
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.content.Context;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.support.v7.preference.PreferenceScreen;
@@ -127,11 +128,13 @@
         when(mFragment.getActivity()).thenReturn(activity);
 
         Account account = new Account("Account11", "com.acct1");
+        UserHandle userHandle = new UserHandle(10);
         RemoveAccountPreferenceController.ConfirmRemoveAccountDialog dialog =
-            RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.show(mFragment, account);
-
+            RemoveAccountPreferenceController.ConfirmRemoveAccountDialog.show(
+                    mFragment, account, userHandle);
+        dialog.onCreate(new Bundle());
         dialog.onClick(null, 0);
         verify(mAccountManager).removeAccountAsUser(eq(account), any(Activity.class),
-            any(AccountManagerCallback.class), any(Handler.class), any(UserHandle.class));
+            any(AccountManagerCallback.class), any(Handler.class), eq(userHandle));
     }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/accounts/UserAndAccountDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/accounts/UserAndAccountDashboardFragmentTest.java
index e1c2abf..39ffcf8 100644
--- a/tests/robotests/src/com/android/settings/accounts/UserAndAccountDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/UserAndAccountDashboardFragmentTest.java
@@ -16,7 +16,6 @@
 package com.android.settings.accounts;
 
 import android.app.Activity;
-import android.content.Context;
 import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.UserManager;
@@ -25,14 +24,12 @@
 import com.android.settings.R;
 import com.android.settings.TestConfig;
 import com.android.settings.dashboard.SummaryLoader;
-import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.drawer.CategoryKey;
 import com.android.settingslib.drawer.Tile;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
@@ -54,8 +51,6 @@
     private static final String METADATA_CATEGORY = "com.android.settings.category";
     private static final String METADATA_ACCOUNT_TYPE = "com.android.settings.ia.account";
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
     @Mock
     private UserManager mUserManager;
     private UserAndAccountDashboardFragment mFragment;
@@ -63,10 +58,6 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mFragment = new UserAndAccountDashboardFragment();
     }
 
diff --git a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
index 56d4a83..a717306 100644
--- a/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppInfoWithHeaderTest.java
@@ -72,7 +72,6 @@
                 ShadowApplication.getInstance().getApplicationContext(),
                 mAppInfoWithHeader,
                 null);
-        when(mFactory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         when(mFactory.applicationFeatureProvider.newAppHeaderController(mAppInfoWithHeader, null))
                 .thenReturn(appHeaderController);
         mAppInfoWithHeader.onActivityCreated(null);
diff --git a/tests/robotests/src/com/android/settings/applications/AppStorageSizesControllerTest.java b/tests/robotests/src/com/android/settings/applications/AppStorageSizesControllerTest.java
new file mode 100644
index 0000000..7204bd1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/AppStorageSizesControllerTest.java
@@ -0,0 +1,95 @@
+package com.android.settings.applications;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import com.android.settings.R;
+import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AppStorageSizesControllerTest {
+    private static final String COMPUTING = "Computing…";
+    private static final String INVALID_SIZE = "Couldn’t compute package size.";
+    private AppStorageSizesController mController;
+    private Context mContext;
+
+    private Preference mAppPreference;
+    private Preference mCachePreference;
+    private Preference mDataPreference;
+    private Preference mTotalPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mAppPreference = new Preference(mContext);
+        mCachePreference = new Preference(mContext);
+        mDataPreference = new Preference(mContext);
+        mTotalPreference = new Preference(mContext);
+
+        mController = new AppStorageSizesController.Builder()
+                .setAppSizePreference(mAppPreference)
+                .setCacheSizePreference(mCachePreference)
+                .setDataSizePreference(mDataPreference)
+                .setTotalSizePreference(mTotalPreference)
+                .setErrorString(R.string.invalid_size_value)
+                .setComputingString(R.string.computing_size)
+                .build();
+    }
+
+    @Test
+    public void requestingUpdateBeforeValuesSetIsComputing() {
+        mController.updateUi(mContext);
+
+        assertThat(mAppPreference.getSummary()).isEqualTo(COMPUTING);
+        assertThat(mCachePreference.getSummary()).isEqualTo(COMPUTING);
+        assertThat(mDataPreference.getSummary()).isEqualTo(COMPUTING);
+        assertThat(mTotalPreference.getSummary()).isEqualTo(COMPUTING);
+    }
+
+    @Test
+    public void requestingUpdateAfterFailureHasErrorText() {
+        mController.setResult(null);
+        mController.updateUi(mContext);
+
+        assertThat(mAppPreference.getSummary()).isEqualTo(INVALID_SIZE);
+        assertThat(mCachePreference.getSummary()).isEqualTo(INVALID_SIZE);
+        assertThat(mDataPreference.getSummary()).isEqualTo(INVALID_SIZE);
+        assertThat(mTotalPreference.getSummary()).isEqualTo(INVALID_SIZE);
+    }
+
+    @Test
+    public void properlyPopulatedAfterValidEntry() {
+        AppStorageStats result = mock(AppStorageStats.class);
+        when(result.getCodeBytes()).thenReturn(1L);
+        when(result.getCacheBytes()).thenReturn(10L);
+        when(result.getDataBytes()).thenReturn(100L);
+        when(result.getTotalBytes()).thenReturn(111L);
+
+        mController.setResult(result);
+        mController.updateUi(mContext);
+
+        assertThat(mAppPreference.getSummary()).isEqualTo("1.00B");
+        assertThat(mCachePreference.getSummary()).isEqualTo("10.00B");
+        assertThat(mDataPreference.getSummary()).isEqualTo("100B");
+        assertThat(mTotalPreference.getSummary()).isEqualTo("111B");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/FetchPackageStorageAsyncLoaderTest.java b/tests/robotests/src/com/android/settings/applications/FetchPackageStorageAsyncLoaderTest.java
index 0b1d1aa..04eeb02 100644
--- a/tests/robotests/src/com/android/settings/applications/FetchPackageStorageAsyncLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/applications/FetchPackageStorageAsyncLoaderTest.java
@@ -43,6 +43,7 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class FetchPackageStorageAsyncLoaderTest {
+    private static final String PACKAGE_NAME = "com.test.package";
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     @Mock
@@ -63,10 +64,22 @@
         when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class)))
                 .thenReturn(stats);
         ApplicationInfo info = new ApplicationInfo();
-        info.packageName = "com.test.package";
+        info.packageName = PACKAGE_NAME;
 
         FetchPackageStorageAsyncLoader task = new FetchPackageStorageAsyncLoader(
                 mContext, mSource, info, new UserHandle(0));
         assertThat(task.loadInBackground()).isEqualTo(stats);
     }
+
+    @Test
+    public void installerExceptionHandledCleanly() {
+        when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class))).
+                thenThrow(new IllegalStateException("intentional failure"));
+        ApplicationInfo info = new ApplicationInfo();
+        info.packageName = PACKAGE_NAME;
+        FetchPackageStorageAsyncLoader task = new FetchPackageStorageAsyncLoader(
+                mContext, mSource, info, new UserHandle(0));
+
+        assertThat(task.loadInBackground()).isNull();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index 2a703ef..b0cd8d5 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -16,7 +16,10 @@
 
 package com.android.settings.applications;
 
+
+import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
+import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.os.UserManager;
@@ -25,6 +28,7 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -32,14 +36,18 @@
 import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.util.ReflectionHelpers;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public final class InstalledAppDetailsTest {
@@ -47,24 +55,27 @@
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private UserManager mUserManager;
     @Mock
+    private Activity mActivity;
+    @Mock
     private DevicePolicyManager mDevicePolicyManager;
 
+    private InstalledAppDetails mAppDetail;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mAppDetail = new InstalledAppDetails();
     }
 
     @Test
     public void getInstallationStatus_notInstalled_shouldReturnUninstalled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
 
         assertThat(mAppDetail.getInstallationStatus(new ApplicationInfo()))
-            .isEqualTo(R.string.not_installed);
+                .isEqualTo(R.string.not_installed);
     }
 
     @Test
     public void getInstallationStatus_enabled_shouldReturnInstalled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         final ApplicationInfo info = new ApplicationInfo();
         info.flags = ApplicationInfo.FLAG_INSTALLED;
         info.enabled = true;
@@ -74,7 +85,6 @@
 
     @Test
     public void getInstallationStatus_disabled_shouldReturnDisabled() {
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         final ApplicationInfo info = new ApplicationInfo();
         info.flags = ApplicationInfo.FLAG_INSTALLED;
         info.enabled = false;
@@ -86,7 +96,6 @@
     public void shouldShowUninstallForAll_installForOneOtherUserOnly_shouldReturnTrue() {
         when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
         when(mUserManager.getUsers().size()).thenReturn(2);
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
         ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
         final ApplicationInfo info = new ApplicationInfo();
@@ -103,7 +112,6 @@
     public void shouldShowUninstallForAll_installForSelfOnly_shouldReturnFalse() {
         when(mDevicePolicyManager.packageHasActiveAdmins(anyString())).thenReturn(false);
         when(mUserManager.getUsers().size()).thenReturn(2);
-        final InstalledAppDetails mAppDetail = new InstalledAppDetails();
         ReflectionHelpers.setField(mAppDetail, "mDpm", mDevicePolicyManager);
         ReflectionHelpers.setField(mAppDetail, "mUserManager", mUserManager);
         final ApplicationInfo info = new ApplicationInfo();
@@ -117,4 +125,40 @@
         assertThat(mAppDetail.shouldShowUninstallForAll(appEntry)).isFalse();
     }
 
+    @Test
+    public void getStorageSummary_shouldWorkForExternal() {
+        Context context = RuntimeEnvironment.application.getApplicationContext();
+        AppStorageStats stats = mock(AppStorageStats.class);
+        when(stats.getTotalBytes()).thenReturn(1L);
+
+        assertThat(InstalledAppDetails.getStorageSummary(context, stats, true))
+                .isEqualTo("1.00B used in External storage");
+    }
+
+    @Test
+    public void getStorageSummary_shouldWorkForInternal() {
+        Context context = RuntimeEnvironment.application.getApplicationContext();
+        AppStorageStats stats = mock(AppStorageStats.class);
+        when(stats.getTotalBytes()).thenReturn(1L);
+
+        assertThat(InstalledAppDetails.getStorageSummary(context, stats, false))
+                .isEqualTo("1.00B used in Internal storage");
+    }
+
+    @Test
+    public void launchFragment_hasNoPackageInfo_shouldFinish() {
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", null);
+
+        assertThat(mAppDetail.ensurePackageInfoAvailable(mActivity)).isFalse();
+        verify(mActivity).finishAndRemoveTask();
+    }
+
+    @Test
+    public void launchFragment_hasPackageInfo_shouldReturnTrue() {
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        ReflectionHelpers.setField(mAppDetail, "mPackageInfo", packageInfo);
+
+        assertThat(mAppDetail.ensurePackageInfoAvailable(mActivity)).isTrue();
+        verify(mActivity, never()).finishAndRemoveTask();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java
index f2cf729..1ee18cf 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutoFillPickerTest.java
@@ -24,6 +24,7 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.applications.PackageManagerWrapper;
+import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -60,6 +61,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mActivity);
         when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
         mPicker = spy(new DefaultAutoFillPicker());
         mPicker.onAttach((Context) mActivity);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
index 83bae50..fc4b75f 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
@@ -15,44 +15,30 @@
  */
 package com.android.settings.connecteddevice;
 
-import android.content.Context;
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.drawer.CategoryKey;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
 import java.util.List;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class ConnectedDeviceDashboardFragmentTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
     private ConnectedDeviceDashboardFragment mFragment;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mFragment = new ConnectedDeviceDashboardFragment();
     }
 
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
index 5902ec0..4eea05e 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
@@ -57,7 +57,6 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
@@ -268,24 +267,12 @@
     }
 
     @Test
-    public void getPreferences_notEnabled_shouldReturnNull() {
-        final DashboardFeatureProviderImpl mSpy = spy(mImpl);
-        when(mSpy.isEnabled()).thenReturn(false);
-
-        assertThat(mSpy.getPreferencesForCategory(null, null,
-                MetricsProto.MetricsEvent.SETTINGS_GESTURES, CategoryKey.CATEGORY_HOMEPAGE))
-                .isNull();
-    }
-
-    @Test
     public void getPreferences_noCategory_shouldReturnNull() {
         mImpl = new DashboardFeatureProviderImpl(mActivity, mCategoryManager);
-        final DashboardFeatureProviderImpl mSpy = spy(mImpl);
-        when(mSpy.isEnabled()).thenReturn(true);
         when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
                 .thenReturn(null);
 
-        assertThat(mSpy.getPreferencesForCategory(null, null,
+        assertThat(mImpl.getPreferencesForCategory(null, null,
                 MetricsProto.MetricsEvent.SETTINGS_GESTURES, CategoryKey.CATEGORY_HOMEPAGE))
                 .isNull();
     }
@@ -293,12 +280,10 @@
     @Test
     public void getPreferences_noTileForCategory_shouldReturnNull() {
         mImpl = new DashboardFeatureProviderImpl(mActivity, mCategoryManager);
-        final DashboardFeatureProviderImpl mSpy = spy(mImpl);
-        when(mSpy.isEnabled()).thenReturn(true);
         when(mCategoryManager.getTilesByCategory(mActivity, CategoryKey.CATEGORY_HOMEPAGE))
                 .thenReturn(new DashboardCategory());
 
-        assertThat(mSpy.getPreferencesForCategory(null, null,
+        assertThat(mImpl.getPreferencesForCategory(null, null,
                 MetricsProto.MetricsEvent.SETTINGS_GESTURES, CategoryKey.CATEGORY_HOMEPAGE))
                 .isNull();
     }
@@ -306,15 +291,13 @@
     @Test
     public void getPreferences_hasTileForCategory_shouldReturnPrefList() {
         mImpl = new DashboardFeatureProviderImpl(mActivity, mCategoryManager);
-        final DashboardFeatureProviderImpl mSpy = spy(mImpl);
-        when(mSpy.isEnabled()).thenReturn(true);
         final DashboardCategory category = new DashboardCategory();
         category.tiles.add(new Tile());
         when(mCategoryManager
                 .getTilesByCategory(any(Context.class), eq(CategoryKey.CATEGORY_HOMEPAGE)))
                 .thenReturn(category);
 
-        assertThat(mSpy.getPreferencesForCategory(mActivity,
+        assertThat(mImpl.getPreferencesForCategory(mActivity,
                 ShadowApplication.getInstance().getApplicationContext(),
                 MetricsProto.MetricsEvent.SETTINGS_GESTURES,
                 CategoryKey.CATEGORY_HOMEPAGE).isEmpty())
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardSummaryTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardSummaryTest.java
index b3f9fe0..a8e294c 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardSummaryTest.java
@@ -75,7 +75,6 @@
     @Test
     public void updateCategoryAndSuggestion_shouldGetCategoryFromFeatureProvider() {
         doReturn(mock(Activity.class)).when(mSummary).getActivity();
-        when(mDashboardFeatureProvider.isEnabled()).thenReturn(true);
         mSummary.updateCategoryAndSuggestion(null);
         verify(mDashboardFeatureProvider).getTilesForCategory(CategoryKey.CATEGORY_HOMEPAGE);
     }
diff --git a/tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java b/tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java
index e7f97c3..e872a09 100644
--- a/tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/ProgressiveDisclosureTest.java
@@ -77,13 +77,11 @@
         mAppContext = ShadowApplication.getInstance().getApplicationContext();
         mFakeFeatureFactory = (FakeFeatureFactory) FeatureFactory.getFactory(mContext);
         mMixin = new ProgressiveDisclosureMixin(mAppContext,
-                mFakeFeatureFactory.dashboardFeatureProvider,
                 mFakeFeatureFactory.metricsFeatureProvider,
                 mPreferenceFragment);
         ReflectionHelpers.setField(mMixin, "mExpandButton", mExpandButton);
         mPreference = new Preference(mAppContext);
         mPreference.setKey("test");
-        when(mFakeFeatureFactory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
     }
 
     @Test
@@ -97,7 +95,6 @@
 
     @Test
     public void shouldCollapse_morePreferenceThanLimit() {
-        when(mFakeFeatureFactory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         when(mScreen.getPreferenceCount()).thenReturn(5);
         mMixin.setTileLimit(3);
 
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java
index 06d81de..ea60e4c 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/DeviceModelPreferenceControllerTest.java
@@ -16,6 +16,7 @@
 package com.android.settings.deviceinfo;
 
 
+import android.app.Fragment;
 import android.content.Context;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
@@ -32,15 +33,20 @@
 import org.robolectric.annotation.Config;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class DeviceModelPreferenceControllerTest {
+
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Fragment mFragment;
     @Mock
     private Preference mPreference;
     @Mock
@@ -50,9 +56,10 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mController = new DeviceModelPreferenceController(mContext);
+        mController = new DeviceModelPreferenceController(mContext, mFragment);
         when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
                 .thenReturn(mPreference);
+        when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
     }
 
     @Test
@@ -66,4 +73,13 @@
 
         verify(mPreference).setSummary(anyString());
     }
+
+    @Test
+    public void clickPreference_shouldLaunchHardwareInfoDialog() {
+        assertThat(mController.handlePreferenceTreeClick(mPreference))
+                .isTrue();
+        verify(mFragment).getFragmentManager();
+        verify(mFragment.getFragmentManager().beginTransaction())
+                .add(any(HardwareInfoDialogFragment.class), eq(HardwareInfoDialogFragment.TAG));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java
new file mode 100644
index 0000000..e3dec76
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import android.app.Activity;
+import android.os.SystemProperties;
+import android.view.View;
+
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class HardwareInfoDialogFragmentTest {
+
+    private Activity mActivity;
+
+    @Before
+    public void setUp() {
+        mActivity = Robolectric.setupActivity(Activity.class);
+    }
+
+    @Test
+    public void display_shouldShowHardwareRevision() {
+        final String TEST_HARDWARE_REV = "123";
+        SystemProperties.set("ro.boot.hardware.revision", TEST_HARDWARE_REV);
+
+        final HardwareInfoDialogFragment fragment = spy(HardwareInfoDialogFragment.newInstance());
+        fragment.show(mActivity.getFragmentManager(), HardwareInfoDialogFragment.TAG);
+
+        verify(fragment).setText(
+                any(View.class), eq(R.id.hardware_rev_label), eq(R.id.hardware_rev_value),
+                eq(TEST_HARDWARE_REV));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
index e2a46de..9baeda3 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
@@ -15,7 +15,6 @@
  */
 package com.android.settings.deviceinfo;
 
-import android.content.Context;
 import android.os.Bundle;
 import android.os.storage.DiskInfo;
 import android.os.storage.StorageManager;
@@ -24,7 +23,6 @@
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.drawer.CategoryKey;
 
 import org.junit.Before;
@@ -46,8 +44,6 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class StorageDashboardFragmentTest {
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private StorageManager mStorageManager;
@@ -57,10 +53,6 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mFragment = new StorageDashboardFragment();
     }
 
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java
new file mode 100644
index 0000000..8da2a9c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.settings.deviceinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.util.SparseArray;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
+import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
+import com.android.settingslib.applications.StorageStatsSource;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class StorageProfileFragmentTest {
+    @Test
+    public void verifyAppSizesAreZeroedOut() {
+        StorageItemPreferenceController controller = mock(StorageItemPreferenceController.class);
+        StorageProfileFragment fragment = new StorageProfileFragment();
+        StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
+        result.musicAppsSize = 100;
+        result.otherAppsSize = 200;
+        result.gamesSize = 300;
+        result.externalStats = new StorageStatsSource.ExternalStorageStats(6, 1, 2, 3);
+        SparseArray<StorageAsyncLoader.AppsStorageResult> resultsArray = new SparseArray<>();
+        resultsArray.put(0, result);
+        fragment.setPreferenceController(controller);
+
+        fragment.onLoadFinished(null, resultsArray);
+
+        ArgumentCaptor<StorageAsyncLoader.AppsStorageResult> resultCaptor = ArgumentCaptor.forClass(
+                StorageAsyncLoader.AppsStorageResult.class);
+        verify(controller).onLoadFinished(resultCaptor.capture());
+
+        StorageAsyncLoader.AppsStorageResult extractedResult = resultCaptor.getValue();
+        assertThat(extractedResult.musicAppsSize).isEqualTo(0);
+        assertThat(extractedResult.otherAppsSize).isEqualTo(0);
+        assertThat(extractedResult.gamesSize).isEqualTo(0);
+        assertThat(extractedResult.externalStats.audioBytes).isEqualTo(1);
+        assertThat(extractedResult.externalStats.videoBytes).isEqualTo(2);
+        assertThat(extractedResult.externalStats.imageBytes).isEqualTo(3);
+        assertThat(extractedResult.externalStats.totalBytes).isEqualTo(6);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
index 7222f53..c8f3069 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
@@ -55,6 +55,10 @@
     private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users";
     @Mock
     private UserManagerWrapper mUserManager;
+    @Mock
+    private PreferenceScreen mScreen;
+    @Mock
+    private PreferenceGroup mGroup;
 
     private Context mContext;
     private SecondaryUserController mController;
@@ -66,19 +70,19 @@
         mContext = RuntimeEnvironment.application;
         mPrimaryUser = new UserInfo();
         mController = new SecondaryUserController(mContext, mPrimaryUser);
+
+        when(mScreen.getContext()).thenReturn(mContext);
+        when(mScreen.findPreference(anyString())).thenReturn(mGroup);
+        when(mGroup.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
     }
 
     @Test
     public void controllerAddsSecondaryUser() throws Exception {
         mPrimaryUser.name = TEST_NAME;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        PreferenceGroup group = mock(PreferenceGroup.class);
-        when(screen.findPreference(anyString())).thenReturn(group);
-        when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
 
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(group).addPreference(argumentCaptor.capture());
+        verify(mGroup).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
         assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
     }
@@ -86,15 +90,11 @@
     @Test
     public void controllerUpdatesSummaryOfNewPreference() throws Exception {
         mPrimaryUser.name = TEST_NAME;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        PreferenceGroup group = mock(PreferenceGroup.class);
-        when(screen.findPreference(anyString())).thenReturn(group);
-        when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
         mController.setSize(10L);
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
 
-        verify(group).addPreference(argumentCaptor.capture());
+        verify(mGroup).addPreference(argumentCaptor.capture());
 
         Preference preference = argumentCaptor.getValue();
         assertThat(preference.getSummary()).isEqualTo("10.00B");
@@ -153,11 +153,7 @@
     public void controllerUpdatesPreferenceOnAcceptingResult() throws Exception {
         mPrimaryUser.name = TEST_NAME;
         mPrimaryUser.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        PreferenceGroup group = mock(PreferenceGroup.class);
-        when(screen.findPreference(anyString())).thenReturn(group);
-        when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
         StorageAsyncLoader.AppsStorageResult userResult =
                 new StorageAsyncLoader.AppsStorageResult();
         SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
@@ -166,7 +162,7 @@
 
         mController.handleResult(result);
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(group).addPreference(argumentCaptor.capture());
+        verify(mGroup).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
         assertThat(preference.getSummary()).isEqualTo("99.00B");
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
index 2cd4f76..ed49da4 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.Intent;
@@ -53,6 +54,8 @@
 
     @Mock
     private UserManagerWrapper mUserManager;
+    @Mock
+    private PreferenceScreen mScreen;
 
     private Context mContext;
     private UserProfileController mController;
@@ -64,17 +67,17 @@
         mContext = spy(RuntimeEnvironment.application);
         mPrimaryProfile = new UserInfo();
         mController = new UserProfileController(mContext, mPrimaryProfile, 0);
+        when(mScreen.getContext()).thenReturn(mContext);
     }
 
     @Test
     public void controllerAddsPrimaryProfilePreference() throws Exception {
         mPrimaryProfile.name = TEST_NAME;
         mPrimaryProfile.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
 
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(screen).addPreference(argumentCaptor.capture());
+        verify(mScreen).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
         assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
@@ -85,11 +88,10 @@
     public void tappingProfilePreferenceSendsToStorageProfileFragment() throws Exception {
         mPrimaryProfile.name = TEST_NAME;
         mPrimaryProfile.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
 
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(screen).addPreference(argumentCaptor.capture());
+        verify(mScreen).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
         assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -105,8 +107,7 @@
     public void acceptingResultUpdatesPreferenceSize() throws Exception {
         mPrimaryProfile.name = TEST_NAME;
         mPrimaryProfile.id = 10;
-        PreferenceScreen screen = mock(PreferenceScreen.class);
-        mController.displayPreference(screen);
+        mController.displayPreference(mScreen);
         SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
         StorageAsyncLoader.AppsStorageResult userResult =
                 new StorageAsyncLoader.AppsStorageResult();
@@ -115,7 +116,7 @@
 
         mController.handleResult(result);
         final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
-        verify(screen).addPreference(argumentCaptor.capture());
+        verify(mScreen).addPreference(argumentCaptor.capture());
         Preference preference = argumentCaptor.getValue();
 
         assertThat(preference.getSummary()).isEqualTo("99.00B");
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
index 9b955e4..da9569e 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
@@ -18,12 +18,14 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.ProxyInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.text.SpannableStringBuilder;
 
 import com.android.settings.R;
@@ -46,6 +48,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.when;
 
 /**
@@ -61,11 +64,16 @@
     private final int MY_USER_ID = UserHandle.myUserId();
     private final int MANAGED_PROFILE_USER_ID = MY_USER_ID + 1;
     private final String VPN_PACKAGE_ID = "com.example.vpn";
+    private final String IME_PACKAGE_ID = "com.example.ime";
+    private final String OTHER_PACKAGE_ID = "com.example.other";
+    private final String IME_PACKAGE_LABEL = "Test IME";
 
     private List<UserInfo> mProfiles = new ArrayList();
 
+    private @Mock Context mContext;
     private @Mock DevicePolicyManagerWrapper mDevicePolicyManager;
-    private @Mock PackageManagerWrapper mPackageManager;
+    private @Mock PackageManagerWrapper mPackageManagerWrapper;
+    private @Mock PackageManager mPackageManager;
     private @Mock UserManager mUserManager;
     private @Mock ConnectivityManagerWrapper mConnectivityManger;
     private Resources mResources;
@@ -76,14 +84,14 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
-                .thenReturn(true);
+        when(mContext.getApplicationContext()).thenReturn(mContext);
+        resetAndInitializePackageManagerWrapper();
         when(mUserManager.getProfiles(MY_USER_ID)).thenReturn(mProfiles);
         mProfiles.add(new UserInfo(MY_USER_ID, "", "", 0 /* flags */));
         mResources = ShadowApplication.getInstance().getApplicationContext().getResources();
 
-        mProvider = new EnterprisePrivacyFeatureProviderImpl(mDevicePolicyManager, mPackageManager,
-                mUserManager, mConnectivityManger, mResources);
+        mProvider = new EnterprisePrivacyFeatureProviderImpl(mContext, mDevicePolicyManager,
+                mPackageManagerWrapper, mUserManager, mConnectivityManger, mResources);
     }
 
     @Test
@@ -106,28 +114,26 @@
 
     @Test
     public void testGetDeviceOwnerDisclosure() {
-        final Context context = mock(Context.class);
-
         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(null);
-        assertThat(mProvider.getDeviceOwnerDisclosure(context)).isNull();
+        assertThat(mProvider.getDeviceOwnerDisclosure()).isNull();
 
         SpannableStringBuilder disclosure = new SpannableStringBuilder();
         disclosure.append(mResources.getString(R.string.do_disclosure_generic));
         disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
         disclosure.append(mResources.getString(R.string.do_disclosure_learn_more),
-                new EnterprisePrivacyFeatureProviderImpl.EnterprisePrivacySpan(context), 0);
+                new EnterprisePrivacyFeatureProviderImpl.EnterprisePrivacySpan(mContext), 0);
         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(OWNER);
         when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(null);
-        assertThat(mProvider.getDeviceOwnerDisclosure(context)).isEqualTo(disclosure);
+        assertThat(mProvider.getDeviceOwnerDisclosure()).isEqualTo(disclosure);
 
         disclosure = new SpannableStringBuilder();
         disclosure.append(mResources.getString(R.string.do_disclosure_with_name,
                 OWNER_ORGANIZATION));
         disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
         disclosure.append(mResources.getString(R.string.do_disclosure_learn_more),
-                new EnterprisePrivacyFeatureProviderImpl.EnterprisePrivacySpan(context), 0);
+                new EnterprisePrivacyFeatureProviderImpl.EnterprisePrivacySpan(mContext), 0);
         when(mDevicePolicyManager.getDeviceOwnerOrganizationName()).thenReturn(OWNER_ORGANIZATION);
-        assertThat(mProvider.getDeviceOwnerDisclosure(context)).isEqualTo(disclosure);
+        assertThat(mProvider.getDeviceOwnerDisclosure()).isEqualTo(disclosure);
     }
 
     @Test
@@ -217,4 +223,43 @@
         mProfiles.add(new UserInfo(MANAGED_PROFILE_USER_ID, "", "", UserInfo.FLAG_MANAGED_PROFILE));
         assertThat(mProvider.getMaximumFailedPasswordsBeforeWipeInManagedProfile()).isEqualTo(10);
     }
+
+    @Test
+    public void testGetImeLabelIfOwnerSet() throws Exception {
+        final ApplicationInfo applicationInfo = mock(ApplicationInfo.class);
+        when(applicationInfo.loadLabel(mPackageManager)).thenReturn(IME_PACKAGE_LABEL);
+
+        Settings.Secure.putString(null, Settings.Secure.DEFAULT_INPUT_METHOD, IME_PACKAGE_ID);
+        when(mPackageManagerWrapper.getApplicationInfoAsUser(IME_PACKAGE_ID, 0, MY_USER_ID))
+                .thenReturn(applicationInfo);
+
+        // IME not set by Device Owner.
+        when(mDevicePolicyManager.isCurrentInputMethodSetByOwner()).thenReturn(false);
+        assertThat(mProvider.getImeLabelIfOwnerSet()).isNull();
+
+        // Device Owner set IME to empty string.
+        when(mDevicePolicyManager.isCurrentInputMethodSetByOwner()).thenReturn(true);
+        Settings.Secure.putString(null, Settings.Secure.DEFAULT_INPUT_METHOD, null);
+        assertThat(mProvider.getImeLabelIfOwnerSet()).isNull();
+
+        // Device Owner set IME to nonexistent package.
+        Settings.Secure.putString(null, Settings.Secure.DEFAULT_INPUT_METHOD, IME_PACKAGE_ID);
+        when(mPackageManagerWrapper.getApplicationInfoAsUser(IME_PACKAGE_ID, 0, MY_USER_ID))
+                .thenThrow(new PackageManager.NameNotFoundException());
+        assertThat(mProvider.getImeLabelIfOwnerSet()).isNull();
+
+        // Device Owner set IME to existent package.
+        resetAndInitializePackageManagerWrapper();
+        when(mPackageManagerWrapper.getApplicationInfoAsUser(IME_PACKAGE_ID, 0, MY_USER_ID))
+                .thenReturn(applicationInfo);
+        assertThat(mProvider.getImeLabelIfOwnerSet()).isEqualTo(IME_PACKAGE_LABEL);
+    }
+
+    private void resetAndInitializePackageManagerWrapper() {
+        reset(mPackageManagerWrapper);
+        when(mPackageManagerWrapper.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
+                .thenReturn(true);
+        when(mPackageManagerWrapper.getPackageManager()).thenReturn(mPackageManager);
+
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index 6c062ae..f74c63a 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -73,7 +73,7 @@
         final List<PreferenceController> controllers = mSettings.getPreferenceControllers(
                 ShadowApplication.getInstance().getApplicationContext());
         assertThat(controllers).isNotNull();
-        assertThat(controllers.size()).isEqualTo(14);
+        assertThat(controllers.size()).isEqualTo(15);
         assertThat(controllers.get(0)).isInstanceOf(InstalledPackagesPreferenceController.class);
         assertThat(controllers.get(1)).isInstanceOf(NetworkLogsPreferenceController.class);
         assertThat(controllers.get(2)).isInstanceOf(BugReportsPreferenceController.class);
@@ -95,5 +95,6 @@
         assertThat(controllers.get(11)).isInstanceOf(GlobalHttpProxyPreferenceController.class);
         assertThat(controllers.get(12)).isInstanceOf(FailedPasswordWipePrimaryUserPreferenceController.class);
         assertThat(controllers.get(13)).isInstanceOf(FailedPasswordWipeManagedProfilePreferenceController.class);
+        assertThat(controllers.get(14)).isInstanceOf(ImePreferenceController.class);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/enterprise/ImePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/ImePreferenceControllerTest.java
new file mode 100644
index 0000000..232a872
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/ImePreferenceControllerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.enterprise;
+
+import android.content.Context;
+import android.content.res.Resources;
+import com.android.settings.R;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link ImePreferenceController}.
+ */
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class ImePreferenceControllerTest {
+
+    private final String DEFAULT_IME_LABEL = "Test IME";
+    private final String DEFAULT_IME_TEXT = "IME set to Test IME";
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    private FakeFeatureFactory mFeatureFactory;
+
+    private ImePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+        mController = new ImePreferenceController(mContext);
+        when(mContext.getResources().getString(R.string.enterprise_privacy_input_method,
+                DEFAULT_IME_LABEL)).thenReturn(DEFAULT_IME_TEXT);
+    }
+
+    @Test
+    public void testUpdateState() {
+        final Preference preference = new Preference(mContext, null, 0, 0);
+        preference.setVisible(true);
+
+        when(mFeatureFactory.enterprisePrivacyFeatureProvider.getImeLabelIfOwnerSet())
+            .thenReturn(null);
+        mController.updateState(preference);
+        assertThat(preference.isVisible()).isFalse();
+
+        when(mFeatureFactory.enterprisePrivacyFeatureProvider.getImeLabelIfOwnerSet())
+            .thenReturn(DEFAULT_IME_LABEL);
+        mController.updateState(preference);
+        assertThat(preference.isVisible()).isTrue();
+        assertThat(preference.getTitle()).isEqualTo(DEFAULT_IME_TEXT);
+    }
+
+    @Test
+    public void testIsAvailable() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick() {
+        assertThat(mController.handlePreferenceTreeClick(new Preference(mContext, null, 0, 0)))
+                .isFalse();
+    }
+
+    @Test
+    public void testGetPreferenceKey() {
+        assertThat(mController.getPreferenceKey()).isEqualTo("input_method");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
index 285a393..4efc822 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
@@ -23,12 +23,10 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.core.PreferenceController;
-import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
@@ -42,17 +40,13 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class AssistGestureSettingsTest {
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    @Mock
     private Context mContext;
     private AssistGestureSettings mSettings;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mSettings = new AssistGestureSettings();
     }
 
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java
index b5fdfea..f8c3367 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java
@@ -16,43 +16,29 @@
 
 package com.android.settings.gestures;
 
-import android.content.Context;
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
 import java.util.List;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class DoubleTapPowerSettingsTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
     private DoubleTapPowerSettings mSettings;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mSettings = new DoubleTapPowerSettings();
     }
 
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenSettingsTest.java
index c0aac43..433ba46 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenSettingsTest.java
@@ -16,43 +16,29 @@
 
 package com.android.settings.gestures;
 
-import android.content.Context;
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
 import java.util.List;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class DoubleTapScreenSettingsTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
     private DoubleTapScreenSettings mSettings;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mSettings = new DoubleTapScreenSettings();
     }
 
diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTwistGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTwistGestureSettingsTest.java
index f2a56d7..35c48ec 100644
--- a/tests/robotests/src/com/android/settings/gestures/DoubleTwistGestureSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/DoubleTwistGestureSettingsTest.java
@@ -16,19 +16,14 @@
 
 package com.android.settings.gestures;
 
-import android.content.Context;
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
@@ -40,18 +35,11 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class DoubleTwistGestureSettingsTest {
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
 
     private DoubleTwistGestureSettings mSettings;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mSettings = new DoubleTwistGestureSettings();
     }
 
diff --git a/tests/robotests/src/com/android/settings/gestures/PickupGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/PickupGestureSettingsTest.java
index cf08836..921a1be 100644
--- a/tests/robotests/src/com/android/settings/gestures/PickupGestureSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/PickupGestureSettingsTest.java
@@ -16,19 +16,14 @@
 
 package com.android.settings.gestures;
 
-import android.content.Context;
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
@@ -41,18 +36,10 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class PickupGestureSettingsTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
     private PickupGestureSettings mSettings;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mSettings = new PickupGestureSettings();
     }
 
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationSettingsTest.java
index b9f3bac..78dc27ac 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationSettingsTest.java
@@ -23,12 +23,10 @@
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
 import com.android.settings.core.PreferenceController;
-import com.android.settings.testutils.FakeFeatureFactory;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
@@ -43,17 +41,13 @@
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SwipeToNotificationSettingsTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    @Mock
     private Context mContext;
     private SwipeToNotificationSettings mFragment;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mFragment = new SwipeToNotificationSettings();
     }
 
diff --git a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
index 7626ec4..2201c68 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
@@ -15,21 +15,16 @@
  */
 package com.android.settings.network;
 
-import android.content.Context;
 import android.provider.SearchIndexableResource;
 import android.view.Menu;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.drawer.CategoryKey;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.util.ReflectionHelpers;
@@ -40,24 +35,15 @@
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class NetworkDashboardFragmentTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
     private NetworkDashboardFragment mFragment;
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        FakeFeatureFactory.setupForTest(mContext);
-        final FakeFeatureFactory factory =
-                (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
-        when(factory.dashboardFeatureProvider.isEnabled()).thenReturn(true);
         mFragment = new NetworkDashboardFragment();
     }