Merge "Ignore MobileNetworkActivityTest"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4242609..86fb8d9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9969,6 +9969,12 @@
     <!-- [CHAR_LIMIT=40] Positive button text in dark theme notification -->
     <string name="dark_ui_settings_dialog_acknowledge">Got it</string>
 
+    <!-- [CHAR_LIMIT=50] Title string in the dark theme slice(suggestion) -->
+    <string name="dark_theme_slice_title">Try Dark theme</string>
+
+    <!-- [CHAR_LIMIT=50] Subtitle string in the dark theme slice(suggestion) -->
+    <string name="dark_theme_slice_subtitle">Helps extend battery life</string>
+
     <!-- [CHAR LIMIT=60] Name of dev option to enable extra quick settings tiles -->
     <string name="quick_settings_developer_tiles">Quick settings developer tiles</string>
 
diff --git a/res/xml/inactive_apps.xml b/res/xml/dummy_preference_screen.xml
similarity index 85%
rename from res/xml/inactive_apps.xml
rename to res/xml/dummy_preference_screen.xml
index 6f93bdb..4ffa916 100644
--- a/res/xml/inactive_apps.xml
+++ b/res/xml/dummy_preference_screen.xml
@@ -15,8 +15,7 @@
 -->
 
 <PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:title="@string/inactive_apps_title">
-
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    settings:searchable="false">
 </PreferenceScreen>
 
diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml
index 63ce90b..66447cd 100644
--- a/res/xml/storage_dashboard_fragment.xml
+++ b/res/xml/storage_dashboard_fragment.xml
@@ -22,7 +22,9 @@
     android:orderingFromXml="false">
     <com.android.settings.deviceinfo.storage.StorageSummaryDonutPreference
         android:key="pref_summary"
-        android:order="0" />
+        android:order="0"
+        settings:searchable="false"
+        settings:controller="com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController"/>
     <com.android.settings.widget.MasterSwitchPreference
         android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings"
         android:key="toggle_asm"
diff --git a/res/xml/storage_summary_donut.xml b/res/xml/storage_summary_donut.xml
new file mode 100644
index 0000000..be95cf8
--- /dev/null
+++ b/res/xml/storage_summary_donut.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="storage_dashboard_screen"
+    android:title="@string/storage_settings"
+    android:orderingFromXml="false">
+    <com.android.settings.deviceinfo.storage.StorageSummaryDonutPreference
+        android:key="pref_summary"
+        android:order="0"
+        settings:searchable="false"
+        settings:controller="com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 65d0c82..b5a1539 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -21,9 +21,6 @@
 import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
 import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
 
-import static com.android.settings.applications.manageapplications.ManageApplications.EXTRA_PERSONAL_ONLY;
-import static com.android.settings.applications.manageapplications.ManageApplications.EXTRA_WORK_ONLY;
-
 import android.annotation.Nullable;
 import android.app.ActionBar;
 import android.app.Activity;
@@ -106,6 +103,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.dashboard.profileselector.ProfileFragmentBridge;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.password.ChooseLockSettingsHelper;
 import com.android.settingslib.widget.ActionBarShadowController;
 
