Merge "Add modify button to WifiNetworkDetailsFragment."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7702257..46c6490 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1934,6 +1934,32 @@
                 android:value="true" />
         </activity>
 
+        <activity android:name="Settings$DevelopmentSettingsDashboardActivity"
+                  android:label="@string/development_settings_title"
+                  android:icon="@drawable/ic_settings_development"
+                  android:taskAffinity="com.android.settings"
+                  android:parentActivityName="Settings">
+
+            <!-- Enable when deleting DevelopmentSettingsActivity
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
+                <action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            -->
+            <intent-filter android:priority="50">
+                <action android:name="com.android.settings.action.SETTINGS" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.system" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/summary_empty"/>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.development.DevelopmentSettingsDashboardFragment" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity>
+
         <!-- The opposite of DevelopmentSettingsActivity, it's no-op and only enabled when the real
              activity is disabled to be CTS compliant. -->
         <activity
diff --git a/res/layout-land/choose_lock_pattern.xml b/res/layout-land/choose_lock_pattern.xml
index 0743577..8e78b05 100644
--- a/res/layout-land/choose_lock_pattern.xml
+++ b/res/layout-land/choose_lock_pattern.xml
@@ -138,10 +138,12 @@
         </LinearLayout>
 
         <!-- right side: lock pattern -->
-        <FrameLayout
+        <com.android.setupwizardlib.view.FillContentLayout
+            style="@style/LockPatternContainerStyle"
             android:layout_width="0dp"
             android:layout_height="match_parent"
-            android:layout_weight="1.0">
+            android:layout_weight="1.0"
+            android:paddingStart="0dp">
 
             <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
                 android:layout_width="match_parent"
@@ -149,7 +151,7 @@
                 android:layout_gravity="center"
                 android:background="@color/lock_pattern_background" />
 
-        </FrameLayout>
+        </com.android.setupwizardlib.view.FillContentLayout>
 
     </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
 
diff --git a/res/layout-land/confirm_lock_pattern_internal.xml b/res/layout-land/confirm_lock_pattern_internal.xml
index 4e58f32..952ab49 100644
--- a/res/layout-land/confirm_lock_pattern_internal.xml
+++ b/res/layout-land/confirm_lock_pattern_internal.xml
@@ -96,10 +96,12 @@
 
         </ScrollView>
 
-        <FrameLayout
+        <com.android.setupwizardlib.view.FillContentLayout
+            style="@style/LockPatternContainerStyle"
             android:layout_width="0dp"
             android:layout_height="match_parent"
-            android:layout_weight="1">
+            android:layout_weight="1"
+            android:paddingStart="0dp">
 
             <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
                 android:layout_width="match_parent"
@@ -107,7 +109,7 @@
                 android:layout_gravity="center"
                 android:background="@color/lock_pattern_background" />
 
-        </FrameLayout>
+        </com.android.setupwizardlib.view.FillContentLayout>
 
     </com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient>
 </com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/choose_lock_pattern_common.xml b/res/layout/choose_lock_pattern_common.xml
index 3ea960d..7dca27d 100644
--- a/res/layout/choose_lock_pattern_common.xml
+++ b/res/layout/choose_lock_pattern_common.xml
@@ -64,19 +64,31 @@
             android:gravity="center"
             android:clipChildren="false"
             android:clipToPadding="false"
-            android:orientation="vertical">
+            android:orientation="vertical"
+            android:paddingLeft="0dp"
+            android:paddingRight="0dp">
 
             <TextView android:id="@+id/headerText"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:minLines="2"
                 android:gravity="center"
+                android:paddingHorizontal="?attr/suwMarginSides"
                 android:textSize="18sp" />
 
-            <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
-                android:layout_width="match_parent"
-                android:layout_height="0dip"
-                android:layout_weight="1" />
+            <com.android.setupwizardlib.view.FillContentLayout
+                style="@style/LockPatternContainerStyle"
+                android:layout_width="wrap_content"
+                android:layout_height="0dp"
+                android:layout_weight="1">
+
+                <com.android.internal.widget.LockPatternView
+                    android:id="@+id/lockPattern"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_gravity="center" />
+
+            </com.android.setupwizardlib.view.FillContentLayout>
 
         </LinearLayout>
 
diff --git a/res/layout/confirm_lock_pattern_internal_base.xml b/res/layout/confirm_lock_pattern_internal_base.xml
index 5109632..d0ce769 100644
--- a/res/layout/confirm_lock_pattern_internal_base.xml
+++ b/res/layout/confirm_lock_pattern_internal_base.xml
@@ -61,14 +61,23 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:gravity="center">
+            android:gravity="center"
+            android:paddingLeft="0dp"
+            android:paddingRight="0dp">
 
-            <com.android.internal.widget.LockPatternView
-                android:id="@+id/lockPattern"
-                android:layout_width="match_parent"
+            <com.android.setupwizardlib.view.FillContentLayout
+                style="@style/LockPatternContainerStyle"
+                android:layout_width="wrap_content"
                 android:layout_height="0dp"
-                android:layout_weight="4"
-                android:layout_gravity="center_horizontal"/>
+                android:layout_weight="1">
+
+                <com.android.internal.widget.LockPatternView
+                    android:id="@+id/lockPattern"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_gravity="center" />
+
+            </com.android.setupwizardlib.view.FillContentLayout>
 
             <TextView
                 style="@style/TextAppearance.ConfirmDeviceCredentialsErrorText"
@@ -77,9 +86,8 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal"
+                android:layout_marginHorizontal="?attr/suwMarginSides"
                 android:layout_marginTop="12dp"
-                android:layout_marginStart="12dp"
-                android:layout_marginEnd="12dp"
                 android:gravity="center_vertical"/>
 
             <ImageView
@@ -87,6 +95,7 @@
                 android:layout_gravity="center_horizontal"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_marginHorizontal="?attr/suwMarginSides"
                 android:layout_marginBottom="24dp"
                 android:contentDescription="@string/confirm_fingerprint_icon_content_description"
                 android:visibility="gone"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fcc0b6d..c58f6bb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4630,6 +4630,12 @@
     <string name="background_activity_summary_off">App\'s background activity is limited when not in use</string>
     <!-- Summary for the background activity when it is disabled [CHAR_LIMIT=120] -->
     <string name="background_activity_summary_disabled">App not allowed to run in background</string>
+    <!-- TODO: Pending UX review. Summary for the background activity when it is whitlisted [CHAR_LIMIT=120] -->
+    <string name="background_activity_summary_whitelisted">App can not be optimized for battery use</string>
+    <!-- TODO: Pending UX review. Title for the warning dialog to show to the user when limiting background activity for an app -->
+    <string name="background_activity_warning_dialog_title">Limit background activity?</string>
+    <!-- TODO: Pending UX review. Text for the warning dialog to show to the user when limiting background activity for an app -->
+    <string name="background_activity_warning_dialog_text">If you limit background activity for an app, it may misbehave</string>
 
     <!-- Title for the screen usage in power use UI [CHAR_LIMIT=60] -->
     <string name="device_screen_usage">Screen usage since full charge</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a3bfcdf..fe92e6d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -427,6 +427,16 @@
 
     <style name="DreamStartButton" parent="android:Widget.Material.Button" />
 
+    <style name="LockPatternContainerStyle">
+        <item name="android:maxHeight">400dp</item>
+        <item name="android:maxWidth">420dp</item>
+        <item name="android:minHeight">0dp</item>
+        <item name="android:minWidth">0dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:paddingHorizontal">44dp</item>
+        <item name="android:paddingTop">0dp</item>
+    </style>
+
     <style name="LockPatternStyle">
         <item name="*android:regularColor">@color/lock_pattern_view_regular_color</item>
         <item name="*android:successColor">@color/lock_pattern_view_success_color</item>
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 1ec4284..cd479a5 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -17,6 +17,7 @@
 package com.android.settings;
 
 import android.os.Bundle;
