Merge "Remove app info page v1 related codes."
diff --git a/Android.mk b/Android.mk
index b9121ec..df85bbc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -37,8 +37,8 @@
     ims-common
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    apptoolkit-arch-core-runtime \
-    apptoolkit-lifecycle-extensions \
+    android-arch-lifecycle-runtime \
+    android-arch-lifecycle-extensions \
     jsr305 \
     settings-logtags \
 
diff --git a/res/layout/suggestion_container.xml b/res/layout/suggestion_container.xml
index 9110c58..640a91f 100644
--- a/res/layout/suggestion_container.xml
+++ b/res/layout/suggestion_container.xml
@@ -55,7 +55,7 @@
         android:id="@+id/suggestion_list"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingTop="18dp"
+        android:paddingTop="14dp"
         android:paddingBottom="16dp"
         android:scrollbars="none"/>
 
diff --git a/res/layout/suggestion_tile_v2.xml b/res/layout/suggestion_tile_v2.xml
index e04febb..a7717b7 100644
--- a/res/layout/suggestion_tile_v2.xml
+++ b/res/layout/suggestion_tile_v2.xml
@@ -18,7 +18,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/suggestion_card"
-    android:layout_width="328dp"
+    android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     app:cardPreventCornerOverlap="false"
     app:cardUseCompatPadding="true"
@@ -65,7 +65,7 @@
             android:layout_marginEnd="12dp"
             android:singleLine="true"
             android:textAppearance="@style/TextAppearance.SuggestionTitleV2"
-            android:ellipsize="marquee"
+            android:ellipsize="end"
             android:fadingEdge="horizontal" />
 
         <TextView
diff --git a/res/layout/suggestion_tile_with_button_v2.xml b/res/layout/suggestion_tile_with_button_v2.xml
index 5f4ed18..bedc6da 100644
--- a/res/layout/suggestion_tile_with_button_v2.xml
+++ b/res/layout/suggestion_tile_with_button_v2.xml
@@ -18,8 +18,9 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/suggestion_card"
-    android:layout_width="328dp"
+    android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    app:cardPreventCornerOverlap="false"
     app:cardUseCompatPadding="true"
     app:cardElevation="2dp"
     app:cardCornerRadius="@dimen/suggestion_card_corner_radius">
@@ -37,16 +38,17 @@
 
             <ImageView
                 android:id="@android:id/icon"
-                android:layout_width="@dimen/dashboard_tile_image_size"
-                android:layout_height="@dimen/dashboard_tile_image_size"
+                android:layout_width="@dimen/suggestion_card_icon_size"
+                android:layout_height="@dimen/suggestion_card_icon_size"
                 style="@style/SuggestionCardIcon"
                 android:layout_marginTop="16dp"
                 android:layout_marginBottom="8dp" />
 
             <ImageView
                 android:id="@+id/close_button"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
+                android:layout_width="18dp"
+                android:layout_height="18dp"
+                android:alpha="0.54"
                 android:layout_alignParentEnd="true"
                 android:layout_marginTop="8dp"
                 android:layout_marginEnd="8dp"
@@ -62,8 +64,8 @@
             android:layout_marginStart="12dp"
             android:layout_marginEnd="12dp"
             android:singleLine="true"
-            android:textAppearance="@style/TextAppearance.TileTitle"
-            android:ellipsize="marquee"
+            android:textAppearance="@style/TextAppearance.SuggestionTitleV2"
+            android:ellipsize="end"
             android:fadingEdge="horizontal" />
 
         <TextView
diff --git a/res/values-sw400dp/dimens.xml b/res/values-sw400dp/dimens.xml
index 4f13e09..8d45dd4 100755
--- a/res/values-sw400dp/dimens.xml
+++ b/res/values-sw400dp/dimens.xml
@@ -23,9 +23,9 @@
     <dimen name="support_escalation_card_padding_end">56dp</dimen>
 
     <!-- Suggestion cards-->
-    <dimen name="suggestion_card_width_one_card">380dp</dimen>
-    <dimen name="suggestion_card_width_two_cards">184dp</dimen>
-    <dimen name="suggestion_card_width_multiple_cards">176dp</dimen>
+    <dimen name="suggestion_card_width_one_card">384dp</dimen>
+    <dimen name="suggestion_card_width_two_cards">188dp</dimen>
+    <dimen name="suggestion_card_width_multiple_cards">180dp</dimen>
     <dimen name="suggestion_card_padding_bottom_one_card">22dp</dimen>
 
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 332deea..f9ab821 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -304,9 +304,9 @@
 
     <!-- Suggestion cards size and padding -->
     <dimen name="suggestion_card_icon_size">24dp</dimen>
-    <dimen name="suggestion_card_width_one_card">328dp</dimen>
-    <dimen name="suggestion_card_width_two_cards">158dp</dimen>
-    <dimen name="suggestion_card_width_multiple_cards">152dp</dimen>
+    <dimen name="suggestion_card_width_one_card">332dp</dimen>
+    <dimen name="suggestion_card_width_two_cards">162dp</dimen>
+    <dimen name="suggestion_card_width_multiple_cards">156dp</dimen>
     <dimen name="suggestion_card_outer_margin">16dp</dimen>
     <dimen name="suggestion_card_inner_margin">12dp</dimen>
     <dimen name="suggestion_card_padding_bottom_one_card">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f917d81..fe32e9d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1133,8 +1133,12 @@
     <!-- Title for suggested actions for settings up a fingerprint lock [CHAR LIMIT=34] -->
     <string name="suggested_fingerprint_lock_settings_title">Unlock with fingerprint</string>
 
-    <!-- Summary for suggested actions for settings up a fingerprint lock -->
-    <string name="suggested_fingerprint_lock_settings_summary">Unlock with your fingerprint</string>
+    <!-- Summary for suggested actions for settings up a fingerprint lock (tablet)  -->
+    <string name="suggested_fingerprint_lock_settings_summary" product="tablet">Unlock with your fingerprint</string>
+    <!-- Summary for suggested actions for settings up a fingerprint lock (device)  -->
+    <string name="suggested_fingerprint_lock_settings_summary" product="device">Unlock with your fingerprint</string>
+    <!-- Summary for suggested actions for settings up a fingerprint lock (phone)  -->
+    <string name="suggested_fingerprint_lock_settings_summary" product="default">Unlock with your fingerprint</string>
 
     <!--  Title for security picker to choose the unlock method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
     <string name="lock_settings_picker_title">Choose screen lock</string>
@@ -2579,6 +2583,7 @@
 
     <!-- [CHAR LIMIT=30] Title of the preference that opens the Ambient display settings screen. -->
     <string name="ambient_display_screen_title">Ambient display</string>
