Merge "Add an activity that starts DataUsageList fragment for mobile."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f574688..282eedd 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3054,7 +3054,8 @@
                        android:value="com.android.settings.deletionhelper.AutomaticStorageManagerSettings" />
         </activity>
 
-        <activity android:name="Settings$LegacySupportActivity">
+        <activity android:name="Settings$LegacySupportActivity"
+                  android:label="@string/page_tab_title_support">
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
             android:value="com.android.settings.dashboard.SupportFragment"/>
         </activity>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8822460..2c58aae 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4649,23 +4649,30 @@
     <!-- Title for force stop dialog [CHAR LIMIT=30] -->
     <string name="dialog_stop_title">Stop app?</string>
     <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
-    <string name="dialog_stop_message" product="default">Your phone can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> is keeping your phone awake.\n\nTo try to fix this issue, you can force stop the app.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
+    <string name="dialog_stop_message" product="default">Your phone can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> is keeping your phone awake.\n\nTo try to fix this issue, you can stop the app.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
     <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
-    <string name="dialog_stop_message" product="tablet">Your tablet can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> is keeping your tablet awake.\n\nTo try to fix this issue, you can force stop the app.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
+    <string name="dialog_stop_message" product="tablet">Your tablet can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> is keeping your tablet awake.\n\nTo try to fix this issue, you can stop the app.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
     <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
-    <string name="dialog_stop_message" product="device">Your device can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> is keeping your device awake.\n\nTo try to fix this issue, you can force stop the app.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
+    <string name="dialog_stop_message" product="device">Your device can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> is keeping your device awake.\n\nTo try to fix this issue, you can stop the app.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
+
+    <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
+    <string name="dialog_stop_message_wakeup_alarm" product="default">Your phone can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your phone.\n\nTo try to fix this issue, you can stop <xliff:g id="app">%1$s</xliff:g>.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
+    <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
+    <string name="dialog_stop_message_wakeup_alarm" product="tablet">Your tablet can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your tablet.\n\nTo try to fix this issue, you can stop <xliff:g id="app">%1$s</xliff:g>.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
+    <!-- Message body for force stop dialog [CHAR LIMIT=NONE] -->
+    <string name="dialog_stop_message_wakeup_alarm" product="device">Your device can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your device.\n\nTo try to fix this issue, you can stop <xliff:g id="app">%1$s</xliff:g>.\n\nIf this keeps happening, you may need to uninstall the app to improve battery performance.</string>
 
     <!-- Text for OK button in force stop dialog [CHAR LIMIT=30] -->
     <string name="dialog_stop_ok">Stop app</string>
 
     <!-- Title for background usage dialog [CHAR LIMIT=60] -->
-    <string name="dialog_background_check_title">Turn off background usage?</string>
+    <string name="dialog_background_check_title">Turn off background usage &amp; stop app?</string>
     <!-- Message body for background usage dialog [CHAR LIMIT=NONE] -->
-    <string name="dialog_background_check_message" product="default">Your phone can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your phone.\n\nTo address this issue, your phone can prevent this app from running in the background.</string>
+    <string name="dialog_background_check_message" product="default">Your phone can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your phone.\n\nTo try to fix this issue, you can stop <xliff:g id="app">%1$s</xliff:g> and prevent it from running in the background.</string>
     <!-- Message body for background usage dialog [CHAR LIMIT=NONE] -->
-    <string name="dialog_background_check_message" product="tablet">Your tablet can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your tablet.\n\nTo address this issue, your tablet can prevent this app from running in the background.</string>
+    <string name="dialog_background_check_message" product="tablet">Your tablet can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your tablet.\n\nTo try to fix this issue, you can stop <xliff:g id="app">%1$s</xliff:g> and prevent it from running in the background.</string>
     <!-- Message body for background usage dialog [CHAR LIMIT=NONE] -->
-    <string name="dialog_background_check_message" product="device">Your device can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your device.\n\nTo address this issue, your device can prevent this app from running in the background.</string>
+    <string name="dialog_background_check_message" product="device">Your device can\'t manage battery normally because <xliff:g id="app">%1$s</xliff:g> keeps waking up your device.\n\nTo try to fix this issue, you can stop <xliff:g id="app">%1$s</xliff:g> and prevent it from running in the background.</string>
     <!-- Text for OK button in background usage dialog [CHAR LIMIT=30] -->
     <string name="dialog_background_check_ok">Turn off</string>
 
diff --git a/res/xml/account_type_settings.xml b/res/xml/account_type_settings.xml
index 0ba961f..31f3f69 100644
--- a/res/xml/account_type_settings.xml
+++ b/res/xml/account_type_settings.xml
@@ -25,20 +25,21 @@
         android:selectable="false"
         android:order="-10000"/>
 
+    <PreferenceCategory
+      android:key="dashboard_tile_placeholder"
+      android:order="100"/>
+
     <Preference
         android:key="account_sync"
         android:title="@string/account_sync_title"
         android:icon="@drawable/ic_sync"
-        android:order="-9999"/>
-
-    <PreferenceCategory
-      android:key="dashboard_tile_placeholder"
-      android:order="-9998"/>
+        android:order="200"/>
 
     <com.android.settings.applications.LayoutPreference
       android:key="remove_account"
       android:layout="@layout/remove_account_button"
       android:order="1000"
-      android:selectable="false"/>
+      android:selectable="false"
+      settings:allowDividerAbove="true"/>
 
 </PreferenceScreen>
diff --git a/res/xml/app_storage_settings.xml b/res/xml/app_storage_settings.xml
index 1c71bfa..b96afbf 100644
--- a/res/xml/app_storage_settings.xml
+++ b/res/xml/app_storage_settings.xml
@@ -41,7 +41,6 @@
 
     <PreferenceCategory
         android:key="storage_category"
-        android:layout="@layout/tall_preference_category"
         android:title="@string/app_info_storage_title"
         settings:allowDividerAbove="false"
         settings:allowDividerBelow="false">
diff --git a/res/xml/installed_app_details.xml b/res/xml/installed_app_details.xml
index 865f41f..df7027c 100644
--- a/res/xml/installed_app_details.xml
+++ b/res/xml/installed_app_details.xml
@@ -45,9 +45,9 @@
     <com.android.settings.widget.FixedLineSummaryPreference
         android:key="permission_settings"
         android:title="@string/permissions_label"
-        android:summary="@string/summary_two_lines_placeholder"
+        android:summary="@string/summary_placeholder"
         android:selectable="true"
-        app:summaryLineCount="2" />
+        app:summaryLineCount="1" />
 
     <Preference
         android:key="storage_settings"
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index d288a9d..f5705bb 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -14,12 +14,15 @@
      limitations under the License.
 -->
 
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-                  xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
-          android:title="@string/sound_settings"
-          android:key="sound_settings"
-          settings:keywords="@string/keywords_sounds">
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+    android:title="@string/sound_settings"
+    android:key="sound_settings"
+    settings:keywords="@string/keywords_sounds">
 
+    <PreferenceCategory
+        android:order="-100">
         <!-- Media volume -->
         <com.android.settings.notification.VolumeSeekBarPreference
                 android:key="media_volume"
@@ -49,7 +52,6 @@
                 android:key="vibrate_when_ringing"
                 android:title="@string/vibrate_when_ringing_title" />
 
-
         <!-- Interruptions -->
         <com.android.settingslib.RestrictedPreference
                 android:key="zen_mode"
@@ -84,11 +86,13 @@
             android:summary="@string/summary_placeholder"
             android:persistent="false"
             android:ringtoneType="alarm" />
+    </PreferenceCategory>
 
-        <!-- Other sounds -->
-        <PreferenceCategory
+    <!-- Other sounds -->
+    <PreferenceCategory
           android:key="other_sound_preferecence_category"
-          android:title="@string/other_sound_category_preference_title" />
+          android:title="@string/other_sound_category_preference_title"
+          android:order="-50">
 
         <!-- Dial pad tones -->
         <SwitchPreference
@@ -136,21 +140,24 @@
           android:key="emergency_tone"
           android:title="@string/emergency_tone_title"
           android:summary="%s" />
+    </PreferenceCategory>
 
-        <com.android.settingslib.RestrictedPreference
-          android:key="cell_broadcast_settings"
-          android:title="@string/cell_broadcast_settings"
-          settings:useAdminDisabledSummary="true"
-          settings:allowDividerAbove="true" >
-                <intent
-                  android:action="android.intent.action.MAIN"
-                  android:targetPackage="com.android.cellbroadcastreceiver"
-                  android:targetClass="com.android.cellbroadcastreceiver.CellBroadcastSettings" />
-        </com.android.settingslib.RestrictedPreference>
+    <com.android.settingslib.RestrictedPreference
+      android:key="cell_broadcast_settings"
+      android:title="@string/cell_broadcast_settings"
+      settings:useAdminDisabledSummary="true"
+      settings:allowDividerAbove="true"
+      android:order="-1">
+            <intent
+              android:action="android.intent.action.MAIN"
+              android:targetPackage="com.android.cellbroadcastreceiver"
+              android:targetClass="com.android.cellbroadcastreceiver.CellBroadcastSettings" />
+    </com.android.settingslib.RestrictedPreference>
 
-        <com.android.settings.WorkOnlyCategory
-            android:key="sound_work_settings_section"
-            android:title="@string/sound_work_settings">
+    <com.android.settings.WorkOnlyCategory
+        android:key="sound_work_settings_section"
+        android:title="@string/sound_work_settings"
+        android:order="100">
 
                 <!-- Use the same sounds of the work profile -->
                 <SwitchPreference
@@ -184,5 +191,5 @@
                     android:ringtoneType="alarm"
                     android:dependency="work_use_personal_sounds" />
 
-        </com.android.settings.WorkOnlyCategory>
+    </com.android.settings.WorkOnlyCategory>
 </PreferenceScreen>
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index a7d18df..fee12e3 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -127,6 +127,7 @@
                 public List<String> getNonIndexableKeys(Context context) {
                     List<String> keys = super.getNonIndexableKeys(context);
                     keys.add(KEY_DISPLAY_SIZE);
+                    keys.add(WallpaperPreferenceController.KEY_WALLPAPER);
                     return keys;
                 }
 
diff --git a/src/com/android/settings/EncryptionInterstitial.java b/src/com/android/settings/EncryptionInterstitial.java
index c352bf0..f0115b8 100644
--- a/src/com/android/settings/EncryptionInterstitial.java
+++ b/src/com/android/settings/EncryptionInterstitial.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -57,6 +58,12 @@
     }
 
     @Override
+    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
+        resid = SetupWizardUtils.getTheme(getIntent());
+        super.onApplyThemeResource(theme, resid, first);
+    }
+
+    @Override
     protected boolean isValidFragment(String fragmentName) {
         return EncryptionInterstitialFragment.class.getName().equals(fragmentName);
     }
diff --git a/src/com/android/settings/SetupEncryptionInterstitial.java b/src/com/android/settings/SetupEncryptionInterstitial.java
index 4f30cc0..989cc2b 100644
--- a/src/com/android/settings/SetupEncryptionInterstitial.java
+++ b/src/com/android/settings/SetupEncryptionInterstitial.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.Resources;
 import android.os.Bundle;
 import android.widget.LinearLayout;
 
@@ -55,12 +54,6 @@
     }
 
     @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
-    @Override
     protected void onCreate(Bundle savedInstance) {
         super.onCreate(savedInstance);
         LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
diff --git a/src/com/android/settings/SetupRedactionInterstitial.java b/src/com/android/settings/SetupRedactionInterstitial.java
index 321040e..ac1db15 100644
--- a/src/com/android/settings/SetupRedactionInterstitial.java
+++ b/src/com/android/settings/SetupRedactionInterstitial.java
@@ -60,12 +60,6 @@
         return SetupRedactionInterstitialFragment.class.getName().equals(fragmentName);
     }
 