@@ -1061,12 +1059,14 @@
      */
     public static Fragment getTargetFragment(Activity activity, String fragmentName, Bundle args) {
         Fragment f = null;
-        final boolean isWorkOnly = args == null ? false : args.getBoolean(EXTRA_WORK_ONLY);
-        final boolean isPersonalOnly = args == null ? false : args.getBoolean(EXTRA_PERSONAL_ONLY);
+        final boolean isPersonal = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
+                == ProfileSelectFragment.PERSONAL : false;
+        final boolean isWork = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
+                == ProfileSelectFragment.WORK : false;
         if (FeatureFlagUtils.isEnabled(activity, FeatureFlags.PERSONAL_WORK_PROFILE)
                 && UserManager.get(activity).getUserProfiles().size() > 1
                 && ProfileFragmentBridge.FRAGMENT_MAP.get(fragmentName) != null
-                && !isWorkOnly && !isPersonalOnly) {
+                && !isWork && !isPersonal) {
             f = Fragment.instantiate(activity, ProfileFragmentBridge.FRAGMENT_MAP.get(fragmentName),
                     args);
         } else {
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 01289f2..1906a2d 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -29,6 +29,7 @@
 import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_WHITELIST_ALL;
 import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_RECENT;
 import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WORK;
+import static com.android.settings.search.actionbar.SearchMenuController.MENU_SEARCH;
 
 import android.annotation.Nullable;
 import android.annotation.StringRes;
@@ -99,6 +100,7 @@
 import com.android.settings.applications.appinfo.WriteSettingsDetails;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.fuelgauge.HighPowerDetail;
 import com.android.settings.notification.AppNotificationSettings;
 import com.android.settings.notification.ConfigureNotificationSettings;
@@ -141,9 +143,7 @@
     public static final String EXTRA_VOLUME_UUID = "volumeUuid";
     public static final String EXTRA_VOLUME_NAME = "volumeName";
     public static final String EXTRA_STORAGE_TYPE = "storageType";
-    public static final String EXTRA_WORK_ONLY = "workProfileOnly";
     public static final String EXTRA_WORK_ID = "workId";
-    public static final String EXTRA_PERSONAL_ONLY = "personalOnly";
 
     private static final String EXTRA_SORT_ORDER = "sortOrder";
     private static final String EXTRA_SHOW_SYSTEM = "showSystem";
@@ -310,8 +310,10 @@
         }
         final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
         mFilter = appFilterRegistry.get(appFilterRegistry.getDefaultFilterType(mListType));
-        mIsPersonalOnly = args != null ? args.getBoolean(EXTRA_PERSONAL_ONLY) : false;
-        mIsWorkOnly = args != null ? args.getBoolean(EXTRA_WORK_ONLY) : false;
+        mIsPersonalOnly = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
+                == ProfileSelectFragment.PERSONAL : false;
+        mIsWorkOnly = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
+                == ProfileSelectFragment.WORK : false;
         mWorkUserId = args != null ? args.getInt(EXTRA_WORK_ID) : NO_USER_SPECIFIED;
         mExpandSearch = activity.getIntent().getBooleanExtra(EXTRA_EXPAND_SEARCH_VIEW, false);
 
@@ -696,6 +698,10 @@
         // Hide notification menu items, because sorting happens when filtering
         mOptionsMenu.findItem(R.id.sort_order_recent_notification).setVisible(false);
         mOptionsMenu.findItem(R.id.sort_order_frequent_notification).setVisible(false);
+        final MenuItem searchItem = mOptionsMenu.findItem(MENU_SEARCH);
+        if (searchItem != null) {
+            searchItem.setVisible(false);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
index b7a1301..b8d4be1 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectFragment.java
@@ -22,13 +22,15 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
 
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentStatePagerAdapter;
 import androidx.viewpager.widget.ViewPager;
 
 import com.android.settings.R;
-import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.dashboard.DashboardFragment;
 
 import com.google.android.material.tabs.TabLayout;
 
@@ -38,7 +40,9 @@
 /**
  * Base fragment class for profile settings.
  */
-public abstract class ProfileSelectFragment extends InstrumentedFragment {
+public abstract class ProfileSelectFragment extends DashboardFragment {
+
+    private static final String TAG = "ProfileSelectFragment";
 
     /**
      * Denotes the profile type.
@@ -63,16 +67,29 @@
      */
     public static final int ALL = PERSONAL | WORK;
 
-    private View mContentView;
+    /**
+     * Used in fragment argument and pass {@link ProfileType} to it
+     */
+    public static final String EXTRA_PROFILE = "profile";
+
+    private ViewGroup mContentView;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        mContentView = inflater.inflate(R.layout.profile_select_tablayout, null /* root */);
-        final ViewPager viewPager = mContentView.findViewById(R.id.view_pager);
-        viewPager.setAdapter(new ViewPagerAdapter(this));
-        final TabLayout tabs = mContentView.findViewById(R.id.tabs);
+        mContentView = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState);
+
+        final View tabContainer = mContentView.findViewById(R.id.tab_container);
+        final ViewPager viewPager = tabContainer.findViewById(R.id.view_pager);
+        viewPager.setAdapter(new ProfileSelectFragment.ViewPagerAdapter(this));
+        final TabLayout tabs = tabContainer.findViewById(R.id.tabs);
         tabs.setupWithViewPager(viewPager);
+        tabContainer.setVisibility(View.VISIBLE);
+
+        final FrameLayout listContainer = mContentView.findViewById(android.R.id.list_container);
+        listContainer.setLayoutParams(new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
         return mContentView;
     }
 
@@ -87,13 +104,23 @@
      */
     public abstract Fragment[] getFragments();
 
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.dummy_preference_screen;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
     static class ViewPagerAdapter extends FragmentStatePagerAdapter {
 
         private final Fragment[] mChildFragments;
         private final Context mContext;
 
         ViewPagerAdapter(ProfileSelectFragment fragment) {
-            super(fragment.getActivity().getSupportFragmentManager());
+            super(fragment.getChildFragmentManager());
             mContext = fragment.getContext();
             mChildFragments = fragment.getFragments();
         }
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
index 7290258..8a9e4f8 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectManageApplications.java
@@ -16,9 +16,6 @@
 
 package com.android.settings.dashboard.profileselector;
 
-import static com.android.settings.applications.manageapplications.ManageApplications.EXTRA_PERSONAL_ONLY;
-import static com.android.settings.applications.manageapplications.ManageApplications.EXTRA_WORK_ONLY;
-
 import android.os.Bundle;
 
 import androidx.fragment.app.Fragment;
@@ -33,12 +30,12 @@
     @Override
     public Fragment[] getFragments() {
         final Bundle workOnly = new Bundle();
-        workOnly.putBoolean(EXTRA_WORK_ONLY, true);
+        workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.WORK);
         final Fragment workFragment = new ManageApplications();
         workFragment.setArguments(workOnly);
 
         final Bundle personalOnly = new Bundle();
-        personalOnly.putBoolean(EXTRA_PERSONAL_ONLY, true);
+        personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.PERSONAL);
         final Fragment personalFragment = new ManageApplications();
         personalFragment.setArguments(personalOnly);
         return new Fragment[]{
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
index c7e4fd8..fccabb5 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectStorageFragment.java
@@ -23,6 +23,7 @@
 
 import androidx.fragment.app.Fragment;
 
+import com.android.settings.R;
 import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.deviceinfo.StorageProfileFragment;
 
@@ -35,6 +36,7 @@
 
         final Bundle storageBundle = new Bundle();
         storageBundle.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
+        storageBundle.putInt(EXTRA_PROFILE, ProfileSelectFragment.PERSONAL);
 
         final Fragment storageDashboardFragment = new StorageDashboardFragment();
         storageDashboardFragment.setArguments(storageBundle);
@@ -46,7 +48,6 @@
                 break;
             }
         }
-        // TODO(b/143330969): Need to think about more profile users case
         if (targetUser != null) {
             storageBundle.putInt(StorageProfileFragment.USER_ID_EXTRA, targetUser.id);
         }
@@ -58,5 +59,10 @@
                 storageProfileFragment
         };
     }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.storage_summary_donut;