+
     <!-- [CHAR LIMIT=50] Summary of the preference that opens the Ambient display settings screen, when Ambient display is set to be always on -->
     <string name="ambient_display_screen_summary_always_on">Always on / Increased battery usage</string>
     <!-- [CHAR LIMIT=30] Summary of the preference that opens the Ambient display settings screen, when Ambient display is set to show when new notifications come in. -->
@@ -6714,6 +6719,8 @@
     <string name="keywords_sim_status">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid</string>
     <string name="keywords_model_and_hardware">serial number, hardware version</string>
     <string name="keywords_android_version">android security patch level, baseband version, kernel version</string>
+    <!-- Search keyword for Ambient display settings screen. -->
+    <string name="keywords_ambient_display_screen">Ambient display, Lock screen display</string>
 
     <!-- NFC Wi-Fi pairing/setup strings-->
 
diff --git a/res/xml/ambient_display_settings.xml b/res/xml/ambient_display_settings.xml
index a8ded0d..8bd9bd6 100644
--- a/res/xml/ambient_display_settings.xml
+++ b/res/xml/ambient_display_settings.xml
@@ -17,7 +17,9 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:key="ambient_display_preference_screen"
+    settings:keywords="@string/keywords_ambient_display_screen"
     android:title="@string/ambient_display_screen_title">
 
     <PreferenceCategory
diff --git a/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceController.java b/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceController.java
index 130138c..1a5a285 100644
--- a/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceController.java
@@ -16,18 +16,14 @@
 
 package com.android.settings.applications.appinfo;
 
-import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -35,7 +31,6 @@
 import android.os.UserManager;
 import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.PreferenceScreen;
-import android.util.Log;
 import android.webkit.IWebViewUpdateService;
 
 import com.android.settings.R;
@@ -71,16 +66,6 @@
     private UserManager mUserManager;
     private PackageManager mPm;
 
-    private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final boolean enabled = getResultCode() != Activity.RESULT_CANCELED;
-            Log.d(TAG, "Got broadcast response: Restart status for "
-                    + mParent.getAppEntry().info.packageName + " " + enabled);
-            updateForceStopButton(enabled);
-        }
-    };
-
     public AppActionButtonPreferenceController(Context context, AppInfoDashboardFragment parent,
             String packageName) {
         super(context, KEY_ACTION_BUTTONS);
@@ -101,9 +86,7 @@
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
         mActionButtons = ((ActionButtonPreference) screen.findPreference(KEY_ACTION_BUTTONS))
-                .setButton2Text(R.string.force_stop)
-                .setButton2Positive(false)
-                .setButton2Enabled(false);
+                .setButton2Visible(false);
     }
 
     @Override
@@ -140,7 +123,6 @@
             }
         }
 
-        checkForceStop(appEntry, packageInfo);
         initUninstallButtons(appEntry, packageInfo);
     }
 
@@ -269,41 +251,6 @@
         return disableable;
     }
 
-    private void updateForceStopButton(boolean enabled) {
-        final boolean disallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
-                mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId);
-        mActionButtons
-                .setButton2Enabled(disallowedBySystem ? false : enabled)
-                .setButton2OnClickListener(
-                        disallowedBySystem ? null : v -> mParent.handleForceStopButtonClick());
-    }
-
-    void checkForceStop(AppEntry appEntry, PackageInfo packageInfo) {
-        if (mDpm.packageHasActiveAdmins(packageInfo.packageName)) {
-            // User can't force stop device admin.
-            Log.w(TAG, "User can't force stop device admin");
-            updateForceStopButton(false);
-        } else if (AppUtils.isInstant(packageInfo.applicationInfo)) {
-            updateForceStopButton(false);
-            mActionButtons.setButton2Visible(false);
-        } else if ((appEntry.info.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
-            // If the app isn't explicitly stopped, then always show the
-            // force stop button.
-            Log.w(TAG, "App is not explicitly stopped");
-            updateForceStopButton(true);
-        } else {
-            final Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
-                    Uri.fromParts("package", appEntry.info.packageName, null));
-            intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { appEntry.info.packageName });
-            intent.putExtra(Intent.EXTRA_UID, appEntry.info.uid);
-            intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(appEntry.info.uid));
-            Log.d(TAG, "Sending broadcast to query restart status for "
-                    + appEntry.info.packageName);
-            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
-                    mCheckKillProcessesReceiver, null, Activity.RESULT_CANCELED, null, null);
-        }
-    }
-
     private boolean signaturesMatch(String pkg1, String pkg2) {
         if (pkg1 != null && pkg2 != null) {
             try {
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index f363473..a99ba65 100755
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -19,7 +19,6 @@
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -85,6 +84,7 @@
     // Menu identifiers
     private static final int UNINSTALL_ALL_USERS_MENU = 1;
     private static final int UNINSTALL_UPDATES = 2;
+    static final int FORCE_STOP_MENU = 3;
 
     // Result code identifiers
     @VisibleForTesting
@@ -99,7 +99,7 @@
 
     // Dialog identifiers used in showDialog
     private static final int DLG_BASE = 0;
-    private static final int DLG_FORCE_STOP = DLG_BASE + 1;
+    static final int DLG_FORCE_STOP = DLG_BASE + 1;
     private static final int DLG_DISABLE = DLG_BASE + 2;
     private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
 
@@ -137,6 +137,7 @@
 
     private InstantAppButtonsPreferenceController mInstantAppButtonPreferenceController;
     private AppActionButtonPreferenceController mAppActionButtonPreferenceController;
+    private ForceStopOptionsMenuController mForceStopOptionsMenuController;
 
     /**
      * Callback to invoke when app info has been changed.
@@ -168,6 +169,9 @@
             return;
         }
 
+        mForceStopOptionsMenuController =
+            new ForceStopOptionsMenuController(activity, this /* parent */, mDpm,
+                mMetricsFeatureProvider, getLifecycle());
         setHasOptionsMenu(true);
     }
 
@@ -264,6 +268,10 @@
         return mAppEntry;
     }
 
+    void setAppEntry(ApplicationsState.AppEntry appEntry) {
+        mAppEntry = appEntry;
+    }
+
     PackageInfo getPackageInfo() {
         if (mAppEntry == null) {
             retrieveAppEntry();
@@ -271,6 +279,10 @@
         return mPackageInfo;
     }
 
+    ApplicationsState getAppState() {
+        return mState;
+    }
+
     @Override
     public void onPackageSizeChanged(String packageName) {
         if (!TextUtils.equals(packageName, mPackageName)) {
@@ -311,6 +323,7 @@
         if (mFinishing) {
             return;
         }
+        super.onPrepareOptionsMenu(menu);
         menu.findItem(UNINSTALL_ALL_USERS_MENU).setVisible(shouldShowUninstallForAll(mAppEntry));
         mUpdatedSysApp = (mAppEntry.info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
         final MenuItem uninstallUpdatesItem = menu.findItem(UNINSTALL_UPDATES);
@@ -331,7 +344,7 @@
                 uninstallPkg(mAppEntry.info.packageName, false, false);
                 return true;
         }
-        return false;
+        return super.onOptionsItemSelected(item);
     }
 
     @Override
@@ -461,18 +474,10 @@
                         })
                         .setNegativeButton(R.string.dlg_cancel, null)
                         .create();
