Merge "Clean up task affinity."
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 0a058d5..e57cbfa 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1119,4 +1119,18 @@
         <item>0</item>
     </string-array>
 
+    <!-- Titles for autofill logging level preference. [CHAR LIMIT=50] -->
+    <string-array name="autofill_logging_level_entries">
+        <item>Off</item>
+        <item>Debug</item>
+        <item>Verbose</item>
+    </string-array>
+
+    <!-- Values for autofill logging level preference. -->
+    <string-array name="autofill_logging_level_values" translatable="false" >
+        <item>0</item> <!-- AutofillManager.NO_LOGGING -->
+        <item>2</item> <!-- AutofillManager.FLAG_ADD_CLIENT_DEBUG -->
+        <item>4</item> <!-- AutofillManager.FLAG_ADD_CLIENT_VERBOSE -->
+    </string-array>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2bef192..06f4123 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5091,6 +5091,9 @@
         <item quantity="other">Limiting battery usage for %1$d apps</item>
     </plurals>
 
+    <!-- Summary for restricted app to show the restriction time [CHAR LIMIT=NONE] -->
+    <string name="restricted_app_time_summary">Restricted <xliff:g id="time" example="5 days ago">%1$s</xliff:g></string>
+
     <!-- Footer message for restrict app details page -->
     <string name="restricted_app_detail_footer">These apps have been using battery in the background. Restricted apps may not work properly and notifications may be delayed.</string>
 
@@ -9861,6 +9864,24 @@
         ]]>
     </string>
 
+    <!-- Preference category for autofill debugging development settings. [CHAR LIMIT=25] -->
+    <string name="debug_autofill_category">Autofill</string>
+
+    <!-- UI debug setting: logging level for Android Autofill [CHAR LIMIT=25] -->
+    <string name="autofill_logging_level_title">Logging level</string>
+
+    <!-- Title of developer options to set the maximum number of partitions per session [CHAR LIMIT=60]-->
+    <string name="autofill_max_partitions">Max partitions</string>
+
+    <!-- Title of developer options to set the maximum number of visible datasets in the autofill UX [CHAR LIMIT=60]-->
+    <string name="autofill_max_visible_datasets">Max visible datasets</string>
+
+    <!-- Reset all autofill developer options to their default values.[CHAR_LIMIT=60] -->
+    <string name="autofill_reset_developer_options">Reset to default values</string>
+
+    <!-- Toast message shown when autofill_reset_developer_options has been performed. [CHAR_LIMIT=none] -->
+    <string name="autofill_reset_developer_options_complete">Autofill developer options have been reset</string>
+
     <!-- Name of setting for switching device theme [CHAR LIMIT=60] -->
     <string name="device_theme">Device theme</string>
     <!-- Name of default device theme [CHAR LIMIT=60] -->
diff --git a/res/values/themes_suw.xml b/res/values/themes_suw.xml
index 11ef373..f09b2b1 100644
--- a/res/values/themes_suw.xml
+++ b/res/values/themes_suw.xml
@@ -18,8 +18,8 @@
 <!-- SUW related themes -->
 <resources>
     <style name="GlifTheme" parent="SuwThemeGlif">
-        <!-- For all Alert Dialogs -->
-        <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
+        <!-- For all AndroidX Alert Dialogs -->
+        <item name="alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -37,8 +37,8 @@
     </style>
 
     <style name="GlifTheme.Light" parent="SuwThemeGlif.Light">
-        <!-- For all Alert Dialogs -->
-        <item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
+        <!-- For all AndroidX Alert Dialogs -->
+        <item name="alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -56,8 +56,8 @@
     </style>
 
     <style name="GlifV2Theme" parent="SuwThemeGlifV2">
-        <!-- For all Alert Dialogs -->
-        <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
+        <!-- For all AndroidX Alert Dialogs -->
+        <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -75,8 +75,8 @@
     </style>
 
     <style name="GlifV2Theme.Light" parent="SuwThemeGlifV2.Light">
-        <!-- For all Alert Dialogs -->
-        <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
+        <!-- For all AndroidX Alert Dialogs -->
+        <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -94,8 +94,8 @@
     </style>
 
     <style name="GlifV3Theme" parent="SuwThemeGlifV3">
-        <!-- For all Alert Dialogs -->
-        <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
+        <!-- For all AndroidX Alert Dialogs -->
+        <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -113,8 +113,8 @@
     </style>
 
     <style name="GlifV3Theme.Light" parent="SuwThemeGlifV3.Light">
-        <!-- For all Alert Dialogs -->
-        <item name="android:alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
+        <!-- For all AndroidX Alert Dialogs -->
+        <item name="alertDialogTheme">@style/GlifV2ThemeAlertDialog.Light</item>
         <item name="android:windowBackground">?android:attr/colorBackground</item>
         <item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -145,11 +145,11 @@
         <item name="android:windowAnimationStyle">@null</item>
     </style>
 
-    <style name="GlifV2ThemeAlertDialog" parent="SuwAlertDialogTheme">
+    <style name="GlifV2ThemeAlertDialog" parent="SuwAlertDialogThemeCompat">
         <item name="android:windowSoftInputMode">adjustResize</item>
     </style>
 
-    <style name="GlifV2ThemeAlertDialog.Light" parent="SuwAlertDialogTheme.Light">
+    <style name="GlifV2ThemeAlertDialog.Light" parent="SuwAlertDialogThemeCompat.Light">
         <item name="android:windowSoftInputMode">adjustResize</item>
     </style>
 
@@ -190,4 +190,16 @@
         <item name="preferenceTheme">@style/PreferenceTheme</item>
         <item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.Settings</item>
     </style>
+
+    <style name="SuwAlertDialogThemeCompat" parent="@style/Theme.AppCompat.Dialog.Alert">
+        <!-- copied from Theme.DeviceDefault.Light.Dialog.Alert -->
+        <item name="colorAccent">@*android:color/accent_device_default_light</item>
+        <item name="dialogCornerRadius">@*android:dimen/config_dialogCornerRadius</item>
+    </style>
+
+    <style name="SuwAlertDialogThemeCompat.Light" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
+        <!-- copied from Theme.DeviceDefault.Light.Dialog.Alert -->
+        <item name="colorAccent">@*android:color/accent_device_default_light</item>
+        <item name="dialogCornerRadius">@*android:dimen/config_dialogCornerRadius</item>
+    </style>
 </resources>
\ No newline at end of file
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 3d5f198..b0c7c9c 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -506,4 +506,29 @@
             android:title="@string/reset_shortcut_manager_throttling" />
     </PreferenceCategory>
 