+import android.util.FeatureFlagUtils;
 
 import com.android.settings.applications.AppOpsSummary;
 import com.android.settings.enterprise.EnterprisePrivacySettings;
@@ -70,7 +71,17 @@
     }
     public static class BackgroundCheckSummaryActivity extends SettingsActivity { /* empty */ }
     public static class StorageUseActivity extends SettingsActivity { /* empty */ }
+
+    /**
+     * @deprecated in favor of {@link DevelopmentSettingsDashboardActivity}.
+     */
+    @Deprecated
     public static class DevelopmentSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class DevelopmentSettingsDashboardActivity extends SettingsActivity {
+        public static final boolean isEnabled() {
+            return FeatureFlagUtils.isEnabled("dev_option_v2");
+        }
+    }
     public static class AccessibilitySettingsActivity extends SettingsActivity { /* empty */ }
     public static class CaptioningSettingsActivity extends SettingsActivity { /* empty */ }
     public static class AccessibilityInversionSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index f9b849e..c927889 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -50,6 +50,7 @@
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.Toolbar;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.settings.Settings.WifiSettingsActivity;
 import com.android.settings.backup.BackupSettingsActivity;
@@ -58,7 +59,6 @@
 import com.android.settings.core.instrumentation.SharedPreferencesLogger;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.DashboardSummary;
-import com.android.settings.development.DevelopmentSettings;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.SearchActivity;
 import com.android.settings.wfd.WifiDisplaySettings;
@@ -66,6 +66,7 @@
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.SettingsDrawerActivity;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -831,9 +832,16 @@
 
         final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)
                 && !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
+        final boolean useDevOptionV2 = Settings.DevelopmentSettingsDashboardActivity.isEnabled();
+        // Enable old Dev option if v2 is disabled
         somethingChanged = setTileEnabled(new ComponentName(packageName,
                         Settings.DevelopmentSettingsActivity.class.getName()),
-                showDev, isAdmin)
+                showDev && !useDevOptionV2, isAdmin)
+                || somethingChanged;
+        // Enable new Dev option if v2 is enable
+        somethingChanged = setTileEnabled(new ComponentName(packageName,
+                        Settings.DevelopmentSettingsDashboardActivity.class.getName()),
+                showDev && useDevOptionV2, isAdmin)
                 || somethingChanged;
 
         // Enable/disable backup settings depending on whether the user is admin.
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index a03314c..884696c 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -66,6 +66,7 @@
 import com.android.settings.datausage.DataUsageSummary;
 import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
 import com.android.settings.development.DevelopmentSettings;
+import com.android.settings.development.DevelopmentSettingsDashboardFragment;
 import com.android.settings.deviceinfo.ImeiInformation;
 import com.android.settings.deviceinfo.PrivateVolumeForget;
 import com.android.settings.deviceinfo.PrivateVolumeSettings;
@@ -177,6 +178,7 @@
             PrivateVolumeSettings.class.getName(),
             PublicVolumeSettings.class.getName(),
             DevelopmentSettings.class.getName(),
+            DevelopmentSettingsDashboardFragment.class.getName(),
             AndroidBeam.class.getName(),
             WifiDisplaySettings.class.getName(),
             PowerUsageSummary.class.getName(),
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index b920850..53a51cd 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -230,6 +230,9 @@
 
     @VisibleForTesting
     boolean tintTileIcon(Tile tile) {
+        if (tile.icon == null) {
+            return false;
+        }
         // First check if the tile has set the icon tintable metadata.
         final Bundle metadata = tile.metaData;
         if (metadata != null
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index fddd522..17e556e 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -20,12 +20,14 @@
 
 import com.android.settings.DisplaySettings;
 import com.android.settings.SecuritySettings;
+import com.android.settings.Settings;
 import com.android.settings.accounts.AccountDetailDashboardFragment;
 import com.android.settings.accounts.UserAndAccountDashboardFragment;
 import com.android.settings.applications.AppAndNotificationDashboardFragment;
 import com.android.settings.applications.DefaultAppSettings;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.development.DevelopmentSettings;
+import com.android.settings.development.DevelopmentSettingsDashboardFragment;
 import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.language.LanguageAndInputSettings;
@@ -83,8 +85,13 @@
                 SystemDashboardFragment.class.getName(), CategoryKey.CATEGORY_SYSTEM);
         PARENT_TO_CATEGORY_KEY_MAP.put(LanguageAndInputSettings.class.getName(),
                 CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
-        PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
-                CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
+        if (Settings.DevelopmentSettingsDashboardActivity.isEnabled()) {
+            PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettingsDashboardFragment.class.getName(),
+                    CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
+        } else {
+            PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
+                    CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
+        }
         PARENT_TO_CATEGORY_KEY_MAP.put(ConfigureNotificationSettings.class.getName(),
                 CategoryKey.CATEGORY_NOTIFICATIONS);
         PARENT_TO_CATEGORY_KEY_MAP.put(LockscreenDashboardFragment.class.getName(),
diff --git a/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceController.java b/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceController.java
new file mode 100644
index 0000000..261f66c
--- /dev/null
+++ b/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceController.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * <p>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
+ *
+ * <p>http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * <p>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.deletionhelper;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+/**
+ * Handles the wall of text which appears below the options in the Storage Management settings drill
+ * down.
+ */
+public class AutomaticStorageManagerDescriptionPreferenceController
+        extends AbstractPreferenceController implements PreferenceControllerMixin {
+    private static final String KEY_FREED = "freed_bytes";
+
+    public AutomaticStorageManagerDescriptionPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_FREED;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        Preference preference = screen.findPreference(getPreferenceKey());
+        final Context context = preference.getContext();
+        ContentResolver cr = context.getContentResolver();
+        long freedBytes =
+                Settings.Secure.getLong(
+                        cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED, 0);
+        long lastRunMillis =
+                Settings.Secure.getLong(cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN, 0);
+        if (freedBytes == 0 || lastRunMillis == 0 || !isStorageManagerEnabled(cr)) {
+            preference.setSummary(R.string.automatic_storage_manager_text);
+        } else {
+            preference.setSummary(
+                    context.getString(
+                            R.string.automatic_storage_manager_freed_bytes,
+                            Formatter.formatFileSize(context, freedBytes),
+                            DateUtils.formatDateTime(
+                                    context, lastRunMillis, DateUtils.FORMAT_SHOW_DATE)));
+        }
+    }
+
+    private boolean isStorageManagerEnabled(ContentResolver cr) {
+        return Settings.Secure.getInt(cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0)
+                != 0;
+    }
+}
diff --git a/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
index f7b62b1..e38317a 100644
--- a/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
+++ b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
@@ -16,15 +16,13 @@
 
 package com.android.settings.deletionhelper;
 
-import android.app.Activity;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.support.v7.preference.DropDownPreference;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.text.format.DateUtils;
-import android.text.format.Formatter;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -32,39 +30,34 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
-import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
 import com.android.settings.widget.SwitchBar;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * AutomaticStorageManagerSettings is the Settings screen for configuration and management of the
  * automatic storage manager.
  */
-public class AutomaticStorageManagerSettings extends SettingsPreferenceFragment
+public class AutomaticStorageManagerSettings extends DashboardFragment
         implements OnPreferenceChangeListener {
     private static final String KEY_DAYS = "days";
-    private static final String KEY_FREED = "freed_bytes";
-    private static final String STORAGE_MANAGER_ENABLED_BY_DEFAULT_PROPERTY =
-            "ro.storage_manager.enabled";
 
     private AutomaticStorageManagerSwitchBarController mSwitchController;
     private DropDownPreference mDaysToRetain;
-    private Preference mFreedBytes;
     private SwitchBar mSwitchBar;
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        addPreferencesFromResource(R.xml.automatic_storage_management_settings);
-    }
-
-    @Override
     public View onCreateView(
             LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         View view = super.onCreateView(inflater, container, savedInstanceState);
 
         initializeDaysToRetainPreference();
-        initializeFreedBytesPreference();
         initializeSwitchBar();
 
         return view;
@@ -98,35 +91,25 @@
                         getFragmentManager());
     }
 
-    private void initializeFreedBytesPreference() {
-        ContentResolver cr = getContentResolver();
-        mFreedBytes = findPreference(KEY_FREED);
-        long freedBytes = Settings.Secure.getLong(cr,
-                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
-                0);
-        long lastRunMillis = Settings.Secure.getLong(cr,
-                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
-                0);
-        if (freedBytes == 0 || lastRunMillis == 0) {
-            mFreedBytes.setVisible(false);
-        } else {
-            final Activity activity = getActivity();
-            mFreedBytes.setSummary(
-                    activity.getString(
-                            R.string.automatic_storage_manager_freed_bytes,
-                            Formatter.formatFileSize(activity, freedBytes),
-                            DateUtils.formatDateTime(
-                                    activity, lastRunMillis, DateUtils.FORMAT_SHOW_DATE)));
-        }
-    }
-
     @Override
     public void onResume() {
         super.onResume();
-        boolean isStorageManagerChecked =
-                Settings.Secure.getInt(getContentResolver(),
-                        Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0) != 0;
-        mDaysToRetain.setEnabled(isStorageManagerChecked);
+        mDaysToRetain.setEnabled(isStorageManagerEnabled());
+    }
+
+    @Override
+    protected String getLogTag() {
+        return null;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.automatic_storage_management_settings;
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
+        return buildPreferenceControllers(context);
     }
 
     @Override
@@ -168,4 +151,30 @@
         return indices.length - 1;
     }
 