+    }
 }
 
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 0e53333..b36ad43 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -33,16 +33,17 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.loader.app.LoaderManager;
 import androidx.loader.content.Loader;
+import androidx.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController;
 import com.android.settings.deviceinfo.storage.CachedStorageValuesHelper;
 import com.android.settings.deviceinfo.storage.SecondaryUserController;
 import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
 import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
-import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
 import com.android.settings.deviceinfo.storage.UserIconLoader;
 import com.android.settings.deviceinfo.storage.VolumeSizesLoader;
 import com.android.settings.search.BaseSearchIndexProvider;
@@ -62,6 +63,7 @@
         implements
         LoaderManager.LoaderCallbacks<SparseArray<StorageAsyncLoader.AppsStorageResult>> {
     private static final String TAG = "StorageDashboardFrag";
+    private static final String SUMMARY_PREF_KEY = "pref_summary";
     private static final int STORAGE_JOB_ID = 0;
     private static final int ICON_JOB_ID = 1;
     private static final int VOLUME_SIZE_JOB_ID = 2;
@@ -71,10 +73,10 @@
     private SparseArray<StorageAsyncLoader.AppsStorageResult> mAppsResult;
     private CachedStorageValuesHelper mCachedStorageValuesHelper;
 
-    private StorageSummaryDonutPreferenceController mSummaryController;
     private StorageItemPreferenceController mPreferenceController;
     private PrivateVolumeOptionMenuController mOptionMenuController;
     private List<AbstractPreferenceController> mSecondaryUsers;
+    private boolean mPersonalOnly;
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -84,12 +86,19 @@
         final Activity activity = getActivity();
         StorageManager sm = activity.getSystemService(StorageManager.class);
         mVolume = Utils.maybeInitializeVolume(sm, getArguments());
+        mPersonalOnly = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE)
+                == ProfileSelectFragment.PERSONAL;
         if (mVolume == null) {
             activity.finish();
             return;
         }
-
         initializeOptionsMenu(activity);
+        if (mPersonalOnly) {
+            final Preference summary = getPreferenceScreen().findPreference(SUMMARY_PREF_KEY);
+            if (summary != null) {
+                summary.setVisible(false);
+            }
+        }
     }
 
     @Override
@@ -119,7 +128,6 @@
                 null /* header view */)
                 .setRecyclerView(getListView(), getSettingsLifecycle())
                 .styleActionBar(activity);
-
     }
 
     @Override