-    @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
     public static class SetupRedactionInterstitialFragment extends RedactionInterstitialFragment {
 
         // Setup wizard specific UI customizations can be done here
diff --git a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
index a74b896..b1455bf 100644
--- a/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDetailDashboardFragment.java
@@ -58,6 +58,7 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        getPreferenceManager().setPreferenceComparisonCallback(null);
         Bundle args = getArguments();
         final Activity activity = getActivity();
         UserHandle userHandle = Utils.getSecureTargetUser(activity.getActivityToken(),
diff --git a/src/com/android/settings/accounts/AccountSyncPreferenceController.java b/src/com/android/settings/accounts/AccountSyncPreferenceController.java
index 847bb03..3eed037 100644
--- a/src/com/android/settings/accounts/AccountSyncPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountSyncPreferenceController.java
@@ -19,25 +19,32 @@
 import static android.content.Intent.EXTRA_USER;
 
 import android.accounts.Account;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.SyncAdapterType;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.accounts.AuthenticatorHelper;
 import com.android.settingslib.core.AbstractPreferenceController;
 
 public class AccountSyncPreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin {
+        implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener {
 
     private static final String TAG = "AccountSyncController";
     private static final String KEY_ACCOUNT_SYNC = "account_sync";
 
     private Account mAccount;
     private UserHandle mUserHandle;
+    private AuthenticatorHelper mAuthenticatorHelper;
+    private Preference mPreference;
 
     public AccountSyncPreferenceController(Context context) {
         super(context);
@@ -67,8 +74,64 @@
         return KEY_ACCOUNT_SYNC;
     }
 
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        updateSummary(preference);
+    }
+
+    @Override
+    public void onAccountsUpdate(UserHandle userHandle) {
+        updateSummary(mPreference);
+    }
+
     public void init(Account account, UserHandle userHandle) {
         mAccount = account;
         mUserHandle = userHandle;
+        mAuthenticatorHelper = new AuthenticatorHelper(mContext, mUserHandle, this);
+    }
+
+    @VisibleForTesting
+    void updateSummary(Preference preference) {
+        if (mAccount == null) {
+            return;
+        }
+        final int userId = mUserHandle.getIdentifier();
+        final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId);
+        int total = 0;
+        int enabled = 0;
+        if (syncAdapters != null) {
+            for (int i = 0, n = syncAdapters.length; i < n; i++) {
+                final SyncAdapterType sa = syncAdapters[i];
+                if (!sa.accountType.equals(mAccount.type) || !sa.isUserVisible()) {
+                    continue;
+                }
+                final int syncState =
+                        ContentResolver.getIsSyncableAsUser(mAccount, sa.authority, userId);
+                if (syncState > 0) {
+                    total++;
+                    final boolean syncEnabled = ContentResolver.getSyncAutomaticallyAsUser(
+                            mAccount, sa.authority, userId);
+                    final boolean oneTimeSyncMode =
+                            !ContentResolver.getMasterSyncAutomaticallyAsUser(userId);
+                    if (oneTimeSyncMode || syncEnabled) {
+                        enabled++;
+                    }
+                }
+            }
+        }
+        if (enabled == 0) {
+            preference.setSummary(R.string.account_sync_summary_all_off);
+        } else if (enabled == total) {
+            preference.setSummary(R.string.account_sync_summary_all_on);
+        } else {
+            preference.setSummary(
+                    mContext.getString(R.string.account_sync_summary_some_on, enabled, total));
+        }
     }
 }
diff --git a/src/com/android/settings/applications/LayoutPreference.java b/src/com/android/settings/applications/LayoutPreference.java
index 6ae0772..f2bd183 100644
--- a/src/com/android/settings/applications/LayoutPreference.java
+++ b/src/com/android/settings/applications/LayoutPreference.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.support.annotation.VisibleForTesting;
+import android.support.v4.content.res.TypedArrayUtils;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceViewHolder;
 import android.util.AttributeSet;
@@ -33,19 +34,30 @@
 public class LayoutPreference extends Preference {
 
     private final View.OnClickListener mClickListener = v -> performClick(v);
+    private boolean mAllowDividerAbove;
+    private boolean mAllowDividerBelow;
 
     @VisibleForTesting
     View mRootView;
 
     public LayoutPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
-        final TypedArray a = context.obtainStyledAttributes(
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Preference);
+        mAllowDividerAbove = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerAbove,
+                R.styleable.Preference_allowDividerAbove, false);
+        mAllowDividerBelow = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerBelow,
+                R.styleable.Preference_allowDividerBelow, false);
+        a.recycle();
+
+        a = context.obtainStyledAttributes(
                 attrs, com.android.internal.R.styleable.Preference, 0, 0);
         int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout,
                 0);
         if (layoutResource == 0) {
             throw new IllegalArgumentException("LayoutPreference requires a layout to be defined");
         }
+        a.recycle();
+
         // Need to create view now so that findViewById can be called immediately.
         final View view = LayoutInflater.from(getContext())
                 .inflate(layoutResource, null, false);
@@ -78,6 +90,8 @@
         final boolean selectable = isSelectable();
         holder.itemView.setFocusable(selectable);
         holder.itemView.setClickable(selectable);
+        holder.setDividerAllowedAbove(mAllowDividerAbove);
+        holder.setDividerAllowedBelow(mAllowDividerBelow);
 
         FrameLayout layout = (FrameLayout) holder.itemView;
         layout.removeAllViews();
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index 6a79504..2c793f8 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -107,7 +107,7 @@
             List<Condition> conditions, SuggestionParser suggestionParser,
             SuggestionDismissController.Callback callback) {
         List<Tile> suggestions = null;
-        List<DashboardCategory> categories = null;
+        DashboardCategory category = null;
         int suggestionConditionMode = DashboardData.HEADER_MODE_DEFAULT;
 
         mContext = context;
@@ -123,7 +123,7 @@
 
         if (savedInstanceState != null) {
             suggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
-            categories = savedInstanceState.getParcelableArrayList(STATE_CATEGORY_LIST);
+            category = savedInstanceState.getParcelable(STATE_CATEGORY_LIST);
             suggestionConditionMode = savedInstanceState.getInt(
                 STATE_SUGGESTION_CONDITION_MODE, suggestionConditionMode);
             mSuggestionsShownLogged = savedInstanceState.getStringArrayList(
@@ -135,7 +135,7 @@
         mDashboardData = new DashboardData.Builder()
                 .setConditions(conditions)
                 .setSuggestions(suggestions)
-                .setCategories(categories)
+                .setCategory(category)
                 .setSuggestionConditionMode(suggestionConditionMode)
                 .build();
     }
@@ -144,36 +144,14 @@
         return mDashboardData.getSuggestions();
     }
 
-    public void setCategoriesAndSuggestions(List<DashboardCategory> categories,
+    public void setCategoriesAndSuggestions(DashboardCategory category,
             List<Tile> suggestions) {
-        if (mDashboardFeatureProvider.shouldTintIcon()) {
-            // TODO: Better place for tinting?
-            final TypedArray a = mContext.obtainStyledAttributes(new int[]{
-                    android.R.attr.colorControlNormal});
-            final int tintColor = a.getColor(0, mContext.getColor(R.color.fallback_tintColor));
-            a.recycle();
-            for (int i = 0; i < categories.size(); i++) {
-                for (int j = 0; j < categories.get(i).tiles.size(); j++) {
-                    final Tile tile = categories.get(i).tiles.get(j);
-
-                    if (tile.isIconTintable) {
-                        // If this drawable is tintable, tint it to match the color.
-                        tile.icon.setTint(tintColor);
-                    }
-                }
-            }
-
-            for (Tile suggestion : suggestions) {
-                if (suggestion.isIconTintable) {
-                    suggestion.icon.setTint(tintColor);
-                }
-            }
-        }
+        tintIcons(category, suggestions);
 
         final DashboardData prevData = mDashboardData;
         mDashboardData = new DashboardData.Builder(prevData)
                 .setSuggestions(suggestions)
-                .setCategories(categories)
+                .setCategory(category)
                 .build();
         notifyDashboardDataChanged(prevData);
         List<Tile> shownSuggestions = null;
@@ -195,11 +173,12 @@
         }
     }
 
-    public void setCategory(List<DashboardCategory> category) {
+    public void setCategory(DashboardCategory category) {
+        tintIcons(category, null);
         final DashboardData prevData = mDashboardData;
         Log.d(TAG, "adapter setCategory called");
         mDashboardData = new DashboardData.Builder(prevData)
-                .setCategories(category)
+                .setCategory(category)
                 .build();
         notifyDashboardDataChanged(prevData);
     }
@@ -500,18 +479,40 @@
         }
     }
 