+    <com.android.settings.development.autofill.AutofillPreferenceCategory
+        android:key="debug_autofill_category"
+        android:title="@string/debug_autofill_category"
+        android:order="1100">
+
+        <ListPreference
+            android:key="autofill_logging_level"
+            android:title="@string/autofill_logging_level_title"
+            android:entries="@array/autofill_logging_level_entries"
+            android:entryValues="@array/autofill_logging_level_values" />
+
+        <com.android.settings.development.autofill.AutofillMaxPartitionsPreference
+            android:key="autofill_max_partitions"
+            android:title="@string/autofill_max_partitions" />
+
+        <com.android.settings.development.autofill.AutofillVisibleDatasetsPreference
+            android:key="autofill_visible_datasets"
+            android:title="@string/autofill_max_visible_datasets" />
+
+        <Preference
+            android:key="autofill_reset_developer_options"
+            android:title="@string/autofill_reset_developer_options" />
+
+    </com.android.settings.development.autofill.AutofillPreferenceCategory>
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/FallbackHome.java b/src/com/android/settings/FallbackHome.java
index 7d5948e..59347ad 100644
--- a/src/com/android/settings/FallbackHome.java
+++ b/src/com/android/settings/FallbackHome.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
+import android.app.WallpaperManager.OnColorsChangedListener;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -44,6 +45,7 @@
     private static final int PROGRESS_TIMEOUT = 2000;
 
     private boolean mProvisioned;
+    private WallpaperManager mWallManager;
 
     private final Runnable mProgressTimeoutRunnable = () -> {
         View v = getLayoutInflater().inflate(
@@ -59,6 +61,18 @@
         getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
     };
 
+    private final OnColorsChangedListener mColorsChangedListener = new OnColorsChangedListener() {
+        @Override
+        public void onColorsChanged(WallpaperColors colors, int which) {
+            if (colors != null) {
+                View decorView = getWindow().getDecorView();
+                decorView.setSystemUiVisibility(
+                        updateVisibilityFlagsFromColors(colors, decorView.getSystemUiVisibility()));
+                mWallManager.removeOnColorsChangedListener(this);
+            }
+        }
+    };
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -78,13 +92,17 @@
         }
 
         // Set the system ui flags to light status bar if the wallpaper supports dark text to match
-        // current system ui color tints.
-        final WallpaperColors colors = getSystemService(WallpaperManager.class)
-                .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
-        if (colors != null
-                && (colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0) {
-            flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
-                    | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+        // current system ui color tints. Use a listener to wait for colors if not ready yet.
+        mWallManager = getSystemService(WallpaperManager.class);
+        if (mWallManager == null) {
+            Log.w(TAG, "Wallpaper manager isn't ready, can't listen to color changes!");
+        } else {
+            WallpaperColors colors = mWallManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+            if (colors == null) {
+                mWallManager.addOnColorsChangedListener(mColorsChangedListener, null /* handler */);
+            } else {
+                flags = updateVisibilityFlagsFromColors(colors, flags);
+            }
         }
         getWindow().getDecorView().setSystemUiVisibility(flags);
 
@@ -109,6 +127,9 @@
     protected void onDestroy() {
         super.onDestroy();
         unregisterReceiver(mReceiver);
+        if (mWallManager != null) {
+            mWallManager.removeOnColorsChangedListener(mColorsChangedListener);
+        }
     }
 
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -141,6 +162,15 @@
         }
     }
 