-            case DLG_FORCE_STOP:
-                return new AlertDialog.Builder(getActivity())
-                        .setTitle(getActivity().getText(R.string.force_stop_dlg_title))
-                        .setMessage(getActivity().getText(R.string.force_stop_dlg_text))
-                        .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
-                            public void onClick(DialogInterface dialog, int which) {
-                                // Force stop
-                                forceStopPackage(mAppEntry.info.packageName);
-                            }
-                        })
-                        .setNegativeButton(R.string.dlg_cancel, null)
-                        .create();
+        }
+        final AlertDialog dialog = mForceStopOptionsMenuController.createDialog(id);
+        if (dialog != null) {
+            return dialog;
         }
         return mInstantAppButtonPreferenceController.createDialog(id);
     }
@@ -489,21 +494,6 @@
         mDisableAfterUninstall = andDisable;
     }
 
-    private void forceStopPackage(String pkgName) {
-        mMetricsFeatureProvider.action(getContext(), MetricsEvent.ACTION_APP_FORCE_STOP, pkgName);
-        final ActivityManager am = (ActivityManager) getActivity().getSystemService(
-                Context.ACTIVITY_SERVICE);
-        Log.d(TAG, "Stopping package " + pkgName);
-        am.forceStopPackage(pkgName);
-        final int userId = UserHandle.getUserId(mAppEntry.info.uid);
-        mState.invalidatePackage(pkgName, userId);
-        final AppEntry newEnt = mState.getEntry(pkgName, userId);
-        if (newEnt != null) {
-            mAppEntry = newEnt;
-        }
-        mAppActionButtonPreferenceController.checkForceStop(mAppEntry, mPackageInfo);
-    }
-
     public static void startAppInfoFragment(Class<?> fragment, int title,
             SettingsPreferenceFragment caller, AppEntry appEntry) {
         // start new fragment to display extended information
@@ -564,20 +554,6 @@
         }
     }
 
-    void handleForceStopButtonClick() {
-        if (mAppEntry == null) {
-            setIntentAndFinish(true, true);
-            return;
-        }
-        if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) {
-            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
-                    getActivity(), mAppsControlDisallowedAdmin);
-        } else {
-            showDialogInner(DLG_FORCE_STOP, 0);
-            //forceStopPackage(mAppInfo.packageName);
-        }
-    }
-
     /** Returns whether there is only one user on this device, not including the system-only user */
     private boolean isSingleUser() {
         final int userCount = mUserManager.getUserCount();
@@ -675,7 +651,7 @@
         }
     }
 
-    private void setIntentAndFinish(boolean finish, boolean appChanged) {
+    void setIntentAndFinish(boolean finish, boolean appChanged) {
         if (localLOGV) Log.i(TAG, "appChanged="+appChanged);
         final Intent intent = new Intent();
         intent.putExtra(ManageApplications.APP_CHG, appChanged);
diff --git a/src/com/android/settings/applications/appinfo/ForceStopOptionsMenuController.java b/src/com/android/settings/applications/appinfo/ForceStopOptionsMenuController.java
new file mode 100644
index 0000000..cf87147
--- /dev/null
+++ b/src/com/android/settings/applications/appinfo/ForceStopOptionsMenuController.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.appinfo;
+
+import static com.android.settings.applications.appinfo.AppInfoDashboardFragment.FORCE_STOP_MENU;
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.wrapper.DevicePolicyManagerWrapper;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
+import com.android.settingslib.core.lifecycle.events.OnOptionsItemSelected;
+import com.android.settingslib.core.lifecycle.events.OnPrepareOptionsMenu;
+
+public class ForceStopOptionsMenuController implements LifecycleObserver, OnCreateOptionsMenu,
+        OnPrepareOptionsMenu, OnOptionsItemSelected {
+
+    private static final String TAG = "ForceStopMenuController";
+
+    private final Context mContext;
+    private final AppInfoDashboardFragment mParent;
+    private final DevicePolicyManagerWrapper mDpm;
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
+
+    private int mUserId;
+    private MenuItem mForceStopMenu;
+
+    private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final boolean enabled = getResultCode() != Activity.RESULT_CANCELED;
+            Log.d(TAG, "Got broadcast response: Restart status for "
+                + mParent.getAppEntry().info.packageName + " " + enabled);
+            enableForceStopMenu(enabled);
+        }
+    };
+
+    public ForceStopOptionsMenuController(Context context, AppInfoDashboardFragment parent,
+            DevicePolicyManagerWrapper devicePolicyManager,
+            MetricsFeatureProvider metricsFeatureProvider, Lifecycle lifecycle) {
+        mContext = context;
+        mParent = parent;
+        mDpm = devicePolicyManager;
+        mMetricsFeatureProvider = metricsFeatureProvider;
+        mUserId = UserHandle.myUserId();
+        if (lifecycle != null) {
+            lifecycle.addObserver(this);
+        }
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        menu.add(0, FORCE_STOP_MENU, 2, R.string.force_stop)
+            .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem menuItem) {
+        if (menuItem.getItemId() == FORCE_STOP_MENU) {
+            handleForceStopMenuClick();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        mForceStopMenu = menu.findItem(FORCE_STOP_MENU);
+        updateForceStopMenu(mParent.getAppEntry(), mParent.getPackageInfo());
+    }
+
+    @VisibleForTesting
+    void updateForceStopMenu(AppEntry appEntry, PackageInfo packageInfo) {
+        boolean enabled = false;
+        if (mDpm.packageHasActiveAdmins(packageInfo.packageName)) {
+            // User can't force stop device admin.
+            Log.w(TAG, "User can't force stop device admin");
+        } else if (AppUtils.isInstant(packageInfo.applicationInfo)) {
+            // No force stop for instant app
+            if (mForceStopMenu != null) {
+                mForceStopMenu.setVisible(false);
+            }
+        } else if ((appEntry.info.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
+            // If the app isn't explicitly stopped, then always show the
+            // force stop button.
+            Log.w(TAG, "App is not explicitly stopped");
+            enabled = true;
+        } else {
+            final Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
+                Uri.fromParts("package", appEntry.info.packageName, null));
+            intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { appEntry.info.packageName });
+            intent.putExtra(Intent.EXTRA_UID, appEntry.info.uid);
+            intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(appEntry.info.uid));
+            Log.d(TAG, "Sending broadcast to query restart status for "
+                + appEntry.info.packageName);
+            mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
+                mCheckKillProcessesReceiver, null, Activity.RESULT_CANCELED, null, null);
+        }
+        enableForceStopMenu(enabled);
+    }
+
+    private void enableForceStopMenu(boolean enabled) {
+        if (mForceStopMenu != null) {
+            final boolean disallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
+                mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId);
+            mForceStopMenu.setEnabled(disallowedBySystem ? false : enabled);
+        }
+    }
+
+    @VisibleForTesting
+    void handleForceStopMenuClick() {
+        if (mParent.getAppEntry() == null) {
+            mParent.setIntentAndFinish(true, true);
+            return;
+        }
+        final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+            mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId);
+        final boolean disallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
+            mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId);
+        if (admin != null && !disallowedBySystem) {
+            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin);
+        } else {
+            mParent.showDialogInner(mParent.DLG_FORCE_STOP, 0);
+        }
+    }
+
+    private void forceStopPackage(String pkgName) {
+        mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_APP_FORCE_STOP, pkgName);
+        final ActivityManager am = (ActivityManager) mContext.getSystemService(
+            Context.ACTIVITY_SERVICE);
+        Log.d(TAG, "Stopping package " + pkgName);
+        am.forceStopPackage(pkgName);
+        final int userId = UserHandle.getUserId(mParent.getAppEntry().info.uid);
+        final ApplicationsState appState = mParent.getAppState();
+        appState.invalidatePackage(pkgName, userId);
+        final AppEntry newEnt = appState.getEntry(pkgName, userId);
+        if (newEnt != null) {
+            mParent.setAppEntry(newEnt);
+        }
+    }
+
+    public AlertDialog createDialog(int id) {
+        if (id != mParent.DLG_FORCE_STOP) {
+            return null;
+        }
+        return new AlertDialog.Builder(mContext)
+            .setTitle(mContext.getText(R.string.force_stop_dlg_title))
+            .setMessage(mContext.getText(R.string.force_stop_dlg_text))
+            .setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
+                public void onClick(DialogInterface dialog, int which) {
+                    // Force stop
+                    forceStopPackage(mParent.getAppEntry().info.packageName);
+                }
+            })
+            .setNegativeButton(R.string.dlg_cancel, null)
+            .create();
+    }
+
+}
diff --git a/src/com/android/settings/dashboard/DashboardAdapterV2.java b/src/com/android/settings/dashboard/DashboardAdapterV2.java
index 7cd4f38..f98b440 100644
--- a/src/com/android/settings/dashboard/DashboardAdapterV2.java
+++ b/src/com/android/settings/dashboard/DashboardAdapterV2.java
@@ -151,13 +151,10 @@
         if (list.size() == 1) {
             // The only suggestion is dismissed, and the the empty suggestion container will
             // remain as the dashboard item. Need to refresh the dashboard list.
-            final DashboardDataV2 prevData = mDashboardData;
-            mDashboardData = new DashboardDataV2.Builder(prevData)
-                    .setSuggestions(null)
-                    .build();
-            notifyDashboardDataChanged(prevData);
+            setSuggestions(null);
         } else {
             mSuggestionAdapter.removeSuggestion(suggestion);
+            notifyItemChanged(0, null);
         }
     }
 
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2.java b/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2.java
index 483af92..e29ca5f 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2.java
@@ -18,6 +18,8 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.service.settings.suggestions.Suggestion;
 import android.support.v7.widget.RecyclerView;
