Merge "Use SoftAp API to get number of connected device"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 51a811d..5a4db20 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -476,7 +476,7 @@
             </intent-filter>
         </activity>
 
-        <service android:name=".TetherService"
+        <service android:name=".wifi.tether.TetherService"
             android:exported="true"
             android:permission="android.permission.TETHER_PRIVILEGED" />
 
@@ -3311,6 +3311,25 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="Settings$AdvancedConnectedDeviceActivity"
+                  android:label="@string/connected_device_connections_title"
+                  android:taskAffinity="com.android.settings"
+                  android:parentActivityName="Settings$ConnectedDeviceDashboardActivity"
+                  android:enabled="false">
+            <intent-filter android:priority="1">
+                <action android:name="com.android.settings.ADVANCED_CONNECTED_DEVICE_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity>
+
         <provider android:name=".slices.SettingsSliceProvider"
                   android:authorities="com.android.settings.slices"
                   android:exported="true">
diff --git a/res/layout/master_clear.xml b/res/layout/master_clear.xml
index 779e504..f81c7e8 100644
--- a/res/layout/master_clear.xml
+++ b/res/layout/master_clear.xml
@@ -93,7 +93,7 @@
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:layout_gravity="center_vertical"
-                        android:paddingEnd="8dp"
+                        android:paddingEnd="@dimen/reset_checkbox_padding_end"
                         android:focusable="false"
                         android:clickable="false"
                         android:duplicateParentState="true" />
@@ -104,14 +104,14 @@
                     <TextView
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:paddingTop="12dp"
-                        android:textSize="18sp"
+                        android:paddingTop="@dimen/reset_checkbox_title_padding_top"
+                        android:textSize="@dimen/reset_checkbox_title_text_size"
                         android:text="@string/erase_external_storage" />
                     <TextView
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:paddingTop="4sp"
-                        android:textSize="14sp"
+                        android:paddingTop="@dimen/reset_checkbox_summary_padding_top"
+                        android:textSize="@dimen/reset_checkbox_summary_text_size"
                         android:text="@string/erase_external_storage_description" />
                 </LinearLayout>
             </LinearLayout>
diff --git a/res/layout/reset_esim_checkbox.xml b/res/layout/reset_esim_checkbox.xml
new file mode 100644
index 0000000..e76ced0
--- /dev/null
+++ b/res/layout/reset_esim_checkbox.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:focusable="true"
+    android:clickable="true"
+    android:visibility="gone">
+
+    <CheckBox android:id="@+id/erase_esim"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:paddingEnd="@dimen/reset_checkbox_padding_end"
+        android:focusable="false"
+        android:clickable="false"
+        android:duplicateParentState="true" />
+
+    <LinearLayout android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:orientation="vertical">
+
+        <TextView android:id="@+id/erase_esim_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingTop="@dimen/reset_checkbox_title_padding_top"
+            android:textSize="@dimen/reset_checkbox_title_text_size" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingTop="@dimen/reset_checkbox_summary_padding_top"
+            android:textSize="@dimen/reset_checkbox_summary_text_size"
+            android:text="@string/reset_esim_desc" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/reset_network.xml b/res/layout/reset_network.xml
index be966dd..1850bb2 100644
--- a/res/layout/reset_network.xml
+++ b/res/layout/reset_network.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >
@@ -27,7 +28,8 @@
         android:layout_marginTop="12dp"
         android:layout_weight="1">
 
-        <LinearLayout android:layout_width="match_parent"
+        <LinearLayout
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical">
 
@@ -38,6 +40,11 @@
                 android:textDirection="locale"
                 android:text="@string/reset_network_desc" />
 
+            <include layout="@layout/reset_esim_checkbox"
+                android:id="@+id/erase_esim_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
         </LinearLayout>
 
     </ScrollView>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 339eaf2..d4071ed 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -311,4 +311,11 @@
     <dimen name="suggestion_card_title_padding_bottom_one_card">6dp</dimen>
     <dimen name="suggestion_card_title_padding_bottom_multiple_cards">8dp</dimen>
 
+    <!-- Padding for the reset screens -->
+    <dimen name="reset_checkbox_padding_end">8dp</dimen>
+    <dimen name="reset_checkbox_title_padding_top">12dp</dimen>
+    <dimen name="reset_checkbox_summary_padding_top">4dp</dimen>
+    <dimen name="reset_checkbox_title_text_size">18sp</dimen>
+    <dimen name="reset_checkbox_summary_text_size">14sp</dimen>
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4182fd9..164f6d5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3213,6 +3213,10 @@
     <string name="reset_network_title">Reset Wi-Fi, mobile &amp; Bluetooth</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Reset network settings [CHAR LIMIT=NONE] -->
     <string name="reset_network_desc">This will reset all network settings, including:\n\n<li>Wi\u2011Fi</li>\n<li>Mobile data</li>\n<li>Bluetooth</li>"</string>
+    <!-- SD card & phone storage settings screen, title for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
+    <string name="reset_esim_title">Also reset eSIMs</string>
+    <!-- SD card & phone storage settings screen, message for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
+    <string name="reset_esim_desc">Erase all eSIMs on the phone. You\u2019ll have to contract your carrier to redownload your eSIMs. This will not cancel your mobile service plan.</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Reset network settings -->
     <string name="reset_network_button_text">Reset settings</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Reset settings button -->
@@ -3225,6 +3229,10 @@
     <string name="network_reset_not_available">Network reset is not available for this user</string>
     <!-- Reset settings complete toast text [CHAR LIMIT=75] -->
     <string name="reset_network_complete_toast">Network settings have been reset</string>
+    <!-- Title of the error message shown when error happens during erase eSIM data [CHAR LIMIT=NONE] -->
+    <string name="reset_esim_error_title">Cant\u2019t reset eSIMs</string>
+    <!-- Message of the error message shown when error happens during erase eSIM data [CHAR LIMIT=NONE] -->
+    <string name="reset_esim_error_msg">The eSIMs can\u2019tt be reset due to an error.</string>
 
     <!-- Master Clear -->
     <!-- Button title to factory data reset the entire device -->
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 3cc722b..dd7ef80 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -76,7 +76,7 @@
     private static final String TAG = "MasterClear";
 
     private static final int KEYGUARD_REQUEST = 55;
-    private static final int CREDENTIAL_CONFIRM_REQUEST = 56;
+    @VisibleForTesting static final int CREDENTIAL_CONFIRM_REQUEST = 56;
 
     static final String ERASE_EXTERNAL_EXTRA = "erase_sd";
     static final String ERASE_ESIMS_EXTRA = "erase_esim";
@@ -157,9 +157,12 @@
                 .setAction("android.accounts.action.PRE_FACTORY_RESET");
             // Check to make sure that the intent is supported.
             final PackageManager pm = context.getPackageManager();
-            final List<ResolveInfo> resolutions =
-                pm.queryIntentActivities(requestAccountConfirmation, 0);
-            if (resolutions != null && resolutions.size() > 0) {
+            final ResolveInfo resolution = pm.resolveActivity(requestAccountConfirmation, 0);
+            if (resolution != null
+                    && resolution.activityInfo != null
+                    && packageName.equals(resolution.activityInfo.packageName)) {
+                // Note that we need to check the packagename to make sure that an Activity resolver
+                // wasn't returned.
                 getActivity().startActivityForResult(
                     requestAccountConfirmation, CREDENTIAL_CONFIRM_REQUEST);
                 return true;
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 0f08c26..f64f6dc 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -18,20 +18,28 @@
 
 import android.annotation.Nullable;
 import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
+import android.provider.Settings.Global;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.CheckBox;
 import android.widget.Spinner;
+import android.widget.TextView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.PhoneConstants;
@@ -64,6 +72,8 @@
     private View mContentView;
     private Spinner mSubscriptionSpinner;
     private Button mInitiateButton;
+    private View mEsimContainer;
+    private CheckBox mEsimCheckbox;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -107,6 +117,7 @@
             SubscriptionInfo subscription = mSubscriptions.get(selectedIndex);
             args.putInt(PhoneConstants.SUBSCRIPTION_KEY, subscription.getSubscriptionId());
         }
+        args.putBoolean(MasterClear.ERASE_ESIMS_EXTRA, mEsimCheckbox.isChecked());
         ((SettingsActivity) getActivity()).startPreferencePanel(
                 this, ResetNetworkConfirm.class.getName(),
                 args, R.string.reset_network_confirm_title, null, null, 0);
@@ -141,6 +152,8 @@
      */
     private void establishInitialState() {
         mSubscriptionSpinner = (Spinner) mContentView.findViewById(R.id.reset_network_subscription);
+        mEsimContainer = mContentView.findViewById(R.id.erase_esim_container);
+        mEsimCheckbox = mContentView.findViewById(R.id.erase_esim);
 
         mSubscriptions = SubscriptionManager.from(getActivity()).getActiveSubscriptionInfoList();
         if (mSubscriptions != null && mSubscriptions.size() > 0) {
@@ -192,6 +205,30 @@
         }
         mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_reset_network);
         mInitiateButton.setOnClickListener(mInitiateListener);
+        if (showEuiccSettings(getContext())) {
+            mEsimContainer.setVisibility(View.VISIBLE);
+            TextView title = mContentView.findViewById(R.id.erase_esim_title);
+            title.setText(R.string.reset_esim_title);
+            mEsimContainer.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mEsimCheckbox.toggle();
+                }
+            });
+        } else {
+            mEsimCheckbox.setChecked(false /* checked */);
+        }
+    }
+
+    private boolean showEuiccSettings(Context context) {
+        EuiccManager euiccManager =
+                (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
+        if (!euiccManager.isEnabled()) {
+            return false;
+        }
+        ContentResolver resolver = context.getContentResolver();
+        return Settings.Global.getInt(resolver, Global.EUICC_PROVISIONED, 0) != 0
+                || Settings.Global.getInt(resolver, Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
     }
 
     @Override
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index 58b8289..53d9386 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -16,6 +16,7 @@
 
 package com.android.settings;
 
+import android.app.AlertDialog;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothManager;
 import android.content.ContentResolver;
@@ -24,9 +25,12 @@
 import android.net.NetworkPolicyManager;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.RecoverySystem;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.view.LayoutInflater;
@@ -39,6 +43,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.wrapper.RecoverySystemWrapper;
 import com.android.settingslib.RestrictedLockUtils;
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -57,6 +62,43 @@
 
     private View mContentView;
     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    @VisibleForTesting boolean mEraseEsim;
+    @VisibleForTesting EraseEsimAsyncTask mEraseEsimTask;
+    @VisibleForTesting static RecoverySystemWrapper mRecoverySystem;
+
+    /**
+     * Async task used to erase all the eSIM profiles from the phone. If error happens during
+     * erasing eSIM profiles or timeout, an error msg is shown.
+     */
+    private static class EraseEsimAsyncTask extends AsyncTask<Void, Void, Boolean> {
+        private final Context mContext;
+        private final String mPackageName;
+
+        EraseEsimAsyncTask(Context context, String packageName) {
+            mContext = context;
+            mPackageName = packageName;
+        }
+
+        @Override
+        protected Boolean doInBackground(Void... params) {
+            return mRecoverySystem.wipeEuiccData(
+                    mContext, true /* isWipeEuicc */, mPackageName);
+        }
+
+        @Override
+        protected void onPostExecute(Boolean succeeded) {
+            if (succeeded) {
+                Toast.makeText(mContext, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
+                        .show();
+            } else {
+                new AlertDialog.Builder(mContext)
+                        .setTitle(R.string.reset_esim_error_title)
+                        .setMessage(R.string.reset_esim_error_msg)
+                        .setPositiveButton(android.R.string.ok, null /* listener */)
+                        .show();
+            }
+        }
+    }
 
     /**
      * The user has gone through the multiple confirmation, so now we go ahead
@@ -69,7 +111,8 @@
             if (Utils.isMonkeyRunning()) {
                 return;
             }
-            // TODO maybe show a progress dialog if this ends up taking a while
+            // TODO maybe show a progress screen if this ends up taking a while and won't let user
+            // go back until the tasks finished.
             Context context = getActivity();
 
             ConnectivityManager connectivityManager = (ConnectivityManager)
@@ -108,11 +151,20 @@
 
             ImsManager.factoryReset(context);
             restoreDefaultApn(context);
+            esimFactoryReset(context, context.getPackageName());
+        }
+    };
 
+    @VisibleForTesting
+    void esimFactoryReset(Context context, String packageName) {
+        if (mEraseEsim) {
+            mEraseEsimTask = new EraseEsimAsyncTask(context, packageName);
+            mEraseEsimTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        } else {
             Toast.makeText(context, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
                     .show();
         }
-    };
+    }
 
     /**
      * Restore APN settings to default.
@@ -163,6 +215,16 @@
         if (args != null) {
             mSubId = args.getInt(PhoneConstants.SUBSCRIPTION_KEY,
                     SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+            mEraseEsim = args.getBoolean(MasterClear.ERASE_ESIMS_EXTRA);
+        }
+        mRecoverySystem = new RecoverySystemWrapper();
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mEraseEsimTask != null) {
+            mEraseEsimTask.cancel(true /* mayInterruptIfRunning */);
+            mEraseEsimTask = null;
         }
     }
 
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 5e815bc..d13a62d 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -178,5 +178,10 @@
     public static class StorageDashboardActivity extends SettingsActivity {}
     public static class UserAndAccountDashboardActivity extends SettingsActivity {}
     public static class SystemDashboardActivity extends SettingsActivity {}