+    private int updateVisibilityFlagsFromColors(WallpaperColors colors, int flags) {
+        if ((colors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0) {
+            return flags | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
+                    | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+        }
+        return flags & ~(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
+                & ~(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+    }
+
     private Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 82ca54b..5be381a 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -39,6 +39,8 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.development.autofill.AutofillLoggingLevelPreferenceController;
+import com.android.settings.development.autofill.AutofillResetOptionsPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.widget.SwitchBar;
@@ -466,6 +468,8 @@
         controllers.add(new DefaultLaunchPreferenceController(context, "density"));
         controllers.add(new DefaultLaunchPreferenceController(context, "background_check"));
         controllers.add(new DefaultLaunchPreferenceController(context, "inactive_apps"));
+        controllers.add(new AutofillLoggingLevelPreferenceController(context));
+        controllers.add(new AutofillResetOptionsPreferenceController(context));
         return controllers;
     }
 
diff --git a/src/com/android/settings/development/autofill/AbstractGlobalSettingsPreference.java b/src/com/android/settings/development/autofill/AbstractGlobalSettingsPreference.java
new file mode 100644
index 0000000..080c387
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AbstractGlobalSettingsPreference.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.text.BidiFormatter;
+import android.text.InputType;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Slog;
+import android.view.Display;
+import android.view.View;
+import android.view.autofill.AutofillManager;
+import android.widget.EditText;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settingslib.CustomEditTextPreferenceCompat;
+
+import java.text.NumberFormat;
+
+/**
+ * Base class for Autofill integer properties that are backed by
+ * {@link android.provider.Settings.Global}.
+ */
+abstract class AbstractGlobalSettingsPreference extends CustomEditTextPreferenceCompat {
+
+    private static final String TAG = "AbstractGlobalSettingsPreference";
+
+    private final String mKey;
+    private final int mDefaultValue;
+
+    private final AutofillDeveloperSettingsObserver mObserver;
+
+    protected AbstractGlobalSettingsPreference(Context context, AttributeSet attrs,
+            String key, int defaultValue) {
+        super(context, attrs);
+
+        mKey = key;
+        mDefaultValue = defaultValue;
+        mObserver = new AutofillDeveloperSettingsObserver(context, () -> updateSummary());
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+
+        mObserver.register();
+        updateSummary();
+    }
+
+    @Override
+    public void onDetached() {
+        mObserver.unregister();
+
+        super.onDetached();
+    }
+
+    private String getCurrentValue() {
+        final int value = Settings.Global.getInt(getContext().getContentResolver(),
+                mKey, mDefaultValue);
+
+        return Integer.toString(value);
+    }
+
+    private void updateSummary() {
+        setSummary(getCurrentValue());
+
+    }
+
+    @Override
+    protected void onBindDialogView(View view) {
+        super.onBindDialogView(view);
+
+        EditText editText = view.findViewById(android.R.id.edit);
+        if (editText != null) {
+            editText.setInputType(InputType.TYPE_CLASS_NUMBER);
+            editText.setText(getCurrentValue());
+            Utils.setEditTextCursorPosition(editText);
+        }
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        if (positiveResult) {
+            final String stringValue = getText();
+            int newValue = mDefaultValue;
+            try {
+                newValue = Integer.parseInt(stringValue);
+            } catch (Exception e) {
+                Log.e(TAG, "Error converting '" + stringValue + "' to integer. Using "
+                        + mDefaultValue + " instead");
+            }
+            Settings.Global.putInt(getContext().getContentResolver(), mKey, newValue);
+        }
+    }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillDeveloperSettingsObserver.java b/src/com/android/settings/development/autofill/AutofillDeveloperSettingsObserver.java
new file mode 100644
index 0000000..ae8e246
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillDeveloperSettingsObserver.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+final class AutofillDeveloperSettingsObserver extends ContentObserver {
+
+    private final Runnable mChangeCallback;
+    private final ContentResolver mResolver;
+
+    public AutofillDeveloperSettingsObserver(Context context, Runnable changeCallback) {
+        super(new Handler());
+
+        mResolver = context.getContentResolver();
+        mChangeCallback = changeCallback;
+    }
+
+    public void register() {
+        mResolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.AUTOFILL_LOGGING_LEVEL), false, this,
+                UserHandle.USER_ALL);
+        mResolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE), false, this,
+                UserHandle.USER_ALL);
+        mResolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS), false, this,
+                UserHandle.USER_ALL);
+    }
+
+    public void unregister() {
+        mResolver.unregisterContentObserver(this);
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri, int userId) {
+        mChangeCallback.run(); // Run Forrest, Run!
+    }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceController.java b/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceController.java
new file mode 100644
index 0000000..a22295c
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceController.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.view.autofill.AutofillManager;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+public final class AutofillLoggingLevelPreferenceController
+        extends DeveloperOptionsPreferenceController
+        implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
+
+    private static final String AUTOFILL_LOGGING_LEVEL_KEY = "autofill_logging_level";
+
+    private final String[] mListValues;
+    private final String[] mListSummaries;
+    private final AutofillDeveloperSettingsObserver mObserver;
+
+    public AutofillLoggingLevelPreferenceController(Context context) {
+        super(context);
+
+        Resources resources = context.getResources();
+        mListValues = resources.getStringArray(R.array.autofill_logging_level_values);
+        mListSummaries = resources.getStringArray(R.array.autofill_logging_level_entries);
+        mObserver = new AutofillDeveloperSettingsObserver(mContext, () -> updateOptions());
+        mObserver.register();
+        // TODO: there should be a hook on AbstractPreferenceController where we could unregister it
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return AUTOFILL_LOGGING_LEVEL_KEY;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        writeLevel(newValue);
+        updateOptions();
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        updateOptions();
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        writeLevel(null);
+    }
+
+    private void updateOptions() {
+        final int level = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AUTOFILL_LOGGING_LEVEL, AutofillManager.DEFAULT_LOGGING_LEVEL);
+
+        final int index;
+        if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) {
+            index = 1;
+        } else if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) {
+            index = 2;
+        } else {
+            index = 0;
+        }
+        final ListPreference listPreference = (ListPreference) mPreference;
+        listPreference.setValue(mListValues[index]);
+        listPreference.setSummary(mListSummaries[index]);
+    }
+
+    private void writeLevel(Object newValue) {
+        int level = AutofillManager.NO_LOGGING;
+        if (newValue instanceof String) {
+            level = Integer.parseInt((String) newValue);
+        }
+        Settings.Global.putInt(mContext.getContentResolver(),
+                Settings.Global.AUTOFILL_LOGGING_LEVEL, level);
+    }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillMaxPartitionsPreference.java b/src/com/android/settings/development/autofill/AutofillMaxPartitionsPreference.java
new file mode 100644
index 0000000..ab0cec9
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillMaxPartitionsPreference.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.view.autofill.AutofillManager;
+
+import java.text.NumberFormat;
+
+public final class AutofillMaxPartitionsPreference extends AbstractGlobalSettingsPreference {
+
+    public AutofillMaxPartitionsPreference(Context context, AttributeSet attrs) {
+        super(context, attrs, Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
+                AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
+    }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java b/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java
new file mode 100644
index 0000000..ed07f62
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillPreferenceCategory.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.autofill.AutofillManager;
+
+import androidx.preference.PreferenceCategory;
+
+public final class AutofillPreferenceCategory extends PreferenceCategory {
+
+    private static final String TAG = "AutofillPreferenceCategory";
+
+    private final ContentResolver mContentResolver;
+    private final ContentObserver mSettingsObserver;
+
+    public AutofillPreferenceCategory(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mSettingsObserver = new ContentObserver(new Handler()) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri, int userId) {
+                Log.w(TAG, "Autofill Service changed, but UI cannot be refreshed");
+                // TODO(b/111838239): we cannot update the UI because AFM.isEnabled() will return
+                // the previous value. Once that's fixed, we'll need to call one of the 2 callbacks
+                // below:
+                // notifyChanged();
+                // notifyDependencyChange(shouldDisableDependents());
+            }
+        };
+        mContentResolver = context.getContentResolver();
+    }
+
+    @Override
+    public void onAttached() {
+        super.onAttached();
+
+        mContentResolver.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.AUTOFILL_SERVICE), false,
+                mSettingsObserver);
+    }
+
+    @Override
+    public void onDetached() {
+        mContentResolver.unregisterContentObserver(mSettingsObserver);
+
+        super.onDetached();
+    }
+
+    // PreferenceCategory.isEnabled() always return false, so we rather not change that logic
+    // decide whether the children should be shown using isAutofillEnabled() instead.
+    private boolean isAutofillEnabled() {
+        final AutofillManager afm = getContext().getSystemService(AutofillManager.class);
+        final boolean enabled = afm != null && afm.isEnabled();
+        Log.v(TAG, "isAutofillEnabled(): " + enabled);
+        return enabled;
+    }
+
+    @Override
+    public boolean shouldDisableDependents() {
+        final boolean shouldIt = !isAutofillEnabled();
+        Log.v(TAG, "shouldDisableDependents(): " + shouldIt);
+        return shouldIt;
+    }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceController.java b/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceController.java
new file mode 100644
index 0000000..42f7a48
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.autofill.AutofillManager;
+import android.widget.Toast;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+public final class AutofillResetOptionsPreferenceController
+        extends DeveloperOptionsPreferenceController
+        implements PreferenceControllerMixin {
+
+    private static final String AUTOFILL_RESET_OPTIONS_KEY = "autofill_reset_developer_options";
+
+    public AutofillResetOptionsPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return AUTOFILL_RESET_OPTIONS_KEY;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!TextUtils.equals(AUTOFILL_RESET_OPTIONS_KEY, preference.getKey())) {
+            return false;
+        }
+        final ContentResolver contentResolver = mContext.getContentResolver();
+        Settings.Global.putInt(contentResolver, Settings.Global.AUTOFILL_LOGGING_LEVEL,
+                AutofillManager.DEFAULT_LOGGING_LEVEL);
+        Settings.Global.putInt(contentResolver, Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
+                AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
+        Settings.Global.putInt(contentResolver, Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0);
+        Toast.makeText(mContext, R.string.autofill_reset_developer_options_complete,
+                Toast.LENGTH_SHORT).show();
+        return true;
+    }
+}
diff --git a/src/com/android/settings/development/autofill/AutofillVisibleDatasetsPreference.java b/src/com/android/settings/development/autofill/AutofillVisibleDatasetsPreference.java
new file mode 100644
index 0000000..2f0d15f
--- /dev/null
+++ b/src/com/android/settings/development/autofill/AutofillVisibleDatasetsPreference.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+public final class AutofillVisibleDatasetsPreference extends AbstractGlobalSettingsPreference {
+
+    public AutofillVisibleDatasetsPreference(Context context, AttributeSet attrs) {
+        super(context, attrs, Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0);
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 9e920c4..3676761 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -38,11 +38,14 @@
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.util.ArrayUtils;
 import com.android.settings.R;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
 import com.android.settings.fuelgauge.batterytip.StatsManagerConfig;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
 import com.android.settingslib.utils.PowerUtil;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -101,8 +104,8 @@
         mContext = context;
         mPackageManager = context.getPackageManager();
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
-        mPowerUsageFeatureProvider = FeatureFactory.getFactory(
-                context).getPowerUsageFeatureProvider(context);
+        mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
+                .getPowerUsageFeatureProvider(context);
     }
 
     public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid,
@@ -400,6 +403,18 @@
         }
         // Control whether app could run jobs in the background
         mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName, mode);