@@ -34,6 +36,7 @@
 import com.android.settings.dashboard.DashboardAdapterV2.DashboardItemHolder;
 import com.android.settings.dashboard.DashboardAdapterV2.IconCache;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.Utils;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -55,6 +58,7 @@
     private final MetricsFeatureProvider mMetricsFeatureProvider;
     private final IconCache mCache;
     private final ArrayList<String> mSuggestionsShownLogged;
+    private final SuggestionFeatureProvider mSuggestionFeatureProvider;
     private final SuggestionControllerMixin mSuggestionControllerMixin;
     private final Callback mCallback;
     private final CardConfig mConfig;
@@ -75,6 +79,7 @@
         mCache = new IconCache(context);
         final FeatureFactory factory = FeatureFactory.getFactory(context);
         mMetricsFeatureProvider = factory.getMetricsFeatureProvider();
+        mSuggestionFeatureProvider = factory.getSuggestionFeatureProvider(context);
         mCallback = callback;
         if (savedInstanceState != null) {
             mSuggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST);
@@ -109,7 +114,12 @@
             mSuggestionsShownLogged.add(id);
         }
         mConfig.setCardLayout(holder, suggestionCount, position);
-        holder.icon.setImageDrawable(mCache.getIcon(suggestion.getIcon()));
+        final Icon icon = suggestion.getIcon();
+        final Drawable drawable = mCache.getIcon(icon);
+        if (drawable != null && TextUtils.equals(icon.getResPackage(), mContext.getPackageName())) {
+            drawable.setTint(Utils.getColorAccent(mContext));
+        }
+        holder.icon.setImageDrawable(drawable);
         holder.title.setText(suggestion.getTitle());
         holder.title.setSingleLine(suggestionCount == 1);
 
@@ -129,13 +139,13 @@
 
         final ImageView closeButton = holder.itemView.findViewById(R.id.close_button);
         if (closeButton != null) {
-            if (mCallback != null) {
-                closeButton.setOnClickListener(v -> {
+            closeButton.setOnClickListener(v -> {
+                mSuggestionFeatureProvider.dismissSuggestion(
+                    mContext, mSuggestionControllerMixin, suggestion);
+                if (mCallback != null) {
                     mCallback.onSuggestionClosed(suggestion);
-                });
-            } else {
-                closeButton.setOnClickListener(null);
-            }
+                }
+            });
         }
 
         View clickHandler = holder.itemView;
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index e0954e5..2a841f9 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -93,14 +93,10 @@
     private static final int MENU_STATS_TYPE = Menu.FIRST;
     @VisibleForTesting
     static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
-    @VisibleForTesting
-    static final int MENU_TOGGLE_APPS = Menu.FIRST + 4;
     private static final int MENU_HELP = Menu.FIRST + 5;
     public static final int DEBUG_INFO_LOADER = 3;
 
     @VisibleForTesting
-    boolean mShowAllApps = false;
-    @VisibleForTesting
     PowerGaugePreference mScreenUsagePref;
     @VisibleForTesting
     PowerGaugePreference mLastFullChargePref;
@@ -221,7 +217,6 @@
         mAnomalySparseArray = new SparseArray<>();
 
         restartBatteryInfoLoader();