-    private void onBindCategory(DashboardItemHolder holder, DashboardCategory category) {
-        holder.title.setText(category.title);
+    private void tintIcons(DashboardCategory category, List<Tile> suggestions) {
+        if (!mDashboardFeatureProvider.shouldTintIcon()) {
+            return;
+        }
+        // TODO: Better place for tinting?
+        final TypedArray a = mContext.obtainStyledAttributes(new int[]{
+                android.R.attr.colorControlNormal});
+        final int tintColor = a.getColor(0, mContext.getColor(R.color.fallback_tintColor));
+        a.recycle();
+        if (category != null) {
+            for (Tile tile : category.tiles) {
+                if (tile.isIconTintable) {
+                    // If this drawable is tintable, tint it to match the color.
+                    tile.icon.setTint(tintColor);
+                }
+            }
+        }
+        if (suggestions != null) {
+            for (Tile suggestion : suggestions) {
+                if (suggestion.isIconTintable) {
+                    suggestion.icon.setTint(tintColor);
+                }
+            }
+        }
     }
 
     void onSaveInstanceState(Bundle outState) {
         final List<Tile> suggestions = mDashboardData.getSuggestions();
-        final List<DashboardCategory> categories = mDashboardData.getCategories();
+        final DashboardCategory category = mDashboardData.getCategory();
         if (suggestions != null) {
             outState.putParcelableArrayList(STATE_SUGGESTION_LIST, new ArrayList<>(suggestions));
         }
-        if (categories != null) {
-            outState.putParcelableArrayList(STATE_CATEGORY_LIST, new ArrayList<>(categories));
+        if (category != null) {
+            outState.putParcelable(STATE_CATEGORY_LIST, category);
         }
         outState.putStringArrayList(STATE_SUGGESTIONS_SHOWN_LOGGED, mSuggestionsShownLogged);
         outState.putInt(STATE_SUGGESTION_CONDITION_MODE,
diff --git a/src/com/android/settings/dashboard/DashboardData.java b/src/com/android/settings/dashboard/DashboardData.java
index 7593f82..34fc178 100644
--- a/src/com/android/settings/dashboard/DashboardData.java
+++ b/src/com/android/settings/dashboard/DashboardData.java
@@ -17,7 +17,7 @@
 
 import android.annotation.IntDef;
 import android.graphics.drawable.Icon;
-import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.util.DiffUtil;
 import android.text.TextUtils;
 
@@ -30,6 +30,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Description about data list used in the DashboardAdapter. In the data list each item can be
@@ -42,34 +43,42 @@
     public static final int HEADER_MODE_SUGGESTION_EXPANDED = 1;
     public static final int HEADER_MODE_FULLY_EXPANDED = 2;
     public static final int HEADER_MODE_COLLAPSED = 3;
+
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({HEADER_MODE_DEFAULT, HEADER_MODE_SUGGESTION_EXPANDED, HEADER_MODE_FULLY_EXPANDED,
-        HEADER_MODE_COLLAPSED})
-    public @interface HeaderMode{}
+            HEADER_MODE_COLLAPSED})
+    public @interface HeaderMode {
+    }
 
     public static final int POSITION_NOT_FOUND = -1;
     public static final int DEFAULT_SUGGESTION_COUNT = 2;
 
-    // id namespace for different type of items.
-    private static final int NS_SPACER = 0;
-    private static final int NS_ITEMS = 2000;
-    private static final int NS_SUGGESTION_CONDITION = 3000;
+    // stable id for different type of items.
+    @VisibleForTesting
+    static final int STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER = 0;
+    @VisibleForTesting
+    static final int STABLE_ID_SUGGESTION_CONDITION_MIDDLE_HEADER = 1;
+    @VisibleForTesting
+    static final int STABLE_ID_SUGGESTION_CONDITION_FOOTER = 2;
+    @VisibleForTesting
+    static final int STABLE_ID_SUGGESTION_CONTAINER = 3;
+    @VisibleForTesting
+    static final int STABLE_ID_CONDITION_CONTAINER = 4;
 
     private final List<Item> mItems;
-    private final List<DashboardCategory> mCategories;
+    private final DashboardCategory mCategory;
     private final List<Condition> mConditions;
     private final List<Tile> mSuggestions;
-    private final @HeaderMode int mSuggestionConditionMode;
-    private int mId;
+    @HeaderMode
+    private final int mSuggestionConditionMode;
 
     private DashboardData(Builder builder) {
-        mCategories = builder.mCategories;
+        mCategory = builder.mCategory;
         mConditions = builder.mConditions;
         mSuggestions = builder.mSuggestions;
         mSuggestionConditionMode = builder.mSuggestionConditionMode;
 
         mItems = new ArrayList<>();
-        mId = 0;
 
         buildItemsData();
     }
@@ -103,8 +112,8 @@
         return null;
     }
 
-    public List<DashboardCategory> getCategories() {
-        return mCategories;
+    public DashboardCategory getCategory() {
+        return mCategory;
     }
 
     public List<Condition> getConditions() {
@@ -186,33 +195,18 @@
         return suggestionSize;
     }
 
-    public boolean hasMoreSuggestions() {
-        return mSuggestionConditionMode == HEADER_MODE_COLLAPSED && mSuggestions.size() > 0
-                || mSuggestionConditionMode == HEADER_MODE_DEFAULT
-                && mSuggestions.size() > DEFAULT_SUGGESTION_COUNT;
-    }
-
-    private void resetCount() {
-        mId = 0;
-    }
-
     /**
-     * Count the item and add it into list when {@paramref add} is true.
+     * Add item into list when {@paramref add} is true.
      *
-     * Note that {@link #mId} will increment automatically and the real
-     * id stored in {@link Item} is shifted by {@paramref nameSpace}. This is a
-     * simple way to keep the id stable.
-     *
-     * @param object    maybe {@link Condition}, {@link Tile}, {@link DashboardCategory} or null
-     * @param type      type of the item, and value is the layout id
-     * @param add       flag about whether to add item into list
-     * @param nameSpace namespace based on the type
+     * @param item     maybe {@link Condition}, {@link Tile}, {@link DashboardCategory} or null
+     * @param type     type of the item, and value is the layout id
+     * @param stableId The stable id for this item
+     * @param add      flag about whether to add item into list
      */
-    private void countItem(Object object, int type, boolean add, int nameSpace) {
+    private void addToItemList(Object item, int type, int stableId, boolean add) {
         if (add) {
-            mItems.add(new Item(object, type, mId + nameSpace));
+            mItems.add(new Item(item, type, stableId));
         }
-        mId++;
     }
 
     /**
@@ -228,51 +222,51 @@
         final int hiddenSuggestion =
                 hasSuggestions ? sizeOf(mSuggestions) - sizeOf(suggestions) : 0;
 
-        resetCount();
-            /* Top suggestion/condition header. This will be present when there is any suggestion or
-             * condition to show, except in the case that there is only conditions to show and the
-             * mode is fully expanded. */
-        countItem(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
-                R.layout.suggestion_condition_header, hasSuggestions
-                        || hasConditions && mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED,
-                NS_SUGGESTION_CONDITION);
-
-            /* Suggestion container. This is the card view that contains the list of suggestions.
-             * This will be added whenever the suggestion list is not empty */
-        countItem(suggestions, R.layout.suggestion_condition_container, sizeOf(suggestions) > 0,
-                NS_SUGGESTION_CONDITION);
-
-            /* Second suggestion/condition header. This will be added when there is at least one
-             * suggestion or condition that is not currently displayed, and the user can expand the
-              * section to view more items. */
-        countItem(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
+        /* Top suggestion/condition header. This will be present when there is any suggestion or
+         * condition to show, except in the case that there is only conditions to show and the
+         * mode is fully expanded. */
+        addToItemList(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
                 R.layout.suggestion_condition_header,
+                STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER,
+                hasSuggestions
+                        || hasConditions && mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED);
+
+        /* Suggestion container. This is the card view that contains the list of suggestions.
+         * This will be added whenever the suggestion list is not empty */
+        addToItemList(suggestions, R.layout.suggestion_condition_container,
+                STABLE_ID_SUGGESTION_CONTAINER, sizeOf(suggestions) > 0);
+
+        /* Second suggestion/condition header. This will be added when there is at least one
+         * suggestion or condition that is not currently displayed, and the user can expand the
+         * section to view more items. */
+        addToItemList(new SuggestionConditionHeaderData(conditions, hiddenSuggestion),
+                R.layout.suggestion_condition_header,
+                STABLE_ID_SUGGESTION_CONDITION_MIDDLE_HEADER,
                 mSuggestionConditionMode != HEADER_MODE_COLLAPSED
                         && mSuggestionConditionMode != HEADER_MODE_FULLY_EXPANDED
-                        && (hiddenSuggestion > 0
-                        || hasConditions && hasSuggestions),
-                NS_SUGGESTION_CONDITION);
+                        && (hiddenSuggestion > 0 || hasConditions && hasSuggestions));
 
             /* Condition container. This is the card view that contains the list of conditions.
              * This will be added whenever the condition list is not empty */
-        countItem(conditions, R.layout.suggestion_condition_container,
-                hasConditions && mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED,
-                NS_SUGGESTION_CONDITION);
+        addToItemList(conditions, R.layout.suggestion_condition_container,
+                STABLE_ID_CONDITION_CONTAINER,
+                hasConditions && mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED);
 
             /* Suggestion/condition footer. This will be present when the section is fully expanded
              * or when there is no conditions and no hidden suggestions */
-        countItem(null, R.layout.suggestion_condition_footer,
-                (hasConditions || hasSuggestions) &&
-                        mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED
-                        || hasSuggestions && !hasConditions && hiddenSuggestion == 0,
-                NS_SUGGESTION_CONDITION);
+        addToItemList(null /* item */, R.layout.suggestion_condition_footer,
+                STABLE_ID_SUGGESTION_CONDITION_FOOTER,
+                (hasConditions || hasSuggestions)
+                        && mSuggestionConditionMode == HEADER_MODE_FULLY_EXPANDED
+                        || hasSuggestions
+                        && !hasConditions
+                        && hiddenSuggestion == 0);
 
-        resetCount();
-        for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
-            DashboardCategory category = mCategories.get(i);
-            for (int j = 0; j < category.tiles.size(); j++) {
-                Tile tile = category.tiles.get(j);
-                countItem(tile, R.layout.dashboard_tile, true, NS_ITEMS);
+        if(mCategory != null) {
+            for (int j = 0; j < mCategory.tiles.size(); j++) {
+                final Tile tile = mCategory.tiles.get(j);
+                addToItemList(tile, R.layout.dashboard_tile, Objects.hash(tile.title),
+                        true /* add */);
             }
         }
     }
@@ -313,9 +307,10 @@
      * {@link #mSuggestionConditionMode} have default value while others are not.
      */
     public static class Builder {
-        private @HeaderMode int mSuggestionConditionMode = HEADER_MODE_DEFAULT;
+        @HeaderMode
+        private int mSuggestionConditionMode = HEADER_MODE_DEFAULT;
 
-        private List<DashboardCategory> mCategories;
+        private DashboardCategory mCategory;
         private List<Condition> mConditions;
         private List<Tile> mSuggestions;
 
@@ -323,14 +318,14 @@
         }
 
         public Builder(DashboardData dashboardData) {
-            mCategories = dashboardData.mCategories;
+            mCategory = dashboardData.mCategory;
             mConditions = dashboardData.mConditions;
             mSuggestions = dashboardData.mSuggestions;
             mSuggestionConditionMode = dashboardData.mSuggestionConditionMode;
         }
 
-        public Builder setCategories(List<DashboardCategory> categories) {
-            this.mCategories = categories;
+        public Builder setCategory(DashboardCategory category) {
+            this.mCategory = category;
             return this;
         }
 
@@ -392,13 +387,13 @@
     /**
      * An item contains the data needed in the DashboardData.
      */
-    private static class Item {
+    static class Item {
         // valid types in field type
         private static final int TYPE_DASHBOARD_TILE = R.layout.dashboard_tile;
         private static final int TYPE_SUGGESTION_CONDITION_CONTAINER =
-            R.layout.suggestion_condition_container;
+                R.layout.suggestion_condition_container;
         private static final int TYPE_SUGGESTION_CONDITION_HEADER =
-            R.layout.suggestion_condition_header;
+                R.layout.suggestion_condition_header;
         private static final int TYPE_SUGGESTION_CONDITION_FOOTER =
                 R.layout.suggestion_condition_footer;
         private static final int TYPE_DASHBOARD_SPACER = R.layout.dashboard_spacer;
@@ -407,7 +402,8 @@
                 TYPE_SUGGESTION_CONDITION_HEADER, TYPE_SUGGESTION_CONDITION_FOOTER,
                 TYPE_DASHBOARD_SPACER})
         @Retention(RetentionPolicy.SOURCE)
-        public @interface ItemTypes{}
+        public @interface ItemTypes {
+        }
 
         /**
          * The main data object in item, usually is a {@link Tile}, {@link Condition}
@@ -420,7 +416,8 @@
         /**
          * The type of item, value inside is the layout id(e.g. R.layout.dashboard_tile)
          */
-        public final @ItemTypes int type;
+        @ItemTypes
+        public final int type;
 
         /**
          * Id of this item, used in the {@link ItemsDataDiffCallback} to identify the same item.
@@ -435,6 +432,7 @@
 
         /**
          * Override it to make comparision in the {@link ItemsDataDiffCallback}
+         *
          * @param obj object to compared with
          * @return true if the same object or has equal value.
          */
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index bc102b0..71a4d8f 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -292,15 +292,12 @@
             return;
         }
 
-        // Temporary hack to wrap homepage category into a list. Soon we will create adapter
-        // API that takes a single category.
-        List<DashboardCategory> categories = new ArrayList<>();
-        categories.add(mDashboardFeatureProvider.getTilesForCategory(
-                CategoryKey.CATEGORY_HOMEPAGE));
+        final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(
+                CategoryKey.CATEGORY_HOMEPAGE);
         if (suggestions != null) {
-            mAdapter.setCategoriesAndSuggestions(categories, suggestions);
+            mAdapter.setCategoriesAndSuggestions(category, suggestions);
         } else {
-            mAdapter.setCategory(categories);
+            mAdapter.setCategory(category);
         }
     }
 }
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
index 4b4e03f..73c1177 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
@@ -17,13 +17,14 @@
 package com.android.settings.dashboard.suggestions;
 
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
-import android.support.annotation.NonNull;
-import android.content.ContentResolver;
 import android.provider.Settings.Secure;
+import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
+import android.text.format.DateUtils;
 import android.util.Log;
 
 import com.android.internal.logging.nano.MetricsProto;
@@ -43,6 +44,12 @@
 
     private static final String SHARED_PREF_FILENAME = "suggestions";
 
+    // Suggestion category name and expiration threshold for first impression type. Needs to keep
+    // in sync with suggestion_ordering.xml
+    private static final String CATEGORY_FIRST_IMPRESSION =
+            "com.android.settings.suggested.category.FIRST_IMPRESSION";
+    private static final long FIRST_IMPRESSION_EXPIRE_DAY_IN_MILLIS = 14 * DateUtils.DAY_IN_MILLIS;
+
     private final SuggestionRanker mSuggestionRanker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
 
@@ -101,7 +108,11 @@
                 context, MetricsProto.MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION,
                 getSuggestionIdentifier(context, suggestion));
 
-        final boolean isSmartSuggestionEnabled = isSmartSuggestionEnabled(context);
+        boolean isSmartSuggestionEnabled = isSmartSuggestionEnabled(context);
+        if (isSmartSuggestionEnabled) {
+            // Disable smart suggestion if we are still showing first impression suggestions.
+            isSmartSuggestionEnabled = !isShowingFirstImpressionSuggestion(context);
+        }
         if (!parser.dismissSuggestion(suggestion, isSmartSuggestionEnabled)) {
             return;
         }
@@ -111,6 +122,19 @@
                 PackageManager.DONT_KILL_APP);
     }
 