+
+        ThreadUtils.postOnBackgroundThread(() -> {
+            final BatteryDatabaseManager batteryDatabaseManager = BatteryDatabaseManager
+                    .getInstance(mContext);
+            if (mode == AppOpsManager.MODE_IGNORED) {
+                batteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION,
+                        uid, packageName, System.currentTimeMillis());
+            } else if (mode == AppOpsManager.MODE_ALLOWED) {
+                batteryDatabaseManager.deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION,
+                        uid, packageName);
+            }
+        });
     }
 
     public boolean isForceAppStandbyEnabled(int uid, String packageName) {
diff --git a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
index 4934bce..b64a707 100644
--- a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
+++ b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
@@ -22,6 +22,8 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.IconDrawableFactory;
+import android.util.Log;
+import android.util.SparseLongArray;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
@@ -29,7 +31,9 @@
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
 import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment;
 import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
@@ -37,6 +41,7 @@
 import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
 import com.android.settings.widget.AppCheckBoxPreference;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.utils.StringUtil;
 import com.android.settingslib.widget.FooterPreferenceMixinCompat;
 
 import java.util.List;
@@ -57,6 +62,7 @@
     @VisibleForTesting
     static final String EXTRA_APP_INFO_LIST = "app_info_list";
     private static final String KEY_PREF_RESTRICTED_APP_LIST = "restrict_app_list";
+    private static final long TIME_NULL = -1;
 
     @VisibleForTesting
     List<AppInfo> mAppInfos;
@@ -68,6 +74,8 @@
     BatteryUtils mBatteryUtils;
     @VisibleForTesting
     PackageManager mPackageManager;
+    @VisibleForTesting
+    BatteryDatabaseManager mBatteryDatabaseManager;
     private final FooterPreferenceMixinCompat mFooterPreferenceMixin =
             new FooterPreferenceMixinCompat(this, getSettingsLifecycle());
 
@@ -96,6 +104,7 @@
         mPackageManager = context.getPackageManager();
         mIconDrawableFactory = IconDrawableFactory.newInstance(context);
         mBatteryUtils = BatteryUtils.getInstance(context);
+        mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
 
         refreshUi();
     }
@@ -135,6 +144,9 @@
     void refreshUi() {
         mRestrictedAppListGroup.removeAll();
         final Context context = getPrefContext();
+        final SparseLongArray timestampArray = mBatteryDatabaseManager
+                .queryActionTime(AnomalyDatabaseHelper.ActionType.RESTRICTION);
+        final long now = System.currentTimeMillis();
 
         for (int i = 0, size = mAppInfos.size(); i < size; i++) {
             final CheckBoxPreference checkBoxPreference = new AppCheckBoxPreference(context);
@@ -158,9 +170,16 @@
 
                     return false;
                 });
+
+                final long timestamp = timestampArray.get(appInfo.uid, TIME_NULL);
+                if (timestamp != TIME_NULL) {
+                    checkBoxPreference.setSummary(getString(R.string.restricted_app_time_summary,
+                            StringUtil.formatRelativeTime(context, now - timestamp, false)));
+                }
+                final CharSequence test = checkBoxPreference.getSummaryOn();
                 mRestrictedAppListGroup.addPreference(checkBoxPreference);
             } catch (PackageManager.NameNotFoundException e) {
-                e.printStackTrace();
+                Log.e(TAG, "Can't find package: " + appInfo.packageName);
             }
         }
     }
diff --git a/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java b/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java
index bc332b6..bd1633f 100644
--- a/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java
+++ b/src/com/android/settings/fuelgauge/batterytip/AnomalyDatabaseHelper.java
@@ -33,7 +33,7 @@
     private static final String TAG = "BatteryDatabaseHelper";
 
     private static final String DATABASE_NAME = "battery_settings.db";