-        restoreSavedInstance(icicle);
     }
 
     @Override
@@ -230,12 +225,6 @@
     }
 
     @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putBoolean(KEY_SHOW_ALL_APPS, mShowAllApps);
-    }
-
-    @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (KEY_BATTERY_HEADER.equals(preference.getKey())) {
             performBatteryHeaderClick();
@@ -284,11 +273,6 @@
 
         menu.add(Menu.NONE, MENU_HIGH_POWER_APPS, Menu.NONE, R.string.high_power_apps);
 
-        if (mPowerFeatureProvider.isPowerAccountingToggleEnabled()) {
-            menu.add(Menu.NONE, MENU_TOGGLE_APPS, Menu.NONE,
-                    mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
-        }
-
         super.onCreateOptionsMenu(menu, inflater);
     }
 
@@ -322,25 +306,11 @@
                 metricsFeatureProvider.action(context,
                         MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION);
                 return true;
-            case MENU_TOGGLE_APPS:
-                mShowAllApps = !mShowAllApps;
-                item.setTitle(mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
-                metricsFeatureProvider.action(context,
-                        MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE, mShowAllApps);
-                restartBatteryStatsLoader(false /* clearHeader */);
-                return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
     }
 
-    @VisibleForTesting
-    void restoreSavedInstance(Bundle savedInstance) {
-        if (savedInstance != null) {
-            mShowAllApps = savedInstance.getBoolean(KEY_SHOW_ALL_APPS, false);
-        }
-    }
-
     private void performBatteryHeaderClick() {
         if (mPowerFeatureProvider.isAdvancedUiEnabled()) {
             Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
@@ -375,8 +345,8 @@
 
         final CharSequence timeSequence = Utils.formatRelativeTime(context, lastFullChargeTime,
                 false);
-        mBatteryAppListPreferenceController.refreshAppListGroup(mStatsHelper, mShowAllApps,
-                timeSequence);
+        mBatteryAppListPreferenceController.refreshAppListGroup(mStatsHelper,
+                false /* showAllApps */, timeSequence);
     }
 
     @VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceControllerTest.java
index 7d5eb31..70b9cc9 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppActionButtonPreferenceControllerTest.java
@@ -18,27 +18,18 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.support.v7.preference.PreferenceScreen;
 
@@ -120,16 +111,14 @@
     }
 
     @Test
-    public void displayPreference_shouldInitializeForceStopButton() {
+    public void displayPreference_shouldSetButton2Invisible() {
         final PreferenceScreen screen = mock(PreferenceScreen.class);
         final ActionButtonPreference preference = spy(new ActionButtonPreference(mContext));
         when(screen.findPreference(mController.getPreferenceKey())).thenReturn(preference);
 
         mController.displayPreference(screen);
 
-        verify(preference).setButton2Positive(false);
-        verify(preference).setButton2Text(R.string.force_stop);
-        verify(preference).setButton2Enabled(false);
+        verify(preference).setButton2Visible(false);
     }
 
     @Test
@@ -138,14 +127,12 @@
         final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
         final ApplicationInfo info = new ApplicationInfo();
         appEntry.info = info;
-        doNothing().when(mController).checkForceStop(appEntry, packageInfo);
         doNothing().when(mController).initUninstallButtons(appEntry, packageInfo);
         when(mFragment.getAppEntry()).thenReturn(appEntry);
         when(mFragment.getPackageInfo()).thenReturn(packageInfo);
 
         mController.refreshUi();
 
-        verify(mController).checkForceStop(appEntry, packageInfo);
         verify(mController).initUninstallButtons(appEntry, packageInfo);
     }
 
@@ -198,71 +185,6 @@
         assertThat(mController.initUninstallButtonForUserApp()).isFalse();
     }
 
-    // Tests that we don't show the force stop button for instant apps (they aren't allowed to run
-    // when they aren't in the foreground).
-    @Test
-    public void checkForceStop_instantApps_shouldNotShowForceStop() {
-        // Make this app appear to be instant.
-        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
-                (InstantAppDataProvider) (i -> true));
-        final PackageInfo packageInfo = mock(PackageInfo.class);
-        final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
-        final ApplicationInfo info = new ApplicationInfo();
-        appEntry.info = info;
-
-        mController.checkForceStop(appEntry, packageInfo);
-
-        verify(mController.mActionButtons).setButton2Visible(false);
-    }
-
-    @Test
-    public void checkForceStop_hasActiveAdmin_shouldDisableForceStop() {
-        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
-                (InstantAppDataProvider) (i -> false));
-        final String packageName = "Package1";
-        final PackageInfo packageInfo = new PackageInfo();
-        packageInfo.packageName = packageName;
-        final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
-        when(mDevicePolicyManager.packageHasActiveAdmins(packageName)).thenReturn(true);
-
-        mController.checkForceStop(appEntry, packageInfo);
-
-        verify(mController.mActionButtons).setButton2Enabled(false);
-    }
-
-    @Test
-    public void checkForceStop_appRunning_shouldEnableForceStop() {
-        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
-                (InstantAppDataProvider) (i -> false));
-        final PackageInfo packageInfo = mock(PackageInfo.class);
-        final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
-        final ApplicationInfo info = new ApplicationInfo();
-        appEntry.info = info;
-
-        mController.checkForceStop(appEntry, packageInfo);
-
-        verify(mController.mActionButtons).setButton2Enabled(true);
-    }
-
-    @Test
-    public void checkForceStop_appStopped_shouldQueryPackageRestart() {
-        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
-                (InstantAppDataProvider) (i -> false));
-        final PackageInfo packageInfo = mock(PackageInfo.class);
-        final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
-        final ApplicationInfo info = new ApplicationInfo();
-        appEntry.info = info;
-        info.flags = ApplicationInfo.FLAG_STOPPED;
-        info.packageName = "com.android.setting";
-
-        mController.checkForceStop(appEntry, packageInfo);
-
-        verify(mContext).sendOrderedBroadcastAsUser(argThat(intent-> intent != null
-                        && intent.getAction().equals(Intent.ACTION_QUERY_PACKAGE_RESTART)),
-                any(UserHandle.class), nullable(String.class), any(BroadcastReceiver.class),
-                nullable(Handler.class), anyInt(), nullable(String.class), nullable(Bundle.class));
-    }
-
     @Test
     public void handleDisableable_appIsHomeApp_buttonShouldNotWork() {
         final ApplicationInfo info = new ApplicationInfo();
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java
index ee870b7..7108ef0 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppHeaderViewPreferenceControllerTest.java
@@ -42,7 +42,9 @@
 import com.android.settings.TestConfig;
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -53,6 +55,7 @@
 import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -103,7 +106,8 @@
         appEntry.info = info;
         when(mFragment.getAppEntry()).thenReturn(appEntry);
         when(mFragment.getPackageInfo()).thenReturn(packageInfo);
-
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+            (InstantAppDataProvider) (i -> false));
 
         final TextView title = mHeader.findViewById(R.id.entity_header_title);
         final TextView summary = mHeader.findViewById(R.id.entity_header_summary);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/ForceStopOptionsMenuControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/ForceStopOptionsMenuControllerTest.java