+    private boolean isShowingFirstImpressionSuggestion(Context context) {
+        final String keySetupTime = CATEGORY_FIRST_IMPRESSION + SuggestionParser.SETUP_TIME;
+        final long currentTime = System.currentTimeMillis();
+        final SharedPreferences sharedPrefs = getSharedPrefs(context);
+        if (!sharedPrefs.contains(keySetupTime)) {
+            return true;
+        }
+        final long setupTime = sharedPrefs.getLong(keySetupTime, 0);
+        final long elapsedTime = currentTime - setupTime;
+        Log.d(TAG, "Day " + elapsedTime / DateUtils.DAY_IN_MILLIS + " for first impression");
+        return elapsedTime <= FIRST_IMPRESSION_EXPIRE_DAY_IN_MILLIS;
+    }
+
     @Override
     public String getSuggestionIdentifier(Context context, Tile suggestion) {
         if (suggestion.intent == null || suggestion.intent.getComponent() == null
@@ -130,7 +154,7 @@
     boolean hasUsedNightDisplay(Context context) {
         final ContentResolver cr = context.getContentResolver();
         final long lastActivatedTimeMillis = Secure.getLong(cr,
-            Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1);
+                Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1);
         return lastActivatedTimeMillis > 0;
     }
 }
diff --git a/src/com/android/settings/display/WallpaperPreferenceController.java b/src/com/android/settings/display/WallpaperPreferenceController.java
index 1c26440..fe76ae1 100644
--- a/src/com/android/settings/display/WallpaperPreferenceController.java
+++ b/src/com/android/settings/display/WallpaperPreferenceController.java
@@ -27,7 +27,7 @@
 public class WallpaperPreferenceController extends AbstractPreferenceController implements
         PreferenceControllerMixin {
 
-    private static final String KEY_WALLPAPER = "wallpaper";
+    public static final String KEY_WALLPAPER = "wallpaper";
 
     public WallpaperPreferenceController(Context context) {
         super(context);
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollBase.java b/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
index df7bf3c..7c34f2d 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollBase.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -27,6 +28,7 @@
 import android.widget.TextView;
 
 import com.android.settings.R;
+import com.android.settings.SetupWizardUtils;
 import com.android.settings.core.InstrumentedActivity;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.setupwizardlib.GlifLayout;
@@ -57,6 +59,12 @@
     }
 
     @Override
+    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
+        resid = SetupWizardUtils.getTheme(getIntent());
+        super.onApplyThemeResource(theme, resid, first);
+    }
+
+    @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
index 5d0152c..fbbf033 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollEnrolling.java
@@ -17,7 +17,6 @@
 package com.android.settings.fingerprint;
 
 import android.content.Intent;
-import android.content.res.Resources;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.SetupWizardUtils;
@@ -32,12 +31,6 @@
     }
 
     @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
-    @Override
     public int getMetricsCategory() {
         return MetricsEvent.FINGERPRINT_ENROLLING_SETUP;
     }
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
index d7a4a73..f62b701 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
@@ -17,7 +17,6 @@
 package com.android.settings.fingerprint;
 
 import android.content.Intent;
-import android.content.res.Resources;
 import android.os.UserHandle;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -44,12 +43,6 @@
     }
 
     @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
-    @Override
     public int getMetricsCategory() {
         return MetricsEvent.FINGERPRINT_FIND_SENSOR_SETUP;
     }
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java
index 02f6cb8..e81203f 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFinish.java
@@ -17,7 +17,6 @@
 package com.android.settings.fingerprint;
 
 import android.content.Intent;
-import android.content.res.Resources;
 import android.os.UserHandle;
 import android.widget.Button;
 
@@ -40,12 +39,6 @@
     }
 
     @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
-    @Override
     protected void initViews() {
         super.initViews();
         Button nextButton = findViewById(R.id.next_button);
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
index e668812..8f93bca 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -19,7 +19,6 @@
 import android.app.KeyguardManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Intent;
-import android.content.res.Resources;
 import android.os.UserHandle;
 import android.widget.Button;
 import android.widget.TextView;
@@ -53,12 +52,6 @@
     }
 
     @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
-    @Override
     protected void initViews() {
         super.initViews();
 
diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java
index 5eada88..b0f2f84 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfo.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfo.java
@@ -46,6 +46,7 @@
     public String statusLabel;
     private boolean mCharging;
     private BatteryStats mStats;
+    private static final String LOG_TAG = "BatteryInfo";
     private long timePeriod;
 
     public interface Callback {
@@ -132,6 +133,7 @@
         new AsyncTask<Void, Void, BatteryInfo>() {
             @Override
             protected BatteryInfo doInBackground(Void... params) {
+                final long startTime = System.currentTimeMillis();
                 PowerUsageFeatureProvider provider =
                         FeatureFactory.getFactory(context).getPowerUsageFeatureProvider(context);
                 final BatteryUtils batteryUtils = BatteryUtils.getInstance(context);
@@ -144,17 +146,19 @@
                 // 0 means we are discharging, anything else means charging
                 boolean discharging =
                         batteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) == 0;
+
                 if (discharging && provider != null
                         && provider.isEnhancedBatteryPredictionEnabled(context)) {
+                    final long prediction = provider.getEnhancedBatteryPrediction(context);
+                    BatteryUtils.logRuntime(LOG_TAG, "time for enhanced BatteryInfo", startTime);
                     return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
-                            elapsedRealtimeUs, shortString,
-                            utils.convertMsToUs(provider.getEnhancedBatteryPrediction(context)),
-                            true);
+                            elapsedRealtimeUs, shortString, utils.convertMsToUs(prediction), true);
                 } else {
+                    long prediction = discharging
+                            ? stats.computeBatteryTimeRemaining(elapsedRealtimeUs) : 0;
+                    BatteryUtils.logRuntime(LOG_TAG, "time for regular BatteryInfo", startTime);
                     return BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
-                            elapsedRealtimeUs, shortString,
-                            discharging ? stats.computeBatteryTimeRemaining(elapsedRealtimeUs) : 0,
-                            false);
+                            elapsedRealtimeUs, shortString, prediction, false);
                 }
             }
 
@@ -176,6 +180,7 @@
     public static BatteryInfo getBatteryInfo(Context context, Intent batteryBroadcast,
             BatteryStats stats, long elapsedRealtimeUs, boolean shortString, long drainTimeUs,
             boolean basedOnUsage) {
+        final long startTime = System.currentTimeMillis();
         BatteryInfo info = new BatteryInfo();
         info.mStats = stats;
         info.batteryLevel = Utils.getBatteryLevel(batteryBroadcast);
@@ -232,6 +237,7 @@
                                 chargeStatusLabel);
             }
         }
+        BatteryUtils.logRuntime(LOG_TAG, "time for getBatteryInfo", startTime);
         return info;
     }
 
diff --git a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java
index e85acc5..efaca30 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfoLoader.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfoLoader.java
@@ -33,7 +33,9 @@
  * when not available.
  */
 public class BatteryInfoLoader extends AsyncLoader<BatteryInfo>{
+
     BatteryStatsHelper mStatsHelper;
+    private static final String LOG_TAG = "BatteryInfoLoader";
 
     public BatteryInfoLoader(Context context, BatteryStatsHelper batteryStatsHelper) {
         super(context);
@@ -47,6 +49,7 @@
 
     @Override
     public BatteryInfo loadInBackground() {
+        final long startTime = System.currentTimeMillis();
         Context context = getContext();
         PowerUsageFeatureProvider powerUsageFeatureProvider =
                 FeatureFactory.getFactory(context).getPowerUsageFeatureProvider(context);
@@ -67,19 +70,20 @@
             final Uri queryUri = powerUsageFeatureProvider.getEnhancedBatteryPredictionUri();
             cursor = context.getContentResolver().query(queryUri, null, null, null, null);
         }
+        BatteryStats stats = mStatsHelper.getStats();
+        batteryUtils.logRuntime(LOG_TAG, "BatteryInfoLoader post query", startTime);
         if (cursor != null && cursor.moveToFirst()) {
             long enhancedEstimate = powerUsageFeatureProvider.getTimeRemainingEstimate(cursor);
-            batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast,
-                    mStatsHelper.getStats(), elapsedRealtimeUs, false /* shortString */,
+            batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
+                    elapsedRealtimeUs, false /* shortString */,
                     batteryUtils.convertMsToUs(enhancedEstimate), true /* basedOnUsage */);
         } else {
-            BatteryStats stats = mStatsHelper.getStats();
             batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast, stats,
                     elapsedRealtimeUs, false /* shortString */,
                     discharging ? 0 : stats.computeBatteryTimeRemaining(elapsedRealtimeUs),
                     false /* basedOnUsage */);
         }
-
+        batteryUtils.logRuntime(LOG_TAG, "BatteryInfoLoader.loadInBackground", startTime);
         return batteryInfo;
     }
 }
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 17c0cd7..b8646f7 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -285,6 +285,10 @@
 
     }
 
+    public static void logRuntime(String tag, String message, long startTime) {
+        Log.d(tag, message + ": " + (System.currentTimeMillis() - startTime) + "ms");
+    }
+
     /**
      * Find package uid from package name
      *
@@ -331,8 +335,8 @@
     long getForegroundActivityTotalTimeMs(BatteryStats.Uid uid, long rawRealtimeMs) {
         final BatteryStats.Timer timer = uid.getForegroundActivityTimer();
         if (timer != null) {
-            return convertUsToMs(
-                    timer.getTotalTimeLocked(rawRealtimeMs, BatteryStats.STATS_SINCE_CHARGED));
+            return convertUsToMs(timer.getTotalTimeLocked(convertMsToUs(rawRealtimeMs),
+                            BatteryStats.STATS_SINCE_CHARGED));
         }
 
         return 0;
diff --git a/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java b/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java
index 3344eb6..87212e7 100644
--- a/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java
+++ b/src/com/android/settings/fuelgauge/anomaly/action/AnomalyAction.java
@@ -16,26 +16,47 @@
 
 package com.android.settings.fuelgauge.anomaly.action;
 
+import android.content.Context;
+import android.util.Pair;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.instrumentation.MetricsFeatureProvider;
 import com.android.settings.fuelgauge.anomaly.Anomaly;
+import com.android.settings.overlay.FeatureFactory;
 
 /**
- * Interface for anomaly action, which is triggered if we need to handle the anomaly
+ * Abstract class for anomaly action, which is triggered if we need to handle the anomaly
  */
-public interface AnomalyAction {
+public abstract class AnomalyAction {
+    protected Context mContext;
+    protected int mActionMetricKey;
+
+    private MetricsFeatureProvider mMetricsFeatureProvider;
+
+    public AnomalyAction(Context context) {
+        mContext = context;
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+    }
+
     /**
      * handle the action when user clicks positive button
-     * @param anomaly about the app that we need to handle
-     * @param metricsKey key for the page that invokes the action
      *
+     * @param anomaly    about the app that we need to handle
+     * @param contextMetricsKey key for the page that invokes the action
      * @see com.android.internal.logging.nano.MetricsProto
      */
-    void handlePositiveAction(Anomaly anomaly, int metricsKey);
+    public void handlePositiveAction(Anomaly anomaly, int contextMetricsKey) {
+        mMetricsFeatureProvider.action(mContext, mActionMetricKey, anomaly.packageName,
+                Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, contextMetricsKey));
+    }
 
     /**
      * Check whether the action is active for {@code anomaly}
+     *
      * @param anomaly about the app that we need to handle
      * @return {@code true} if action is active, otherwise return {@code false}
      */
-    boolean isActionActive(Anomaly anomaly);
-    int getActionType();
+    public abstract boolean isActionActive(Anomaly anomaly);
+
+    public abstract int getActionType();
 }
diff --git a/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java b/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java
index 16fd0df..799bddc 100644
--- a/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java
+++ b/src/com/android/settings/fuelgauge/anomaly/action/BackgroundCheckAction.java
@@ -19,28 +19,26 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 
-import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.fuelgauge.anomaly.Anomaly;
-import com.android.settings.overlay.FeatureFactory;
 
 /**
  * Background check action for anomaly app, which means to stop app running in the background
  */