-    private static final int DATABASE_VERSION = 4;
+    private static final int DATABASE_VERSION = 5;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({State.NEW,
@@ -45,8 +45,15 @@
         int AUTO_HANDLED = 2;
     }
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({ActionType.RESTRICTION})
+    public @interface ActionType {
+        int RESTRICTION = 0;
+    }
+
     public interface Tables {
         String TABLE_ANOMALY = "anomaly";
+        String TABLE_ACTION = "action";
     }
 
     public interface AnomalyColumns {
@@ -91,6 +98,42 @@
                     + AnomalyColumns.ANOMALY_STATE + "," + AnomalyColumns.TIME_STAMP_MS + ")"
                     + ")";
 
+
+    public interface ActionColumns {
+        /**
+         * The package name of an app been performed an action
+         */
+        String PACKAGE_NAME = "package_name";
+        /**
+         * The uid of an app been performed an action
+         */
+        String UID = "uid";
+        /**
+         * The type of user action
+         * @see ActionType
+         */
+        String ACTION_TYPE = "action_type";
+        /**
+         * The time when action been performed
+         */
+        String TIME_STAMP_MS = "time_stamp_ms";
+    }
+
+    private static final String CREATE_ACTION_TABLE =
+            "CREATE TABLE " + Tables.TABLE_ACTION +
+                    "(" +
+                    ActionColumns.UID +
+                    " INTEGER NOT NULL, " +
+                    ActionColumns.PACKAGE_NAME +
+                    " TEXT, " +
+                    ActionColumns.ACTION_TYPE +
+                    " INTEGER NOT NULL, " +
+                    ActionColumns.TIME_STAMP_MS +
+                    " INTEGER NOT NULL, " +
+                    " PRIMARY KEY (" + ActionColumns.ACTION_TYPE + "," + ActionColumns.UID + ","
+                    + ActionColumns.PACKAGE_NAME + ")"
+                    + ")";
+
     private static AnomalyDatabaseHelper sSingleton;
 
     public static synchronized AnomalyDatabaseHelper getInstance(Context context) {
@@ -109,11 +152,6 @@
         bootstrapDB(db);
     }
 
-    private void bootstrapDB(SQLiteDatabase db) {
-        db.execSQL(CREATE_ANOMALY_TABLE);
-        Log.i(TAG, "Bootstrapped database");
-    }
-
     @Override
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
         if (oldVersion < DATABASE_VERSION) {
@@ -137,7 +175,14 @@
         bootstrapDB(db);
     }
 
+    private void bootstrapDB(SQLiteDatabase db) {
+        db.execSQL(CREATE_ANOMALY_TABLE);
+        db.execSQL(CREATE_ACTION_TABLE);
+        Log.i(TAG, "Bootstrapped database");
+    }
+
     private void dropTables(SQLiteDatabase db) {
         db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ANOMALY);
+        db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ACTION);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
index 910b368..513244e 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
@@ -17,6 +17,8 @@
 package com.android.settings.fuelgauge.batterytip;
 
 import static android.database.sqlite.SQLiteDatabase.CONFLICT_IGNORE;
+import static android.database.sqlite.SQLiteDatabase.CONFLICT_REPLACE;
+
 import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
         .ANOMALY_STATE;
 import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
@@ -26,6 +28,7 @@
 import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
         .TIME_STAMP_MS;
 import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns.UID;
+import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.Tables.TABLE_ACTION;
 import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.Tables.TABLE_ANOMALY;
 
 import android.content.ContentValues;
@@ -34,12 +37,15 @@
 import android.database.sqlite.SQLiteDatabase;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.SparseLongArray;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.ActionColumns;
+
 import androidx.annotation.VisibleForTesting;
 
 /**
@@ -158,4 +164,65 @@
             }
         }
     }
+
+    /**
+     * Query latest timestamps when an app has been performed action {@code type}
+     *
+     * @param type of action been performed
+     * @return {@link SparseLongArray} where key is uid and value is timestamp
+     */
+    public synchronized SparseLongArray queryActionTime(
+            @AnomalyDatabaseHelper.ActionType int type) {
+        final SparseLongArray timeStamps = new SparseLongArray();
+        try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
+            final String[] projection = {ActionColumns.UID, ActionColumns.TIME_STAMP_MS};
+            final String selection = ActionColumns.ACTION_TYPE + " = ? ";
+            final String[] selectionArgs = new String[]{String.valueOf(type)};
+
+            try (Cursor cursor = db.query(TABLE_ACTION, projection, selection, selectionArgs,
+                    null /* groupBy */, null /* having */, null /* orderBy */)) {
+                final int uidIndex = cursor.getColumnIndex(ActionColumns.UID);
+                final int timestampIndex = cursor.getColumnIndex(ActionColumns.TIME_STAMP_MS);
+
+                while (cursor.moveToNext()) {
+                    final int uid = cursor.getInt(uidIndex);
+                    final long timeStamp = cursor.getLong(timestampIndex);
+                    timeStamps.append(uid, timeStamp);
+                }
+            }
+        }
+
+        return timeStamps;
+    }
+
+    /**
+     * Insert an action, or update it if already existed
+     */
+    public synchronized boolean insertAction(@AnomalyDatabaseHelper.ActionType int type,
+            int uid, String packageName, long timestampMs) {
+        try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
+            final ContentValues values = new ContentValues();
+            values.put(ActionColumns.UID, uid);
+            values.put(ActionColumns.PACKAGE_NAME, packageName);
+            values.put(ActionColumns.ACTION_TYPE, type);
+            values.put(ActionColumns.TIME_STAMP_MS, timestampMs);
+            return db.insertWithOnConflict(TABLE_ACTION, null, values, CONFLICT_REPLACE) != -1;
+        }
+    }
+
+    /**
+     * Remove an action
+     */
+    public synchronized boolean deleteAction(@AnomalyDatabaseHelper.ActionType int type,
+            int uid, String packageName) {
+        try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
+            final String where =
+                    ActionColumns.ACTION_TYPE + " = ? AND " + ActionColumns.UID + " = ? AND "
+                            + ActionColumns.PACKAGE_NAME + " = ? ";
+            final String[] whereArgs = new String[]{String.valueOf(type), String.valueOf(uid),
+                    String.valueOf(packageName)};
+
+            return db.delete(TABLE_ACTION, where, whereArgs) != 0;
+        }
+    }
 }
diff --git a/src/com/android/settings/widget/AppCheckBoxPreference.java b/src/com/android/settings/widget/AppCheckBoxPreference.java
index a0d95e9..bd643ba 100644
--- a/src/com/android/settings/widget/AppCheckBoxPreference.java
+++ b/src/com/android/settings/widget/AppCheckBoxPreference.java
@@ -17,11 +17,16 @@
 package com.android.settings.widget;
 
 import android.content.Context;
+import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import com.android.settings.R;
 
 import androidx.preference.CheckBoxPreference;
+import androidx.preference.PreferenceViewHolder;
 
 /**
  * {@link CheckBoxPreference} that used only to display app
@@ -36,4 +41,20 @@
         super(context);
         setLayoutResource(R.layout.preference_app);
     }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        final TextView appendix = (TextView) holder.findViewById(R.id.appendix);
+        if (appendix != null) {
+            appendix.setVisibility(View.GONE);
+        }
+
+        final LinearLayout layout = (LinearLayout) holder.findViewById(R.id.summary_container);
+        if (layout != null) {
+            // If summary doesn't exist, make it gone
+            layout.setVisibility(TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE);
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/LinkablePreference.java b/src/com/android/settings/wifi/LinkablePreference.java
index 9c00ee2..9581e7a 100644
--- a/src/com/android/settings/wifi/LinkablePreference.java
+++ b/src/com/android/settings/wifi/LinkablePreference.java
@@ -23,12 +23,14 @@
 import android.util.AttributeSet;
 import android.widget.TextView;
 
-import com.android.settings.LinkifyUtils;
-
 import androidx.annotation.Nullable;
+import androidx.core.content.res.TypedArrayUtils;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
+import com.android.settings.LinkifyUtils;
+import com.android.settingslib.R;
+
 /**
  * A preference with a title that can have linkable content on click.
  */
@@ -38,19 +40,20 @@
     private CharSequence mContentTitle;
     private CharSequence mContentDescription;
 