new file mode 100644
index 0000000..4719008
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/ForceStopOptionsMenuControllerTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.appinfo;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.wrapper.DevicePolicyManagerWrapper;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+    manifest = TestConfig.MANIFEST_PATH,
+    sdk = TestConfig.SDK_VERSION
+)
+public final class ForceStopOptionsMenuControllerTest {
+
+    private static final String PACKAGE_NAME = "test_package_name";
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private UserManager mUserManager;
+    @Mock
+    private SettingsActivity mActivity;
+    @Mock
+    private DevicePolicyManagerWrapper mDevicePolicyManager;
+    @Mock
+    private PackageManager mPackageManager;
+
+    private AppInfoDashboardFragment mFragment;
+    private ForceStopOptionsMenuController mController;
+    private Context mShadowContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowContext = spy(RuntimeEnvironment.application);
+        mFragment = spy(new AppInfoDashboardFragment());
+        ReflectionHelpers.setField(mFragment, "mDpm", mDevicePolicyManager);
+        ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
+        doReturn(mActivity).when(mFragment).getActivity();
+        doReturn(mShadowContext).when(mFragment).getContext();
+        doReturn(mPackageManager).when(mActivity).getPackageManager();
+        when(mShadowContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        mController = spy(new ForceStopOptionsMenuController(
+            mShadowContext, mFragment, mDevicePolicyManager,
+            null /* metricsFeatureProvider */, null /* lifecycle */));
+
+        // Default to not considering any apps to be instant (individual tests can override this).
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                (InstantAppDataProvider) (i -> false));
+    }
+
+    @Test
+    public void onCreateOptionsMenu_shouldAddForceStop() {
+        final Menu menu = mock(Menu.class);
+        when(menu.add(anyInt(), anyInt(), anyInt(), anyInt())).thenReturn(mock(MenuItem.class));
+
+        mController.onCreateOptionsMenu(menu, null /* inflater */);
+
+        verify(menu).add(anyInt(), eq(AppInfoDashboardFragment.FORCE_STOP_MENU), anyInt(),
+            eq(R.string.force_stop));
+    }
+
+    @Test
+    public void onPrepareOptionsMenu_shouldUpdateForceStopMenu() {
+        final Menu menu = mock(Menu.class);
+        doNothing().when(mController).updateForceStopMenu(any(), any());
+        doReturn(mock(AppEntry.class)).when(mFragment).getAppEntry();
+        doReturn(mock(PackageInfo.class)).when(mFragment).getPackageInfo();
+
+        mController.onPrepareOptionsMenu(menu);
+
+        verify(mController).updateForceStopMenu(any(), any());
+    }
+
+    @Test
+    public void onOptionsItemSelected_shouldHandleForceStopMenuClick() {
+        doReturn(mock(AppEntry.class)).when(mFragment).getAppEntry();
+        doNothing().when(mController).handleForceStopMenuClick();
+        final MenuItem menu = mock(MenuItem.class);
+        when(menu.getItemId()).thenReturn(AppInfoDashboardFragment.FORCE_STOP_MENU);
+
+        mController.onOptionsItemSelected(menu);
+
+        verify(mController).handleForceStopMenuClick();
+    }
+
+    // Tests that we don't show the force stop button for instant apps (they aren't allowed to run
+    // when they aren't in the foreground).
+    @Test
+    public void updateForceStopMenu_instantApps_shouldNotShowForceStop() {
+        when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
+        final MenuItem forceStopMenu = mock(MenuItem.class);
+        ReflectionHelpers.setField(mController, "mForceStopMenu", forceStopMenu);
+        // Make this app appear to be instant.
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+            (InstantAppDataProvider) (i -> true));
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        final AppEntry appEntry = mock(AppEntry.class);
+        final ApplicationInfo info = new ApplicationInfo();
+        appEntry.info = info;
+
+        mController.updateForceStopMenu(appEntry, packageInfo);
+
+        verify(forceStopMenu).setVisible(false);
+    }
+
+    @Test
+    public void updateForceStopMenu_hasActiveAdmin_shouldDisableForceStop() {
+        when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
+        final MenuItem forceStopMenu = mock(MenuItem.class);
+        ReflectionHelpers.setField(mController, "mForceStopMenu", forceStopMenu);
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+            (InstantAppDataProvider) (i -> false));
+        final String packageName = "Package1";
+        final PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = packageName;
+        final AppEntry appEntry = mock(AppEntry.class);
+        when(mDevicePolicyManager.packageHasActiveAdmins(packageName)).thenReturn(true);
+
+        mController.updateForceStopMenu(appEntry, packageInfo);
+
+        verify(forceStopMenu).setEnabled(false);
+    }
+
+    @Test
+    public void updateForceStopMenu_appRunning_shouldEnableForceStop() {
+        when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
+        final MenuItem forceStopMenu = mock(MenuItem.class);
+        ReflectionHelpers.setField(mController, "mForceStopMenu", forceStopMenu);
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+            (InstantAppDataProvider) (i -> false));
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        final AppEntry appEntry = mock(AppEntry.class);
+        final ApplicationInfo info = new ApplicationInfo();
+        appEntry.info = info;
+
+        mController.updateForceStopMenu(appEntry, packageInfo);
+
+        verify(forceStopMenu).setEnabled(true);
+    }
+
+    @Test
+    public void updateForceStopMenu_appStopped_shouldQueryPackageRestart() {
+        when(mDevicePolicyManager.packageHasActiveAdmins(nullable(String.class))).thenReturn(false);
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+            (InstantAppDataProvider) (i -> false));
+        final PackageInfo packageInfo = mock(PackageInfo.class);
+        final AppEntry appEntry = mock(AppEntry.class);
+        final ApplicationInfo info = new ApplicationInfo();
+        appEntry.info = info;
+        info.flags = ApplicationInfo.FLAG_STOPPED;
+        info.packageName = "com.android.setting";
+
+        mController.updateForceStopMenu(appEntry, packageInfo);
+
+        verify(mShadowContext).sendOrderedBroadcastAsUser(argThat(intent-> intent != null
+                && intent.getAction().equals(Intent.ACTION_QUERY_PACKAGE_RESTART)),
+            any(UserHandle.class), nullable(String.class), any(BroadcastReceiver.class),
+            nullable(Handler.class), anyInt(), nullable(String.class), nullable(Bundle.class));
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2Test.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2Test.java
index 1e76e2d..181c878 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2Test.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterV2Test.java
@@ -17,12 +17,19 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.PendingIntent;
 import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.service.settings.suggestions.Suggestion;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -46,6 +53,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -200,7 +208,71 @@
         mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
         mSuggestionHolder.itemView.findViewById(R.id.close_button).performClick();
 