+    public static class AdvancedConnectedDeviceActivity extends SettingsActivity {
+        public static final boolean isEnabled() {
+            return FeatureFlagUtils.isEnabled(null /* context */, CONNECTED_DEVICE_V2);
+        }
+    }
 
 }
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 1c674b6..f45ac5e 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -515,7 +515,8 @@
             Fragment resultTo, int resultRequestCode, String titleResPackageName, int titleResId,
             CharSequence title, boolean isShortcut, int metricsCategory) {
         startWithFragment(context, fragmentName, args, resultTo, resultRequestCode,
-                titleResPackageName, titleResId, title, isShortcut, metricsCategory, 0);
+                titleResPackageName, titleResId, title, isShortcut, metricsCategory,
+                Intent.FLAG_ACTIVITY_NEW_TASK);
     }
 
 
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 0a4b1f2..026cc2b 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -57,6 +57,7 @@
 import com.android.settings.applications.manageapplications.ManageApplications;
 import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
 import com.android.settings.bluetooth.BluetoothSettings;
+import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragmentOld;
 import com.android.settings.datausage.DataPlanUsageSummary;
@@ -254,7 +255,8 @@
             LockscreenDashboardFragment.class.getName(),
             BluetoothDeviceDetailsFragment.class.getName(),
             DataUsageList.class.getName(),