+
     public LinkablePreference(Context ctx, AttributeSet attrs, int defStyle) {
         super(ctx, attrs, defStyle);
+        setIcon(R.drawable.ic_info_outline_24dp);
         setSelectable(false);
     }
 
     public LinkablePreference(Context ctx, AttributeSet attrs) {
-        super(ctx, attrs);
-        setSelectable(false);
+        this(ctx, attrs, TypedArrayUtils.getAttr(
+                ctx, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
     }
 
     public LinkablePreference(Context ctx) {
-        super(ctx);
-        setSelectable(false);
+        this(ctx, null);
     }
 
     @Override
@@ -75,21 +78,20 @@
 
         boolean linked = LinkifyUtils.linkify(textView, contentBuilder, mClickListener);
         if (linked && mContentTitle != null) {
-            // Embolden and enlarge the title.
-            Spannable boldSpan = (Spannable) textView.getText();
-            boldSpan.setSpan(
-                    new TextAppearanceSpan(
-                            getContext(), android.R.style.TextAppearance_Medium),
+            Spannable spannableContent = (Spannable) textView.getText();
+            spannableContent.setSpan(
+                    new TextAppearanceSpan(getContext(), android.R.style.TextAppearance_Small),
                     0,
                     mContentTitle.length(),
                     Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
-            textView.setText(boldSpan);
+            textView.setText(spannableContent);
             textView.setMovementMethod(new LinkMovementMethod());
         }
     }
 
     /**
      * Sets the linkable text for the Preference title.
+     *
      * @param contentTitle text to set the Preference title.
      * @param contentDescription description text to append underneath title, can be null.
      * @param clickListener OnClickListener for the link portion of the text.
diff --git a/tests/robotests/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceControllerTest.java
new file mode 100644
index 0000000..b9da71d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/autofill/AutofillLoggingLevelPreferenceControllerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.RemoteException;
+import android.view.autofill.AutofillManager;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.ListPreference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AutofillLoggingLevelPreferenceControllerTest {
+
+    private static final int IDX_OFF = 0;
+    private static final int IDX_DEBUG = 1;
+    private static final int IDX_VERBOSE = 2;
+
+    @Mock
+    private ListPreference mPreference;
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+
+    private Context mContext;
+    private AutofillLoggingLevelPreferenceController mController;
+    private AutofillTestingHelper mHelper;
+
+    private String[] mListValues;
+    private String[] mListSummaries;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this); // TODO: use @Rule
+        mContext = RuntimeEnvironment.application;
+        mHelper = new AutofillTestingHelper(mContext);
+        final Resources resources = mContext.getResources();
+        mListValues = resources.getStringArray(R.array.autofill_logging_level_values);
+        mListSummaries = resources.getStringArray(R.array.autofill_logging_level_entries);
+        mController = new AutofillLoggingLevelPreferenceController(mContext);
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_differentPreferenceKey_shouldNotTrigger()
+            throws Exception {
+        when(mPreference.getKey()).thenReturn("SomeRandomKey");
+
+        mHelper.setLoggingLevel(108);
+
+        assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
+
+        assertThat(mHelper.getLoggingLevel()).isEqualTo(108);
+    }
+
+    @Test
+    public void onPreferenceChange_off() throws Exception {
+        mHelper.setLoggingLevel(108);
+
+        mController.onPreferenceChange(mPreference, mListValues[IDX_OFF]);
+
+        assertThat(mHelper.getLoggingLevel()).isEqualTo(AutofillManager.NO_LOGGING);
+    }
+
+    @Test
+    public void onPreferenceChange_debug() throws Exception {
+        mHelper.setLoggingLevel(108);
+
+        mController.onPreferenceChange(mPreference, mListValues[IDX_DEBUG]);
+
+        assertThat(mHelper.getLoggingLevel())
+                .isEqualTo(AutofillManager.FLAG_ADD_CLIENT_DEBUG);
+    }
+
+    @Test
+    public void onPreferenceChange_verbose() throws Exception {
+        mHelper.setLoggingLevel(108);
+
+        mController.onPreferenceChange(mPreference, mListValues[IDX_VERBOSE]);
+
+        assertThat(mHelper.getLoggingLevel())
+                .isEqualTo(AutofillManager.FLAG_ADD_CLIENT_VERBOSE);
+    }
+
+    @Test
+    public void onSettingsChange_off() throws Exception {
+        mHelper.setLoggingLevel(AutofillManager.NO_LOGGING);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setValue(mListValues[IDX_OFF]);
+        verify(mPreference).setSummary(mListSummaries[IDX_OFF]);
+    }
+
+    @Test
+    public void onSettingsChange_debug() throws Exception {
+        mHelper.setLoggingLevel(AutofillManager.FLAG_ADD_CLIENT_DEBUG);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setValue(mListValues[IDX_DEBUG]);
+        verify(mPreference).setSummary(mListSummaries[IDX_DEBUG]);
+    }
+
+    @Test
+    public void onSettingsChange_verbose() throws Exception {
+        mHelper.setLoggingLevel(AutofillManager.FLAG_ADD_CLIENT_VERBOSE);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setValue(mListValues[IDX_VERBOSE]);
+        verify(mPreference).setSummary(mListSummaries[IDX_VERBOSE]);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceControllerTest.java
new file mode 100644
index 0000000..e560a83
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/autofill/AutofillResetOptionsPreferenceControllerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.view.autofill.AutofillManager;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AutofillResetOptionsPreferenceControllerTest {
+
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+
+    private Context mContext;
+    private AutofillResetOptionsPreferenceController mController;
+    private AutofillTestingHelper mHelper;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this); // TODO: use @Rule
+        mContext = RuntimeEnvironment.application;
+        mHelper = new AutofillTestingHelper(mContext);
+        mController = new AutofillResetOptionsPreferenceController(mContext);
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_differentPreferenceKey_shouldNotReset() throws Exception {
+        when(mPreference.getKey()).thenReturn("SomeRandomKey");
+
+        mHelper.setLoggingLevel(4);
+        mHelper.setMaxPartitionsSize(8);
+        mHelper.setMaxVisibleDatasets(15);
+
+        assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
+
+        assertThat(mHelper.getLoggingLevel()).isEqualTo(4);
+        assertThat(mHelper.getMaxPartitionsSize()).isEqualTo(8);
+        assertThat(mHelper.getMaxVisibleDatasets()).isEqualTo(15);
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_correctPreferenceKey_shouldReset() throws Exception {
+        when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+
+        mHelper.setMaxPartitionsSize(16);
+        mHelper.setMaxVisibleDatasets(23);
+        mHelper.setLoggingLevel(42);
+
+        assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
+
+        assertThat(mHelper.getLoggingLevel())
+                .isEqualTo(AutofillManager.DEFAULT_LOGGING_LEVEL);
+        assertThat(mHelper.getMaxPartitionsSize())
+                .isEqualTo(AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
+        assertThat(mHelper.getMaxVisibleDatasets())
+                .isEqualTo(0);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/autofill/AutofillTestingHelper.java b/tests/robotests/src/com/android/settings/development/autofill/AutofillTestingHelper.java
new file mode 100644
index 0000000..59090bc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/autofill/AutofillTestingHelper.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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.autofill;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+
+final class AutofillTestingHelper {
+    private final ContentResolver mResolver;
+
+    public AutofillTestingHelper(Context context) {
+        mResolver = context.getContentResolver();
+    }
+
+    public void setLoggingLevel(int max) {
+        setGlobal(Settings.Global.AUTOFILL_LOGGING_LEVEL, max);
+    }
+
+    public void setMaxPartitionsSize(int max) {
+        setGlobal(Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max);
+    }
+
+    public void setMaxVisibleDatasets(int level) {
+        setGlobal(Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, level);
+    }
+
+    public int getLoggingLevel() throws SettingNotFoundException {
+        return getGlobal(Settings.Global.AUTOFILL_LOGGING_LEVEL);
+    }
+
+    public int getMaxPartitionsSize() throws SettingNotFoundException {
+        return getGlobal(Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE);
+    }
+
+    public int getMaxVisibleDatasets() throws SettingNotFoundException {
+        return getGlobal(Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS);
+    }
+
+    private void setGlobal(String key, int value) {
+        Settings.Global.putInt(mResolver, key, value);
+    }
+
+    private int getGlobal(String key) throws SettingNotFoundException {
+        return Settings.Global.getInt(mResolver, key);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
index 58bfe0e..41e77e9 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.text.format.DateUtils;
+import android.util.SparseLongArray;
 
 import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 import com.android.settings.fuelgauge.batterytip.AppInfo;
@@ -88,7 +89,7 @@
     }
 
     @Test
-    public void testAllFunctions() {
+    public void allAnomalyFunctions() {
         mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
                 AnomalyDatabaseHelper.State.NEW, NOW);
         mBatteryDatabaseManager.insertAnomaly(UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD,
@@ -113,7 +114,7 @@
     }
 
     @Test
-    public void testUpdateAnomalies_updateSuccessfully() {
+    public void updateAnomalies_updateSuccessfully() {
         mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
                 AnomalyDatabaseHelper.State.NEW, NOW);
         mBatteryDatabaseManager.insertAnomaly(UID_OLD, PACKAGE_NAME_OLD, TYPE_OLD,
@@ -138,7 +139,7 @@
     }
 
     @Test
-    public void testQueryAnomalies_removeDuplicateByUid() {
+    public void queryAnomalies_removeDuplicateByUid() {
         mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_NEW,
                 AnomalyDatabaseHelper.State.NEW, NOW);
         mBatteryDatabaseManager.insertAnomaly(UID_NEW, PACKAGE_NAME_NEW, TYPE_OLD,
@@ -149,4 +150,28 @@
                 AnomalyDatabaseHelper.State.NEW);
         assertThat(newAppInfos).containsExactly(mCombinedAppInfo);
     }
+
+    @Test
+    public void allActionFunctions() {
+        final long timestamp = System.currentTimeMillis();
+        mBatteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_OLD,
+                PACKAGE_NAME_OLD, 0);
+        mBatteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_OLD,
+                PACKAGE_NAME_OLD, 1);
+        mBatteryDatabaseManager.insertAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_NEW,
+                PACKAGE_NAME_NEW, timestamp);
+
+        final SparseLongArray timeArray = mBatteryDatabaseManager.queryActionTime(
+                AnomalyDatabaseHelper.ActionType.RESTRICTION);
+        assertThat(timeArray.size()).isEqualTo(2);
+        assertThat(timeArray.get(UID_OLD)).isEqualTo(1);
+        assertThat(timeArray.get(UID_NEW)).isEqualTo(timestamp);
+
+        mBatteryDatabaseManager.deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION, UID_NEW,
+                PACKAGE_NAME_NEW);
+        final SparseLongArray recentTimeArray = mBatteryDatabaseManager.queryActionTime(
+                AnomalyDatabaseHelper.ActionType.RESTRICTION);
+        assertThat(recentTimeArray.size()).isEqualTo(1);
+        assertThat(timeArray.get(UID_OLD)).isEqualTo(1);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index df34b78..b274492 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -51,9 +51,12 @@
 
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 import com.android.settings.fuelgauge.batterytip.AnomalyInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowThreadUtils;
 import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
 
 import org.junit.Before;
@@ -148,6 +151,8 @@
     private ApplicationInfo mLowApplicationInfo;
     @Mock
     private PowerWhitelistBackend mPowerWhitelistBackend;
+    @Mock
+    private BatteryDatabaseManager mBatteryDatabaseManager;
     private AnomalyInfo mAnomalyInfo;
     private BatteryUtils mBatteryUtils;
     private FakeFeatureFactory mFeatureFactory;
@@ -225,6 +230,8 @@
             .thenReturn(TOTAL_BATTERY_USAGE + BATTERY_SCREEN_USAGE);
         when(mBatteryStatsHelper.getStats().getDischargeAmount(anyInt()))
             .thenReturn(DISCHARGE_AMOUNT);
+        BatteryDatabaseManager.setUpForTest(mBatteryDatabaseManager);
+        ShadowThreadUtils.setIsMainThread(true);
     }
 
     @Test
@@ -570,6 +577,23 @@
     }
 
     @Test
+    public void testSetForceAppStandby_restrictApp_recordTime() {
+        mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
+
+        verify(mBatteryDatabaseManager).insertAction(
+                eq(AnomalyDatabaseHelper.ActionType.RESTRICTION), eq(UID),
+                eq(HIGH_SDK_PACKAGE), anyLong());
+    }
+
+    @Test
+    public void testSetForceAppStandby_unrestrictApp_deleteTime() {
+        mBatteryUtils.setForceAppStandby(UID, HIGH_SDK_PACKAGE, AppOpsManager.MODE_ALLOWED);
+
+        verify(mBatteryDatabaseManager).deleteAction(AnomalyDatabaseHelper.ActionType.RESTRICTION,
+                UID, HIGH_SDK_PACKAGE);
+    }
+
+    @Test
     public void testIsForceAppStandbyEnabled_enabled_returnTrue() {
         when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
                 PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_IGNORED);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
index b9ed509..7219f18 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
@@ -28,10 +28,13 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.IconDrawableFactory;
+import android.util.SparseLongArray;
 
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
 import com.android.settings.fuelgauge.batterytip.BatteryTipDialogFragment;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
@@ -52,6 +55,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import androidx.appcompat.app.AlertDialog;
 import androidx.preference.CheckBoxPreference;
@@ -76,6 +80,8 @@
     private IconDrawableFactory mIconDrawableFactory;
     @Mock
     private InstrumentedPreferenceFragment mFragment;
+    @Mock
+    private BatteryDatabaseManager mBatteryDatabaseManager;
     private PreferenceManager mPreferenceManager;
     private RestrictedAppDetails mRestrictedAppDetails;
     private Context mContext;
@@ -98,12 +104,14 @@
 
         doReturn(mPreferenceManager).when(mRestrictedAppDetails).getPreferenceManager();
         doReturn(mContext).when(mFragment).getContext();
+        doReturn(mContext).when(mRestrictedAppDetails).getContext();
         mRestrictedAppDetails.mPackageManager = mPackageManager;
         mRestrictedAppDetails.mIconDrawableFactory = mIconDrawableFactory;
         mRestrictedAppDetails.mAppInfos = new ArrayList<>();
         mRestrictedAppDetails.mAppInfos.add(mAppInfo);
         mRestrictedAppDetails.mRestrictedAppListGroup = spy(new PreferenceCategory(mContext));
         mRestrictedAppDetails.mBatteryUtils = spy(new BatteryUtils(mContext));
+        mRestrictedAppDetails.mBatteryDatabaseManager = mBatteryDatabaseManager;
         doReturn(mPreferenceManager).when(
                 mRestrictedAppDetails.mRestrictedAppListGroup).getPreferenceManager();
 
@@ -118,6 +126,10 @@
         doReturn(APP_NAME).when(mPackageManager).getApplicationLabel(mApplicationInfo);
         doReturn(true).when(mRestrictedAppDetails.mBatteryUtils).isForceAppStandbyEnabled(UID,
                 PACKAGE_NAME);
+        final SparseLongArray timestampArray = new SparseLongArray();
+        timestampArray.put(UID, System.currentTimeMillis() - TimeUnit.HOURS.toMillis(5));
+        doReturn(timestampArray).when(mBatteryDatabaseManager)
+                .queryActionTime(AnomalyDatabaseHelper.ActionType.RESTRICTION);
 
         mRestrictedAppDetails.refreshUi();
 
@@ -126,6 +138,7 @@
                 (CheckBoxPreference) mRestrictedAppDetails.mRestrictedAppListGroup.getPreference(0);
         assertThat(preference.getTitle()).isEqualTo(APP_NAME);
         assertThat(preference.isChecked()).isTrue();
+        assertThat(preference.getSummary()).isEqualTo("Restricted 5 hours ago");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java b/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java
new file mode 100644
index 0000000..57d7798
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wallpaper/FallbackHomeActivityTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 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.wallpaper;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.app.WallpaperManager.OnColorsChangedListener;
+import android.os.Handler;
+
+import com.android.settings.FallbackHome;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Build/Install/Run:
+ *     make RunSettingsRoboTests -j40 ROBOTEST_FILTER=FallbackHomeActivityTest
+ */
+@RunWith(SettingsRobolectricTestRunner.class)
+public class FallbackHomeActivityTest {
+
+    private ActivityController<FallbackHome> mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = Robolectric.buildActivity(FallbackHome.class);
+    }
+
+    @Test
+    @Config(shadows = ShadowWallpaperManager.class)
+    public void wallpaperColorsChangedListener_ensured_removed() {
+        // onCreate adds the first color listener by WallpaperManager returning null colors
+        ActivityController controller = mController.setup();
+        ShadowWallpaperManager shadowManager = Shadow.extract(RuntimeEnvironment.application
+                .getSystemService(WallpaperManager.class));
+        assertThat(shadowManager.size()).isEqualTo(1);
+
+        // Assert onDestroy will remove the original listener
+        controller.destroy();
+        assertThat(shadowManager.size()).isEqualTo(0);
+    }
+
+    @Implements(WallpaperManager.class)
+    public static class ShadowWallpaperManager {
+
+        private final List<OnColorsChangedListener> mListener = new ArrayList<>();
+
+        public int size() {
+            return mListener.size();
+        }
+
+        @Implementation
+        public boolean isWallpaperServiceEnabled() {
+            return true;
+        }
+
+        @Implementation
+        public @Nullable WallpaperColors getWallpaperColors(int which) {
+            return null;
+        }
+
+        @Implementation
+        public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener,
+                @NonNull Handler handler) {
+            mListener.add(listener);
+        }
+
+        @Implementation
+        public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
+            mListener.remove(listener);
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
index af867e6..e20520f 100644
--- a/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
@@ -19,6 +19,8 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
 
 import com.android.settings.R;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -28,18 +30,25 @@
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
 
+import androidx.preference.PreferenceViewHolder;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class AppCheckBoxPreferenceTest {
 
+    private static final String SUMMARY = "summary info";
+
     private Context mContext;
     private AppCheckBoxPreference mPreference;
     private AppCheckBoxPreference mAttrPreference;
+    private PreferenceViewHolder mPreferenceViewHolder;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
         mPreference = new AppCheckBoxPreference(mContext);
         mAttrPreference = new AppCheckBoxPreference(mContext, null /* attrs */);
+        mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(
+                LayoutInflater.from(mContext).inflate(R.layout.preference_app, null));
     }
 
     @Test
@@ -47,4 +56,32 @@
         assertThat(mPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
         assertThat(mAttrPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
     }
+
+    @Test
+    public void onBindViewHolder_noSummary_layoutGone() {
+        mPreference.setSummary("");
+
+        mPreference.onBindViewHolder(mPreferenceViewHolder);
+
+        assertThat(mPreferenceViewHolder.findViewById(R.id.summary_container).getVisibility())
+                .isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void onBindViewHolder_hasSummary_layoutVisible() {
+        mPreference.setSummary(SUMMARY);
+
+        mPreference.onBindViewHolder(mPreferenceViewHolder);
+
+        assertThat(mPreferenceViewHolder.findViewById(R.id.summary_container).getVisibility())
+                .isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void onBindViewHolder_appendixGone() {
+        mPreference.onBindViewHolder(mPreferenceViewHolder);
+
+        assertThat(mPreferenceViewHolder.findViewById(R.id.appendix).getVisibility())
+                .isEqualTo(View.GONE);
+    }
 }
diff --git a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
index 176d3c4..59f22db 100644
--- a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
+++ b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
@@ -19,6 +19,7 @@
 import static junit.framework.Assert.fail;
 
 import android.content.Context;
+import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.MediumTest;
@@ -52,6 +53,7 @@
     @Test
     @Presubmit
     public void controllersInSearchShouldImplementPreferenceControllerMixin() {
+        Looper.prepare(); // Required by AutofillLoggingLevelPreferenceController
         final Set<String> errorClasses = new ArraySet<>();
 
         final SearchIndexableResources resources =