-        verify(callback).onSuggestionClosed(suggestions.get(0));
+        final Suggestion suggestion = suggestions.get(0);
+        verify(mFeatureFactory.suggestionsFeatureProvider).dismissSuggestion(
+            mActivity, mSuggestionControllerMixin, suggestion);
+        verify(callback).onSuggestionClosed(suggestion);
+    }
+
+    @Test
+    public void onBindViewHolder_differentPackage_shouldNotTintIcon()
+            throws PendingIntent.CanceledException {
+        final Icon icon = mock(Icon.class);
+        when(icon.getResPackage()).thenReturn("pkg1");
+        when(mActivity.getPackageName()).thenReturn("pkg2");
+        final Suggestion suggestion = new Suggestion.Builder("pkg1")
+            .setPendingIntent(mock(PendingIntent.class))
+            .setIcon(icon)
+            .build();
+        final List<Suggestion> suggestions = new ArrayList<>();
+        suggestions.add(suggestion);
+        mSuggestionAdapter = new SuggestionAdapterV2(mActivity, mSuggestionControllerMixin,
+            null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
+        mSuggestionAdapter.setSuggestions(suggestions);
+        mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
+            new FrameLayout(RuntimeEnvironment.application),
+            mSuggestionAdapter.getItemViewType(0));
+        DashboardAdapterV2.IconCache cache = mock(DashboardAdapterV2.IconCache.class);
+        final Drawable drawable = mock(Drawable.class);
+        when(cache.getIcon(icon)).thenReturn(drawable);
+        ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache);
+
+        mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
+
+        verify(drawable, never()).setTint(anyInt());
+    }
+
+    @Test
+    public void onBindViewHolder_samePackage_shouldTintIcon()
+            throws PendingIntent.CanceledException {
+        final Icon icon = mock(Icon.class);
+        final String packageName = "pkg1";
+        when(icon.getResPackage()).thenReturn(packageName);
+        when(mActivity.getPackageName()).thenReturn(packageName);
+        final Suggestion suggestion = new Suggestion.Builder(packageName)
+            .setPendingIntent(mock(PendingIntent.class))
+            .setIcon(icon)
+            .build();
+        final List<Suggestion> suggestions = new ArrayList<>();
+        suggestions.add(suggestion);
+        mSuggestionAdapter = new SuggestionAdapterV2(mActivity, mSuggestionControllerMixin,
+            null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
+        mSuggestionAdapter.setSuggestions(suggestions);
+        mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder(
+            new FrameLayout(RuntimeEnvironment.application),
+            mSuggestionAdapter.getItemViewType(0));
+        DashboardAdapterV2.IconCache cache = mock(DashboardAdapterV2.IconCache.class);
+        final Drawable drawable = mock(Drawable.class);
+        when(cache.getIcon(icon)).thenReturn(drawable);
+        ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache);
+        TypedArray typedArray = mock(TypedArray.class);
+        final int colorAccent = 1234;
+        when(mActivity.obtainStyledAttributes(any())).thenReturn(typedArray);
+        when(typedArray.getColor(anyInt(), anyInt())).thenReturn(colorAccent);
+
+        mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
+
+        verify(drawable).setTint(colorAccent);
     }
 
     private void setupSuggestions(Context context, List<Suggestion> suggestions) {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacyTest.java
index 45448a9..e707ede 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacyTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryLegacyTest.java
@@ -15,8 +15,8 @@
  */
 package com.android.settings.fuelgauge;
 
-import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
-import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
+import static com.android.settings.fuelgauge.PowerUsageSummaryLegacy.MENU_HIGH_POWER_APPS;
+import static com.android.settings.fuelgauge.PowerUsageSummaryLegacy.MENU_TOGGLE_APPS;
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 6fecf3c..35af8bb 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -16,7 +16,6 @@
 package com.android.settings.fuelgauge;
 
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
-import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -170,7 +169,6 @@
         doReturn(mock(LoaderManager.class)).when(mFragment).getLoaderManager();
 
         when(mFragment.getActivity()).thenReturn(mSettingsActivity);
-        when(mToggleAppsMenu.getItemId()).thenReturn(MENU_TOGGLE_APPS);
         when(mHighPowerMenu.getItemId()).thenReturn(MENU_HIGH_POWER_APPS);
         when(mFeatureFactory.powerUsageFeatureProvider.getAdditionalBatteryInfoIntent())
                 .thenReturn(sAdditionalBatteryInfoIntent);
@@ -215,39 +213,6 @@
     }
 
     @Test
-    public void testOptionsMenu_menuAppToggle_metricEventInvoked() {
-        mFragment.onOptionsItemSelected(mToggleAppsMenu);
-        mFragment.mShowAllApps = false;
-
-        verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
-                MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE, true);
-    }
-
-    @Test
-    public void testOptionsMenu_toggleAppsEnabled() {
-        when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
-                .thenReturn(true);
-        mFragment.mShowAllApps = false;
-
-        mFragment.onCreateOptionsMenu(mMenu, mMenuInflater);
-
-        verify(mMenu).add(Menu.NONE, MENU_TOGGLE_APPS, Menu.NONE, R.string.show_all_apps);
-    }
-
-    @Test
-    public void testOptionsMenu_clickToggleAppsMenu_dataChanged() {
-        testToggleAllApps(true);
-        testToggleAllApps(false);
-    }
-
-    private void testToggleAllApps(final boolean isShowApps) {
-        mFragment.mShowAllApps = isShowApps;
-
-        mFragment.onOptionsItemSelected(mToggleAppsMenu);
-        assertThat(mFragment.mShowAllApps).isEqualTo(!isShowApps);
-    }
-
-    @Test
     public void testUpdateLastFullChargePreference_showCorrectSummary() {
         doReturn(mRealContext).when(mFragment).getContext();
 
@@ -324,18 +289,6 @@
     }
 
     @Test