-            DirectoryAccessDetails.class.getName()
+            DirectoryAccessDetails.class.getName(),
+            AdvancedConnectedDeviceDashboardFragment.class.getName()
     };
 
     public static final String[] SETTINGS_FOR_RESTRICTED = {
diff --git a/src/com/android/settings/datetime/timezone/ZonePicker.java b/src/com/android/settings/datetime/timezone/ZonePicker.java
index eafbaa2..d0d1720 100644
--- a/src/com/android/settings/datetime/timezone/ZonePicker.java
+++ b/src/com/android/settings/datetime/timezone/ZonePicker.java
@@ -31,6 +31,7 @@
 import android.view.ViewGroup;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
 import android.widget.Spinner;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
@@ -56,11 +57,14 @@
     private List<RegionInfo> mRegions;
     private Map<String, List<TimeZoneInfo>> mZoneInfos;
     private List<TimeZoneInfo> mFixedOffsetTimeZones;
-    private TimeZoneAdapter mTimeZoneAdapter;
     private String mSelectedTimeZone;
     private boolean mSelectByRegion;
     private DataLoader mDataLoader;
+    private TimeZoneAdapter mTimeZoneAdapter;
+
     private RecyclerView mRecyclerView;
+    private LinearLayout mRegionSpinnerLayout;
+    private Spinner mRegionSpinner;
 
     @Override
     public int getMetricsCategory() {
@@ -88,15 +92,17 @@
         final ArrayAdapter<RegionInfo> regionAdapter = new ArrayAdapter<>(getContext(),
                 R.layout.filter_spinner_item, mRegions);
         regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
-        final Spinner spinner = view.findViewById(R.id.tz_region_spinner);
-        spinner.setAdapter(regionAdapter);
-        spinner.setOnItemSelectedListener(this);
-        setupForCurrentTimeZone(spinner);
+
+        mRegionSpinnerLayout = view.findViewById(R.id.tz_region_spinner_layout);
+        mRegionSpinner = view.findViewById(R.id.tz_region_spinner);
+        mRegionSpinner.setAdapter(regionAdapter);
+        mRegionSpinner.setOnItemSelectedListener(this);
+        setupForCurrentTimeZone();
         setHasOptionsMenu(true);
         return view;
     }
 
-    private void setupForCurrentTimeZone(Spinner spinner) {
+    private void setupForCurrentTimeZone() {
         final String localeRegionId = mLocale.getCountry().toUpperCase(Locale.ROOT);
         final String currentTimeZone = TimeZone.getDefault().getID();
         boolean fixedOffset = currentTimeZone.startsWith("Etc/GMT") ||
@@ -105,12 +111,12 @@
         for (int regionIndex = 0; regionIndex < mRegions.size(); regionIndex++) {
             final RegionInfo region = mRegions.get(regionIndex);
             if (localeRegionId.equals(region.getId())) {
-                spinner.setSelection(regionIndex);
+                mRegionSpinner.setSelection(regionIndex);
             }
             if (!fixedOffset) {
                 for (String timeZoneId: region.getTimeZoneIds()) {
                     if (TextUtils.equals(timeZoneId, mSelectedTimeZone)) {
-                        spinner.setSelection(regionIndex);
+                        mRegionSpinner.setSelection(regionIndex);
                         return;
                     }
                 }
@@ -179,16 +185,15 @@
 
     private void setSelectByRegion(boolean selectByRegion) {
         mSelectByRegion = selectByRegion;
-        getView().findViewById(R.id.tz_region_spinner_layout).setVisibility(
+        mRegionSpinnerLayout.setVisibility(
             mSelectByRegion ? View.VISIBLE : View.GONE);
         List<TimeZoneInfo> tzInfos;
         if (selectByRegion) {
-            Spinner regionSpinner = getView().findViewById(R.id.tz_region_spinner);
-            int selectedRegion = regionSpinner.getSelectedItemPosition();
+            int selectedRegion = mRegionSpinner.getSelectedItemPosition();
             if (selectedRegion == -1) {
                 // Arbitrarily pick the first item if no region was selected above.
                 selectedRegion = 0;
-                regionSpinner.setSelection(selectedRegion);
+                mRegionSpinner.setSelection(selectedRegion);
             }
             tzInfos = getTimeZoneInfos(mRegions.get(selectedRegion));
         } else {
diff --git a/src/com/android/settings/display/TimeoutPreferenceController.java b/src/com/android/settings/display/TimeoutPreferenceController.java
index 1d86999..84f9641 100644
--- a/src/com/android/settings/display/TimeoutPreferenceController.java
+++ b/src/com/android/settings/display/TimeoutPreferenceController.java
@@ -13,9 +13,11 @@
  */
 package com.android.settings.display;
 
-import android.app.admin.DevicePolicyManager;
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+
 import android.content.Context;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 import android.util.Log;
@@ -25,10 +27,9 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.wrapper.DevicePolicyManagerWrapper;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.core.AbstractPreferenceController;
 
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-
 public class TimeoutPreferenceController extends AbstractPreferenceController implements
         PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
 
@@ -69,6 +70,13 @@
             timeoutListPreference.removeUnusableTimeouts(maxTimeout, admin);
         }
         updateTimeoutPreferenceDescription(timeoutListPreference, currentTimeout);
+
+        EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
+                        mContext, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
+                        UserHandle.myUserId());
+        if(admin != null) {
+            timeoutListPreference.removeUnusableTimeouts(0/* disable all*/, admin);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java
index acd8144..c4c795b 100644
--- a/src/com/android/settings/fuelgauge/BatteryInfo.java
+++ b/src/com/android/settings/fuelgauge/BatteryInfo.java
@@ -272,7 +272,7 @@
         void onParsingDone();
     }
 
-    private static void parse(BatteryStats stats, BatteryDataParser... parsers) {
+    public static void parse(BatteryStats stats, BatteryDataParser... parsers) {
         long startWalltime = 0;
         long endWalltime = 0;
         long historyStart = 0;
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java
index 6af859b..a580db1 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java
@@ -19,9 +19,12 @@
 import android.content.Context;
 import android.provider.Settings;
 import android.support.annotation.VisibleForTesting;
+import android.text.format.DateUtils;
 import android.util.KeyValueListParser;
 import android.util.Log;
 
+import java.time.Duration;
+
 /**
  * Class to store the policy for battery tips, which comes from
  * {@link Settings.Global}
@@ -34,6 +37,8 @@
     private static final String KEY_BATTERY_SAVER_TIP_ENABLED = "battery_saver_tip_enabled";
     private static final String KEY_HIGH_USAGE_ENABLED = "high_usage_enabled";
     private static final String KEY_HIGH_USAGE_APP_COUNT = "high_usage_app_count";
+    private static final String KEY_HIGH_USAGE_PERIOD_MS = "high_usage_period_ms";
+    private static final String KEY_HIGH_USAGE_BATTERY_DRAINING = "high_usage_battery_draining";
     private static final String KEY_APP_RESTRICTION_ENABLED = "app_restriction_enabled";
     private static final String KEY_REDUCED_BATTERY_ENABLED = "reduced_battery_enabled";
     private static final String KEY_REDUCED_BATTERY_PERCENT = "reduced_battery_percent";
@@ -81,6 +86,24 @@
     public final int highUsageAppCount;
 
     /**
+     * The size of the window(milliseconds) for checking if the device is being heavily used
+     *
+     * @see Settings.Global#BATTERY_TIP_CONSTANTS
+     * @see #KEY_HIGH_USAGE_PERIOD_MS
+     */
+    public final long highUsagePeriodMs;
+
+    /**
+     * The battery draining threshold to detect whether device is heavily used.
+     * If battery drains more than {@link #highUsageBatteryDraining} in last {@link
+     * #highUsagePeriodMs}, treat device as heavily used.
+     *
+     * @see Settings.Global#BATTERY_TIP_CONSTANTS
+     * @see #KEY_HIGH_USAGE_BATTERY_DRAINING
+     */
+    public final int highUsageBatteryDraining;
+
+    /**
      * {@code true} if app restriction tip is enabled
      *
      * @see Settings.Global#BATTERY_TIP_CONSTANTS
@@ -143,6 +166,9 @@
         batterySaverTipEnabled = mParser.getBoolean(KEY_BATTERY_SAVER_TIP_ENABLED, true);
         highUsageEnabled = mParser.getBoolean(KEY_HIGH_USAGE_ENABLED, true);
         highUsageAppCount = mParser.getInt(KEY_HIGH_USAGE_APP_COUNT, 3);
+        highUsagePeriodMs = mParser.getLong(KEY_HIGH_USAGE_PERIOD_MS,
+                Duration.ofHours(2).toMillis());
+        highUsageBatteryDraining = mParser.getInt(KEY_HIGH_USAGE_BATTERY_DRAINING, 25);
         appRestrictionEnabled = mParser.getBoolean(KEY_APP_RESTRICTION_ENABLED, true);
         reducedBatteryEnabled = mParser.getBoolean(KEY_REDUCED_BATTERY_ENABLED, false);
         reducedBatteryPercent = mParser.getInt(KEY_REDUCED_BATTERY_PERCENT, 50);
diff --git a/src/com/android/settings/fuelgauge/batterytip/HighUsageDataParser.java b/src/com/android/settings/fuelgauge/batterytip/HighUsageDataParser.java
new file mode 100644
index 0000000..cc5aed6
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/HighUsageDataParser.java
@@ -0,0 +1,79 @@
+/*
+ * 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.fuelgauge.batterytip;
+
+import android.os.BatteryStats;
+
+import com.android.settings.fuelgauge.BatteryInfo;
+
+/**
+ * DataParser used to go through battery data and detect whether battery is
+ * heavily used.
+ */
+public class HighUsageDataParser implements BatteryInfo.BatteryDataParser {
+    /**
+     * time period to check the battery usage
+     */
+    private final long mTimePeriodMs;
+    /**
+     * treat device as heavily used if battery usage is more than {@code threshold}. 1 means 1%
+     * battery usage.
+     */
+    private int mThreshold;
+    private long mEndTimeMs;
+    private byte mEndBatteryLevel;
+    private byte mLastPeriodBatteryLevel;
+    private int mBatteryDrain;
+
+    public HighUsageDataParser(long timePeriodMs, int threshold) {
+        mTimePeriodMs = timePeriodMs;
+        mThreshold = threshold;
+    }
+
+    @Override
+    public void onParsingStarted(long startTime, long endTime) {
+        mEndTimeMs = endTime;
+    }
+
+    @Override
+    public void onDataPoint(long time, BatteryStats.HistoryItem record) {
+        if (record.currentTime <= mEndTimeMs - mTimePeriodMs) {
+            // Since onDataPoint is invoked sorted by time, so we could use this way to get the
+            // closet battery level 'mTimePeriodMs' time ago.
+            mLastPeriodBatteryLevel = record.batteryLevel;
+        }
+        mEndBatteryLevel = record.batteryLevel;
+    }
+
+    @Override
+    public void onDataGap() {
+        // do nothing
+    }
+
+    @Override
+    public void onParsingDone() {
+        mBatteryDrain = mLastPeriodBatteryLevel - mEndBatteryLevel;
+    }
+
+    /**
+     * Return {@code true} if the battery drain in {@link #mTimePeriodMs} is too much
+     */
+    public boolean isDeviceHeavilyUsed() {
+        return mBatteryDrain > mThreshold;
+    }
+}
+
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java
index 3c69667..ed3fa04 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetector.java
@@ -19,13 +19,14 @@
 import android.content.Context;
 import android.os.BatteryStats;
 import android.support.annotation.VisibleForTesting;
-import android.text.format.DateUtils;
 
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
 import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settings.fuelgauge.BatteryInfo;
+import com.android.settings.fuelgauge.batterytip.HighUsageDataParser;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
 
@@ -43,6 +44,8 @@
     private List<AppInfo> mHighUsageAppList;
     private Context mContext;
     @VisibleForTesting
+    HighUsageDataParser mDataParser;
+    @VisibleForTesting
     BatteryUtils mBatteryUtils;
 
     public HighUsageDetector(Context context, BatteryTipPolicy policy,
@@ -52,32 +55,42 @@
         mBatteryStatsHelper = batteryStatsHelper;
         mHighUsageAppList = new ArrayList<>();
         mBatteryUtils = BatteryUtils.getInstance(context);
+        mDataParser = new HighUsageDataParser(mPolicy.highUsagePeriodMs,
+                mPolicy.highUsageBatteryDraining);
     }
 
     @Override
     public BatteryTip detect() {
         final long screenUsageTimeMs = mBatteryUtils.calculateScreenUsageTime(mBatteryStatsHelper);
-        //TODO(b/70570352): Change it to detect whether battery drops 25% in last 2 hours
-        if (mPolicy.highUsageEnabled && screenUsageTimeMs > DateUtils.HOUR_IN_MILLIS) {
-            final List<BatterySipper> batterySippers = mBatteryStatsHelper.getUsageList();
-            for (int i = 0, size = batterySippers.size(); i < size; i++) {
-                final BatterySipper batterySipper = batterySippers.get(i);
-                if (!mBatteryUtils.shouldHideSipper(batterySipper)) {
-                    final long foregroundTimeMs = mBatteryUtils.getProcessTimeMs(
-                            BatteryUtils.StatusType.FOREGROUND, batterySipper.uidObj,
-                            BatteryStats.STATS_SINCE_CHARGED);
-                    mHighUsageAppList.add(new AppInfo.Builder()
-                            .setPackageName(mBatteryUtils.getPackageName(batterySipper.getUid()))
-                            .setScreenOnTimeMs(foregroundTimeMs)
-                            .build());
+        if (mPolicy.highUsageEnabled) {
+            parseBatteryData();
+            if (mDataParser.isDeviceHeavilyUsed()) {
+                final List<BatterySipper> batterySippers = mBatteryStatsHelper.getUsageList();
+                for (int i = 0, size = batterySippers.size(); i < size; i++) {
+                    final BatterySipper batterySipper = batterySippers.get(i);
+                    if (!mBatteryUtils.shouldHideSipper(batterySipper)) {
+                        final long foregroundTimeMs = mBatteryUtils.getProcessTimeMs(
+                                BatteryUtils.StatusType.FOREGROUND, batterySipper.uidObj,
+                                BatteryStats.STATS_SINCE_CHARGED);
+                        mHighUsageAppList.add(new AppInfo.Builder()
+                                .setPackageName(
+                                        mBatteryUtils.getPackageName(batterySipper.getUid()))
+                                .setScreenOnTimeMs(foregroundTimeMs)
+                                .build());
+                    }
                 }
-            }
 
-            mHighUsageAppList = mHighUsageAppList.subList(0,
-                    Math.min(mPolicy.highUsageAppCount, mHighUsageAppList.size()));
-            Collections.sort(mHighUsageAppList, Collections.reverseOrder());
+                mHighUsageAppList = mHighUsageAppList.subList(0,
+                        Math.min(mPolicy.highUsageAppCount, mHighUsageAppList.size()));
+                Collections.sort(mHighUsageAppList, Collections.reverseOrder());
+            }
         }
 
         return new HighUsageTip(screenUsageTimeMs, mHighUsageAppList);
     }
+
+    @VisibleForTesting
+    void parseBatteryData() {
+        BatteryInfo.parse(mBatteryStatsHelper.getStats(), mDataParser);
+    }
 }
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 878bbfd..cbe49f8 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -48,6 +48,11 @@
 
     DatabaseIndexingManager getIndexingManager(Context context);
 
+    /**
+     * @return a {@link SearchIndexableResources} to be used for indexing search results.
+     */
+    SearchIndexableResources getSearchIndexableResources();
+
     default String getSettingsIntelligencePkgName() {
         return "com.android.settings.intelligence";
     }
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index ccd4ff1..78c47ed 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -36,6 +36,7 @@
 
     private static final String METRICS_ACTION_SETTINGS_INDEX = "search_synchronous_indexing";
     private DatabaseIndexingManager mDatabaseIndexingManager;
+    private SearchIndexableResources mSearchIndexableResources;
 
     @Override
     public void verifyLaunchSearchResultPageCaller(Context context, ComponentName caller) {
@@ -72,6 +73,14 @@
                 .histogram(context, METRICS_ACTION_SETTINGS_INDEX, indexingTime);
     }
 
+    @Override
+    public SearchIndexableResources getSearchIndexableResources() {
+        if (mSearchIndexableResources == null) {
+            mSearchIndexableResources = new SearchIndexableResourcesImpl();
+        }
+        return mSearchIndexableResources;
+    }
+
     protected boolean isSignatureWhitelisted(Context context, String callerPackage) {
         return false;
     }
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index b0159cf..5a0a131 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -16,170 +16,14 @@
 
 package com.android.settings.search;
 
-import android.support.annotation.VisibleForTesting;
-
-import com.android.settings.DateTimeSettings;
-import com.android.settings.DisplaySettings;
-import com.android.settings.LegalSettings;
-import com.android.settings.accessibility.AccessibilitySettings;
-import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
-import com.android.settings.accessibility.MagnificationPreferenceFragment;
-import com.android.settings.accounts.UserAndAccountDashboardFragment;
-import com.android.settings.applications.AppAndNotificationDashboardFragment;
-import com.android.settings.applications.DefaultAppSettings;
-import com.android.settings.applications.SpecialAccessSettings;
-import com.android.settings.applications.assist.ManageAssist;
-import com.android.settings.backup.BackupSettingsActivity;
-import com.android.settings.backup.BackupSettingsFragment;
-import com.android.settings.bluetooth.BluetoothSettings;
-import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
-import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
-import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragmentOld;
-import com.android.settings.datausage.DataUsageSummary;
-import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
-import com.android.settings.development.DevelopmentSettingsDashboardFragment;
-import com.android.settings.deviceinfo.DeviceInfoSettings;
-import com.android.settings.deviceinfo.StorageDashboardFragment;
-import com.android.settings.deviceinfo.StorageSettings;
-import com.android.settings.display.AmbientDisplaySettings;
-import com.android.settings.display.NightDisplaySettings;
-import com.android.settings.display.ScreenZoomSettings;
-import com.android.settings.dream.DreamSettings;
-import com.android.settings.enterprise.EnterprisePrivacySettings;
-import com.android.settings.fuelgauge.BatterySaverSettings;
-import com.android.settings.fuelgauge.PowerUsageAdvanced;
-import com.android.settings.fuelgauge.PowerUsageSummary;
-import com.android.settings.fuelgauge.SmartBatterySettings;
-import com.android.settings.gestures.AssistGestureSettings;
-import com.android.settings.gestures.DoubleTapPowerSettings;
-import com.android.settings.gestures.DoubleTapScreenSettings;
-import com.android.settings.gestures.DoubleTwistGestureSettings;
-import com.android.settings.gestures.GestureSettings;
-import com.android.settings.gestures.PickupGestureSettings;
-import com.android.settings.gestures.SwipeToNotificationSettings;
-import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment;
-import com.android.settings.inputmethod.VirtualKeyboardFragment;
-import com.android.settings.language.LanguageAndInputSettings;
-import com.android.settings.location.LocationMode;
-import com.android.settings.location.LocationSettings;
-import com.android.settings.location.ScanningSettings;
-import com.android.settings.network.NetworkDashboardFragment;
-import com.android.settings.nfc.PaymentSettings;
-import com.android.settings.notification.ConfigureNotificationSettings;
-import com.android.settings.notification.SoundSettings;
-import com.android.settings.notification.ZenModeAutomationSettings;
-import com.android.settings.notification.ZenModeBehaviorSettings;
-import com.android.settings.notification.ZenModeSettings;
-import com.android.settings.print.PrintSettingsFragment;
-import com.android.settings.security.EncryptionAndCredential;
-import com.android.settings.security.LockscreenDashboardFragment;
-import com.android.settings.security.ScreenPinningSettings;
-import com.android.settings.security.SecuritySettingsV2;
-import com.android.settings.security.screenlock.ScreenLockSettings;
-import com.android.settings.sim.SimSettings;
-import com.android.settings.support.SupportDashboardActivity;
-import com.android.settings.system.ResetDashboardFragment;
-import com.android.settings.system.SystemDashboardFragment;
-import com.android.settings.tts.TextToSpeechSettings;
-import com.android.settings.tts.TtsEnginePreferenceFragment;
-import com.android.settings.users.UserSettings;
-import com.android.settings.wallpaper.WallpaperTypeSettings;
-import com.android.settings.wfd.WifiDisplaySettings;
-import com.android.settings.wifi.ConfigureWifiSettings;
-import com.android.settings.wifi.WifiSettings;
-
 import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
 
-public final class SearchIndexableResources {
+public interface SearchIndexableResources {
 
-    @VisibleForTesting
-    static final Set<Class> sProviders = new HashSet<>();
-
-    @VisibleForTesting
-    static void addIndex(Class indexClass) {
-        sProviders.add(indexClass);
-    }
-
-    static {
-        addIndex(WifiSettings.class);
-        addIndex(NetworkDashboardFragment.class);
-        addIndex(ConfigureWifiSettings.class);
-        addIndex(BluetoothSettings.class);
-        addIndex(SimSettings.class);
-        addIndex(DataUsageSummary.class);
-        addIndex(ScreenZoomSettings.class);
-        addIndex(DisplaySettings.class);
-        addIndex(AmbientDisplaySettings.class);
-        addIndex(WallpaperTypeSettings.class);
-        addIndex(AppAndNotificationDashboardFragment.class);
-        addIndex(SoundSettings.class);
-        addIndex(ZenModeSettings.class);
-        addIndex(StorageSettings.class);
-        addIndex(PowerUsageAdvanced.class);
-        addIndex(DefaultAppSettings.class);
-        addIndex(ManageAssist.class);
-        addIndex(SpecialAccessSettings.class);
-        addIndex(UserSettings.class);
-        addIndex(AssistGestureSettings.class);
-        addIndex(PickupGestureSettings.class);
-        addIndex(DoubleTapScreenSettings.class);
-        addIndex(DoubleTapPowerSettings.class);
-        addIndex(DoubleTwistGestureSettings.class);
-        addIndex(SwipeToNotificationSettings.class);
-        addIndex(GestureSettings.class);
-        addIndex(LanguageAndInputSettings.class);
-        addIndex(LocationSettings.class);
-        addIndex(LocationMode.class);
-        addIndex(ScanningSettings.class);
-        addIndex(SecuritySettingsV2.class);
-        addIndex(ScreenLockSettings.class);
-        addIndex(EncryptionAndCredential.class);
-        addIndex(ScreenPinningSettings.class);
-        addIndex(UserAndAccountDashboardFragment.class);
-        addIndex(VirtualKeyboardFragment.class);
-        addIndex(AvailableVirtualKeyboardFragment.class);
-        addIndex(PhysicalKeyboardFragment.class);
-        addIndex(BackupSettingsActivity.class);
-        addIndex(BackupSettingsFragment.class);
-        addIndex(DateTimeSettings.class);
-        addIndex(AccessibilitySettings.class);
-        addIndex(PrintSettingsFragment.class);
-        addIndex(DevelopmentSettingsDashboardFragment.class);
-        addIndex(DeviceInfoSettings.class);
-        addIndex(LegalSettings.class);
-        addIndex(SystemDashboardFragment.class);
-        addIndex(ResetDashboardFragment.class);
-        addIndex(StorageDashboardFragment.class);
-        addIndex(ConnectedDeviceDashboardFragment.class);
-        addIndex(ConnectedDeviceDashboardFragmentOld.class);
-        addIndex(AdvancedConnectedDeviceDashboardFragment.class);
-        addIndex(EnterprisePrivacySettings.class);
-        addIndex(PaymentSettings.class);
-        addIndex(TextToSpeechSettings.class);
-        addIndex(TtsEnginePreferenceFragment.class);
-        addIndex(MagnificationPreferenceFragment.class);
-        addIndex(AccessibilityShortcutPreferenceFragment.class);
-        addIndex(DreamSettings.class);
-        addIndex(SupportDashboardActivity.class);
-        addIndex(AutomaticStorageManagerSettings.class);
-        addIndex(ConfigureNotificationSettings.class);
-        addIndex(PowerUsageSummary.class);
-        addIndex(BatterySaverSettings.class);
-        addIndex(LockscreenDashboardFragment.class);
-        addIndex(WifiDisplaySettings.class);
-        addIndex(ZenModeBehaviorSettings.class);
-        addIndex(ZenModeAutomationSettings.class);
-        addIndex(NightDisplaySettings.class);
-        addIndex(SmartBatterySettings.class);
-    }
-
-    private SearchIndexableResources() {
-    }
-
-    public static Collection<Class> providerValues() {
-        return sProviders;
-    }
-}
\ No newline at end of file
+    /**
+     * Returns a collection of classes that should be indexed for search.
+     *
+     * Each class should have the SEARCH_INDEX_DATA_PROVIDER public static member.
+     */
+    Collection<Class> getProviderValues();
+}
diff --git a/src/com/android/settings/search/SearchIndexableResourcesImpl.java b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
new file mode 100644
index 0000000..2c20703
--- /dev/null
+++ b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2014 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.search;
+
+import android.support.annotation.VisibleForTesting;
+
+import com.android.settings.DateTimeSettings;
+import com.android.settings.DisplaySettings;
+import com.android.settings.LegalSettings;
+import com.android.settings.accessibility.AccessibilitySettings;
+import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
+import com.android.settings.accessibility.MagnificationPreferenceFragment;
+import com.android.settings.accounts.UserAndAccountDashboardFragment;
+import com.android.settings.applications.AppAndNotificationDashboardFragment;
+import com.android.settings.applications.DefaultAppSettings;
+import com.android.settings.applications.SpecialAccessSettings;
+import com.android.settings.applications.assist.ManageAssist;
+import com.android.settings.backup.BackupSettingsActivity;
+import com.android.settings.backup.BackupSettingsFragment;
+import com.android.settings.bluetooth.BluetoothSettings;
+import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
+import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
+import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragmentOld;
+import com.android.settings.datausage.DataUsageSummary;
+import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
+import com.android.settings.development.DevelopmentSettingsDashboardFragment;
+import com.android.settings.deviceinfo.DeviceInfoSettings;
+import com.android.settings.deviceinfo.StorageDashboardFragment;
+import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.display.AmbientDisplaySettings;
+import com.android.settings.display.NightDisplaySettings;
+import com.android.settings.display.ScreenZoomSettings;
+import com.android.settings.dream.DreamSettings;
+import com.android.settings.enterprise.EnterprisePrivacySettings;
+import com.android.settings.fuelgauge.BatterySaverSettings;
+import com.android.settings.fuelgauge.PowerUsageAdvanced;
+import com.android.settings.fuelgauge.PowerUsageSummary;
+import com.android.settings.fuelgauge.SmartBatterySettings;
+import com.android.settings.gestures.AssistGestureSettings;
+import com.android.settings.gestures.DoubleTapPowerSettings;
+import com.android.settings.gestures.DoubleTapScreenSettings;
+import com.android.settings.gestures.DoubleTwistGestureSettings;
+import com.android.settings.gestures.GestureSettings;
+import com.android.settings.gestures.PickupGestureSettings;
+import com.android.settings.gestures.SwipeToNotificationSettings;
+import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
+import com.android.settings.inputmethod.PhysicalKeyboardFragment;
+import com.android.settings.inputmethod.VirtualKeyboardFragment;
+import com.android.settings.language.LanguageAndInputSettings;
+import com.android.settings.location.LocationMode;
+import com.android.settings.location.LocationSettings;
+import com.android.settings.location.ScanningSettings;
+import com.android.settings.network.NetworkDashboardFragment;
+import com.android.settings.nfc.PaymentSettings;
+import com.android.settings.notification.ConfigureNotificationSettings;
+import com.android.settings.notification.SoundSettings;
+import com.android.settings.notification.ZenModeAutomationSettings;
+import com.android.settings.notification.ZenModeBehaviorSettings;
+import com.android.settings.notification.ZenModeSettings;
+import com.android.settings.print.PrintSettingsFragment;
+import com.android.settings.security.EncryptionAndCredential;
+import com.android.settings.security.LockscreenDashboardFragment;
+import com.android.settings.security.ScreenPinningSettings;
+import com.android.settings.security.SecuritySettingsV2;
+import com.android.settings.security.screenlock.ScreenLockSettings;
+import com.android.settings.sim.SimSettings;
+import com.android.settings.support.SupportDashboardActivity;
+import com.android.settings.system.ResetDashboardFragment;
+import com.android.settings.system.SystemDashboardFragment;
+import com.android.settings.tts.TextToSpeechSettings;
+import com.android.settings.tts.TtsEnginePreferenceFragment;
+import com.android.settings.users.UserSettings;
+import com.android.settings.wallpaper.WallpaperTypeSettings;
+import com.android.settings.wfd.WifiDisplaySettings;
+import com.android.settings.wifi.ConfigureWifiSettings;
+import com.android.settings.wifi.WifiSettings;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SearchIndexableResourcesImpl implements SearchIndexableResources {
+
+    private final Set<Class> sProviders = new HashSet<>();
+
+    @VisibleForTesting
+    void addIndex(Class indexClass) {
+        sProviders.add(indexClass);
+    }
+
+    public SearchIndexableResourcesImpl() {
+        addIndex(WifiSettings.class);
+        addIndex(NetworkDashboardFragment.class);
+        addIndex(ConfigureWifiSettings.class);
+        addIndex(BluetoothSettings.class);
+        addIndex(SimSettings.class);
+        addIndex(DataUsageSummary.class);
+        addIndex(ScreenZoomSettings.class);
+        addIndex(DisplaySettings.class);
+        addIndex(AmbientDisplaySettings.class);
+        addIndex(WallpaperTypeSettings.class);
+        addIndex(AppAndNotificationDashboardFragment.class);
+        addIndex(SoundSettings.class);
+        addIndex(ZenModeSettings.class);
+        addIndex(StorageSettings.class);
+        addIndex(PowerUsageAdvanced.class);
+        addIndex(DefaultAppSettings.class);
+        addIndex(ManageAssist.class);
+        addIndex(SpecialAccessSettings.class);
+        addIndex(UserSettings.class);
+        addIndex(AssistGestureSettings.class);
+        addIndex(PickupGestureSettings.class);
+        addIndex(DoubleTapScreenSettings.class);
+        addIndex(DoubleTapPowerSettings.class);
+        addIndex(DoubleTwistGestureSettings.class);
+        addIndex(SwipeToNotificationSettings.class);
+        addIndex(GestureSettings.class);
+        addIndex(LanguageAndInputSettings.class);
+        addIndex(LocationSettings.class);
+        addIndex(LocationMode.class);
+        addIndex(ScanningSettings.class);
+        addIndex(SecuritySettingsV2.class);
+        addIndex(ScreenLockSettings.class);
+        addIndex(EncryptionAndCredential.class);
+        addIndex(ScreenPinningSettings.class);
+        addIndex(UserAndAccountDashboardFragment.class);
+        addIndex(VirtualKeyboardFragment.class);
+        addIndex(AvailableVirtualKeyboardFragment.class);
+        addIndex(PhysicalKeyboardFragment.class);
+        addIndex(BackupSettingsActivity.class);
+        addIndex(BackupSettingsFragment.class);
+        addIndex(DateTimeSettings.class);
+        addIndex(AccessibilitySettings.class);
+        addIndex(PrintSettingsFragment.class);
+        addIndex(DevelopmentSettingsDashboardFragment.class);
+        addIndex(DeviceInfoSettings.class);
+        addIndex(LegalSettings.class);
+        addIndex(SystemDashboardFragment.class);
+        addIndex(ResetDashboardFragment.class);
+        addIndex(StorageDashboardFragment.class);
+        addIndex(ConnectedDeviceDashboardFragment.class);
+        addIndex(ConnectedDeviceDashboardFragmentOld.class);
+        addIndex(AdvancedConnectedDeviceDashboardFragment.class);
+        addIndex(EnterprisePrivacySettings.class);
+        addIndex(PaymentSettings.class);
+        addIndex(TextToSpeechSettings.class);
+        addIndex(TtsEnginePreferenceFragment.class);
+        addIndex(MagnificationPreferenceFragment.class);
+        addIndex(AccessibilityShortcutPreferenceFragment.class);
+        addIndex(DreamSettings.class);
+        addIndex(SupportDashboardActivity.class);
+        addIndex(AutomaticStorageManagerSettings.class);
+        addIndex(ConfigureNotificationSettings.class);
+        addIndex(PowerUsageSummary.class);
+        addIndex(BatterySaverSettings.class);
+        addIndex(LockscreenDashboardFragment.class);
+        addIndex(WifiDisplaySettings.class);
+        addIndex(ZenModeBehaviorSettings.class);
+        addIndex(ZenModeAutomationSettings.class);
+        addIndex(NightDisplaySettings.class);
+        addIndex(SmartBatterySettings.class);
+    }
+
+    @Override
+    public Collection<Class> getProviderValues() {
+        return sProviders;
+    }
+}
diff --git a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java
index 0c98b9c..3ef1b85 100644
--- a/src/com/android/settings/search/SettingsSearchIndexablesProvider.java
+++ b/src/com/android/settings/search/SettingsSearchIndexablesProvider.java
@@ -175,7 +175,8 @@
     }
 
     private List<String> getNonIndexableKeysFromProvider(Context context) {
-        final Collection<Class> values = SearchIndexableResources.providerValues();
+        final Collection<Class> values = FeatureFactory.getFactory(context)
+                .getSearchFeatureProvider().getSearchIndexableResources().getProviderValues();
         final List<String> nonIndexableKeys = new ArrayList<>();
 
         for (Class<?> clazz : values) {
@@ -209,7 +210,8 @@
     }
 
     private List<SearchIndexableResource> getSearchIndexableResourcesFromProvider(Context context) {
-        Collection<Class> values = SearchIndexableResources.providerValues();
+        Collection<Class> values = FeatureFactory.getFactory(context)
+                .getSearchFeatureProvider().getSearchIndexableResources().getProviderValues();
         List<SearchIndexableResource> resourceList = new ArrayList<>();
 
         for (Class<?> clazz : values) {
@@ -236,7 +238,8 @@
     }
 
     private List<SearchIndexableRaw> getSearchIndexableRawFromProvider(Context context) {
-        final Collection<Class> values = SearchIndexableResources.providerValues();
+        final Collection<Class> values = FeatureFactory.getFactory(context)
+                .getSearchFeatureProvider().getSearchIndexableResources().getProviderValues();
         final List<SearchIndexableRaw> rawList = new ArrayList<>();
 
         for (Class<?> clazz : values) {
diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java
index c10753f..e5a21e4 100644
--- a/src/com/android/settings/slices/SliceDataConverter.java
+++ b/src/com/android/settings/slices/SliceDataConverter.java
@@ -27,9 +27,9 @@
 import android.util.Xml;
 
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.Indexable.SearchIndexProvider;
-import com.android.settings.search.SearchIndexableResources;
 import com.android.settings.search.XmlParserUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -62,7 +62,8 @@
      * @return a list of {@link SliceData} to be indexed and later referenced as a Slice.
      *
      * The collection works as follows:
-     * - Collects a list of Fragments from {@link SearchIndexableResources}.
+     * - Collects a list of Fragments from
+     * {@link FeatureFactory#getSearchFeatureProvider()}.
      * - From each fragment, grab a {@link SearchIndexProvider}.
      * - For each provider, collect XML resource layout and a list of
      * {@link com.android.settings.core.BasePreferenceController}.
@@ -72,7 +73,8 @@
             return mSliceData;
         }
 
-        final Collection<Class> indexableClasses = SearchIndexableResources.providerValues();
+        final Collection<Class> indexableClasses = FeatureFactory.getFactory(mContext)
+                .getSearchFeatureProvider().getSearchIndexableResources().getProviderValues();
 
         for (Class clazz : indexableClasses) {
             final String fragmentName = clazz.getName();
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 13ffd5b..4d9ad27 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -280,7 +280,7 @@
                 .setButton1Text(R.string.forget)
                 .setButton1Positive(false)
                 .setButton1OnClickListener(view -> forgetNetwork())
-                .setButton2Text(R.string.support_sign_in_button_text)
+                .setButton2Text(R.string.wifi_sign_in_button_text)
                 .setButton2Positive(true)
                 .setButton2OnClickListener(view -> signIntoNetwork());
 
diff --git a/src/com/android/settings/HotspotOffReceiver.java b/src/com/android/settings/wifi/tether/HotspotOffReceiver.java
similarity index 97%
rename from src/com/android/settings/HotspotOffReceiver.java
rename to src/com/android/settings/wifi/tether/HotspotOffReceiver.java
index 4083082..fcbf888 100644
--- a/src/com/android/settings/HotspotOffReceiver.java
+++ b/src/com/android/settings/wifi/tether/HotspotOffReceiver.java
@@ -1,5 +1,5 @@
 
-package com.android.settings;
+package com.android.settings.wifi.tether;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
diff --git a/src/com/android/settings/TetherService.java b/src/com/android/settings/wifi/tether/TetherService.java
similarity index 98%
rename from src/com/android/settings/TetherService.java
rename to src/com/android/settings/wifi/tether/TetherService.java
index fce3f27..e491de8 100644
--- a/src/com/android/settings/TetherService.java
+++ b/src/com/android/settings/wifi/tether/TetherService.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings;
+package com.android.settings.wifi.tether;
 
 import android.app.Activity;
 import android.app.AlarmManager;
@@ -167,11 +167,16 @@
         SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
         prefs.edit().putString(KEY_TETHERS, tethersToString(mCurrentTethers)).commit();
 
+        unregisterReceivers();
         if (DEBUG) Log.d(TAG, "Destroying TetherService");
-        unregisterReceiver(mReceiver);
         super.onDestroy();
     }
 
+    private void unregisterReceivers() {
+        unregisterReceiver(mReceiver);
+        mHotspotReceiver.unregister();
+    }
+
     private void removeTypeAtIndex(int index) {
         mCurrentTethers.remove(index);
         // If we are currently in the middle of a check, we may need to adjust the
diff --git a/src/com/android/settings/wrapper/RecoverySystemWrapper.java b/src/com/android/settings/wrapper/RecoverySystemWrapper.java
new file mode 100644
index 0000000..8a36969
--- /dev/null
+++ b/src/com/android/settings/wrapper/RecoverySystemWrapper.java
@@ -0,0 +1,39 @@
+/*
+ * 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.wrapper;
+
+import android.content.Context;
+import android.os.RecoverySystem;
+
+/**
+ * This class replicates a subset of the {@link RecoverySystem}.
+ * The interface exists so that we can use a thin wrapper around the RecoverySystem in
+ * production code and a mock in tests.
+ */
+public class RecoverySystemWrapper {
+
+    /**
+     * Returns whether wipe Euicc data successfully or not.
+     *
+     * @param isWipeEuicc whether we want to wipe Euicc data or not
+     * @param packageName the package name of the caller app.
+     */
+    public boolean wipeEuiccData(
+            Context context, final boolean isWipeEuicc, final String packageName) {
+        return RecoverySystem.wipeEuiccData(context, isWipeEuicc, packageName);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/MasterClearTest.java b/tests/robotests/src/com/android/settings/MasterClearTest.java
index 361bc8f..26cfc3a 100644
--- a/tests/robotests/src/com/android/settings/MasterClearTest.java
+++ b/tests/robotests/src/com/android/settings/MasterClearTest.java
@@ -19,16 +19,24 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.app.Activity;
 import android.app.Fragment;
 import android.content.ComponentName;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.view.LayoutInflater;
@@ -46,6 +54,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.Robolectric;
 import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAccountManager;
 import org.robolectric.shadows.ShadowActivity;
 
 @RunWith(SettingsRobolectricTestRunner.class)
@@ -55,6 +64,9 @@
     shadows = {ShadowUtils.class}
 )
 public class MasterClearTest {
+    private static final String TEST_ACCOUNT_TYPE = "android.test.account.type";
+    private static final String TEST_CONFIRMATION_PACKAGE = "android.test.confirmation.pkg";
+    private static final String TEST_ACCOUNT_NAME = "test@example.com";
 
     @Mock
     private MasterClear mMasterClear;
@@ -62,7 +74,18 @@
     private ScrollView mScrollView;
     @Mock
     private LinearLayout mLinearLayout;
+
+    @Mock
+    private PackageManager mPackageManager;
+
+    @Mock
+    private AccountManager mAccountManager;
+
+    @Mock
+    private Activity mMockActivity;
+
     private ShadowActivity mShadowActivity;
+    private ShadowAccountManager mShadowAccountManager;
     private Activity mActivity;
     private View mContentView;
 
@@ -86,6 +109,7 @@
         mMasterClear = spy(new MasterClear());
         mActivity = Robolectric.setupActivity(Activity.class);
         mShadowActivity = shadowOf(mActivity);
+        // mShadowAccountManager = shadowOf(AccountManager.get(mActivity));
         mContentView = LayoutInflater.from(mActivity).inflate(R.layout.master_clear, null);
 
         // Make scrollView only have one child
@@ -162,9 +186,61 @@
 
     @Test
     public void testTryShowAccountConfirmation_unsupported() {
-      doReturn(mActivity).when(mMasterClear).getActivity();
-      /* Using the default resources, account confirmation shouldn't trigger */
-      assertThat(mMasterClear.tryShowAccountConfirmation()).isFalse();
+        when(mMasterClear.getActivity()).thenReturn(mActivity);
+        /* Using the default resources, account confirmation shouldn't trigger */
+        assertThat(mMasterClear.tryShowAccountConfirmation()).isFalse();
+    }
+
+    @Test
+    public void testTryShowAccountConfirmation_no_relevant_accounts() {
+        when(mMasterClear.getActivity()).thenReturn(mMockActivity);
+        when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
+        when(mMockActivity.getString(R.string.account_confirmation_package)).thenReturn(TEST_CONFIRMATION_PACKAGE);
+
+        Account[] accounts = new Account[0];
+        when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
+        when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
+        assertThat(mMasterClear.tryShowAccountConfirmation()).isFalse();
+    }
+
+    @Test
+    public void testTryShowAccountConfirmation_unresolved() {
+        when(mMasterClear.getActivity()).thenReturn(mMockActivity);
+        when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
+        when(mMockActivity.getString(R.string.account_confirmation_package)).thenReturn(TEST_CONFIRMATION_PACKAGE);
+        Account[] accounts = new Account[] { new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE) };
+        when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
+        when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
+        // The package manager should not resolve the confirmation intent targeting the non-existent
+        // confirmation package.
+        when(mMockActivity.getPackageManager()).thenReturn(mPackageManager);
+        assertThat(mMasterClear.tryShowAccountConfirmation()).isFalse();
+    }
+
+    @Test
+    public void testTryShowAccountConfirmation_ok() {
+        when(mMasterClear.getActivity()).thenReturn(mMockActivity);
+        // Only try to show account confirmation if the appropriate resource overlays are available.
+        when(mMockActivity.getString(R.string.account_type)).thenReturn(TEST_ACCOUNT_TYPE);
+        when(mMockActivity.getString(R.string.account_confirmation_package)).thenReturn(TEST_CONFIRMATION_PACKAGE);
+        // Add accounts to trigger the search for a resolving intent.
+        Account[] accounts = new Account[] { new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE) };
+        when(mMockActivity.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mAccountManager);
+        when(mAccountManager.getAccountsByType(TEST_ACCOUNT_TYPE)).thenReturn(accounts);
+        // The package manager should not resolve the confirmation intent targeting the non-existent
+        // confirmation package.
+        when(mMockActivity.getPackageManager()).thenReturn(mPackageManager);
+
+        ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = TEST_CONFIRMATION_PACKAGE;
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = activityInfo;
+        when(mPackageManager.resolveActivity(any(), eq(0))).thenReturn(resolveInfo);
+
+        // Finally mock out the startActivityForResultCall
+        doNothing().when(mMockActivity).startActivityForResult(any(), eq(MasterClear.CREDENTIAL_CONFIRM_REQUEST));
+
+        assertThat(mMasterClear.tryShowAccountConfirmation()).isTrue();
     }
 
     private void initScrollView(int height, int scrollY, int childBottom) {
diff --git a/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java b/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java
new file mode 100644
index 0000000..354cacf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/ResetNetworkConfirmTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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;
+
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.content.Context;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.wrapper.RecoverySystemWrapper;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+    manifest = TestConfig.MANIFEST_PATH,
+    sdk = TestConfig.SDK_VERSION
+)
+public class ResetNetworkConfirmTest {
+
+    private Activity mActivity;
+    @Mock
+    private ResetNetworkConfirm mResetNetworkConfirm;
+    @Mock
+    private RecoverySystemWrapper mRecoverySystem;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mResetNetworkConfirm = spy(new ResetNetworkConfirm());
+        mRecoverySystem = spy(new RecoverySystemWrapper());
+        ResetNetworkConfirm.mRecoverySystem = mRecoverySystem;
+        mActivity = Robolectric.setupActivity(Activity.class);
+    }
+
+    @Test
+    public void testResetNetworkData_resetEsim() {
+        mResetNetworkConfirm.mEraseEsim = true;
+        doReturn(true)
+                .when(mRecoverySystem).wipeEuiccData(any(Context.class), anyBoolean(), anyString());
+
+        mResetNetworkConfirm.esimFactoryReset(mActivity, "" /* packageName */);
+        try {
+            // Waiting the Async task finished
+            Thread.sleep(10000); // 10 sec
+        } catch (InterruptedException ignore) {
+
+        }
+
+        Assert.assertNotNull(mResetNetworkConfirm.mEraseEsimTask);
+        verify(mRecoverySystem).wipeEuiccData(any(Context.class), anyBoolean(), anyString());
+    }
+
+    @Test
+    public void testResetNetworkData_notResetEsim() {
+        mResetNetworkConfirm.mEraseEsim = false;
+
+        mResetNetworkConfirm.esimFactoryReset(mActivity, "" /* packageName */);
+
+        Assert.assertNull(mResetNetworkConfirm.mEraseEsimTask);
+        verify(mRecoverySystem, never())
+                .wipeEuiccData(any(Context.class), anyBoolean(), anyString());
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java b/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java
index c561d0d..8ded9d6 100644
--- a/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java
+++ b/tests/robotests/src/com/android/settings/core/XmlControllerAttributeTest.java
@@ -2,6 +2,8 @@
 
 import static com.google.common.truth.Truth.assertWithMessage;
 
+import static org.mockito.Mockito.mock;
+
 import android.content.Context;
 import android.content.res.XmlResourceParser;
 import android.provider.SearchIndexableResource;
@@ -13,10 +15,12 @@
 import com.android.settings.TestConfig;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableResources;
+import com.android.settings.search.SearchFeatureProvider;
+import com.android.settings.search.SearchFeatureProviderImpl;
 import com.android.settings.search.XmlParserUtils;
 import com.android.settings.security.SecuritySettings;
 import com.android.settings.security.SecuritySettingsV2;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.After;
@@ -82,19 +86,21 @@
                     + "IllegalAccessException. Please fix the following classes:\n";
 
     Context mContext;
-
-    private Set<Class> mProviderClassesCopy;
+    SearchFeatureProvider mSearchProvider;
+    private FakeFeatureFactory mFakeFeatureFactory;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
-        mProviderClassesCopy = new HashSet<>(SearchIndexableResources.providerValues());
+        mSearchProvider = new SearchFeatureProviderImpl();
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.searchFeatureProvider = mSearchProvider;
     }
 
     @After
     public void cleanUp() {
-        SearchIndexableResources.providerValues().clear();
-        SearchIndexableResources.providerValues().addAll(mProviderClassesCopy);
+        mFakeFeatureFactory.searchFeatureProvider = mock(
+                SearchFeatureProvider.class);
     }
 
     @Test
@@ -156,7 +162,8 @@
     private Set<Integer> getIndexableXml() {
         Set<Integer> xmlResSet = new HashSet();
 
-        Collection<Class> indexableClasses = SearchIndexableResources.providerValues();
+        Collection<Class> indexableClasses =
+                mSearchProvider.getSearchIndexableResources().getProviderValues();
         indexableClasses.removeAll(illegalClasses);
 
         for (Class clazz : indexableClasses) {
diff --git a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
index 33bc4f8..d4af8b8 100644
--- a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
@@ -20,8 +20,12 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -34,16 +38,20 @@
 import com.android.settings.TimeoutListPreference;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.shadow.ShadowDevicePolicyManagerWrapper;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
@@ -93,4 +101,34 @@
         mController.updateState(mPreference);
         verify(mPreference).removeUnusableTimeouts(timeout, null);
     }
+
+    @Test
+    public void testUpdateStateWithAdminTimeoutsAndRestriction() {
+        final int profileUserId = UserHandle.myUserId();
+        final long timeout = 100;
+        when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList());
+        ShadowDevicePolicyManagerWrapper.setMaximumTimeToLock(profileUserId, timeout);
+
+        int userId = UserHandle.myUserId();
+        List<UserManager.EnforcingUser> enforcingUsers = new ArrayList<>();
+        // Add two enforcing users so that RestrictedLockUtils.checkIfRestrictionEnforced returns
+        // non-null.
+        enforcingUsers.add(new UserManager.EnforcingUser(userId,
+                UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
+        enforcingUsers.add(new UserManager.EnforcingUser(userId,
+                UserManager.RESTRICTION_SOURCE_PROFILE_OWNER));
+        when(mUserManager.getUserRestrictionSources(
+                UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT, UserHandle.of(userId)))
+                .thenReturn(enforcingUsers);
+
+        mController.updateState(mPreference);
+
+        ArgumentCaptor<Long> longCaptor = ArgumentCaptor.forClass(Long.class);
+        ArgumentCaptor<EnforcedAdmin> adminCaptor = ArgumentCaptor.forClass(EnforcedAdmin.class);
+
+        verify(mPreference, times(2)).removeUnusableTimeouts(
+                longCaptor.capture(), adminCaptor.capture());
+        assertEquals(0, (long)longCaptor.getValue());
+        assertTrue(adminCaptor.getValue() != null);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
index 53c9766..83b3225 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
@@ -37,6 +37,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
@@ -54,7 +55,7 @@
             BatteryTip.TipType.BATTERY_SAVER,
             BatteryTip.TipType.LOW_BATTERY,
             BatteryTip.TipType.SUMMARY};
-    @Mock
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private BatteryStatsHelper mBatteryStatsHelper;
     @Mock
     private PowerManager mPowerManager;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java
index bb9a37b..78c86f8 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java
@@ -24,6 +24,7 @@
 
 import android.content.Context;
 import android.provider.Settings;
+import android.text.format.DateUtils;
 
 import com.android.settings.TestConfig;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -42,6 +43,8 @@
             + ",battery_saver_tip_enabled=false"
             + ",high_usage_enabled=true"
             + ",high_usage_app_count=5"
+            + ",high_usage_period_ms=2000"
+            + ",high_usage_battery_draining=30"
             + ",app_restriction_enabled=true"
             + ",reduced_battery_enabled=true"
             + ",reduced_battery_percent=30"
@@ -66,6 +69,8 @@
         assertThat(batteryTipPolicy.batterySaverTipEnabled).isFalse();
         assertThat(batteryTipPolicy.highUsageEnabled).isTrue();
         assertThat(batteryTipPolicy.highUsageAppCount).isEqualTo(5);
+        assertThat(batteryTipPolicy.highUsagePeriodMs).isEqualTo(2000);
+        assertThat(batteryTipPolicy.highUsageBatteryDraining).isEqualTo(30);
         assertThat(batteryTipPolicy.appRestrictionEnabled).isTrue();
         assertThat(batteryTipPolicy.reducedBatteryEnabled).isTrue();
         assertThat(batteryTipPolicy.reducedBatteryPercent).isEqualTo(30);
@@ -85,6 +90,8 @@
         assertThat(batteryTipPolicy.batterySaverTipEnabled).isTrue();
         assertThat(batteryTipPolicy.highUsageEnabled).isTrue();
         assertThat(batteryTipPolicy.highUsageAppCount).isEqualTo(3);
+        assertThat(batteryTipPolicy.highUsagePeriodMs).isEqualTo(2 * DateUtils.HOUR_IN_MILLIS);
+        assertThat(batteryTipPolicy.highUsageBatteryDraining).isEqualTo(25);
         assertThat(batteryTipPolicy.appRestrictionEnabled).isTrue();
         assertThat(batteryTipPolicy.reducedBatteryEnabled).isFalse();
         assertThat(batteryTipPolicy.reducedBatteryPercent).isEqualTo(50);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/HighUsageDataParserTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/HighUsageDataParserTest.java
new file mode 100644
index 0000000..5bdae0c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/HighUsageDataParserTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.fuelgauge.batterytip;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.BatteryStats;
+import android.text.format.DateUtils;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import java.time.Duration;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class HighUsageDataParserTest {
+    private static final long PERIOD_ONE_MINUTE_MS = Duration.ofMinutes(1).toMillis();
+    private static final long END_TIME_MS = 2 * PERIOD_ONE_MINUTE_MS;
+    private static final int THRESHOLD_LOW = 10;
+    private static final int THRESHOLD_HIGH = 20;
+    private HighUsageDataParser mDataParser;
+    private BatteryStats.HistoryItem mFirstItem;
+    private BatteryStats.HistoryItem mSecondItem;
+    private BatteryStats.HistoryItem mThirdItem;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mFirstItem = new BatteryStats.HistoryItem();
+        mFirstItem.batteryLevel = 100;
+        mFirstItem.currentTime = 0;
+        mSecondItem = new BatteryStats.HistoryItem();
+        mSecondItem.batteryLevel = 95;
+        mSecondItem.currentTime = PERIOD_ONE_MINUTE_MS;
+        mThirdItem = new BatteryStats.HistoryItem();
+        mThirdItem.batteryLevel = 80;
+        mThirdItem.currentTime = END_TIME_MS;
+    }
+
+    @Test
+    public void testDataParser_thresholdLow_isHeavilyUsed() {
+        mDataParser = new HighUsageDataParser(PERIOD_ONE_MINUTE_MS, THRESHOLD_LOW);
+        parseData();
+
+        assertThat(mDataParser.isDeviceHeavilyUsed()).isTrue();
+    }
+
+    @Test
+    public void testDataParser_thresholdHigh_notHeavilyUsed() {
+        mDataParser = new HighUsageDataParser(PERIOD_ONE_MINUTE_MS, THRESHOLD_HIGH);
+        parseData();
+
+        assertThat(mDataParser.isDeviceHeavilyUsed()).isFalse();
+    }
+
+    private void parseData() {
+        mDataParser.onParsingStarted(0, END_TIME_MS);
+        mDataParser.onDataPoint(0, mFirstItem);
+        mDataParser.onDataPoint(PERIOD_ONE_MINUTE_MS, mSecondItem);
+        mDataParser.onDataPoint(END_TIME_MS, mThirdItem);
+
+        mDataParser.onParsingDone();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java
index 2a71991..8df7c56 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/HighUsageDetectorTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
@@ -31,6 +33,7 @@
 import com.android.settings.fuelgauge.BatteryInfo;
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
+import com.android.settings.fuelgauge.batterytip.HighUsageDataParser;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.Before;
@@ -55,6 +58,8 @@
     private BatteryUtils mBatteryUtils;
     @Mock
     private BatterySipper mBatterySipper;
+    @Mock
+    private HighUsageDataParser mDataParser;
 
     private BatteryTipPolicy mPolicy;
     private HighUsageDetector mHighUsageDetector;
@@ -66,8 +71,10 @@
 
         mContext = RuntimeEnvironment.application;
         mPolicy = spy(new BatteryTipPolicy(mContext));
-        mHighUsageDetector = new HighUsageDetector(mContext, mPolicy, mBatteryStatsHelper);
+        mHighUsageDetector = spy(new HighUsageDetector(mContext, mPolicy, mBatteryStatsHelper));
         mHighUsageDetector.mBatteryUtils = mBatteryUtils;
+        mHighUsageDetector.mDataParser = mDataParser;
+        doNothing().when(mHighUsageDetector).parseBatteryData();
 
         mUsageList = new ArrayList<>();
         mUsageList.add(mBatterySipper);
@@ -82,8 +89,7 @@
 
     @Test
     public void testDetect_containsHighUsageApp_tipVisible() {
-        doReturn(2 * DateUtils.HOUR_IN_MILLIS).when(mBatteryUtils).calculateScreenUsageTime(
-                mBatteryStatsHelper);
+        doReturn(true).when(mDataParser).isDeviceHeavilyUsed();
         doReturn(mUsageList).when(mBatteryStatsHelper).getUsageList();
         doReturn(DateUtils.HOUR_IN_MILLIS).when(mBatteryUtils).getProcessTimeMs(
                 BatteryUtils.StatusType.FOREGROUND, mBatterySipper.uidObj,
diff --git a/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java b/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java
index f84f9a2..d610363 100644
--- a/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java
+++ b/tests/robotests/src/com/android/settings/search/SearchIndexProviderCodeInspector.java
@@ -121,7 +121,8 @@
                 continue;
             }
             // Must be in SearchProviderRegistry
-            if (!SearchIndexableResources.providerValues().contains(clazz)) {
+            SearchFeatureProvider provider = new SearchFeatureProviderImpl();
+            if (!provider.getSearchIndexableResources().getProviderValues().contains(clazz)) {
                 if (!notInSearchIndexableRegistryGrandfatherList.remove(className)) {
                     notInSearchProviderRegistry.add(className);
                 }
diff --git a/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java b/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java
index eedb324..72dd94c 100644
--- a/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchIndexableResourcesTest.java
@@ -21,12 +21,14 @@
 
 import static junit.framework.Assert.fail;
 
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 
 import android.database.Cursor;
 import android.text.TextUtils;
 
 import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.wifi.WifiSettings;
 
@@ -36,49 +38,56 @@
 import org.junit.runner.RunWith;
 import org.robolectric.annotation.Config;
 
-import java.util.HashSet;
-import java.util.Set;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SearchIndexableResourcesTest {
 
-    Set<Class> sProviderClassCopy;
+    SearchFeatureProviderImpl mSearchProvider;
+    private FakeFeatureFactory mFakeFeatureFactory;
 
     @Before
     public void setUp() {
-        sProviderClassCopy = new HashSet<>(SearchIndexableResources.sProviders);
+        mSearchProvider = new SearchFeatureProviderImpl();
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.searchFeatureProvider = mSearchProvider;
     }
 
     @After
     public void cleanUp() {
-        SearchIndexableResources.sProviders.clear();
-        SearchIndexableResources.sProviders.addAll(sProviderClassCopy);
+        mFakeFeatureFactory.searchFeatureProvider = mock(
+                SearchFeatureProvider.class);
     }
 
     @Test
     public void testAddIndex() {
         final Class stringClass = java.lang.String.class;
         // Confirms that String.class isn't contained in SearchIndexableResources.
-        assertThat(SearchIndexableResources.sProviders).doesNotContain(stringClass);
-        final int beforeCount = SearchIndexableResources.providerValues().size();
+        assertThat(mSearchProvider.getSearchIndexableResources().getProviderValues())
+                .doesNotContain(stringClass);
+        final int beforeCount =
+                mSearchProvider.getSearchIndexableResources().getProviderValues().size();
 
-        SearchIndexableResources.addIndex(java.lang.String.class);
+        ( (SearchIndexableResourcesImpl) mSearchProvider.getSearchIndexableResources())
+                .addIndex(java.lang.String.class);
 
-        assertThat(SearchIndexableResources.sProviders).contains(stringClass);
-        final int afterCount = SearchIndexableResources.providerValues().size();
+        assertThat(mSearchProvider.getSearchIndexableResources().getProviderValues())
+                .contains(stringClass);
+        final int afterCount =
+                mSearchProvider.getSearchIndexableResources().getProviderValues().size();
         assertThat(afterCount).isEqualTo(beforeCount + 1);
     }
 
     @Test
     public void testIndexHasWifiSettings() {
-        assertThat(sProviderClassCopy).contains(WifiSettings.class);
+        assertThat(mSearchProvider.getSearchIndexableResources().getProviderValues())
+                .contains(WifiSettings.class);
     }
 
     @Test
     public void testNonIndexableKeys_GetsKeyFromProvider() {
-        SearchIndexableResources.sProviders.clear();
-        SearchIndexableResources.addIndex(FakeIndexProvider.class);
+        mSearchProvider.getSearchIndexableResources().getProviderValues().clear();
+        ( (SearchIndexableResourcesImpl) mSearchProvider.getSearchIndexableResources())
+                .addIndex(FakeIndexProvider.class);
 
         SettingsSearchIndexablesProvider provider = spy(new SettingsSearchIndexablesProvider());
 
@@ -97,7 +106,7 @@
 
     @Test
     public void testAllClassNamesHaveProviders() {
-        for (Class clazz: sProviderClassCopy) {
+        for (Class clazz: mSearchProvider.getSearchIndexableResources().getProviderValues()) {
             if(DatabaseIndexingUtils.getSearchIndexProvider(clazz) == null) {
                 fail(clazz.getName() + "is not an index provider");
             }
diff --git a/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java b/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
index efeaed7..cca2794 100644
--- a/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
+++ b/tests/robotests/src/com/android/settings/search/SettingsSearchIndexablesProviderTest.java
@@ -2,6 +2,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 
 import android.Manifest;
@@ -14,6 +15,7 @@
 import com.android.settings.R;
 import com.android.settings.TestConfig;
 import com.android.settings.search.indexing.FakeSettingsFragment;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.After;
@@ -23,9 +25,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import java.util.HashSet;
-import java.util.Set;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SettingsSearchIndexablesProviderTest {
@@ -33,8 +32,8 @@
     private final String BASE_AUTHORITY = "com.android.settings";
 
     private SettingsSearchIndexablesProvider mProvider;
-
-    Set<Class> sProviderClasses;
+    private SearchFeatureProvider mFeatureProvider;
+    private FakeFeatureFactory mFakeFeatureFactory;
     Context mContext;
 
     @Before
@@ -49,15 +48,18 @@
         info.readPermission = Manifest.permission.READ_SEARCH_INDEXABLES;
         mProvider.attachInfo(mContext, info);
 
-        sProviderClasses = new HashSet<>(SearchIndexableResources.sProviders);
-        SearchIndexableResources.sProviders.clear();
-        SearchIndexableResources.sProviders.add(FakeSettingsFragment.class);
+        mFeatureProvider = new SearchFeatureProviderImpl();
+        mFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        mFeatureProvider.getSearchIndexableResources().getProviderValues()
+                .add(FakeSettingsFragment.class);
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.searchFeatureProvider = mFeatureProvider;
     }
 
     @After
     public void cleanUp() {
-        SearchIndexableResources.sProviders.clear();
-        SearchIndexableResources.sProviders.addAll(sProviderClasses);
+        mFakeFeatureFactory.searchFeatureProvider = mock(
+                SearchFeatureProvider.class);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
index efd1cc5..f5d5ff0 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
@@ -19,6 +19,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.mock;
+
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
@@ -26,8 +28,9 @@
 
 import com.android.settings.TestConfig;
 import com.android.settings.search.FakeIndexProvider;
-import com.android.settings.search.SearchIndexableResources;
-import com.android.settings.testutils.DatabaseTestUtils;
+import com.android.settings.search.SearchFeatureProvider;
+import com.android.settings.search.SearchFeatureProviderImpl;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.After;
@@ -37,9 +40,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import java.util.HashSet;
-import java.util.Set;
-
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SliceBroadcastReceiverTest {
@@ -54,30 +54,30 @@
     private Context mContext;
     private SQLiteDatabase mDb;
     private SliceBroadcastReceiver mReceiver;
-
-    private Set<Class> mProviderClassesCopy;
+    private SearchFeatureProvider mSearchFeatureProvider;
+    private FakeFeatureFactory mFakeFeatureFactory;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
         mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
         mReceiver = new SliceBroadcastReceiver();
-        mProviderClassesCopy = new HashSet<>(SearchIndexableResources.providerValues());
         SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext);
         helper.setIndexedState();
+        mSearchFeatureProvider = new SearchFeatureProviderImpl();
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.searchFeatureProvider = mSearchFeatureProvider;
     }
 
     @After
     public void cleanUp() {
-        DatabaseTestUtils.clearDb(mContext);
-        SearchIndexableResources.providerValues().clear();
-        SearchIndexableResources.providerValues().addAll(mProviderClassesCopy);
+        mFakeFeatureFactory.searchFeatureProvider = mock(SearchFeatureProvider.class);
     }
 
     @Test
     public void testOnReceive_toggleChanged() {
         String key = "key";
-        SearchIndexableResources.providerValues().clear();
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
         insertSpecialCase(key);
         // Turn on toggle setting
         FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
index b5c0b5f..1d0ac41 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
@@ -18,11 +18,15 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.mock;
+
 import android.content.Context;
 
 import com.android.settings.TestConfig;
 import com.android.settings.search.FakeIndexProvider;
-import com.android.settings.search.SearchIndexableResources;
+import com.android.settings.search.SearchFeatureProvider;
+import com.android.settings.search.SearchFeatureProviderImpl;
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.After;
@@ -32,9 +36,7 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -49,28 +51,31 @@
 
     Context mContext;
 
-    private Set<Class> mProviderClassesCopy;
-
     SliceDataConverter mSliceDataConverter;
+    SearchFeatureProvider mSearchFeatureProvider;
+    private FakeFeatureFactory mFakeFeatureFactory;
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
-        mProviderClassesCopy = new HashSet<>(SearchIndexableResources.providerValues());
         mSliceDataConverter = new SliceDataConverter(mContext);
+        mSearchFeatureProvider = new SearchFeatureProviderImpl();
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+        mFakeFeatureFactory.searchFeatureProvider = mSearchFeatureProvider;
     }
 
     @After
     public void cleanUp() {
-        SearchIndexableResources.providerValues().clear();
-        SearchIndexableResources.providerValues().addAll(mProviderClassesCopy);
+        mFakeFeatureFactory.searchFeatureProvider = mock(
+                SearchFeatureProvider.class);
     }
 
     @Test
     @Config(qualifiers = "mcc999")
     public void testFakeProvider_convertsFakeData() {
-        SearchIndexableResources.providerValues().clear();
-        SearchIndexableResources.providerValues().add(FakeIndexProvider.class);
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues()
+                .add(FakeIndexProvider.class);
 
         List<SliceData> sliceDataList = mSliceDataConverter.getSliceData();
 
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index b4592b8..3325332 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -55,7 +55,6 @@
     public final LocaleFeatureProvider localeFeatureProvider;
     public final ApplicationFeatureProvider applicationFeatureProvider;
     public final EnterprisePrivacyFeatureProvider enterprisePrivacyFeatureProvider;
-    public final SearchFeatureProvider searchFeatureProvider;
     public final SurveyFeatureProvider surveyFeatureProvider;
     public final SecurityFeatureProvider securityFeatureProvider;
     public final SuggestionFeatureProvider suggestionsFeatureProvider;
@@ -65,6 +64,7 @@
     public final DataPlanFeatureProvider dataPlanFeatureProvider;
     public final SmsMirroringFeatureProvider smsMirroringFeatureProvider;
     public final SlicesFeatureProvider slicesFeatureProvider;
+    public SearchFeatureProvider searchFeatureProvider;
 
     /**
      * Call this in {@code @Before} method of the test class to use fake factory.
diff --git a/tests/robotests/src/com/android/settings/TetherServiceTest.java b/tests/robotests/src/com/android/settings/wifi/tether/TetherServiceTest.java
similarity index 72%
rename from tests/robotests/src/com/android/settings/TetherServiceTest.java
rename to tests/robotests/src/com/android/settings/wifi/tether/TetherServiceTest.java
index 0275c15..583bd52 100644
--- a/tests/robotests/src/com/android/settings/TetherServiceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/TetherServiceTest.java
@@ -13,17 +13,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.settings;
+package com.android.settings.wifi.tether;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.net.wifi.WifiManager;
 
+import com.android.settings.TestConfig;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import java.util.ArrayList;
@@ -87,4 +93,22 @@
         mService.cancelAlarmIfNecessary();
         verify(mContext).unregisterReceiver(any(HotspotOffReceiver.class));
     }
+
+    @Test
+    public void onDestroy_shouldUnregisterReceiver() {
+        final ArrayList<Integer> tethers = new ArrayList<>();
+        ReflectionHelpers.setField(mService, "mCurrentTethers", tethers);
+        ReflectionHelpers.setField(mService, "mBase", mContext);
+        final SharedPreferences prefs = mock(SharedPreferences .class);
+        final SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);
+        when(mContext.getSharedPreferences(anyString(), anyInt())).thenReturn(prefs);
+        when(prefs.edit()).thenReturn(editor);
+        when(editor.putString(anyString(), anyString())).thenReturn(editor);
+        final HotspotOffReceiver hotspotOffReceiver = mock(HotspotOffReceiver.class);
+        mService.setHotspotOffReceiver(hotspotOffReceiver);
+
+        mService.onDestroy();
+
+        verify(hotspotOffReceiver).unregister();
+    }
 }
diff --git a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
index 86e8dc1..b16c700 100644
--- a/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
+++ b/tests/unit/src/com/android/settings/core/PreferenceControllerContractTest.java
@@ -26,6 +26,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.util.ArraySet;
 
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableResources;
@@ -54,7 +55,10 @@
     public void controllersInSearchShouldImplementPreferenceControllerMixin() {
         final Set<String> errorClasses = new ArraySet<>();
 
-        for (Class clazz : SearchIndexableResources.providerValues()) {
+        final SearchIndexableResources resources =
+                FeatureFactory.getFactory(mContext).getSearchFeatureProvider()
+                        .getSearchIndexableResources();
+        for (Class<?> clazz : resources.getProviderValues()) {
 
             final Indexable.SearchIndexProvider provider =
                     DatabaseIndexingUtils.getSearchIndexProvider(clazz);
diff --git a/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java b/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java
index 36865a4..8fe2358 100644
--- a/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java
+++ b/tests/unit/src/com/android/settings/core/UniquePreferenceTest.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 import android.util.Xml;
 
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
@@ -100,7 +101,10 @@
         final Set<String> uniqueKeys = new HashSet<>();
         final Set<String> nullKeyClasses = new HashSet<>();
         final Set<String> duplicatedKeys = new HashSet<>();
-        for (Class<?> clazz : SearchIndexableResources.providerValues()) {
+        final SearchIndexableResources resources =
+                FeatureFactory.getFactory(mContext).getSearchFeatureProvider()
+                        .getSearchIndexableResources();
+        for (Class<?> clazz : resources.getProviderValues()) {
             verifyPreferenceKeys(uniqueKeys, duplicatedKeys, nullKeyClasses, clazz);
         }
 
diff --git a/tests/unit/src/com/android/settings/core/UserRestrictionTest.java b/tests/unit/src/com/android/settings/core/UserRestrictionTest.java
index f37c30b..6d6f06c 100644
--- a/tests/unit/src/com/android/settings/core/UserRestrictionTest.java
+++ b/tests/unit/src/com/android/settings/core/UserRestrictionTest.java
@@ -32,6 +32,7 @@
 import android.util.Log;
 import android.util.Xml;
 
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableResources;
@@ -65,7 +66,8 @@
             UserManager.DISALLOW_CONFIG_VPN,
             UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
             UserManager.DISALLOW_AIRPLANE_MODE,
-            UserManager.DISALLOW_CONFIG_BRIGHTNESS
+            UserManager.DISALLOW_CONFIG_BRIGHTNESS,
+            UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT
     );
 
     @Before
@@ -79,7 +81,10 @@
     @Test
     public void userRestrictionAttributeShouldBeValid()
             throws IOException, XmlPullParserException, Resources.NotFoundException {
-        for (Class<?> clazz : SearchIndexableResources.providerValues()) {
+        final SearchIndexableResources resources =
+                FeatureFactory.getFactory(mContext).getSearchFeatureProvider()
+                        .getSearchIndexableResources();
+        for (Class<?> clazz : resources.getProviderValues()) {
             verifyUserRestriction(clazz);
         }
     }
diff --git a/tests/unit/src/com/android/settings/TetherServiceTest.java b/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
similarity index 98%
rename from tests/unit/src/com/android/settings/TetherServiceTest.java
rename to tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
index 899ea7a..7bf5798 100644
--- a/tests/unit/src/com/android/settings/TetherServiceTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settings;
+package com.android.settings.wifi.tether;
 
 import static org.junit.Assert.*;
 import static org.mockito.Matchers.*;
@@ -49,17 +49,13 @@
 import android.content.SharedPreferences.Editor;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
-import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.ResultReceiver;
 import android.os.SystemClock;
 import android.test.ServiceTestCase;
-import android.test.mock.MockResources;
 import android.util.Log;
 
-import com.android.settings.TetherService;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;