-public class BackgroundCheckAction implements AnomalyAction {
+public class BackgroundCheckAction extends AnomalyAction {
 
-    private Context mContext;
-    private MetricsFeatureProvider mMetricsFeatureProvider;
     private AppOpsManager mAppOpsManager;
 
     public BackgroundCheckAction(Context context) {
-        mContext = context;
-        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+        super(context);
         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        mActionMetricKey = MetricsProto.MetricsEvent.ACTION_APP_BACKGROUND_CHECK;
     }
 
     @Override
-    public void handlePositiveAction(Anomaly anomaly, int metricsKey) {
-        // TODO(b/37681923): add metric log here if possible
+    public void handlePositiveAction(Anomaly anomaly, int contextMetricsKey) {
+        super.handlePositiveAction(anomaly, contextMetricsKey);
+
         mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, anomaly.uid, anomaly.packageName,
                 AppOpsManager.MODE_IGNORED);
     }
diff --git a/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java b/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java
index 557b2a9..fb7306a 100644
--- a/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java
+++ b/src/com/android/settings/fuelgauge/anomaly/action/ForceStopAction.java
@@ -21,43 +21,32 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.util.Log;
-import android.util.Pair;
 
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.core.instrumentation.MetricsFeatureProvider;
 import com.android.settings.fuelgauge.anomaly.Anomaly;
-import com.android.settings.overlay.FeatureFactory;
-
-import java.util.List;
 
 /**
  * Force stop action for anomaly app, which means to stop the app which causes anomaly
  */
-public class ForceStopAction implements AnomalyAction {
+public class ForceStopAction extends AnomalyAction {
     private static final String TAG = "ForceStopAction";
 
-    private Context mContext;
-    private MetricsFeatureProvider mMetricsFeatureProvider;
     private ActivityManager mActivityManager;
     private PackageManager mPackageManager;
 
     public ForceStopAction(Context context) {
-        mContext = context;
-        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+        super(context);
         mActivityManager = (ActivityManager) context.getSystemService(
                 Context.ACTIVITY_SERVICE);
         mPackageManager = context.getPackageManager();
+        mActionMetricKey = MetricsProto.MetricsEvent.ACTION_APP_FORCE_STOP;
     }
 
     @Override
-    public void handlePositiveAction(Anomaly anomaly, int metricsKey) {
-        final String packageName = anomaly.packageName;
-        // force stop the package
-        mMetricsFeatureProvider.action(mContext,
-                MetricsProto.MetricsEvent.ACTION_APP_FORCE_STOP, packageName,
-                Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, metricsKey));
+    public void handlePositiveAction(Anomaly anomaly, int contextMetricsKey) {
+        super.handlePositiveAction(anomaly, contextMetricsKey);
 
-        mActivityManager.forceStopPackage(packageName);
+        mActivityManager.forceStopPackage(anomaly.packageName);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/anomaly/action/LocationCheckAction.java b/src/com/android/settings/fuelgauge/anomaly/action/LocationCheckAction.java
index 4205b6e..6779828 100644
--- a/src/com/android/settings/fuelgauge/anomaly/action/LocationCheckAction.java
+++ b/src/com/android/settings/fuelgauge/anomaly/action/LocationCheckAction.java
@@ -20,28 +20,28 @@
 import android.content.pm.permission.RuntimePermissionPresenter;
 import android.support.v4.content.PermissionChecker;
 
-import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.fuelgauge.anomaly.Anomaly;
-import com.android.settings.overlay.FeatureFactory;
 
 /**
  * Location action for anomaly app, which means to turn off location permission for this app
  */
-public class LocationCheckAction implements AnomalyAction {
+public class LocationCheckAction extends AnomalyAction {
 
     private static final String TAG = "LocationCheckAction";
     private static final String LOCATION_PERMISSION = "android.permission-group.LOCATION";
 
-    private final Context mContext;
     private final RuntimePermissionPresenter mRuntimePermissionPresenter;
 
     public LocationCheckAction(Context context) {
-        mContext = context;
+        super(context);
         mRuntimePermissionPresenter = RuntimePermissionPresenter.getInstance(context);
+        mActionMetricKey = MetricsProto.MetricsEvent.ACTION_APP_LOCATION_CHECK;
     }
 
     @Override
-    public void handlePositiveAction(Anomaly anomaly, int metricsKey) {
+    public void handlePositiveAction(Anomaly anomaly, int contextMetricsKey) {
+        super.handlePositiveAction(anomaly, contextMetricsKey);
         mRuntimePermissionPresenter.revokeRuntimePermission(anomaly.packageName,
                 LOCATION_PERMISSION);
     }
diff --git a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java
index aadfa0c..55686e0 100644
--- a/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java
+++ b/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetector.java
@@ -70,11 +70,12 @@
             String targetPackageName) {
         final List<BatterySipper> batterySippers = batteryStatsHelper.getUsageList();
         final List<Anomaly> anomalies = new ArrayList<>();
-        final long totalRunningHours = mBatteryUtils.calculateRunningTimeBasedOnStatsType(
-                batteryStatsHelper, BatteryStats.STATS_SINCE_CHARGED) / DateUtils.HOUR_IN_MILLIS;
+        final double totalRunningHours = mBatteryUtils.calculateRunningTimeBasedOnStatsType(
+                batteryStatsHelper, BatteryStats.STATS_SINCE_CHARGED)
+                / (double) DateUtils.HOUR_IN_MILLIS;
         final int targetUid = mBatteryUtils.getPackageUid(targetPackageName);
 
-        if (totalRunningHours != 0) {
+        if (totalRunningHours >= 1) {
             for (int i = 0, size = batterySippers.size(); i < size; i++) {
                 final BatterySipper sipper = batterySippers.get(i);
                 final BatteryStats.Uid uid = sipper.uidObj;
diff --git a/src/com/android/settings/gestures/AssistGesturePreferenceController.java b/src/com/android/settings/gestures/AssistGesturePreferenceController.java
index 8bf660b..ede20c2 100644
--- a/src/com/android/settings/gestures/AssistGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/AssistGesturePreferenceController.java
@@ -67,6 +67,7 @@
         mPreference = screen.findPreference(getPreferenceKey());
         if (!mFeatureProvider.isSupported(mContext)) {
             mScreen.removePreference(mPreference);
+            removePreference(mScreen, getPreferenceKey());
             return;
         }
         // Call super last or AbstractPreferenceController might remove the preference from the
diff --git a/src/com/android/settings/inputmethod/SpellCheckersSettings.java b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
index e21ced1..3a3f443 100644
--- a/src/com/android/settings/inputmethod/SpellCheckersSettings.java
+++ b/src/com/android/settings/inputmethod/SpellCheckersSettings.java
@@ -21,6 +21,7 @@
 import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
 import android.support.v7.preference.Preference.OnPreferenceClickListener;
@@ -105,7 +106,8 @@
 
     @Override
     public void onSwitchChanged(final Switch switchView, final boolean isChecked) {
-        mTsm.setSpellCheckerEnabled(isChecked);
+        Settings.Secure.putInt(getContentResolver(), Settings.Secure.SPELL_CHECKER_ENABLED,
+                isChecked ? 1 : 0);
         updatePreferenceScreen();
     }
 
@@ -203,12 +205,17 @@
         builder.setSingleChoiceItems(items, checkedItemId, new AlertDialog.OnClickListener() {
             @Override
             public void onClick(final DialogInterface dialog, final int item) {
+                final int subtypeId;
                 if (item == ITEM_ID_USE_SYSTEM_LANGUAGE) {
-                    mTsm.setSpellCheckerSubtype(null);
+                    subtypeId = SpellCheckerSubtype.SUBTYPE_ID_NONE;
                 } else {
                     final int index = convertDialogItemIdToSubtypeIndex(item);
-                    mTsm.setSpellCheckerSubtype(currentSci.getSubtypeAt(index));
+                    subtypeId = currentSci.getSubtypeAt(index).hashCode();
                 }
+
+                Settings.Secure.putInt(getContentResolver(),
+                        Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, subtypeId);
+
                 if (DBG) {
                     final SpellCheckerSubtype subtype = mTsm.getCurrentSpellCheckerSubtype(
                             true /* allowImplicitlySelectedSubtype */);
@@ -248,7 +255,11 @@
     }
 
     private void changeCurrentSpellChecker(final SpellCheckerInfo sci) {
-        mTsm.setCurrentSpellChecker(sci);
+        Settings.Secure.putString(getContentResolver(), Settings.Secure.SELECTED_SPELL_CHECKER,
+                sci.getId());
+        // Reset the spell checker subtype
+        Settings.Secure.putInt(getContentResolver(), Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE,
+                SpellCheckerSubtype.SUBTYPE_ID_NONE);
         if (DBG) {
             Log.d(TAG, "Current spell check is " + mTsm.getCurrentSpellChecker().getId());
         }
diff --git a/src/com/android/settings/notification/RedactionInterstitial.java b/src/com/android/settings/notification/RedactionInterstitial.java
index b269062..93c14c7 100644
--- a/src/com/android/settings/notification/RedactionInterstitial.java
+++ b/src/com/android/settings/notification/RedactionInterstitial.java
@@ -23,6 +23,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -41,6 +42,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.SetupRedactionInterstitial;
+import com.android.settings.SetupWizardUtils;
 import com.android.settings.Utils;
 import com.android.settingslib.RestrictedLockUtils;
 
@@ -54,6 +56,12 @@
     }
 
     @Override
+    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
+        resid = SetupWizardUtils.getTheme(getIntent());
+        super.onApplyThemeResource(theme, resid, first);
+    }
+
+    @Override
     protected boolean isValidFragment(String fragmentName) {
         return RedactionInterstitialFragment.class.getName().equals(fragmentName);
     }
diff --git a/src/com/android/settings/notification/SettingPrefController.java b/src/com/android/settings/notification/SettingPrefController.java
index 2af1bde..ac613d1 100644
--- a/src/com/android/settings/notification/SettingPrefController.java
+++ b/src/com/android/settings/notification/SettingPrefController.java
@@ -55,6 +55,7 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         mPreference.init(mParent);
+        super.displayPreference(screen);
         if (isAvailable()) {
             mSettingsObserver = new SettingsObserver();
         }
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index 2f359d1..b646360 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -28,6 +28,7 @@
 import android.app.admin.PasswordMetrics;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources.Theme;
 import android.graphics.Insets;
 import android.os.Bundle;
 import android.os.Handler;
@@ -61,6 +62,7 @@
 import com.android.settings.EncryptionInterstitial;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
+import com.android.settings.SetupWizardUtils;
 import com.android.settings.Utils;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.notification.RedactionInterstitial;
@@ -88,6 +90,12 @@
         return modIntent;
     }
 
+    @Override
+    protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
+        resid = SetupWizardUtils.getTheme(getIntent());
+        super.onApplyThemeResource(theme, resid, first);
+    }
+
     public static class IntentBuilder {
 
         private final Intent mIntent;
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index 51c1569..d1964b4 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -20,6 +20,7 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources.Theme;
 import android.os.Bundle;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -40,6 +41,7 @@
 import com.android.settings.EncryptionInterstitial;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
+import com.android.settings.SetupWizardUtils;
 import com.android.settings.Utils;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.notification.RedactionInterstitial;
@@ -80,6 +82,12 @@
         return modIntent;
     }
 
+    @Override
+    protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
+        resid = SetupWizardUtils.getTheme(getIntent());
+        super.onApplyThemeResource(theme, resid, first);
+    }
+
     public static class IntentBuilder {
         private final Intent mIntent;
 
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index 69498a9..f48ec96 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -53,15 +53,16 @@
 public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
 
     // The index of the array is isStrongAuth << 2 + isProfile << 1 + isAlpha.
+    // TODO(b/36511626): add back special strings for strong auth.
     private static final int[] DETAIL_TEXTS = new int[] {
         R.string.lockpassword_confirm_your_pin_generic,
         R.string.lockpassword_confirm_your_password_generic,
         R.string.lockpassword_confirm_your_pin_generic_profile,
         R.string.lockpassword_confirm_your_password_generic_profile,
-        R.string.lockpassword_strong_auth_required_reason_restart_device_pin,
-        R.string.lockpassword_strong_auth_required_reason_restart_device_password,
-        R.string.lockpassword_strong_auth_required_reason_restart_work_pin,
-        R.string.lockpassword_strong_auth_required_reason_restart_work_password,
+        R.string.lockpassword_confirm_your_pin_generic,
+        R.string.lockpassword_confirm_your_password_generic,
+        R.string.lockpassword_confirm_your_pin_generic_profile,
+        R.string.lockpassword_confirm_your_password_generic_profile,
     };
 
     public static class InternalActivity extends ConfirmLockPassword {
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index 2931596..0c0025e 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -243,15 +243,11 @@
         }
 
         private int getDefaultDetails() {
-            boolean isStrongAuthRequired = isStrongAuthRequired();
+            // TODO(b/36511626): add back special strings for strong auth.
             if (UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId)) {
-                return isStrongAuthRequired
-                        ? R.string.lockpassword_strong_auth_required_reason_restart_work_pattern
-                        : R.string.lockpassword_confirm_your_pattern_generic_profile;
+                return R.string.lockpassword_confirm_your_pattern_generic_profile;
             } else {
-                return isStrongAuthRequired
-                        ? R.string.lockpassword_strong_auth_required_reason_restart_device_pattern
-                        : R.string.lockpassword_confirm_your_pattern_generic;
+                return R.string.lockpassword_confirm_your_pattern_generic;
             }
         }
 
diff --git a/src/com/android/settings/password/SetupChooseLockPassword.java b/src/com/android/settings/password/SetupChooseLockPassword.java
index b8ded5e..f23ab6d 100644
--- a/src/com/android/settings/password/SetupChooseLockPassword.java
+++ b/src/com/android/settings/password/SetupChooseLockPassword.java
@@ -20,7 +20,6 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.Resources;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.Button;
@@ -30,7 +29,6 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
 import com.android.settings.SetupRedactionInterstitial;
-import com.android.settings.SetupWizardUtils;
 import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
 import com.android.settings.password.ChooseLockTypeDialogFragment.OnLockTypeSelectedListener;
 import com.android.setupwizardlib.util.WizardManagerHelper;
@@ -69,12 +67,6 @@
         layout.setFitsSystemWindows(false);
     }
 
-    @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
     public static class SetupChooseLockPasswordFragment extends ChooseLockPasswordFragment
             implements OnLockTypeSelectedListener {
 
diff --git a/src/com/android/settings/password/SetupChooseLockPattern.java b/src/com/android/settings/password/SetupChooseLockPattern.java
index 7cb5afb..b1e3d0d 100644
--- a/src/com/android/settings/password/SetupChooseLockPattern.java
+++ b/src/com/android/settings/password/SetupChooseLockPattern.java
@@ -19,10 +19,8 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.Resources;
 
 import com.android.settings.SetupRedactionInterstitial;
-import com.android.settings.SetupWizardUtils;
 
 /**
  * Setup Wizard's version of ChooseLockPattern screen. It inherits the logic and basic structure
@@ -48,12 +46,6 @@
         return SetupChooseLockPatternFragment.class;
     }
 
-    @Override
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        resid = SetupWizardUtils.getTheme(getIntent());
-        super.onApplyThemeResource(theme, resid, first);
-    }
-
     public static class SetupChooseLockPatternFragment extends ChooseLockPatternFragment {
 
         @Override
diff --git a/src/com/android/settings/search/SearchFragment.java b/src/com/android/settings/search/SearchFragment.java
index fdde0af..847285d 100644
--- a/src/com/android/settings/search/SearchFragment.java
+++ b/src/com/android/settings/search/SearchFragment.java
@@ -184,10 +184,11 @@
         mSearchView.requestFocus();
 
         // Updating internal views inside SearchView was the easiest way to get this too look right.
-        // We null-check here so that tests pass since the robotests can't find the internal views.
-        TextView searchText = mSearchView.findViewById(com.android.internal.R.id.search_src_text);
-        if (searchText != null) {
-            searchText.setTextColor(getContext().getColorStateList(
+        // Instead of grabbing the TextView directly, we grab it as a view and do an instanceof
+        // check. This ensures if we return, say, a LinearLayout in the tests, they won't fail.
+        View searchText = mSearchView.findViewById(com.android.internal.R.id.search_src_text);
+        if (searchText instanceof TextView) {
+            ((TextView) searchText).setTextColor(getContext().getColorStateList(
                     com.android.internal.R.color.text_color_primary));
         }
         View editFrame = mSearchView.findViewById(com.android.internal.R.id.search_edit_frame);
diff --git a/src/com/android/settings/search/SearchResultsAdapter.java b/src/com/android/settings/search/SearchResultsAdapter.java
index a26257f..ea395b0 100644
--- a/src/com/android/settings/search/SearchResultsAdapter.java
+++ b/src/com/android/settings/search/SearchResultsAdapter.java
@@ -45,6 +45,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder>
         implements SearchResultsRankerCallback {
@@ -312,22 +313,23 @@
         int appSize = installedAppResults.size();
 
         final List<SearchResult> asyncRankingResults = new ArrayList<>(dbSize + appSize);
-        List<SearchResult> databaseResultsSortedByScores = new ArrayList<>(databaseResults);
-        Collections.sort(databaseResultsSortedByScores, new Comparator<SearchResult>() {
-            @Override
-            public int compare(SearchResult o1, SearchResult o2) {
-                float score1 = getRankingScoreByStableId(o1.stableId);
-                float score2 = getRankingScoreByStableId(o2.stableId);
-                if (score1 > score2) {
-                    return -1;
-                } else if (score1 == score2) {
-                    return 0;
-                } else {
-                    return 1;
-                }
-            }
-        });
-        asyncRankingResults.addAll(databaseResultsSortedByScores);
+        TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>(
+                new Comparator<SearchResult>() {
+                    @Override
+                    public int compare(SearchResult o1, SearchResult o2) {
+                        float score1 = getRankingScoreByStableId(o1.stableId);
+                        float score2 = getRankingScoreByStableId(o2.stableId);
+                        if (score1 > score2) {
+                            return -1;
+                        } else if (score1 == score2) {
+                            return 0;
+                        } else {
+                            return 1;
+                        }
+                    }
+                });
+        dbResultsSortedByScores.addAll(databaseResults);
+        asyncRankingResults.addAll(dbResultsSortedByScores);
         // App results are not ranked by async ranking and appended at the end of the list.
         asyncRankingResults.addAll(installedAppResults);
         return asyncRankingResults;
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 5cb27f9..bef2e9a 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -725,6 +725,7 @@
         final boolean voiceCapable = Utils.isVoiceCapable(context);
         final ArrayList<Integer> missingIcons = new ArrayList<>();
         final ArrayList<UserPreference> userPreferences = new ArrayList<>();
+        int guestId = UserPreference.USERID_GUEST_DEFAULTS;
         userPreferences.add(mMePreference);
 
         for (UserInfo user : users) {
@@ -738,6 +739,7 @@
                 pref = mMePreference;
             } else if (user.isGuest()) {
                 // Skip over Guest. We add generic Guest settings after this loop
+                guestId = user.id;
                 continue;
             } else {
                 // With Telephony:
@@ -814,9 +816,23 @@
             userPreferences.add(pref);
             pref.setDisabledByAdmin(
                     mUserCaps.mDisallowAddUser ? mUserCaps.mEnforcedAdmin : null);
-            if (!pref.isDisabledByAdmin()) {
-                pref.setSelectable(false);
-            }
+            int finalGuestId = guestId;
+            pref.setOnPreferenceClickListener(preference -> {
+                int id = finalGuestId;
+                if (id == UserPreference.USERID_GUEST_DEFAULTS) {
+                    UserInfo guest = mUserManager.createGuest(
+                            getContext(), preference.getTitle().toString());
+                    if (guest != null) {
+                        id = guest.id;
+                    }
+                }
+                try {
+                    ActivityManager.getService().switchUser(id);
+                } catch (RemoteException e) {
+                    e.rethrowFromSystemServer();
+                }
+                return true;
+            });
         }
 
         // Sort list of users by serialNum
diff --git a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
index afbb0b4..90c5888 100644
--- a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
+++ b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
@@ -45,7 +45,7 @@
         finish();
     }
 
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    @VisibleForTesting
     void startFallbackSuggestion() {
         // fall back to default wallpaper picker
         Utils.startWithFragment(this, WallpaperTypeSettings.class.getName(), null, null, 0,
diff --git a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
index bef4777..1ca8ac7 100644
--- a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
+++ b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
@@ -90,8 +90,13 @@
                 final List<ResolveInfo> rList = pm.queryIntentActivities(intent,
                         PackageManager.MATCH_DEFAULT_ONLY);
 
-                // Add indexable data for each of the matching activities
+                // Add indexable data for package that is in config_wallpaper_picker_package
+                final String wallpaperPickerPackage =
+                        context.getString(R.string.config_wallpaper_picker_package);
                 for (ResolveInfo info : rList) {
+                    if (!wallpaperPickerPackage.equals(info.activityInfo.packageName)) {
+                        continue;
+                    }
                     CharSequence label = info.loadLabel(pm);
                     if (label == null) label = info.activityInfo.packageName;
 
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index bf67565..ee4acd1 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -127,17 +127,25 @@
         final List<AccessPoint> accessPoints =
                 WifiSavedConfigUtils.getAllConfigs(context, mWifiManager);
         Collections.sort(accessPoints, SAVED_NETWORK_COMPARATOR);
-        preferenceScreen.removeAll();
+        cacheRemoveAllPrefs(preferenceScreen);
 
         final int accessPointsSize = accessPoints.size();
-        for (int i = 0; i < accessPointsSize; ++i){
+        for (int i = 0; i < accessPointsSize; ++i) {
+            AccessPoint ap = accessPoints.get(i);
+            String key = AccessPointPreference.generatePreferenceKey(ap);
             LongPressAccessPointPreference preference =
-                    new LongPressAccessPointPreference(accessPoints.get(i), context,
-                            mUserBadgeCache, true, this);
-            preference.setIcon(null);
-            preferenceScreen.addPreference(preference);
+                    (LongPressAccessPointPreference) getCachedPreference(key);
+            if (preference == null) {
+                preference = new LongPressAccessPointPreference(
+                        ap, context, mUserBadgeCache, true, this);
+                preference.setKey(key);
+                preference.setIcon(null);
+                preferenceScreen.addPreference(preference);
+            }
         }
 
+        removeCachedPrefs(preferenceScreen);
+
         if(getPreferenceScreen().getPreferenceCount() < 1) {
             Log.w(TAG, "Saved networks activity loaded, but there are no saved networks!");
         }
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index c6c5de7..cb4e723 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -43,7 +43,6 @@
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceCategory;
-import android.text.TextUtils;
 import android.util.Log;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
@@ -735,10 +734,7 @@
             AccessPoint accessPoint = accessPoints.get(index);
             // Ignore access points that are out of range.
             if (accessPoint.isReachable()) {
-                String key = accessPoint.getBssid();
-                if (TextUtils.isEmpty(key)) {
-                    key = accessPoint.getSsidStr();
-                }
+                String key = AccessPointPreference.generatePreferenceKey(accessPoint);
                 hasAvailableAccessPoints = true;
                 LongPressAccessPointPreference pref =
                         (LongPressAccessPointPreference) getCachedPreference(key);
@@ -992,6 +988,7 @@
         mMetricsFeatureProvider.action(getActivity(), MetricsEvent.ACTION_WIFI_CONNECT,
                 isSavedNetwork);
         mWifiManager.connect(config, mConnectListener);
+        scrollToPreference(mConnectedAccessPointPreferenceCategory);
     }
 
     protected void connect(final int networkId, boolean isSavedNetwork) {
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java
index edb5d89..5fbd3a7 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java
@@ -16,11 +16,17 @@
 package com.android.settings.accounts;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
+
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.when;
 
 import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SyncAdapterType;
 import android.os.UserHandle;
 import android.support.v7.preference.Preference;
 
@@ -28,29 +34,58 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowAccountManager;
+import com.android.settings.testutils.shadow.ShadowContentResolver;
 
+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.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
 
 @RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = {ShadowAccountManager.class, ShadowContentResolver.class})
 public class AccountSyncPreferenceControllerTest {
 
+    @Mock(answer = RETURNS_DEEP_STUBS)
+    private AccountManager mAccountManager;
+
+    private Context mContext;
+    private AccountSyncPreferenceController mController;
+    private Preference mPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowApplication application = ShadowApplication.getInstance();
+        application.setSystemService(Context.ACCOUNT_SERVICE, mAccountManager);
+        mContext = application.getApplicationContext();
+
+        when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn(
+                new AuthenticatorDescription[0]);
+        when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
+
+        mPreference = new Preference(mContext);
+        mPreference.setKey("account_sync");
+
+        mController = new AccountSyncPreferenceController(mContext);
+        mController.init(new Account("acct1", "type1"), new UserHandle(3));
+    }
+
+    @After
+    public void tearDown() {
+        ShadowContentResolver.reset();
+    }
+
     @Test
     public void handlePreferenceTreeClick_shouldStartFragment() {
-        final ShadowApplication application = ShadowApplication.getInstance();
-        final Context context = application.getApplicationContext();
-        final Preference preference = new Preference(context);
-        preference.setKey("account_sync");
+        mController.handlePreferenceTreeClick(mPreference);
 
-        final AccountSyncPreferenceController controller =
-                new AccountSyncPreferenceController(context);
-        controller.init(new Account("acct1", "type1"), mock(UserHandle.class));
-        controller.handlePreferenceTreeClick(preference);
-
-        final Intent nextActivity = application.getNextStartedActivity();
+        final Intent nextActivity = ShadowApplication.getInstance().getNextStartedActivity();
 
         assertThat(nextActivity.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
                 .isEqualTo(AccountSyncSettings.class.getName());
@@ -58,4 +93,93 @@
                 .isEqualTo(R.string.account_sync_title);
     }
 
+    @Test
+    public void updateSummary_adapterInvisible_shouldNotCount() {
+        SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */,
+                "type1" /* accountType */, false /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType[] syncAdapters = {syncAdapterType};
+        ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
+
+        mController.updateSummary(mPreference);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off));
+    }
+
+    @Test
+    public void updateSummary_notSameAccountType_shouldNotCount() {
+        SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */,
+                "type5" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType[] syncAdapters = {syncAdapterType};
+        ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
+
+        mController.updateSummary(mPreference);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off));
+    }
+
+    @Test
+    public void updateSummary_notSyncable_shouldNotCount() {
+        SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */,
+                "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType[] syncAdapters = {syncAdapterType};
+        ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
+        ShadowContentResolver.setSyncable("authority", 0);
+
+        mController.updateSummary(mPreference);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off));
+    }
+
+    @Test
+    public void updateSummary_syncDisabled_shouldNotCount() {
+        SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */,
+                "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType[] syncAdapters = {syncAdapterType};
+        ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
+        ShadowContentResolver.setSyncAutomatically("authority", false);
+        ShadowContentResolver.setMasterSyncAutomatically(3, true);
+
+        mController.updateSummary(mPreference);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off));
+    }
+
+    @Test
+    public void updateSummary_syncEnabled_shouldCount() {
+        SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */,
+                "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType[] syncAdapters = {syncAdapterType};
+        ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
+
+        mController.updateSummary(mPreference);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.account_sync_summary_all_on));
+    }
+
+    @Test
+    public void updateSummary_multipleSyncAdapters_shouldSetSummary() {
+        SyncAdapterType syncAdapterType1 = new SyncAdapterType("authority1" /* authority */,
+                "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType syncAdapterType2 = new SyncAdapterType("authority2" /* authority */,
+                "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType syncAdapterType3 = new SyncAdapterType("authority3" /* authority */,
+                "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType syncAdapterType4 = new SyncAdapterType("authority4" /* authority */,
+                "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */);
+        SyncAdapterType[] syncAdapters =
+                {syncAdapterType1, syncAdapterType2, syncAdapterType3, syncAdapterType4};
+        ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
+
+        ShadowContentResolver.setSyncAutomatically("authority4", false);
+
+        mController.updateSummary(mPreference);
+
+        assertThat(mPreference.getSummary())
+                .isEqualTo(mContext.getString(R.string.account_sync_summary_some_on, 3, 4));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index 55bc4ca..a150893 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -15,32 +15,16 @@
  */
 package com.android.settings.dashboard;
 
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Icon;
 import android.support.v7.widget.RecyclerView;
 import android.util.DisplayMetrics;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -68,9 +52,21 @@
 import org.robolectric.annotation.Config;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH,
         sdk = TestConfig.SDK_VERSION,
@@ -321,11 +317,11 @@
     }
 
     @Test
-    public void testSuggestioDismissed_notOnlySuggestion_doNothing() {
+    public void testSuggestionDismissed_notOnlySuggestion_doNothing() {
         final DashboardAdapter adapter =
                 spy(new DashboardAdapter(mContext, null, null, null, null));
         adapter.setCategoriesAndSuggestions(
-                new ArrayList<>(), makeSuggestions("pkg1", "pkg2", "pkg3"));
+                null /* category */, makeSuggestions("pkg1", "pkg2", "pkg3"));
         final DashboardData dashboardData = adapter.mDashboardData;
         reset(adapter); // clear interactions tracking
 
@@ -336,10 +332,10 @@
     }
 
     @Test
-    public void testSuggestioDismissed_onlySuggestion_updateDashboardData() {
+    public void testSuggestionDismissed_onlySuggestion_updateDashboardData() {
         DashboardAdapter adapter =
                 spy(new DashboardAdapter(mContext, null, null, null, null));
-        adapter.setCategoriesAndSuggestions(new ArrayList<>(), makeSuggestions("pkg1"));
+        adapter.setCategoriesAndSuggestions(null /* category */, makeSuggestions("pkg1"));
         final DashboardData dashboardData = adapter.mDashboardData;
         reset(adapter); // clear interactions tracking
 
@@ -360,7 +356,27 @@
         packages.get(0).isIconTintable = true;
         packages.get(0).icon = mockIcon;
 
-        mDashboardAdapter.setCategoriesAndSuggestions(Collections.emptyList(), packages);
+        mDashboardAdapter.setCategoriesAndSuggestions(null /* category */, packages);
+
+        verify(mockIcon).setTint(eq(0x89000000));
+    }
+
+    @Test
+    public void testSetCategories_iconTinted() {
+        TypedArray mockTypedArray = mock(TypedArray.class);
+        doReturn(mockTypedArray).when(mContext).obtainStyledAttributes(any(int[].class));
+        doReturn(0x89000000).when(mockTypedArray).getColor(anyInt(), anyInt());
+
+        final DashboardCategory category = mock(DashboardCategory.class);
+        final List<Tile> tiles = new ArrayList<>();
+        final Icon mockIcon = mock(Icon.class);
+        final Tile tile = new Tile();
+        tile.isIconTintable = true;
+        tile.icon = mockIcon;
+        tiles.add(tile);
+        category.tiles = tiles;
+
+        mDashboardAdapter.setCategory(category);
 
         verify(mockIcon).setTint(eq(0x89000000));
     }
@@ -369,12 +385,12 @@
     public void testBindConditionAndSuggestion_shouldSetSuggestionAdapterAndNoCrash() {
         mDashboardAdapter = new DashboardAdapter(mContext, null, null, null, null);
         final List<Tile> suggestions = makeSuggestions("pkg1");
-        final List<DashboardCategory> categories = new ArrayList<>();
         final DashboardCategory category = mock(DashboardCategory.class);
         final List<Tile> tiles = new ArrayList<>();
         tiles.add(mock(Tile.class));
         category.tiles = tiles;
-        mDashboardAdapter.setCategoriesAndSuggestions(categories, suggestions);
+
+        mDashboardAdapter.setCategoriesAndSuggestions(category, suggestions);
 
         final RecyclerView data = mock(RecyclerView.class);
         when(data.getResources()).thenReturn(mResources);
@@ -404,7 +420,7 @@
     }
 
     private void setupSuggestions(List<Tile> suggestions) {
-        mDashboardAdapter.setCategoriesAndSuggestions(new ArrayList<>(), suggestions);
+        mDashboardAdapter.setCategoriesAndSuggestions(null /* category */, suggestions);
         final Context context = RuntimeEnvironment.application;
         mSuggestionHolder = new DashboardAdapter.SuggestionAndConditionHeaderHolder(
                 LayoutInflater.from(context).inflate(
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
index 46b37a8..df3eb97 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
@@ -37,7 +37,13 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
+import static com.android.settings.dashboard.DashboardData.STABLE_ID_CONDITION_CONTAINER;
+import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONDITION_FOOTER;
+import static com.android.settings.dashboard.DashboardData
+        .STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER;
+import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONTAINER;
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -82,41 +88,53 @@
         twoItemsConditions.add(mTestCondition);
         twoItemsConditions.add(mSecondCondition);
 
-        // Build categories
-        final List<DashboardCategory> categories = new ArrayList<>();
+        // Build category
         mTestCategoryTile.title = TEST_CATEGORY_TILE_TITLE;
         mDashboardCategory.title = "test";
         mDashboardCategory.tiles = new ArrayList<>();
         mDashboardCategory.tiles.add(mTestCategoryTile);
-        categories.add(mDashboardCategory);
 
         // Build DashboardData
         mDashboardDataWithOneConditions = new DashboardData.Builder()
                 .setConditions(oneItemConditions)
-                .setCategories(categories)
+                .setCategory(mDashboardCategory)
                 .setSuggestions(suggestions)
                 .setSuggestionConditionMode(DashboardData.HEADER_MODE_FULLY_EXPANDED)
                 .build();
 
         mDashboardDataWithTwoConditions = new DashboardData.Builder()
                 .setConditions(twoItemsConditions)
-                .setCategories(categories)
+                .setCategory(mDashboardCategory)
                 .setSuggestions(suggestions)
                 .setSuggestionConditionMode(DashboardData.HEADER_MODE_FULLY_EXPANDED)
                 .build();
 
         mDashboardDataWithNoItems = new DashboardData.Builder()
                 .setConditions(null)
-                .setCategories(null)
+                .setCategory(null)
                 .setSuggestions(null)
                 .build();
     }
 
     @Test
+    public void testBuildItemsData_shouldSetstableId() {
+        final List<DashboardData.Item> items = mDashboardDataWithOneConditions.getItemList();
+
+        // Header, suggestion, condition, footer, 1 tile
+        assertThat(items).hasSize(5);
+
+        assertThat(items.get(0).id).isEqualTo(STABLE_ID_SUGGESTION_CONDITION_TOP_HEADER);
+        assertThat(items.get(1).id).isEqualTo(STABLE_ID_SUGGESTION_CONTAINER);
+        assertThat(items.get(2).id).isEqualTo(STABLE_ID_CONDITION_CONTAINER);
+        assertThat(items.get(3).id).isEqualTo(STABLE_ID_SUGGESTION_CONDITION_FOOTER);
+        assertThat(items.get(4).id).isEqualTo(Objects.hash(mTestCategoryTile.title));
+    }
+
+    @Test
     public void testBuildItemsData_containsAllData() {
         final DashboardData.SuggestionConditionHeaderData data =
                 new DashboardData.SuggestionConditionHeaderData(
-                    mDashboardDataWithOneConditions.getConditions(), 0);
+                        mDashboardDataWithOneConditions.getConditions(), 0);
         final Object[] expectedObjects = {data,
                 mDashboardDataWithOneConditions.getSuggestions(),
                 mDashboardDataWithOneConditions.getConditions(),
@@ -131,9 +149,9 @@
                 assertThat(item).isEqualTo(expectedObjects[i]);
             } else if (item instanceof DashboardData.SuggestionConditionHeaderData) {
                 DashboardData.SuggestionConditionHeaderData i1 =
-                    (DashboardData.SuggestionConditionHeaderData)item;
+                        (DashboardData.SuggestionConditionHeaderData) item;
                 DashboardData.SuggestionConditionHeaderData i2 =
-                    (DashboardData.SuggestionConditionHeaderData)expectedObjects[i];
+                        (DashboardData.SuggestionConditionHeaderData) expectedObjects[i];
                 assertThat(i1.title).isEqualTo(i2.title);
                 assertThat(i1.conditionCount).isEqualTo(i2.conditionCount);
                 assertThat(i1.hiddenSuggestionCount).isEqualTo(i2.hiddenSuggestionCount);
@@ -198,7 +216,7 @@
         // Item in position 3 is the condition container containing the list of conditions, which
         // gets 1 more item
         testResultData.add(new ListUpdateResult.ResultData(
-            ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 2, 1));
+                ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 2, 1));
 
         testDiffUtil(mDashboardDataWithOneConditions,
                 mDashboardDataWithTwoConditions, testResultData);
@@ -232,10 +250,6 @@
      * <p>
      * Because baseResultData and {@paramref testResultData} don't have sequence. When do the
      * comparison, we will sort them first and then compare the inside data from them one by one.
-     *
-     * @param baseDashboardData
-     * @param diffDashboardData
-     * @param testResultData
      */
     private void testDiffUtil(DashboardData baseDashboardData, DashboardData diffDashboardData,
             List<ListUpdateResult.ResultData> testResultData) {
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
index e263e2c..93cd314 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
@@ -19,15 +19,15 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
-
 import android.provider.Settings.Secure;
+
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.Settings.NightDisplaySuggestionActivity;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.Settings;
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowSecureSettings;
 import com.android.settingslib.drawer.Tile;
 import com.android.settingslib.suggestions.SuggestionParser;
@@ -50,14 +50,15 @@
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 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)
 @Config(manifest = TestConfig.MANIFEST_PATH,
-    sdk = TestConfig.SDK_VERSION,
-    shadows = ShadowSecureSettings.class)
+        sdk = TestConfig.SDK_VERSION,
+        shadows = ShadowSecureSettings.class)
 public class SuggestionFeatureProviderImplTest {
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -140,6 +141,25 @@
     }
 
     @Test
+    public void dismissSuggestion_isShowingFirstImpressionType_dismissWithoutSmartSuggestionRule() {
+        mProvider = spy(mProvider);
+        when(mProvider.isSmartSuggestionEnabled(any(Context.class))).thenReturn(true);
+        final SharedPreferences pref = RuntimeEnvironment.application.getSharedPreferences(
+                "test_pref", Context.MODE_PRIVATE);
+        when(mProvider.getSharedPrefs(mContext)).thenReturn(pref);
+        when(mSuggestionParser.dismissSuggestion(any(Tile.class), anyBoolean()))
+                .thenReturn(false);
+
+        mProvider.dismissSuggestion(mContext, mSuggestionParser, mSuggestion);
+
+        verify(mFactory.metricsFeatureProvider).action(
+                eq(mContext),
+                eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_DISMISS_SUGGESTION),
+                anyString());
+        verify(mSuggestionParser).dismissSuggestion(any(Tile.class), eq(false));
+    }
+
+    @Test
     public void dismissSuggestion_noContext_shouldDoNothing() {
         mProvider.dismissSuggestion(null, mSuggestionParser, mSuggestion);
 
@@ -195,14 +215,14 @@
     public void nightDisplaySuggestion_isCompleted_ifPreviouslyActivated() {
         Secure.putLong(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, 1L);
         final ComponentName componentName =
-            new ComponentName(mContext, NightDisplaySuggestionActivity.class);
+                new ComponentName(mContext, NightDisplaySuggestionActivity.class);
         assertThat(mProvider.isSuggestionCompleted(mContext, componentName)).isTrue();
     }
 
     @Test
     public void nightDisplaySuggestion_isNotCompleted_byDefault() {
         final ComponentName componentName =
-            new ComponentName(mContext, NightDisplaySuggestionActivity.class);
+                new ComponentName(mContext, NightDisplaySuggestionActivity.class);
         assertThat(mProvider.isSuggestionCompleted(mContext, componentName)).isFalse();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index ff6e52a..151463a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.os.BatteryStats;
 import android.os.Process;
+import android.os.SystemClock;
 import android.text.format.DateUtils;
 
 import com.android.internal.os.BatterySipper;
@@ -369,11 +370,12 @@
 
     @Test
     public void testGetForegroundActivityTotalTimeMs_returnMilliseconds() {
+        final long rawRealtimeMs = SystemClock.elapsedRealtime();
         doReturn(mTimer).when(mUid).getForegroundActivityTimer();
-        doReturn(TIME_SINCE_LAST_FULL_CHARGE_US).when(mTimer).getTotalTimeLocked(anyLong(),
-                anyInt());
+        doReturn(TIME_SINCE_LAST_FULL_CHARGE_US).when(mTimer)
+                .getTotalTimeLocked(rawRealtimeMs * 1000, BatteryStats.STATS_SINCE_CHARGED);
 
-        assertThat(mBatteryUtils.getForegroundActivityTotalTimeMs(mUid, 0)).isEqualTo(
+        assertThat(mBatteryUtils.getForegroundActivityTotalTimeMs(mUid, rawRealtimeMs)).isEqualTo(
                 TIME_SINCE_LAST_FULL_CHARGE_MS);
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/AnomalyActionTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/AnomalyActionTest.java
new file mode 100644
index 0000000..8db1a8c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/action/AnomalyActionTest.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.fuelgauge.anomaly.action;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.util.Pair;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.TestConfig;
+import com.android.settings.fuelgauge.anomaly.Anomaly;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AnomalyActionTest {
+    private static final String PACKAGE_NAME = "com.android.app";
+    private static final int UID = 111;
+    private static final int ACTION_KEY = 2;
+    private static final int METRIC_KEY = 3;
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+    @Mock
+    private AppOpsManager mAppOpsManagerr;
+    private Anomaly mAnomaly;
+    private TestAnomalyAction mTestAnomalyAction;
+    private FakeFeatureFactory mFeatureFactory;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        FakeFeatureFactory.setupForTest(mContext);
+        mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+        doReturn(mAppOpsManagerr).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
+
+        mAnomaly = new Anomaly.Builder()
+                .setUid(UID)
+                .setPackageName(PACKAGE_NAME)
+                .build();
+        mTestAnomalyAction = new TestAnomalyAction(mContext);
+    }
+
+    @Test
+    public void testHandlePositiveAction_logAction() {
+        mTestAnomalyAction.handlePositiveAction(mAnomaly, METRIC_KEY);
+
+        verify(mFeatureFactory.metricsFeatureProvider).action(mContext, ACTION_KEY, PACKAGE_NAME,
+                Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, METRIC_KEY));
+    }
+
+    /**
+     * Test class for {@link AnomalyAction}
+     */
+    public class TestAnomalyAction extends AnomalyAction {
+        public TestAnomalyAction(Context context) {
+            super(context);
+            mActionMetricKey = ACTION_KEY;
+        }
+
+        @Override
+        public boolean isActionActive(Anomaly anomaly) {
+            return false;
+        }
+
+        @Override
+        public int getActionType() {
+            return 0;
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java
index 21b2e54..e7c2664 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/checker/WakeupAlarmAnomalyDetectorTest.java
@@ -59,9 +59,10 @@
     private static final int ANOMALY_UID = 111;
     private static final int NORMAL_UID = 222;
     private static final int TARGET_UID = 333;
-    private static final long RUNNING_TIME_MS = 2 * DateUtils.HOUR_IN_MILLIS;
+    private static final long RUNNING_TIME_MS =
+            1 * DateUtils.HOUR_IN_MILLIS + 10 * DateUtils.MINUTE_IN_MILLIS;
     private static final int ANOMALY_WAKEUP_COUNT = 500;
-    private static final int NORMAL_WAKEUP_COUNT = 50;
+    private static final int NORMAL_WAKEUP_COUNT = 61;
     @Mock
     private BatteryStatsHelper mBatteryStatsHelper;
     @Mock
diff --git a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
index 87a37a2..4fadebf 100644
--- a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java
@@ -32,6 +32,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.hardware.input.InputManager;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -192,10 +193,14 @@
     @Test
     public void testNonIndexableKeys_existInXmlLayout() {
         final Context context = spy(RuntimeEnvironment.application);
+        final Resources res = spy(RuntimeEnvironment.application.getResources());
         //(InputManager) context.getSystemService(Context.INPUT_SERVICE);
         InputManager manager = mock(InputManager.class);
         when(manager.getInputDeviceIds()).thenReturn(new int[]{});
         doReturn(manager).when(context).getSystemService(Context.INPUT_SERVICE);
+        doReturn(res).when(context).getResources();
+        doReturn(false).when(res)
+            .getBoolean(com.android.internal.R.bool.config_supportSystemNavigationKeys);
         final List<String> niks = LanguageAndInputSettings.SEARCH_INDEX_DATA_PROVIDER
                 .getNonIndexableKeys(context);
         final int xmlId = (new LanguageAndInputSettings()).getPreferenceScreenResId();
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
index 36f170a..2e346a2 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.testutils.shadow;
 
+import android.accounts.Account;
 import android.content.ContentResolver;
 import android.content.SyncAdapterType;
 
@@ -28,12 +29,20 @@
 
 import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
 
+import java.util.HashMap;
+import java.util.Map;
+
 @Implements(ContentResolver.class)
 public class ShadowContentResolver {
 
+    private static SyncAdapterType[] sSyncAdapterTypes = new SyncAdapterType[0];
+    private static Map<String, Integer> sSyncable = new HashMap<>();
+    private static Map<String, Boolean> sSyncAutomatically = new HashMap<>();
+    private static Map<Integer, Boolean> sMasterSyncAutomatically = new HashMap<>();
+
     @Implementation
     public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) {
-        return new SyncAdapterType[0];
+        return sSyncAdapterTypes;
     }
 
     @Implementation
@@ -44,4 +53,44 @@
                 .add(SearchIndexablesContract.NonIndexableKey.COLUMN_KEY_VALUE, "");
         return cursor;
     }
+
+    @Implementation
+    public static int getIsSyncableAsUser(Account account, String authority, int userId) {
+        return sSyncable.containsKey(authority) ? sSyncable.get(authority) : 1;
+    }
+
+    @Implementation
+    public static boolean getSyncAutomaticallyAsUser(Account account, String authority,
+            int userId) {
+        return sSyncAutomatically.containsKey(authority) ? sSyncAutomatically.get(authority) : true;
+    }
+
+    @Implementation
+    public static boolean getMasterSyncAutomaticallyAsUser(int userId) {
+        return sMasterSyncAutomatically.containsKey(userId)
+                ? sMasterSyncAutomatically.get(userId) : true;
+    }
+
+    public static void setSyncAdapterTypes(SyncAdapterType[] syncAdapterTypes) {
+        sSyncAdapterTypes = syncAdapterTypes;
+    }
+
+    public static void setSyncable(String authority, int syncable) {
+        sSyncable.put(authority, syncable);
+    }
+
+    public static void setSyncAutomatically(String authority, boolean syncAutomatically) {
+        sSyncAutomatically.put(authority, syncAutomatically);
+    }
+
+    public static void setMasterSyncAutomatically(int userId, boolean syncAutomatically) {
+        sMasterSyncAutomatically.put(userId, syncAutomatically);
+    }
+
+    public static void reset() {
+        sSyncable.clear();
+        sSyncAutomatically.clear();
+        sMasterSyncAutomatically.clear();
+        sSyncAdapterTypes = new SyncAdapterType[0];
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java b/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
index 640c884..a85d591 100644
--- a/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
+++ b/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
@@ -15,6 +15,24 @@
  */
 package com.android.settings.wifi;
 
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
+import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 import android.app.Activity;
 import android.app.Fragment;
 import android.content.Context;
@@ -31,6 +49,7 @@
 
 import com.android.settings.Settings.WifiSettingsActivity;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.TestAccessPointBuilder;
 import com.android.settingslib.wifi.WifiTracker;
 import com.android.settingslib.wifi.WifiTracker.WifiListener;
 import com.android.settingslib.wifi.WifiTrackerFactory;
@@ -46,25 +65,6 @@
 
 import java.util.List;
 
-import static android.support.test.InstrumentationRegistry.getInstrumentation;
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.Visibility.VISIBLE;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.not;
-import static org.hamcrest.Matchers.startsWith;
-
-import static org.mockito.Mockito.atMost;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 @RunWith(AndroidJUnit4.class)
 public class WifiSettingsUiTest {
 
@@ -242,4 +242,34 @@
         getInstrumentation().callActivityOnStart(activity);
         verify(mWifiTracker, atMost(1)).forceUpdate();
     }
+
+    @Test
+    public void changingSecurityStateOnApShouldNotCauseMultipleListItems() {
+        setWifiState(WifiManager.WIFI_STATE_ENABLED);
+        TestAccessPointBuilder builder = new TestAccessPointBuilder(mContext)
+                .setSsid(TEST_SSID).setSecurity(AccessPoint.SECURITY_NONE);
+        AccessPoint open = builder.build();
+
+        builder.setSecurity(AccessPoint.SECURITY_EAP);
+        AccessPoint eap = builder.build();
+
+        builder.setSecurity(AccessPoint.SECURITY_WEP);
+        AccessPoint wep = builder.build();
+
+        // Return a different security state each time getAccessPoints is invoked
+        when(mWifiTracker.getAccessPoints())
+                .thenReturn(Lists.newArrayList(open, eap))
+                .thenReturn(Lists.newArrayList(eap))
+                .thenReturn(Lists.newArrayList(wep));
+
+        launchActivity();
+
+        onView(withText(TEST_SSID)).check(matches(isDisplayed()));
+
+        mWifiListener.onAccessPointsChanged();
+        onView(withText(TEST_SSID)).check(matches(isDisplayed()));
+
+        mWifiListener.onAccessPointsChanged();
+        onView(withText(TEST_SSID)).check(matches(isDisplayed()));
+    }
 }