-    public void testSaveInstanceState_showAllAppsRestored() {
-        Bundle bundle = new Bundle();
-        mFragment.mShowAllApps = true;
-        doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
-
-        mFragment.onSaveInstanceState(bundle);
-        mFragment.restoreSavedInstance(bundle);
-
-        assertThat(mFragment.mShowAllApps).isTrue();
-    }
-
-    @Test
     public void testDebugMode() {
         doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isEstimateDebugEnabled();
 
diff --git a/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java b/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java
new file mode 100644
index 0000000..109c3bc
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/ZonePickerSettingsTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.ui;
+
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+import android.system.helpers.SettingsHelper.SettingsType;
+import android.widget.ListView;
+import android.widget.Spinner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.TimeZone;
+
+import static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
+import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class ZonePickerSettingsTest {
+
+    private static final BySelector SELECTOR_SELECT_TIME_ZONE =
+            By.hasChild(By.text("Select time zone"));
+
+    private UiDevice mDevice;
+    private SettingsHelper mHelper;
+    private String mIsV2EnabledByDefault;
+    private int mIsAutoZoneEnabled;
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mHelper = SettingsHelper.getInstance();
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientation", e);
+        }
+        mIsV2EnabledByDefault = mHelper.getStringSetting(SettingsType.GLOBAL,
+                "settings_zone_picker_v2");
+        mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2", "true");
+        mIsAutoZoneEnabled = mHelper.getIntSetting(SettingsType.GLOBAL,
+                Settings.Global.AUTO_TIME_ZONE);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        // Go back to home for next test.
+        mDevice.pressBack();
+        mDevice.pressBack();
+        mDevice.pressHome();
+        mDevice.waitForIdle(TIMEOUT * 2);
+        mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2",
+                mIsV2EnabledByDefault);
+        mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE,
+                mIsAutoZoneEnabled);
+    }
+
+    @Test
+    public void zonePickerDisabled() throws Exception {
+        mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 1);
+
+        SettingsHelper.launchSettingsPage(
+                InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
+        UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
+        assertFalse(selectTimeZone.isEnabled());
+    }
+
+    // Test 2 time zones with no DST
+    @Test
+    public void testSelectReykjavik() throws Exception {
+        testSelectTimeZone("Iceland", "Reykjavik", "GMT+00:00", "Atlantic/Reykjavik");
+    }
+
+    @Test
+    public void testSelectPhoenix() throws Exception {
+        testSelectTimeZone("United States", "Phoenix", "GMT-07:00", "America/Phoenix");
+    }
+
+    private void testSelectTimeZone(String region, String timezone, String expectedTimeZoneOffset,
+            String expectedTimeZoneId) throws Exception {
+        mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 0);
+
+        SettingsHelper.launchSettingsPage(
+                InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
+
+        UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
+        assertTrue(selectTimeZone.isEnabled());
+        selectTimeZone.click();
+
+        // Select region in the dropdown list
+        selectScrollableItem(selectDropDownInSpinner(By.clazz(Spinner.class)),
+                new UiSelector().textContains(region))
+                .click();
+
+        // Select time zone
+        selectScrollableItem(selectTimeZoneList(),
+                new UiSelector().textContains(timezone))
+                .click();
+
+        // The select button should include the GMT offset in the summary
+        BySelector summarySelector = By.res("android:id/summary");
+        UiObject2 selectedTimeZone = selectTimeZone.findObject(summarySelector);
+        assertUiObjectFound(selectedTimeZone, summarySelector);
+        assertTrue("Expect " + expectedTimeZoneOffset + " is shown for " + timezone,
+                selectedTimeZone.getText().startsWith(expectedTimeZoneOffset));
+
+        waitAndAssertTimeGetDefault(expectedTimeZoneId);
+        assertEquals("Time zone change in Settings should update persist.sys.timezone",
+                expectedTimeZoneId, SystemProperties.get("persist.sys.timezone"));
+    }
+
+    private static final long CHECK_DEFAULT_TIMEZONE_INTERVAL = 200L;
+    private static final long CHECK_DEFAULT_TIMEZONE_TIMEOUT = 3000L;
+
+    /**
+     * Wait for the broadcast ACTION_TIMEZONE_CHANGED propagated, and update the default TimeZone
+     * by ApplicationThread.
+     */
+    private static void waitAndAssertTimeGetDefault(String expectedTimeZoneId)
+            throws InterruptedException {
+        for (int i = 0; i < CHECK_DEFAULT_TIMEZONE_TIMEOUT / CHECK_DEFAULT_TIMEZONE_INTERVAL; i++) {
+            if (expectedTimeZoneId.equals(TimeZone.getDefault().getID())) {
+                return;
+            }
+            Thread.sleep(CHECK_DEFAULT_TIMEZONE_INTERVAL);
+        }
+
+        assertEquals(expectedTimeZoneId, TimeZone.getDefault().getID());
+    }
+
+    /**
+     * Perform click on {@link Spinner} and return the pop-up dropdown list.
+     * @return UiScrollable representing the pop-up dropdown after clicking on the spinner
+     */
+    private UiScrollable selectDropDownInSpinner(BySelector spinnerSelector)
+            throws UiObjectNotFoundException {
+        UiObject2 spinner = wait(spinnerSelector);
+        spinner.click();
+
+        UiSelector dropDownSelector = new UiSelector().className(ListView.class);
+        return new UiScrollable(dropDownSelector);
+    }
+
+    private UiScrollable selectTimeZoneList() {
+        return new UiScrollable(new UiSelector().resourceId(SETTINGS_PACKAGE + ":id/tz_list"));
+    }
+
+    /**
+     * Select the child object in the UiScrollable
+     * @throws UiObjectNotFoundException if scrollable or child is not found
+     */
+    private UiObject selectScrollableItem(UiScrollable scrollable, UiSelector childSelector)
+            throws UiObjectNotFoundException {
+        if (!scrollable.waitForExists(TIMEOUT)) {
+            throw newUiObjectNotFoundException(scrollable.getSelector());
+        }
+        scrollable.scrollIntoView(childSelector);
+
+        UiObject child = mDevice.findObject(childSelector);
+        assertUiObjectFound(child, childSelector);
+        return child;
+    }
+
+    /**
+     * @throws UiObjectNotFoundException if UiDevice.wait returns null
+     */
+    private UiObject2 wait(BySelector selector) throws UiObjectNotFoundException {
+        UiObject2 item = mDevice.wait(Until.findObject(selector), TIMEOUT);
+        assertUiObjectFound(item, selector);
+        return item;
+    }
+
+    private static void assertUiObjectFound(UiObject2 obj, BySelector selector)
+            throws UiObjectNotFoundException {
+        if (obj == null) {
+            throw newUiObjectNotFoundException(selector);
+        }
+    }
+
+
+    private static void assertUiObjectFound(UiObject obj, UiSelector selector)
+            throws UiObjectNotFoundException {
+        if (obj == null) {
+            throw newUiObjectNotFoundException(selector);
+        }
+    }
+
+    private static UiObjectNotFoundException newUiObjectNotFoundException(Object selector) {
+        return new UiObjectNotFoundException(
+                String.format("UI object not found: %s", selector.toString()));
+    }
+}