+    private boolean isStorageManagerEnabled() {
+        return Settings.Secure.getInt(
+                        getContentResolver(), Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0)
+                != 0;
+    }
+
+    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        controllers.add(new AutomaticStorageManagerDescriptionPreferenceController(context));
+        return controllers;
+    }
+
+    /** For Search. */
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return false;
+                }
+
+                @Override
+                public List<AbstractPreferenceController> getPreferenceControllers(
+                        Context context) {
+                    return buildPreferenceControllers(context);
+                }
+            };
 }
diff --git a/src/com/android/settings/development/DevelopmentSettings.java b/src/com/android/settings/development/DevelopmentSettings.java
index 3759ea1..3115dc4 100644
--- a/src/com/android/settings/development/DevelopmentSettings.java
+++ b/src/com/android/settings/development/DevelopmentSettings.java
@@ -110,7 +110,9 @@
 
 /*
  * Displays preferences for application developers.
+ * @deprecated in favor of {@link DevelopmentSettingsDashboardFragment}
  */
+@Deprecated
 public class DevelopmentSettings extends RestrictedSettingsFragment
         implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
         OnPreferenceChangeListener, SwitchBar.OnSwitchChangeListener, Indexable {
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
new file mode 100644
index 0000000..30be654
--- /dev/null
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -0,0 +1,102 @@
+/*
+ * 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.development;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.provider.SearchIndexableResource;
+import android.util.Log;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.widget.SwitchBar;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment {
+
+    private static final String TAG = "DevSettingsDashboard";
+
+    private SwitchBar mSwitchBar;
+
+    public DevelopmentSettingsDashboardFragment() {
+        super(UserManager.DISALLOW_DEBUGGING_FEATURES);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.DEVELOPMENT;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getHelpResource() {
+        return 0;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        Log.d(TAG, "Creating pref screen");
+        return R.xml.development_prefs;
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
+        return buildPreferenceControllers(context);
+    }
+
+    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
+        return null;
+    }
+
+    /**
+     * For Search.
+     */
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
+                }
+
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(
+                        Context context, boolean enabled) {
+
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.development_prefs;
+                    return Arrays.asList(sir);
+                }
+
+                @Override
+                public List<AbstractPreferenceController> getPreferenceControllers(Context
+                        context) {
+                    return buildPreferenceControllers(context);
+                }
+            };
+}
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
index 59907cf..5656a27 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -32,6 +32,7 @@
 import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
 import com.android.settings.password.SetupChooseLockGeneric;
 import com.android.settings.password.SetupSkipDialog;
+import com.android.settings.password.StorageManagerWrapper;
 
 public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
     private static final String KEY_LOCK_SCREEN_PRESENT = "wasLockScreenPresent";