@@ -140,7 +148,6 @@
         boolean stopLoading = false;
         if (mStorageInfo != null) {
             long privateUsedBytes = mStorageInfo.totalBytes - mStorageInfo.freeBytes;
-            mSummaryController.updateBytes(privateUsedBytes, mStorageInfo.totalBytes);
             mPreferenceController.setVolume(mVolume);
             mPreferenceController.setUsedSize(privateUsedBytes);
             mPreferenceController.setTotalSize(mStorageInfo.totalBytes);
@@ -187,8 +194,6 @@
     @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
-        mSummaryController = new StorageSummaryDonutPreferenceController(context);
-        controllers.add(mSummaryController);
 
         StorageManager sm = context.getSystemService(StorageManager.class);
         mPreferenceController = new StorageItemPreferenceController(context, this,
@@ -241,7 +246,6 @@
                     final StorageManager sm = context.getSystemService(StorageManager.class);
                     final UserManager userManager = context.getSystemService(UserManager.class);
                     final List<AbstractPreferenceController> controllers = new ArrayList<>();
-                    controllers.add(new StorageSummaryDonutPreferenceController(context));
                     controllers.add(new StorageItemPreferenceController(context, null /* host */,
                             null /* volume */, new StorageManagerVolumeProvider(sm)));
                     controllers.addAll(SecondaryUserController.getSecondaryUserControllers(
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 31898d1..26039fb 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -41,6 +41,7 @@
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.deviceinfo.PrivateVolumeSettings.SystemInfoFragment;
 import com.android.settings.deviceinfo.StorageItemPreference;
 import com.android.settings.overlay.FeatureFactory;
@@ -392,14 +393,15 @@
 
     private Bundle getWorkAnnotatedBundle(int additionalCapacity) {
         if (FeatureFlagUtils.isEnabled(mContext, FeatureFlags.PERSONAL_WORK_PROFILE)) {
-            final Bundle args = new Bundle(3 + additionalCapacity);
-            args.putBoolean(ManageApplications.EXTRA_WORK_ONLY, mIsWorkProfile);
+            final Bundle args = new Bundle(2 + additionalCapacity);
+            args.putInt(ProfileSelectFragment.EXTRA_PROFILE,
+                    mIsWorkProfile ? ProfileSelectFragment.WORK : ProfileSelectFragment.PERSONAL);
             args.putInt(ManageApplications.EXTRA_WORK_ID, mUserId);
-            args.putBoolean(ManageApplications.EXTRA_PERSONAL_ONLY, !mIsWorkProfile);
             return args;
         } else {
             final Bundle args = new Bundle(2 + additionalCapacity);
-            args.putBoolean(ManageApplications.EXTRA_WORK_ONLY, mIsWorkProfile);
+            args.putInt(ProfileSelectFragment.EXTRA_PROFILE,
+                    mIsWorkProfile ? ProfileSelectFragment.WORK : ProfileSelectFragment.ALL);
             args.putInt(ManageApplications.EXTRA_WORK_ID, mUserId);
             return args;
         }
diff --git a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
index d450a2a..d8ee711 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.deviceinfo.storage;
 
 import android.content.Context;
+import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.text.TextUtils;
 import android.text.format.Formatter;
@@ -25,22 +26,29 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
 import com.android.settingslib.deviceinfo.StorageVolumeProvider;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.text.NumberFormat;
 
 /**
- * StorgaeSummaryPreferenceController updates the donut storage summary preference to have the
+ * SummaryPreferenceController updates the donut storage summary preference to have the
  * correct sizes showing.
  */
-public class StorageSummaryDonutPreferenceController extends AbstractPreferenceController implements
-        PreferenceControllerMixin {
+public class StorageSummaryDonutPreferenceController extends BasePreferenceController {
     private long mUsedBytes;
     private long mTotalBytes;
     private StorageSummaryDonutPreference mSummary;
+    private final StorageManager mStorageManager;
+    private final StorageManagerVolumeProvider mStorageManagerVolumeProvider;
 
-    public StorageSummaryDonutPreferenceController(Context context) {
-        super(context);
+    public StorageSummaryDonutPreferenceController(Context context, String key) {
+        super(context, key);
+        mStorageManager = mContext.getSystemService(StorageManager.class);
+        mStorageManagerVolumeProvider = new StorageManagerVolumeProvider(mStorageManager);
     }
 
     /**
@@ -58,19 +66,31 @@
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
-        mSummary = screen.findPreference("pref_summary");
+        mSummary = screen.findPreference(getPreferenceKey());
         mSummary.setEnabled(true);
+
+        ThreadUtils.postOnBackgroundThread(() -> {
+            final NumberFormat percentageFormat = NumberFormat.getPercentInstance();
+            final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
+                    mStorageManagerVolumeProvider);
+            final double privateUsedBytes = info.totalBytes - info.freeBytes;
+            mTotalBytes = info.totalBytes;
+            mUsedBytes = info.totalBytes - info.freeBytes;
+
+            ThreadUtils.postOnMainThread(() -> {
+                updateState(mSummary);
+            });
+        });
     }
 
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
-        StorageSummaryDonutPreference summary = (StorageSummaryDonutPreference) preference;
-        summary.setTitle(convertUsedBytesToFormattedText(mContext, mUsedBytes));
-        summary.setSummary(mContext.getString(R.string.storage_volume_total,
+        mSummary.setTitle(convertUsedBytesToFormattedText(mContext, mUsedBytes));
+        mSummary.setSummary(mContext.getString(R.string.storage_volume_total,
                 Formatter.formatShortFileSize(mContext, mTotalBytes)));
-        summary.setPercent(mUsedBytes, mTotalBytes);
-        summary.setEnabled(true);
+        mSummary.setPercent(mUsedBytes, mTotalBytes);
+        mSummary.setEnabled(true);
     }
 
     /** Invalidates the data on the view and re-renders. */
@@ -81,13 +101,8 @@
     }
 
     @Override
-    public boolean isAvailable() {
-        return true;
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return "pref_summary";
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
     }
 
     /**
diff --git a/src/com/android/settings/fuelgauge/InactiveApps.java b/src/com/android/settings/fuelgauge/InactiveApps.java
index 6c8a954..c386a7d 100644
--- a/src/com/android/settings/fuelgauge/InactiveApps.java
+++ b/src/com/android/settings/fuelgauge/InactiveApps.java
@@ -67,7 +67,8 @@
         super.onCreate(icicle);
 
         mUsageStats = getActivity().getSystemService(UsageStatsManager.class);
-        addPreferencesFromResource(R.xml.inactive_apps);
+        addPreferencesFromResource(R.xml.dummy_preference_screen);
+        getActivity().setTitle(R.string.inactive_apps_title);
     }
 
     @Override
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 385f8cd..1494293 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -78,6 +78,12 @@
                         .setCardName(CustomSliceRegistry.FACE_ENROLL_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.DEFAULT)
                         .build();
+        final ContextualCard darkThemeCard =
+                ContextualCard.newBuilder()
+                        .setSliceUri(CustomSliceRegistry.DARK_THEME_SLICE_URI.toString())
+                        .setCardName(CustomSliceRegistry.DARK_THEME_SLICE_URI.toString())
+                        .setCardCategory(ContextualCard.Category.IMPORTANT)
+                        .build();
         final ContextualCardList cards = ContextualCardList.newBuilder()
                 .addCard(wifiCard)
                 .addCard(connectedDeviceCard)
@@ -86,6 +92,7 @@
                 .addCard(notificationChannelCard)
                 .addCard(contextualAdaptiveSleepCard)
                 .addCard(contextualFaceSettingsCard)
+                .addCard(darkThemeCard)
                 .build();
 
         return cards;
diff --git a/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java b/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
new file mode 100644
index 0000000..36a3980
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSlice.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2019 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.homepage.contextualcards.slices;
+
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
+import android.annotation.ColorInt;
+import android.app.PendingIntent;
+import android.app.UiModeManager;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
+
+public class DarkThemeSlice implements CustomSliceable {
+    private static final String TAG = "DarkThemeSlice";
+    private static final int BATTERY_LEVEL_THRESHOLD = 50;
+    private static final int DELAY_TIME_EXECUTING_DARK_THEME = 200;
+
+    // Keep the slice even Dark theme mode changed when it is on HomePage
+    @VisibleForTesting
+    static boolean sKeepSliceShow;
+    @VisibleForTesting
+    static long sActiveUiSession = -1000;
+
+    private final Context mContext;
+    private final UiModeManager mUiModeManager;
+
+    public DarkThemeSlice(Context context) {
+        mContext = context;
+        mUiModeManager = context.getSystemService(UiModeManager.class);
+    }
+
+    @Override
+    public Slice getSlice() {
+        final long currentUiSession = FeatureFactory.getFactory(mContext)
+                .getSlicesFeatureProvider().getUiSessionToken();
+        if (currentUiSession != sActiveUiSession) {
+            sActiveUiSession = currentUiSession;
+            sKeepSliceShow = false;
+        }
+        if (!sKeepSliceShow && !isAvailable(mContext)) {
+            return null;
+        }
+        sKeepSliceShow = true;
+        final PendingIntent toggleAction = getBroadcastIntent(mContext);
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+        final IconCompat icon =
+                IconCompat.createWithResource(mContext, R.drawable.dark_theme);
+        final boolean isChecked = mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES;
+        return new ListBuilder(mContext, CustomSliceRegistry.DARK_THEME_SLICE_URI,
+                ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(new ListBuilder.RowBuilder()
+                        .setTitle(mContext.getText(R.string.dark_theme_slice_title))
+                        .setTitleItem(icon, ICON_IMAGE)
+                        .setSubtitle(mContext.getText(R.string.dark_theme_slice_subtitle))
+                        .setPrimaryAction(
+                                SliceAction.createToggle(toggleAction, null /* actionTitle */,
+                                        isChecked)))
+                .build();
+    }
+
+    @Override
+    public Uri getUri() {
+        return CustomSliceRegistry.DARK_THEME_SLICE_URI;
+    }
+
+    @Override
+    public void onNotifyChange(Intent intent) {
+        final boolean isChecked = intent.getBooleanExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE,
+                false);
+        // make toggle transition more smooth before dark theme takes effect
+        new Handler(Looper.getMainLooper()).postDelayed(() -> {
+            mUiModeManager.setNightMode(
+                isChecked ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO);
+        }, DELAY_TIME_EXECUTING_DARK_THEME);
+    }
+
+    @Override
+    public Intent getIntent() {
+        return null;
+    }
+
+    @VisibleForTesting
+    boolean isAvailable(Context context) {
+        // checking dark theme mode.
+        if (mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES) {
+            return false;
+        }
+
+        // checking the current battery level
+        final BatteryManager batteryManager = context.getSystemService(BatteryManager.class);
+        final int level = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
+        Log.d(TAG, "battery level=" + level);
+
+        return level <= BATTERY_LEVEL_THRESHOLD;
+    }
+}
diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java
index 0243c09..9e22bbf 100644
--- a/src/com/android/settings/search/actionbar/SearchMenuController.java
+++ b/src/com/android/settings/search/actionbar/SearchMenuController.java
@@ -42,6 +42,7 @@
 public class SearchMenuController implements LifecycleObserver, OnCreateOptionsMenu {
 
     public static final String NEED_SEARCH_ICON_IN_ACTION_BAR = "need_search_icon_in_action_bar";
+    public static final int MENU_SEARCH = Menu.FIRST + 10;
 
     private final Fragment mHost;
     private final int mPageId;
@@ -80,7 +81,11 @@
         if (arguments != null && !arguments.getBoolean(NEED_SEARCH_ICON_IN_ACTION_BAR, true)) {
             return;
         }
-        final MenuItem searchItem = menu.add(Menu.NONE, Menu.NONE, 0 /* order */,
+        // menu contains search item, skip it
+        if (menu.findItem(MENU_SEARCH) != null) {
+            return;
+        }
+        final MenuItem searchItem = menu.add(Menu.NONE, MENU_SEARCH, 0 /* order */,
                 R.string.search_menu);
         searchItem.setIcon(R.drawable.ic_search_24dp);
         searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index d5b631a..a019687 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -37,6 +37,7 @@
 import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
 import com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice;
 import com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice;
+import com.android.settings.homepage.contextualcards.slices.DarkThemeSlice;
 import com.android.settings.homepage.contextualcards.slices.FaceSetupSlice;
 import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
 import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
@@ -332,6 +333,16 @@
             .appendPath("media_output_indicator")
             .build();
 
+    /**
+     * Backing Uri for the Dark theme Slice.
+     */
+    public static final Uri DARK_THEME_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("dark_theme")
+            .build();
+
     @VisibleForTesting
     static final Map<Uri, Class<? extends CustomSliceable>> sUriToSlice;
 
@@ -357,6 +368,7 @@
         sUriToSlice.put(NOTIFICATION_CHANNEL_SLICE_URI, NotificationChannelSlice.class);
         sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
         sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
+        sUriToSlice.put(DARK_THEME_SLICE_URI, DarkThemeSlice.class);
     }
 
     public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
diff --git a/src/com/android/settings/widget/RadioButtonPickerFragment.java b/src/com/android/settings/widget/RadioButtonPickerFragment.java
index 3193afb..0f4fbc3 100644
--- a/src/com/android/settings/widget/RadioButtonPickerFragment.java
+++ b/src/com/android/settings/widget/RadioButtonPickerFragment.java
@@ -150,12 +150,10 @@
     /**
      * A chance for subclasses to bind additional things to the preference.
      */
-    @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
     public void bindPreferenceExtra(RadioButtonPreference pref,
             String key, CandidateInfo info, String defaultKey, String systemDefaultKey) {
     }
 
-    @VisibleForTesting
     public void updateCandidates() {
         mCandidates.clear();
         final List<? extends CandidateInfo> candidateList = getCandidates();
@@ -204,7 +202,6 @@
         }
     }
 
-    @VisibleForTesting
     public RadioButtonPreference bindPreference(RadioButtonPreference pref,
             String key, CandidateInfo info, String defaultKey) {
         pref.setTitle(info.loadLabel());
@@ -218,7 +215,6 @@
         return pref;
     }
 
-    @VisibleForTesting
     public void updateCheckedState(String selectedKey) {
         final PreferenceScreen screen = getPreferenceScreen();
         if (screen != null) {
@@ -236,7 +232,6 @@
         }
     }
 
-    @VisibleForTesting
     public void mayCheckOnlyRadioButton() {
         final PreferenceScreen screen = getPreferenceScreen();
         // If there is only 1 thing on screen, select it.
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogActivity.java b/src/com/android/settings/wifi/NetworkRequestDialogActivity.java
index 1f2b221..2326a0e 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogActivity.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogActivity.java
@@ -26,12 +26,16 @@
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Message;
 import android.widget.Toast;
+
 import androidx.annotation.Nullable;
 import androidx.fragment.app.FragmentActivity;
+
 import com.android.settings.R;
 import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
+
 import java.util.List;
 
 /**
@@ -115,7 +119,7 @@
 
         final WifiManager wifiManager = getSystemService(WifiManager.class);
         if (wifiManager != null) {
-            wifiManager.registerNetworkRequestMatchCallback(this, mHandler);
+            wifiManager.registerNetworkRequestMatchCallback(new HandlerExecutor(mHandler), this);
         }
         // Sets time-out to stop scanning.
         mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
diff --git a/src/com/android/settings/wifi/RequestToggleWiFiActivity.java b/src/com/android/settings/wifi/RequestToggleWiFiActivity.java
index 879a93e..034ec56 100644
--- a/src/com/android/settings/wifi/RequestToggleWiFiActivity.java
+++ b/src/com/android/settings/wifi/RequestToggleWiFiActivity.java
@@ -29,7 +29,6 @@
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.Log;
-import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 
@@ -313,11 +312,6 @@
                         finish();
                     }
                 } break;
-
-                case WifiManager.ERROR: {
-                    Toast.makeText(activity, R.string.wifi_error, Toast.LENGTH_SHORT).show();
-                    finish();
-                } break;
             }
         }
     }
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index e9d2e08..c935b6a 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -781,6 +781,11 @@
     }
 
     private boolean canConnectNetwork() {
+        // Do not allow a cloned network to connect when out of range
+        // Otherwise it may create inconsistencies in the UI
+        if (mAccessPoint.isCloned() && mIsOutOfRange) {
+            return false;
+        }
         // Display connect button for disconnected AP even not in the range.
         return !mAccessPoint.isActive();
     }
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
index 3975170..8544a53 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pSettings.java
@@ -152,7 +152,7 @@
                 } else {
                     updateSearchMenu(false);
                 }
-            } else if (WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION.equals(action)) {
+            } else if (WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED.equals(action)) {
                 if (mWifiP2pManager != null) {
                     mWifiP2pManager.requestPersistentGroupInfo(mChannel, WifiP2pSettings.this);
                 }
@@ -339,7 +339,7 @@
         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);
-        mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);
+        mIntentFilter.addAction(WifiP2pManager.ACTION_WIFI_P2P_PERSISTENT_GROUPS_CHANGED);
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
 
         getActivity().registerReceiver(mReceiver, mIntentFilter);
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 73fea77..32c706c 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -16,15 +16,13 @@
 package com.android.settings.deviceinfo.storage;
 
 import static com.android.settings.applications.manageapplications.ManageApplications.EXTRA_WORK_ID;
-import static com.android.settings.applications.manageapplications.ManageApplications
-        .EXTRA_WORK_ONLY;
 import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -51,6 +49,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.SubSettings;
 import com.android.settings.applications.manageapplications.ManageApplications;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.deviceinfo.PrivateVolumeSettings;
 import com.android.settings.deviceinfo.StorageItemPreference;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -195,8 +194,8 @@
                 .isEqualTo(R.string.apps_storage);
         assertThat(
                 intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
-                        .getBoolean(EXTRA_WORK_ONLY))
-                .isTrue();
+                        .getInt(ProfileSelectFragment.EXTRA_PROFILE))
+                .isEqualTo(ProfileSelectFragment.WORK);
         assertThat(
                 intent.getBundleExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS)
                         .getInt(EXTRA_WORK_ID))
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java
index 4f72318..cd6f082 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java
@@ -37,24 +37,30 @@
 import android.widget.Button;
 import android.widget.LinearLayout;
 
+import androidx.preference.PreferenceScreen;
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settings.R;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowPrivateStorageInfo;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
 import com.android.settingslib.deviceinfo.StorageVolumeProvider;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
 
 import java.io.File;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowPrivateStorageInfo.class)
 public class StorageSummaryDonutPreferenceControllerTest {
 
     private Context mContext;
@@ -63,14 +69,18 @@
     private PreferenceViewHolder mHolder;
     private FakeFeatureFactory mFakeFeatureFactory;
     private MetricsFeatureProvider mMetricsFeatureProvider;
+    private PreferenceScreen mScreen;
 
     @Before
     public void setUp() throws Exception {
+        ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
         mContext = spy(Robolectric.setupActivity(Activity.class));
         mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
         mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider();
-        mController = new StorageSummaryDonutPreferenceController(mContext);
+        mController = new StorageSummaryDonutPreferenceController(mContext, "key");
         mPreference = new StorageSummaryDonutPreference(mContext);
+        mScreen = spy(new PreferenceScreen(mContext, null));
+        when(mScreen.findPreference("key")).thenReturn(mPreference);
 
         LayoutInflater inflater = LayoutInflater.from(mContext);
         final View view =
@@ -79,10 +89,16 @@
         mHolder = PreferenceViewHolder.createInstanceForTests(view);
     }
 
+    @After
+    public void tearDown() {
+        ShadowPrivateStorageInfo.reset();
+    }
+
     @Test
     public void testEmpty() {
         final long totalSpace = 32 * GIGABYTE;
         final long usedSpace = 0;
+        mController.displayPreference(mScreen);
         mController.updateBytes(0, 32 * GIGABYTE);
         mController.updateState(mPreference);
 
@@ -98,6 +114,7 @@
     public void testTotalStorage() {
         final long totalSpace = KILOBYTE * 10;
         final long usedSpace = KILOBYTE;
+        mController.displayPreference(mScreen);
         mController.updateBytes(KILOBYTE, totalSpace);
         mController.updateState(mPreference);
 
@@ -121,6 +138,7 @@
         when(file.getTotalSpace()).thenReturn(totalSpace);
         when(file.getFreeSpace()).thenReturn(freeSpace);
         when(svp.getPrimaryStorageSize()).thenReturn(totalSpace);
+        mController.displayPreference(mScreen);
 
         mController.updateSizes(svp, volume);
         mController.updateState(mPreference);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
new file mode 100644
index 0000000..bb21332
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/DarkThemeSliceTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2019 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.homepage.contextualcards.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.UiModeManager;
+import android.content.Context;
+import android.net.Uri;
+import android.os.BatteryManager;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.SlicesFeatureProviderImpl;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class DarkThemeSliceTest {
+    @Mock
+    private UiModeManager mUiModeManager;
+    @Mock
+    private BatteryManager mBatteryManager;
+
+    private Context mContext;
+    private DarkThemeSlice mDarkThemeSlice;
+    private FakeFeatureFactory mFeatureFactory;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFeatureFactory.slicesFeatureProvider = new SlicesFeatureProviderImpl();
+        mFeatureFactory.slicesFeatureProvider.newUiSession();
+        doReturn(mUiModeManager).when(mContext).getSystemService(UiModeManager.class);
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+        mDarkThemeSlice = new DarkThemeSlice(mContext);
+        mDarkThemeSlice.sKeepSliceShow = false;
+    }
+
+    @Test
+    public void getUri_shouldBeDarkThemeSliceUri() {
+        final Uri uri = mDarkThemeSlice.getUri();
+
+        assertThat(uri).isEqualTo(CustomSliceRegistry.DARK_THEME_SLICE_URI);
+    }
+
+    @Test
+    public void isAvailable_inDarkThemeMode_returnFalse() {
+        when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+
+        assertThat(mDarkThemeSlice.isAvailable(mContext)).isFalse();
+    }
+
+    @Test
+    public void isAvailable_nonDarkThemeBatteryCapacityEq100_returnFalse() {
+        setBatteryCapacityLevel(100);
+
+        assertThat(mDarkThemeSlice.isAvailable(mContext)).isFalse();
+    }
+
+    @Test
+    public void isAvailable_nonDarkThemeBatteryCapacityLt50_returnTrue() {
+        setBatteryCapacityLevel(40);
+
+        assertThat(mDarkThemeSlice.isAvailable(mContext)).isTrue();
+    }
+
+    @Test
+    public void getSlice_notAvailable_returnNull() {
+        when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+
+        assertThat(mDarkThemeSlice.getSlice()).isNull();
+    }
+
+    @Test
+    public void getSlice_newSession_notAvailable_returnNull() {
+        // previous displayed: yes
+        mDarkThemeSlice.sKeepSliceShow = true;
+        // Session: use original value + 1 to become a new session
+        mDarkThemeSlice.sActiveUiSession =
+                mFeatureFactory.slicesFeatureProvider.getUiSessionToken() + 1;
+
+        when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_YES);
+
+        assertThat(mDarkThemeSlice.getSlice()).isNull();
+    }
+
+    @Test
+    public void getSlice_previouslyDisplayed_isAvailable_returnSlice() {
+        mDarkThemeSlice.sActiveUiSession =
+                mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
+        mDarkThemeSlice.sKeepSliceShow = true;
+        setBatteryCapacityLevel(40);
+
+        assertThat(mDarkThemeSlice.getSlice()).isNotNull();
+    }
+
+    @Test
+    public void getSlice_isAvailable_returnSlice() {
+        setBatteryCapacityLevel(40);
+
+        assertThat(mDarkThemeSlice.getSlice()).isNotNull();
+    }
+
+    @Test
+    public void getSlice_isAvailable_showTitleSubtitle() {
+        setBatteryCapacityLevel(40);
+
+        final Slice slice = mDarkThemeSlice.getSlice();
+        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+        assertThat(metadata.getTitle()).isEqualTo(
+                mContext.getString(R.string.dark_theme_slice_title));
+        assertThat(metadata.getSubtitle()).isEqualTo(
+                mContext.getString(R.string.dark_theme_slice_subtitle));
+    }
+
+    private void setBatteryCapacityLevel(int power_level) {
+        when(mUiModeManager.getNightMode()).thenReturn(UiModeManager.MODE_NIGHT_NO);
+        doReturn(mBatteryManager).when(mContext).getSystemService(BatteryManager.class);
+        when(mBatteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY))
+                .thenReturn(power_level);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
index 99f2723..c8ec57a 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/LowStorageSliceTest.java
@@ -28,8 +28,8 @@
 import androidx.slice.widget.SliceLiveData;
 
 import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowPrivateStorageInfo;
 import com.android.settingslib.deviceinfo.PrivateStorageInfo;
-import com.android.settingslib.deviceinfo.StorageVolumeProvider;
 
 import org.junit.After;
 import org.junit.Before;
@@ -38,9 +38,6 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.Resetter;
 
 @RunWith(RobolectricTestRunner.class)
 public class LowStorageSliceTest {
@@ -104,26 +101,4 @@
 
         assertThat(slice.hasHint(HINT_ERROR)).isTrue();
     }
-
-    @Implements(PrivateStorageInfo.class)
-    public static class ShadowPrivateStorageInfo {
-
-        private static PrivateStorageInfo sPrivateStorageInfo = null;
-
-        @Resetter
-        public static void reset() {
-            sPrivateStorageInfo = null;
-        }
-
-        @Implementation
-        public static PrivateStorageInfo getPrivateStorageInfo(
-                StorageVolumeProvider storageVolumeProvider) {
-            return sPrivateStorageInfo;
-        }
-
-        private static void setPrivateStorageInfo(
-                PrivateStorageInfo privateStorageInfo) {
-            sPrivateStorageInfo = privateStorageInfo;
-        }
-    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
index e2b896a..c646a93 100644
--- a/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
+++ b/tests/robotests/src/com/android/settings/search/actionbar/SearchMenuControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.search.actionbar;
 
+import static com.android.settings.search.actionbar.SearchMenuController.MENU_SEARCH;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -69,7 +71,7 @@
         Global.putInt(mActivity.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
 
         when(mHost.getActivity()).thenReturn(mActivity);
-        when(mMenu.add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu))
+        when(mMenu.add(Menu.NONE, MENU_SEARCH, 0 /* order */, R.string.search_menu))
                 .thenReturn(mock(MenuItem.class));
     }
 