@@ -56,11 +57,14 @@
 
     @Override
     protected Intent getChooseLockIntent() {
-        Intent intent = new Intent(this, SetupChooseLockGeneric.class)
-                .putExtra(
-                        LockPatternUtils.PASSWORD_TYPE_KEY,
-                        DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
-        intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+        Intent intent = new Intent(this, SetupChooseLockGeneric.class);
+
+        if (StorageManagerWrapper.isFileEncryptedNativeOrEmulated()) {
+            intent.putExtra(
+                    LockPatternUtils.PASSWORD_TYPE_KEY,
+                    DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
+            intent.putExtra(ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, true);
+        }
         SetupWizardUtils.copySetupExtras(getIntent(), intent);
         return intent;
     }
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 0142e62..66a0ca2 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -68,7 +68,8 @@
 public class AdvancedPowerUsageDetail extends DashboardFragment implements
         ButtonActionDialogFragment.AppButtonsDialogListener,
         AnomalyDialogFragment.AnomalyDialogListener,
-        LoaderManager.LoaderCallbacks<List<Anomaly>> {
+        LoaderManager.LoaderCallbacks<List<Anomaly>>,
+        BackgroundActivityPreferenceController.WarningConfirmationListener {
 
     public static final String TAG = "AdvancedPowerUsageDetail";
     public static final String EXTRA_UID = "extra_uid";
@@ -109,6 +110,7 @@
     @VisibleForTesting
     AnomalySummaryPreferenceController mAnomalySummaryPreferenceController;
     private AppButtonsPreferenceController mAppButtonsPreferenceController;
+    private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;
 
     private DevicePolicyManagerWrapper mDpm;
     private UserManager mUserManager;
@@ -319,7 +321,9 @@
         final int uid = bundle.getInt(EXTRA_UID, 0);
         final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
 
-        controllers.add(new BackgroundActivityPreferenceController(context, uid));
+        mBackgroundActivityPreferenceController = new BackgroundActivityPreferenceController(
+                context, this, uid, packageName);
+        controllers.add(mBackgroundActivityPreferenceController);
         controllers.add(new BatteryOptimizationPreferenceController(
                 (SettingsActivity) getActivity(), this, packageName));
         mAppButtonsPreferenceController = new AppButtonsPreferenceController(
@@ -364,4 +368,10 @@
     public void onLoaderReset(Loader<List<Anomaly>> loader) {
 
     }
+
+    @Override
+    public void onLimitBackgroundActivity() {
+        mBackgroundActivityPreferenceController.setUnchecked(
+                findPreference(mBackgroundActivityPreferenceController.getPreferenceKey()));
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
index 4d1cf77..cea6d16 100644
--- a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
@@ -14,12 +14,17 @@
 
 package com.android.settings.fuelgauge;
 
+import android.app.AlertDialog;
 import android.app.AppOpsManager;
+import android.app.Dialog;
+import android.app.Fragment;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.UserManager;
 import android.support.annotation.VisibleForTesting;
 import android.support.v14.preference.SwitchPreference;
@@ -29,6 +34,7 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settings.enterprise.DevicePolicyManagerWrapper;
 import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -45,54 +51,72 @@
     private final PackageManager mPackageManager;
     private final AppOpsManager mAppOpsManager;
     private final UserManager mUserManager;
-    private final String[] mPackages;
     private final int mUid;
     @VisibleForTesting
     DevicePolicyManagerWrapper mDpm;
-
+    private Fragment mFragment;
     private String mTargetPackage;
+    private boolean mIsPreOApp;
+    private PowerWhitelistBackend mPowerWhitelistBackend;
 
-    public BackgroundActivityPreferenceController(Context context, int uid) {
+    public BackgroundActivityPreferenceController(Context context, Fragment fragment,
+            int uid, String packageName) {
+        this(context, fragment, uid, packageName, PowerWhitelistBackend.getInstance());
+    }
+
+    @VisibleForTesting
+    BackgroundActivityPreferenceController(Context context, Fragment fragment,
+            int uid, String packageName, PowerWhitelistBackend backend) {
         super(context);
+        mPowerWhitelistBackend = backend;
         mPackageManager = context.getPackageManager();
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mDpm = new DevicePolicyManagerWrapperImpl(
                 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE));
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         mUid = uid;
-        mPackages = mPackageManager.getPackagesForUid(mUid);
+        mFragment = fragment;
+        mTargetPackage = packageName;
+        mIsPreOApp = isLegacyApp(packageName);
     }
 
     @Override
     public void updateState(Preference preference) {
         final int mode = mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
+                .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
+        final boolean whitelisted = mPowerWhitelistBackend.isWhitelisted(mTargetPackage);
         // Set checked or not before we may set it disabled
         if (mode != AppOpsManager.MODE_ERRORED) {
-            final boolean checked = mode != AppOpsManager.MODE_IGNORED;
+            final boolean checked = whitelisted || mode != AppOpsManager.MODE_IGNORED;
             ((SwitchPreference) preference).setChecked(checked);
         }
-        if (mode == AppOpsManager.MODE_ERRORED
+        if (whitelisted || mode == AppOpsManager.MODE_ERRORED
                 || Utils.isProfileOrDeviceOwner(mUserManager, mDpm, mTargetPackage)) {
             preference.setEnabled(false);
+        } else {
+            preference.setEnabled(true);
         }
-
         updateSummary(preference);
     }
 
     @Override
     public boolean isAvailable() {
-        if (mPackages == null) {
-            return false;
-        }
-        for (final String packageName : mPackages) {
-            if (isLegacyApp(packageName)) {
-                mTargetPackage = packageName;
-                return true;
-            }
-        }
+        return mTargetPackage != null;
+    }
 
-        return false;
+    /**
+     * Called from the warning dialog, if the user decides to go ahead and disable background
+     * activity for this package
+     */
+    public void setUnchecked(Preference preference) {
+        if (mIsPreOApp) {
+            mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
+                    AppOpsManager.MODE_IGNORED);
+        }
+        mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
+                AppOpsManager.MODE_IGNORED);
+        ((SwitchPreference) preference).setChecked(false);
+        updateSummary(preference);
     }
 
     @Override
@@ -102,20 +126,24 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        boolean switchOn = (Boolean) newValue;
-        mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
-                switchOn ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
-
+        final boolean switchOn = (Boolean) newValue;
+        if (!switchOn) {
+            final WarningDialogFragment dialogFragment = new WarningDialogFragment();
+            dialogFragment.setTargetFragment(mFragment, 0);
+            dialogFragment.show(mFragment.getFragmentManager(), TAG);
+            return false;
+        }
+        if (mIsPreOApp) {
+            mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
+                    AppOpsManager.MODE_ALLOWED);
+        }
+        mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
+                AppOpsManager.MODE_ALLOWED);
         updateSummary(preference);
         return true;
     }
 
     @VisibleForTesting
-    String getTargetPackage() {
-        return mTargetPackage;
-    }
-
-    @VisibleForTesting
     boolean isLegacyApp(final String packageName) {
         try {
             ApplicationInfo info = mPackageManager.getApplicationInfo(packageName,
@@ -131,8 +159,12 @@
 
     @VisibleForTesting
     void updateSummary(Preference preference) {
+        if (mPowerWhitelistBackend.isWhitelisted(mTargetPackage)) {
+            preference.setSummary(R.string.background_activity_summary_whitelisted);
+            return;
+        }
         final int mode = mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
+                .checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage);
 
         if (mode == AppOpsManager.MODE_ERRORED) {
             preference.setSummary(R.string.background_activity_summary_disabled);
@@ -142,4 +174,37 @@
                     : R.string.background_activity_summary_off);
         }
     }
+
+    interface WarningConfirmationListener {
+        void onLimitBackgroundActivity();
+    }
+
+    /**
+     * Warning dialog to show to the user as turning off background activity can lead to
+     * apps misbehaving as their background task scheduling guarantees will no longer be honored.
+     */
+    public static class WarningDialogFragment extends InstrumentedDialogFragment {
+        @Override
+        public int getMetricsCategory() {
+            // TODO (b/65494831): add metric id
+            return 0;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            final WarningConfirmationListener listener =
+                    (WarningConfirmationListener) getTargetFragment();
+            return new AlertDialog.Builder(getContext())
+                    .setTitle(R.string.background_activity_warning_dialog_title)
+                    .setMessage(R.string.background_activity_warning_dialog_text)
+                    .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            listener.onLimitBackgroundActivity();
+                        }
+                    })
+                    .setNegativeButton(R.string.dlg_cancel, null)
+                    .create();
+        }
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index aa71252..7a18cd0 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -26,6 +26,7 @@
 import android.content.pm.UserInfo;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -47,6 +48,7 @@
     public static final int MSG_REPORT_FULLY_DRAWN = 2;
 
     private static final String TAG = "BatteryEntry";
+    private static final String PACKAGE_SYSTEM = "android";
 
     static final HashMap<String,UidToDetail> sUidCache = new HashMap<String,UidToDetail>();
 
@@ -268,9 +270,11 @@
         if (sipper.mPackages == null) {
             sipper.mPackages = pm.getPackagesForUid(uid);
         }
-        if (sipper.mPackages != null) {
-            String[] packageLabels = new String[sipper.mPackages.length];
-            System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
+
+        final String[] packages = extractPackagesFromSipper(sipper);
+        if (packages != null) {
+            String[] packageLabels = new String[packages.length];
+            System.arraycopy(packages, 0, packageLabels, 0, packages.length);
 
             // Convert package names to user-facing labels where possible
             IPackageManager ipm = AppGlobals.getPackageManager();
@@ -289,7 +293,7 @@
                         packageLabels[i] = label.toString();
                     }
                     if (ai.icon != 0) {
-                        defaultPackageName = sipper.mPackages[i];
+                        defaultPackageName = packages[i];
                         icon = ai.loadIcon(pm);
                         break;
                     }
@@ -303,7 +307,7 @@
                 name = packageLabels[0];
             } else {
                 // Look for an official name for this UID.
-                for (String pkgName : sipper.mPackages) {
+                for (String pkgName : packages) {
                     try {
                         final PackageInfo pi = ipm.getPackageInfo(pkgName, 0 /* no flags */, userId);
                         if (pi == null) {
@@ -349,4 +353,11 @@
             sHandler.sendMessage(sHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
         }
     }
+
+    String[] extractPackagesFromSipper(BatterySipper sipper) {
+        // Only use system package if uid is system uid, so it could find a consistent name and icon
+        return sipper.getUid() == Process.SYSTEM_UID
+                ? new String[]{PACKAGE_SYSTEM}
+                : sipper.mPackages;
+    }
 }
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 34e8cc3..d66b310 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -35,7 +35,6 @@
 import android.widget.Switch;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.DimmableIconPreference;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
@@ -43,6 +42,7 @@
 import com.android.settings.dashboard.SummaryLoader;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedPreference;
 import com.android.settingslib.RestrictedSwitchPreference;
 import com.android.settingslib.location.RecentLocationApps;
 
@@ -207,8 +207,8 @@
 
         List<Preference> recentLocationPrefs = new ArrayList<>(recentLocationRequests.size());
         for (final RecentLocationApps.Request request : recentLocationRequests) {
-            DimmableIconPreference pref = new DimmableIconPreference(getPrefContext(),
-                    request.contentDescription);
+            RestrictedPreference pref = new RestrictedPreference(getPrefContext());
+            pref.setSummary(request.contentDescription);
             pref.setIcon(request.icon);
             pref.setTitle(request.label);
             pref.setOnPreferenceClickListener(
diff --git a/src/com/android/settings/password/StorageManagerWrapper.java b/src/com/android/settings/password/StorageManagerWrapper.java
new file mode 100644
index 0000000..5adfaf2
--- /dev/null
+++ b/src/com/android/settings/password/StorageManagerWrapper.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.password;
+
+import android.os.storage.StorageManager;
+
+/**
+ * Wrapper class to allow Robolectric to shadow methods introduced in newer API
+ */
+public class StorageManagerWrapper {
+
+    public static boolean isFileEncryptedNativeOrEmulated() {
+        return StorageManager.isFileEncryptedNativeOrEmulated();
+    }
+}
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index d67e8eb..044a00c 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -44,6 +44,7 @@
 import com.android.settings.datausage.DataPlanUsageSummary;
 import com.android.settings.datausage.DataUsageMeteredSettings;
 import com.android.settings.datausage.DataUsageSummary;
+import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
 import com.android.settings.development.DevelopmentSettings;
 import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.deviceinfo.StorageSettings;
@@ -213,6 +214,10 @@
                 R.drawable.ic_settings_notifications);
         addIndex(DreamSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_display);
         addIndex(SupportDashboardActivity.class, NO_DATA_RES_ID, R.drawable.ic_help);
+        addIndex(
+                AutomaticStorageManagerSettings.class,
+                NO_DATA_RES_ID,
+                R.drawable.ic_settings_storage);
     }
 
     private SearchIndexableResources() {
diff --git a/src/com/android/settings/widget/ValidatedEditTextPreference.java b/src/com/android/settings/widget/ValidatedEditTextPreference.java
index 76331d4..58c62eb 100644
--- a/src/com/android/settings/widget/ValidatedEditTextPreference.java
+++ b/src/com/android/settings/widget/ValidatedEditTextPreference.java
@@ -21,8 +21,10 @@
 import android.support.annotation.VisibleForTesting;
 import android.text.Editable;
 import android.text.InputType;
+import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.widget.EditText;
 
@@ -61,17 +63,18 @@
     @Override
     protected void onBindDialogView(View view) {
         super.onBindDialogView(view);
-        if (mValidator != null) {
-            final EditText editText = view.findViewById(android.R.id.edit);
-            if (editText != null) {
-                editText.removeTextChangedListener(mTextWatcher);
-                if (mIsPassword) {
-                    editText.setInputType(
-                            InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
-                    editText.setMaxLines(1);
-                }
-                editText.addTextChangedListener(mTextWatcher);
+        final EditText editText = view.findViewById(android.R.id.edit);
+        if (editText != null && !TextUtils.isEmpty(editText.getText())) {
+            editText.setSelection(editText.getText().length());
+        }
+        if (mValidator != null && editText != null) {
+            editText.removeTextChangedListener(mTextWatcher);
+            if (mIsPassword) {
+                editText.setInputType(
+                        InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+                editText.setMaxLines(1);
             }
+            editText.addTextChangedListener(mTextWatcher);
         }
     }
 
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index fcdd0d2..014fb0f 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -464,9 +464,8 @@
             }
         }
 
-        // Find IPv4 DNS addresses.
+        // Find all (IPv4 and IPv6) DNS addresses.
         String dnsServers = mLinkProperties.getDnsServers().stream()
-                .filter(Inet4Address.class::isInstance)
                 .map(InetAddress::getHostAddress)
                 .collect(Collectors.joining("\n"));
 
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index a08536a..e38064a 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -64,7 +64,6 @@
 com.android.settings.deviceinfo.PrivateVolumeSettings
 com.android.settings.users.AppRestrictionsFragment
 com.android.settings.deviceinfo.PrivateVolumeUnmount
-com.android.settings.deletionhelper.AutomaticStorageManagerSettings
 com.android.settings.notification.ZenAccessSettings
 com.android.settings.accessibility.ToggleFontSizePreferenceFragment
 com.android.settings.applications.PremiumSmsAccess
diff --git a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
index 948b14a..a2a772b 100644
--- a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
+++ b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
@@ -1 +1,2 @@
+com.android.settings.development.DevelopmentSettingsDashboardFragment
 com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard
diff --git a/tests/robotests/src/android/util/FeatureFlagUtils.java b/tests/robotests/src/android/util/FeatureFlagUtils.java
new file mode 100644
index 0000000..6bc0557
--- /dev/null
+++ b/tests/robotests/src/android/util/FeatureFlagUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.os.SystemProperties;
+import android.text.TextUtils;
+
+/**
+ * This class is only needed to get around Robolectric issue.
+ */
+public class FeatureFlagUtils {
+    public static final String FFLAG_PREFIX = "sys.fflag.";
+    public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override.";
+
+    /**
+     * Whether or not a flag is enabled.
+     *
+     * @param feature the flag name
+     * @return true if the flag is enabled (either by default in system, or override by user)
+     */
+    public static boolean isEnabled(String feature) {
+        // Tries to get feature flag from system property.
+        // Step 1: check if feature flag has any override. Flag name: sys.fflag.override.<feature>
+        String value = SystemProperties.get(FFLAG_OVERRIDE_PREFIX + feature);
+        if (!TextUtils.isEmpty(value)) {
+            return Boolean.parseBoolean(value);
+        }
+        // Step 2: check if feature flag has any default value. Flag name: sys.fflag.<feature>
+        value = SystemProperties.get(FFLAG_PREFIX + feature);
+        return Boolean.parseBoolean(value);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index 2687714..ea160dd 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -27,6 +27,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceManager;
@@ -158,6 +159,7 @@
     @Test
     public void tintTileIcon_hasMetadata_shouldReturnIconTintableMetadata() {
         final Tile tile = new Tile();
+        tile.icon = mock(Icon.class);
         final Bundle metaData = new Bundle();
         tile.metaData = metaData;
 
@@ -168,10 +170,19 @@
         assertThat(mTestFragment.tintTileIcon(tile)).isTrue();
     }
 
+    @Test
+    public void tintTileIcon_noIcon_shouldReturnFalse() {
+        final Tile tile = new Tile();
+        final Bundle metaData = new Bundle();
+        tile.metaData = metaData;
+
+        assertThat(mTestFragment.tintTileIcon(tile)).isFalse();
+    }
 
     @Test
     public void tintTileIcon_noMetadata_shouldReturnPackageNameCheck() {
         final Tile tile = new Tile();
+        tile.icon = mock(Icon.class);
         final Intent intent = new Intent();
         tile.intent = intent;
 
diff --git a/tests/robotests/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceControllerTest.java
new file mode 100644
index 0000000..dd438ff
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceControllerTest.java
@@ -0,0 +1,83 @@
+package com.android.settings.deletionhelper;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Ignore;
+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;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AutomaticStorageManagerDescriptionPreferenceControllerTest {
+    @Mock private PreferenceScreen mScreen;
+    @Mock private Preference mPreference;
+    private AutomaticStorageManagerDescriptionPreferenceController mController;
+    private Context mContext = RuntimeEnvironment.application;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = new AutomaticStorageManagerDescriptionPreferenceController(mContext);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+        when(mPreference.getContext()).thenReturn(mContext);
+    }
+
+    @Test
+    public void displayPreference_asmDisabled_shouldHaveDescription() {
+        mController.displayPreference(mScreen);
+
+        verify(mPreference).setSummary(eq(R.string.automatic_storage_manager_text));
+    }
+
+    @Test
+    public void displayPreference_asmEnabledButUnused_shouldHaveDescription() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
+                1);
+
+        mController.displayPreference(mScreen);
+
+        verify(mPreference).setSummary(eq(R.string.automatic_storage_manager_text));
+    }
+
+    @Ignore("Robolectric doesn't do locale switching for date localization -- yet.")
+    @Test
+    @Config(qualifiers = "en")
+    public void displayPreference_asmEnabledAndUsed_shouldHaveDescriptionFilledOut() {
+        Settings.Secure.putInt(
+                mContext.getContentResolver(),
+                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
+                1);
+        Settings.Secure.putLong(
+                mContext.getContentResolver(),
+                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
+                10);
+        Settings.Secure.putLong(
+                mContext.getContentResolver(),
+                Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
+                43200000); // January 1, 1970 12:00:00 PM to avoid timezone issues.
+
+        mController.displayPreference(mScreen);
+
+        verify(mPreference)
+                .setSummary(eq("10.00B total made available\n\nLast ran on January 1, 1970"));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
new file mode 100644
index 0000000..04ff721
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                SettingsShadowResources.class,
+                SettingsShadowResources.SettingsShadowTheme.class
+        })
+public class DevelopmentSettingsDashboardFragmentTest {
+
+    private DevelopmentSettingsDashboardFragment mDashboard;
+
+    @Before
+    public void setUp() {
+        mDashboard = new DevelopmentSettingsDashboardFragment();
+    }
+
+    @Test
+    public void shouldNotHaveHelpResource() {
+        assertThat(mDashboard.getHelpResource()).isEqualTo(0);
+    }
+
+    @Test
+    public void shouldLogAsFeatureFlagPage() {
+        assertThat(mDashboard.getMetricsCategory())
+                .isEqualTo(MetricsProto.MetricsEvent.DEVELOPMENT);
+    }
+
+    @Test
+    public void searchIndex_shouldIndexFromPrefXml() {
+        final List<SearchIndexableResource> index =
+                DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getXmlResourcesToIndex(RuntimeEnvironment.application, true);
+
+        assertThat(index.size()).isEqualTo(1);
+        assertThat(index.get(0).xmlResId).isEqualTo(R.xml.development_prefs);
+    }
+
+    @Test
+    public void searchIndex_pageDisabled_shouldAddAllKeysToNonIndexable() {
+        final Context appContext = RuntimeEnvironment.application;
+        DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, false);
+
+        final List<String> nonIndexableKeys =
+                DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getNonIndexableKeys(appContext);
+
+        assertThat(nonIndexableKeys).contains("development_prefs_screen");
+    }
+
+    @Test
+    public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() {
+        final Context appContext = RuntimeEnvironment.application;
+        DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
+
+        final List<String> nonIndexableKeys =
+                DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getNonIndexableKeys(appContext);
+
+        assertThat(nonIndexableKeys).doesNotContain("development_prefs_screen");
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java
index 801ee5d..f5859ac 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroductionTest.java
@@ -23,28 +23,38 @@
 
 import android.app.KeyguardManager;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.view.View;
 import android.widget.Button;
 
 import com.android.settings.R;
 import com.android.settings.TestConfig;
+import com.android.settings.fingerprint.SetupFingerprintEnrollIntroductionTest
+        .ShadowStorageManagerWrapper;
 import com.android.settings.password.SetupChooseLockGeneric.SetupChooseLockGenericFragment;
 import com.android.settings.password.SetupSkipDialog;
+import com.android.settings.password.StorageManagerWrapper;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowEventLogWriter;
+import com.android.settings.testutils.shadow.ShadowFingerprintManager;
 import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
 import com.android.settings.testutils.shadow.ShadowUserManager;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.Shadows;
 import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
 import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowActivity.IntentForResult;
 import org.robolectric.shadows.ShadowKeyguardManager;
 import org.robolectric.util.ActivityController;
 
@@ -54,7 +64,9 @@
         sdk = TestConfig.SDK_VERSION,
         shadows = {
                 ShadowEventLogWriter.class,
+                ShadowFingerprintManager.class,
                 ShadowLockPatternUtils.class,
+                ShadowStorageManagerWrapper.class,
                 ShadowUserManager.class
         })
 public class SetupFingerprintEnrollIntroductionTest {
@@ -68,12 +80,22 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
+        RuntimeEnvironment.getRobolectricPackageManager()
+                .setSystemFeature(PackageManager.FEATURE_FINGERPRINT, true);
+        ShadowFingerprintManager.addToServiceMap();
+
         final Intent intent = new Intent();
         mController = Robolectric.buildActivity(SetupFingerprintEnrollIntroduction.class, intent);
 
         ShadowUserManager.getShadow().setUserInfo(0, mUserInfo);
     }
 
+    @After
+    public void tearDown() {
+        ShadowStorageManagerWrapper.reset();
+        ShadowFingerprintManager.reset();
+    }
+
     @Test
     public void testKeyguardNotSecure_shouldFinishWithSetupSkipDialogResultSkip() {
         getShadowKeyguardManager().setIsKeyguardSecure(false);
@@ -188,8 +210,41 @@
         assertThat(Shadows.shadowOf(activity).getResultIntent()).isNull();
     }
 
+    @Test
+    public void testLockPattern() {
+        ShadowStorageManagerWrapper.sIsFileEncrypted = false;
+
+        mController.create().postCreate(null).resume();
+
+        SetupFingerprintEnrollIntroduction activity = mController.get();
+
+        final Button nextButton = activity.findViewById(R.id.fingerprint_next_button);
+        nextButton.performClick();
+
+        ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+        IntentForResult startedActivity = shadowActivity.getNextStartedActivityForResult();
+        assertThat(startedActivity).isNotNull();
+        assertThat(startedActivity.intent.hasExtra(
+                SetupChooseLockGenericFragment.EXTRA_PASSWORD_QUALITY)).isFalse();
+    }
+
 
     private ShadowKeyguardManager getShadowKeyguardManager() {
         return Shadows.shadowOf(application.getSystemService(KeyguardManager.class));
     }
+
+    @Implements(StorageManagerWrapper.class)
+    public static class ShadowStorageManagerWrapper {
+
+        private static boolean sIsFileEncrypted = true;
+
+        public static void reset() {
+            sIsFileEncrypted = true;
+        }
+
+        @Implementation
+        public static boolean isFileEncryptedNativeOrEmulated() {
+            return sIsFileEncrypted;
+        }
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
index 91f4a2b..86836f9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
@@ -16,14 +16,25 @@
 
 package com.android.settings.fuelgauge;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.AlertDialog;
 import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.UserManager;
 import android.support.v14.preference.SwitchPreference;
+import android.widget.Button;
 
 import com.android.settings.R;
 import com.android.settings.TestConfig;
@@ -38,22 +49,17 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import org.robolectric.shadows.ShadowAlertDialog;
+import org.robolectric.shadows.ShadowDialog;
+import org.robolectric.util.FragmentTestUtil;
 
 @RunWith(RobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class BackgroundActivityPreferenceControllerTest {
-    private static final int UID_NORMAL = 1234;
-    private static final int UID_SPECIAL = 2345;
+    private static final int UID_LOW_SDK = 1234;
+    private static final int UID_HIGH_SDK = 3456;
     private static final String HIGH_SDK_PACKAGE = "com.android.package.high";
     private static final String LOW_SDK_PACKAGE = "com.android.package.low";
-    private static final String[] PACKAGES_NORMAL = {LOW_SDK_PACKAGE};
-    private static final String[] PACKAGES_SPECIAL = {HIGH_SDK_PACKAGE, LOW_SDK_PACKAGE};
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
@@ -71,6 +77,10 @@
     private DevicePolicyManager mDevicePolicyManager;
     @Mock
     private DevicePolicyManagerWrapper mDevicePolicyManagerWrapper;
+    @Mock
+    private AdvancedPowerUsageDetail mFragment;
+    @Mock
+    private PowerWhitelistBackend mPowerWhitelistBackend;
     private BackgroundActivityPreferenceController mController;
     private SwitchPreference mPreference;
     private Context mShadowContext;
@@ -85,19 +95,19 @@
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
         when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(
                 mDevicePolicyManager);
-        when(mPackageManager.getPackagesForUid(UID_NORMAL)).thenReturn(PACKAGES_NORMAL);
-        when(mPackageManager.getPackagesForUid(UID_SPECIAL)).thenReturn(PACKAGES_SPECIAL);
 
         when(mPackageManager.getApplicationInfo(HIGH_SDK_PACKAGE, PackageManager.GET_META_DATA))
                 .thenReturn(mHighApplicationInfo);
         when(mPackageManager.getApplicationInfo(LOW_SDK_PACKAGE, PackageManager.GET_META_DATA))
                 .thenReturn(mLowApplicationInfo);
+
+        when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(false);
         mHighApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
         mLowApplicationInfo.targetSdkVersion = Build.VERSION_CODES.L;
 
         mPreference = new SwitchPreference(mShadowContext);
-        mController = spy(new BackgroundActivityPreferenceController(mContext, UID_NORMAL));
-        mController.isAvailable();
+        mController = spy(new BackgroundActivityPreferenceController(
+                mContext, mFragment, UID_LOW_SDK, LOW_SDK_PACKAGE, mPowerWhitelistBackend));
         mController.mDpm = mDevicePolicyManagerWrapper;
     }
 
@@ -105,49 +115,66 @@
     public void testOnPreferenceChange_TurnOnCheck_MethodInvoked() {
         mController.onPreferenceChange(mPreference, true);
 
-        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL,
-                mController.getTargetPackage(), AppOpsManager.MODE_ALLOWED);
-        verify(mController).updateSummary(mPreference);
+        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_LOW_SDK,
+                LOW_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
+        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
+                LOW_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
     }
 
     @Test
-    public void testOnPreferenceChange_TurnOffCheck_MethodInvoked() {
-        mController.onPreferenceChange(mPreference, false);
-
-        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL,
-                mController.getTargetPackage(), AppOpsManager.MODE_IGNORED);
-        verify(mController).updateSummary(mPreference);
+    public void testOnPreferenceChange_TurnOnCheckHighSDK_MethodInvoked() {
+        mController = new BackgroundActivityPreferenceController(mContext, mFragment, UID_HIGH_SDK,
+                HIGH_SDK_PACKAGE, mPowerWhitelistBackend);
+        mController.onPreferenceChange(mPreference, true);
+        verify(mAppOpsManager).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_HIGH_SDK,
+                HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
+        verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_HIGH_SDK,
+                HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mShadowContext.getText(R.string.background_activity_summary_on));
     }
 
     @Test
     public void testUpdateState_CheckOn_SetCheckedTrue() {
-        when(mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
-                .thenReturn(AppOpsManager.MODE_DEFAULT);
+        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
+                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ALLOWED);
 
         mController.updateState(mPreference);
 
         assertThat(mPreference.isChecked()).isTrue();
+        assertThat(mPreference.isEnabled()).isTrue();
         verify(mController).updateSummary(mPreference);
     }
 
     @Test
     public void testUpdateState_CheckOff_SetCheckedFalse() {
-        when(mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
-                .thenReturn(AppOpsManager.MODE_IGNORED);
+        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
+                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
 
         mController.updateState(mPreference);
 
         assertThat(mPreference.isChecked()).isFalse();
+        assertThat(mPreference.isEnabled()).isTrue();
         verify(mController).updateSummary(mPreference);
     }
 
     @Test
+    public void testUpdateState_whitelisted() {
+        when(mPowerWhitelistBackend.isWhitelisted(LOW_SDK_PACKAGE)).thenReturn(true);
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+        assertThat(mPreference.isEnabled()).isFalse();
+        assertThat(mPreference.getSummary()).isEqualTo(
+                mShadowContext.getText(R.string.background_activity_summary_whitelisted));
+    }
+
+    @Test
     public void testUpdateSummary_modeError_showSummaryDisabled() {
-        when(mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
-                .thenReturn(AppOpsManager.MODE_ERRORED);
+        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
+                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_ERRORED);
         final CharSequence expectedSummary = mShadowContext.getText(
                 R.string.background_activity_summary_disabled);
         mController.updateSummary(mPreference);
@@ -157,9 +184,8 @@
 
     @Test
     public void testUpdateSummary_modeDefault_showSummaryOn() {
-        when(mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
-                .thenReturn(AppOpsManager.MODE_DEFAULT);
+        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
+                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_DEFAULT);
         final CharSequence expectedSummary = mShadowContext.getText(
                 R.string.background_activity_summary_on);
 
@@ -170,9 +196,8 @@
 
     @Test
     public void testUpdateSummary_modeIgnored_showSummaryOff() {
-        when(mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
-                .thenReturn(AppOpsManager.MODE_IGNORED);
+        when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID_LOW_SDK,
+                LOW_SDK_PACKAGE)).thenReturn(AppOpsManager.MODE_IGNORED);
         final CharSequence expectedSummary = mShadowContext.getText(
                 R.string.background_activity_summary_off);
 
@@ -182,31 +207,30 @@
     }
 
     @Test
-    public void testIsPackageAvailable_SdkLowerThanO_ReturnTrue() {
+    public void testIsLegacyApp_SdkLowerThanO_ReturnTrue() {
         assertThat(mController.isLegacyApp(LOW_SDK_PACKAGE)).isTrue();
     }
 
     @Test
-    public void testIsPackageAvailable_SdkLargerOrEqualThanO_ReturnFalse() {
+    public void testIsLegacyApp_SdkLargerOrEqualThanO_ReturnFalse() {
         assertThat(mController.isLegacyApp(HIGH_SDK_PACKAGE)).isFalse();
     }
 
     @Test
-    public void testMultiplePackages_ReturnStatusForTargetPackage() {
-        mController = new BackgroundActivityPreferenceController(mContext, UID_SPECIAL);
-        mController.mDpm = mDevicePolicyManagerWrapper;
-        when(mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, LOW_SDK_PACKAGE))
-                .thenReturn(AppOpsManager.MODE_ALLOWED);
-        when(mAppOpsManager
-                .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, HIGH_SDK_PACKAGE))
-                .thenReturn(AppOpsManager.MODE_IGNORED);
+    public void testIsAvailable_ReturnTrue() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
 
-        final boolean available = mController.isAvailable();
-        mController.updateState(mPreference);
-
-        assertThat(available).isTrue();
-        // Should get status from LOW_SDK_PACKAGE
-        assertThat(mPreference.isChecked()).isTrue();
+    @Test
+    public void testWarningDialog() {
+        BackgroundActivityPreferenceController.WarningDialogFragment dialogFragment =
+                new BackgroundActivityPreferenceController.WarningDialogFragment();
+        dialogFragment.setTargetFragment(mFragment, 0);
+        FragmentTestUtil.startFragment(dialogFragment);
+        final AlertDialog dialog = (AlertDialog) ShadowDialog.getLatestDialog();
+        ShadowAlertDialog shadowDialog = shadowOf(dialog);
+        final Button okButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        shadowDialog.clickOn(okButton.getId());
+        verify(mFragment).onLimitBackgroundActivity();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
index 632d549..a461f46 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Handler;
+import android.os.Process;
 import android.os.UserManager;
 
 import com.android.internal.os.BatterySipper;
@@ -46,9 +47,12 @@
 public class BatteryEntryTest {
 
     private static final int APP_UID = 123;
+    private static final int SYSTEM_UID = Process.SYSTEM_UID;
     private static final String APP_DEFAULT_PACKAGE_NAME = "com.android.test";
     private static final String APP_LABEL = "Test App Name";
     private static final String HIGH_DRAIN_PACKAGE = "com.android.test.screen";
+    private static final String ANDROID_PACKAGE = "android";
+    private static final String[] SYSTEM_PACKAGES = {HIGH_DRAIN_PACKAGE, ANDROID_PACKAGE};
 
     @Rule public MockitoRule mocks = MockitoJUnit.rule();
 
@@ -84,6 +88,18 @@
         return sipper;
     }
 
+    private BatteryEntry createBatteryEntryForSystem() {
+        return new BatteryEntry(mockContext, mockHandler, mockUserManager, createSipperForSystem());
+    }
+
+    private BatterySipper createSipperForSystem() {
+        BatterySipper sipper =
+                new BatterySipper(DrainType.APP, new FakeUid(SYSTEM_UID), 0 /* power use */);
+        sipper.packageWithHighestDrain = HIGH_DRAIN_PACKAGE;
+        sipper.mPackages = SYSTEM_PACKAGES;
+        return sipper;
+    }
+
     @Test
     public void batteryEntryForApp_shouldSetDefaultPackageNameAndLabel() throws Exception {
         BatteryEntry entry = createBatteryEntryForApp();
@@ -118,7 +134,22 @@
             new String[]{APP_DEFAULT_PACKAGE_NAME, "package2", "package3"});
 
         BatteryEntry entry = createBatteryEntryForApp();
-        
+
         assertThat(entry.getLabel()).isEqualTo(HIGH_DRAIN_PACKAGE);
     }
+
+    @Test
+    public void extractPackageFromSipper_systemSipper_returnSystemPackage() {
+        BatteryEntry entry = createBatteryEntryForSystem();
+
+        assertThat(entry.extractPackagesFromSipper(entry.sipper)).isEqualTo(
+                new String[]{ANDROID_PACKAGE});
+    }
+
+    @Test
+    public void extractPackageFromSipper_normalSipper_returnDefaultPakcage() {
+        BatteryEntry entry = createBatteryEntryForApp();
+
+        assertThat(entry.extractPackagesFromSipper(entry.sipper)).isEqualTo(entry.sipper.mPackages);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
index 1f5c9be..7ea42b8 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
@@ -32,6 +32,7 @@
 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;
@@ -43,7 +44,7 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class AssistGestureSettingsTest {
-    @Mock
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     private FakeFeatureFactory mFakeFeatureFactory;
     private AssistGestureSettings mSettings;
@@ -51,6 +52,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest(mContext);
         mFakeFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
         mSettings = new AssistGestureSettings();
     }
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowFingerprintManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowFingerprintManager.java
new file mode 100644
index 0000000..b84cf42
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowFingerprintManager.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintManager;
+import android.support.annotation.NonNull;
+
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+import org.robolectric.internal.ShadowExtractor;
+import org.robolectric.shadows.ShadowContextImpl;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.IntStream;
+
+@Implements(FingerprintManager.class)
+public class ShadowFingerprintManager {
+
+    private static Map<String, String> getSystemServiceMap() {
+        return ReflectionHelpers.getStaticField(ShadowContextImpl.class, "SYSTEM_SERVICE_MAP");
+    }
+
+    /**
+     * Call this in @Before of a test to add FingerprintManager to Robolectric's system service
+     * map. Otherwise getSystemService(FINGERPRINT_SERVICE) will return null.
+     */
+    public static void addToServiceMap() {
+        getSystemServiceMap().put(Context.FINGERPRINT_SERVICE, FingerprintManager.class.getName());
+    }
+
+    @Resetter
+    public static void reset() {
+        getSystemServiceMap().remove(Context.FINGERPRINT_SERVICE);
+    }
+
+    public boolean hardwareDetected = true;
+
+    @NonNull
+    private List<Fingerprint> mFingerprints = Collections.emptyList();
+
+    @Implementation
+    public boolean isHardwareDetected() {
+        return hardwareDetected;
+    }
+
+    @Implementation
+    public boolean hasEnrolledFingerprints() {
+        return !mFingerprints.isEmpty();
+    }
+
+    @Implementation
+    public List<Fingerprint> getEnrolledFingerprints() {
+        return mFingerprints;
+    }
+
+    @Implementation
+    public List<Fingerprint> getEnrolledFingerprints(int userId) {
+        return mFingerprints;
+    }
+
+    public void setEnrolledFingerprints(Fingerprint... fingerprints) {
+        mFingerprints = Arrays.asList(fingerprints);
+    }
+
+    public void setDefaultFingerprints(int num) {
+        setEnrolledFingerprints(
+                IntStream.range(0, num)
+                        .mapToObj(i -> new Fingerprint(
+                                "Fingerprint " + i,
+                                0, /* groupId */
+                                i, /* fingerId */
+                                0 /* deviceId */))
+                        .toArray(Fingerprint[]::new));
+    }
+
+    public static ShadowFingerprintManager get() {
+        return (ShadowFingerprintManager) ShadowExtractor.extract(
+                RuntimeEnvironment.application.getSystemService(FingerprintManager.class));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
index 88a5147..e061787 100644
--- a/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
@@ -35,9 +35,10 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 @RunWith(SettingsRobolectricTestRunner.class)
@@ -58,10 +59,36 @@
     }
 
     @Test
-    public void bindDialogView_noTextWatcher_shouldDoNothing() {
+    public void bindDialogView_nullEditText_shouldNotCrash() {
+        when(mView.findViewById(android.R.id.edit)).thenReturn(null);
+        // should not crash trying to get the EditText text
+        mPreference.onBindDialogView(mView);
+    }
+
+    @Test
+    public void bindDialogView_emptyEditText_shouldNotSetSelection() {
+        final String testText = "";
+        final EditText editText = spy(new EditText(RuntimeEnvironment.application));
+        editText.setText(testText);
+        when(mView.findViewById(android.R.id.edit)).thenReturn(editText);
+
         mPreference.onBindDialogView(mView);
 
-        verifyZeroInteractions(mView);
+        // no need to setSelection if text was empty
+        verify(editText, never()).setSelection(anyInt());
+    }
+
+    @Test
+    public void bindDialogView_nonemptyEditText_shouldSetSelection() {
+        final String testText = "whatever";
+        final EditText editText = spy(new EditText(RuntimeEnvironment.application));
+        editText.setText(testText);
+        when(mView.findViewById(android.R.id.edit)).thenReturn(editText);
+
+        mPreference.onBindDialogView(mView);
+
+        // selection should be set to end of string
+        verify(editText).setSelection(testText.length());
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 275f9a2..1c2ddb4 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -436,10 +436,14 @@
     public void dnsServersPref_shouldHaveDetailTextSet() throws UnknownHostException {
         mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,4,4}));
         mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,8,8}));
+        mLinkProperties.addDnsServer(Constants.IPV6_DNS);
 
         displayAndResume();
 
-        verify(mockDnsPref).setDetailText("8.8.4.4\n8.8.8.8");
+        verify(mockDnsPref).setDetailText(
+                "8.8.4.4\n" +
+                "8.8.8.8\n" +
+                Constants.IPV6_DNS.getHostAddress());
     }
 
     @Test
@@ -545,12 +549,14 @@
 
         lp.addDnsServer(Constants.IPV6_DNS);
         updateLinkProperties(lp);
-        inOrder.verify(mockDnsPref, never()).setVisible(true);
+        inOrder.verify(mockDnsPref).setDetailText(Constants.IPV6_DNS.getHostAddress());
+        inOrder.verify(mockDnsPref).setVisible(true);
 
         lp.addDnsServer(Constants.IPV4_DNS1);
         lp.addDnsServer(Constants.IPV4_DNS2);
         updateLinkProperties(lp);
         inOrder.verify(mockDnsPref).setDetailText(
+                Constants.IPV6_DNS.getHostAddress() + "\n" +
                 Constants.IPV4_DNS1.getHostAddress() + "\n" +
                 Constants.IPV4_DNS2.getHostAddress());
         inOrder.verify(mockDnsPref).setVisible(true);