@@ -78,7 +80,7 @@
         SearchMenuController.init(mHost);
         mHost.getSettingsLifecycle().onCreateOptionsMenu(mMenu, null /* inflater */);
 
-        verify(mMenu).add(Menu.NONE, Menu.NONE, 0 /* order */, R.string.search_menu);
+        verify(mMenu).add(Menu.NONE, MENU_SEARCH, 0 /* order */, R.string.search_menu);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPrivateStorageInfo.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPrivateStorageInfo.java
new file mode 100644
index 0000000..1baf3cb
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowPrivateStorageInfo.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils.shadow;
+
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+import com.android.settingslib.deviceinfo.StorageVolumeProvider;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(PrivateStorageInfo.class)
+public class ShadowPrivateStorageInfo {
+
+    private static PrivateStorageInfo sPrivateStorageInfo = null;
+
+    @Resetter
+    public static void reset() {
+        sPrivateStorageInfo = null;
+    }
+
+    @Implementation
+    protected static PrivateStorageInfo getPrivateStorageInfo(
+            StorageVolumeProvider storageVolumeProvider) {
+        return sPrivateStorageInfo;
+    }
+
+    public static void setPrivateStorageInfo(
+            PrivateStorageInfo privateStorageInfo) {
+        sPrivateStorageInfo = privateStorageInfo;
+    }
+}