Merge "Bluetooth: Add pairing initiator extra"
diff --git a/res/layout/apn_preference_layout.xml b/res/layout/apn_preference_layout.xml
index fa98d88..4d98443 100644
--- a/res/layout/apn_preference_layout.xml
+++ b/res/layout/apn_preference_layout.xml
@@ -4,9 +4,9 @@
      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.
@@ -21,6 +21,7 @@
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:minHeight="?android:attr/listPreferredItemHeight"
+    android:focusable="false"
     android:gravity="center_vertical">
 
     <RelativeLayout
@@ -30,13 +31,14 @@
         android:gravity="center_vertical"
         android:layout_weight="1"
         android:focusable="true"
+        android:clickable="true"
         android:background="?android:attr/selectableItemBackground">
 
         <TextView
             android:id="@android:id/title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:focusable="true"
+            android:focusable="false"
             android:singleLine="true"
             android:textAppearance="?android:attr/textAppearanceListItem" />
 
@@ -48,6 +50,7 @@
             android:layout_alignStart="@android:id/title"
             android:textAppearance="?android:attr/textAppearanceListItemSecondary"
             android:textColor="?android:attr/textColorSecondary"
+            android:focusable="false"
             android:maxLines="2" />
 
     </RelativeLayout>
@@ -59,6 +62,7 @@
         android:layout_marginStart="8dip"
         android:layout_marginEnd="8dip"
         android:layout_gravity="center_vertical"
+        android:focusable="true"
         android:clickable="true" />
 
 </LinearLayout>
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index 5dd53c0..326fee8 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -30,21 +30,20 @@
         <LinearLayout
             android:id="@+id/panel_header"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
+            android:layout_height="94dp"
             android:gravity="start|center_vertical"
             android:orientation="horizontal"
             android:visibility="gone">
 
             <LinearLayout
-                android:layout_width="36dp"
-                android:layout_height="36dp"
-                android:gravity="center_vertical|center_horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
                 android:orientation="horizontal"
                 android:layout_marginStart="16dp">
                 <ImageView
                     android:id="@+id/title_icon"
-                    android:layout_height="wrap_content"
-                    android:layout_width="wrap_content"/>
+                    android:layout_width="@dimen/output_switcher_panel_icon_size"
+                    android:layout_height="@dimen/output_switcher_panel_icon_size"/>
             </LinearLayout>
 
             <LinearLayout
@@ -52,10 +51,7 @@
                 android:layout_height="wrap_content"
                 android:layout_marginStart="16dp"
                 android:layout_marginEnd="16dp"
-                android:gravity="center_vertical"
-                android:orientation="vertical"
-                android:paddingBottom="9dp"
-                android:paddingTop="9dp">
+                android:orientation="vertical">
                 <TextView
                     android:id="@+id/header_title"
                     android:layout_width="wrap_content"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a9ce5c3..abd45af 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -422,7 +422,9 @@
     <dimen name="list_preferred_item_padding">16dp</dimen>
 
     <!-- Output switcher panel related dimensions -->
-    <dimen name="output_switcher_slice_padding_top">12dp</dimen>
+    <dimen name="output_switcher_slice_padding_top">11dp</dimen>
+    <dimen name="output_switcher_slice_max_height">506dp</dimen>
+    <dimen name="output_switcher_panel_icon_size">52dp</dimen>
 
     <!-- Text padding for EmptyTextSettings -->
     <dimen name="empty_text_padding">24dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6f2940e..0cb8e85 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2752,6 +2752,10 @@
     <string name="peak_refresh_rate_title">Smooth Display</string>
     <!-- Display settings screen, peak refresh rate settings summary [CHAR LIMIT=NONE] -->
     <string name="peak_refresh_rate_summary">Automatically raises the refresh rate from 60 to 90 Hz for some content. Increases battery usage.</string>
+    <!-- Display developer settings: Force to the highest refresh rate [CHAR LIMIT=NONE] -->
+    <string name="force_high_refresh_rate_toggle">Smooth Display</string>
+    <!-- Display developer settings: Force to the highest refresh rate description [CHAR LIMIT=NONE]-->
+    <string name="force_high_refresh_rate_desc">Highest refresh rate for improved touch responsiveness &amp; animation quality. Increases battery usage.</string>
     <!-- Display settings screen, setting option name to enable adaptive sleep [CHAR LIMIT=30] -->
     <string name="adaptive_sleep_title">Screen attention</string>
     <!-- Setting option summary when adaptive sleep is on [CHAR LIMIT=NONE] -->
@@ -7278,7 +7282,7 @@
     <!-- Call Manager settings summary.  [CHAR LIMIT=50] -->
     <string name="call_manager_summary"><xliff:g id="app">%1$s</xliff:g></string>
     <!-- Cell Broadcast settings title.  [CHAR LIMIT=50] -->
-    <string name="cell_broadcast_settings">Emergency alerts</string>
+    <string name="cell_broadcast_settings">Wireless emergency alerts</string>
     <!-- Network operators settings title.  [CHAR LIMIT=50] -->
     <string name="network_operators_settings">Network operators</string>
     <!-- Access point names title.  [CHAR LIMIT=50] -->
@@ -11836,6 +11840,8 @@
     <string name="network_connection_errorstate_dialog_message">Something came up. The application has cancelled the request to choose a device.</string>
     <!-- Toast message when connection is successful [CHAR LIMIT=30] -->
     <string name="network_connection_connect_successful">Connection successful</string>
+    <!-- Toast message when connection is failure [CHAR LIMIT=30] -->
+    <string name="network_connection_connect_failure">Connection failed</string>
     <!-- Neutral button for Network connection request Dialog [CHAR LIMIT=30] -->
     <string name="network_connection_request_dialog_showall">Show all</string>
     <!-- Message for Network connection searching progress Dialog. Searching for wifi ap. [CHAR LIMIT=40] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index bf89a23..12b06b0 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -564,16 +564,17 @@
     </style>
 
     <style name="SliceRow.Slider">
-        <!-- 10dp start padding for the start icon -->
-        <item name="titleItemStartPadding">10dp</item>
+        <!-- 4dp start padding for the start icon -->
+        <item name="titleItemStartPadding">4dp</item>
 
         <!-- Padding between content and the start icon is 0dp -->
         <item name="contentStartPadding">0dp</item>
+        <item name="contentEndPadding">36dp</item>
 
         <!-- 0dp start padding for the end item -->
         <item name="endItemStartPadding">0dp</item>
-        <!-- 24dp end padding for the end item -->
-        <item name="endItemEndPadding">24dp</item>
+        <!-- 8dp end padding for the end item -->
+        <item name="endItemEndPadding">8dp</item>
 
         <!-- Align text with slider -->
         <item name="titleStartPadding">11dp</item>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index e860589..746a51c 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -256,6 +256,11 @@
             android:title="@string/overlay_settings_title"
             android:summary="@string/overlay_settings_summary" />
 
+        <SwitchPreference
+            android:key="pref_key_peak_refresh_rate"
+            android:title="@string/force_high_refresh_rate_toggle"
+            android:summary="@string/force_high_refresh_rate_desc" />
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 5e5fab3..ea41dc2 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -142,7 +142,7 @@
         android:order="45"
         android:title="@string/status_wifi_mac_address"
         android:summary="@string/view_saved_network"
-        android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings"
+        android:fragment="com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2"
         settings:enableCopying="false"/>
 
     <!-- Factory Wi-Fi MAC address -->
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 3cded6a..d095e37 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -54,6 +54,7 @@
 import com.android.settings.Utils;
 import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState.Callbacks;
 import com.android.settingslib.applications.StorageStatsSource;
 import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
@@ -317,7 +318,7 @@
                     .setButton1OnClickListener(v -> handleClearDataClick());
         }
 
-        if (mAppsControlDisallowedBySystem) {
+        if (mAppsControlDisallowedBySystem || AppUtils.isMainlineModule(mPm, mPackageName)) {
             mButtonsPref.setButton1Enabled(false);
         }
     }
@@ -575,7 +576,7 @@
                         .setButton2OnClickListener(v -> handleClearCacheClick());
             }
         }
-        if (mAppsControlDisallowedBySystem) {
+        if (mAppsControlDisallowedBySystem || AppUtils.isMainlineModule(mPm, mPackageName)) {
             mButtonsPref.setButton1Enabled(false).setButton2Enabled(false);
         }
     }
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index 147c412..36ad2ce 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -744,7 +744,9 @@
     }
 
     private boolean isSystemModule() {
-        return mAppEntry != null && AppUtils.isSystemModule(mContext, mAppEntry.info.packageName);
+        return mAppEntry != null
+                && (AppUtils.isSystemModule(mContext, mAppEntry.info.packageName)
+                || AppUtils.isMainlineModule(mPm, mAppEntry.info.packageName));
     }
 
     /**
diff --git a/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceController.java b/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceController.java
index 2e11953..5e99e8b 100644
--- a/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceController.java
@@ -43,7 +43,7 @@
             return DISABLED_FOR_USER;
         }
 
-        if (AppUtils.isMainlineModule(mContext, mPackageName)) {
+        if (AppUtils.isMainlineModule(mContext.getPackageManager(), mPackageName)) {
             return DISABLED_FOR_USER;
         }
 
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 9406c89..945970e 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -459,6 +459,7 @@
         controllers.add(new SelectDebugAppPreferenceController(context, fragment));
         controllers.add(new WaitForDebuggerPreferenceController(context));
         controllers.add(new EnableGpuDebugLayersPreferenceController(context));
+        controllers.add(new ForcePeakRefreshRatePreferenceController(context));
         controllers.add(new EnableVerboseVendorLoggingPreferenceController(context));
         controllers.add(new VerifyAppsOverUsbPreferenceController(context));
         controllers.add(new ArtVerifierPreferenceController(context));
diff --git a/src/com/android/settings/development/ForcePeakRefreshRatePreferenceController.java b/src/com/android/settings/development/ForcePeakRefreshRatePreferenceController.java
new file mode 100644
index 0000000..78352d3
--- /dev/null
+++ b/src/com/android/settings/development/ForcePeakRefreshRatePreferenceController.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Display;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+public class ForcePeakRefreshRatePreferenceController extends DeveloperOptionsPreferenceController
+        implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+    @VisibleForTesting
+    static float DEFAULT_REFRESH_RATE = 60f;
+
+    @VisibleForTesting
+    static float NO_CONFIG = 0f;
+
+    @VisibleForTesting
+    float mPeakRefreshRate;
+
+    private static final String TAG = "ForcePeakRefreshRateCtr";
+    private static final String PREFERENCE_KEY = "pref_key_peak_refresh_rate";
+
+    public ForcePeakRefreshRatePreferenceController(Context context) {
+        super(context);
+
+        final DisplayManager dm = context.getSystemService(DisplayManager.class);
+        final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+
+        if (display == null) {
+            Log.w(TAG, "No valid default display device");
+            mPeakRefreshRate = DEFAULT_REFRESH_RATE;
+        } else {
+            mPeakRefreshRate = findPeakRefreshRate(display.getSupportedModes());
+        }
+
+        Log.d(TAG, "DEFAULT_REFRESH_RATE : " + DEFAULT_REFRESH_RATE
+            + " mPeakRefreshRate : " + mPeakRefreshRate);
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return PREFERENCE_KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        final boolean isEnabled = (Boolean) newValue;
+        forcePeakRefreshRate(isEnabled);
+
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        ((SwitchPreference) mPreference).setChecked(isForcePeakRefreshRateEnabled());
+    }
+
+    @Override
+    public boolean isAvailable() {
+        if (mContext.getResources().getBoolean(R.bool.config_show_smooth_display)) {
+            return mPeakRefreshRate > DEFAULT_REFRESH_RATE;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        Settings.System.putFloat(mContext.getContentResolver(),
+            Settings.System.MIN_REFRESH_RATE, NO_CONFIG);
+
+        ((SwitchPreference) mPreference).setChecked(false);
+    }
+
+    @VisibleForTesting
+    void forcePeakRefreshRate(boolean enable) {
+        final float peakRefreshRate = enable ? mPeakRefreshRate : NO_CONFIG;
+        Settings.System.putFloat(mContext.getContentResolver(),
+            Settings.System.MIN_REFRESH_RATE, peakRefreshRate);
+    }
+
+    boolean isForcePeakRefreshRateEnabled() {
+        final float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
+            Settings.System.MIN_REFRESH_RATE, NO_CONFIG);
+
+        return peakRefreshRate >= mPeakRefreshRate;
+    }
+
+    private float findPeakRefreshRate(Display.Mode[] modes) {
+        float peakRefreshRate = DEFAULT_REFRESH_RATE;
+        for (Display.Mode mode : modes) {
+            if (Math.round(mode.getRefreshRate()) > DEFAULT_REFRESH_RATE) {
+                peakRefreshRate = mode.getRefreshRate();
+            }
+        }
+
+        return peakRefreshRate;
+    }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index c0527c9..ebfaca9 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -37,6 +37,7 @@
 
 import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
+import com.android.settings.homepage.contextualcards.slices.BluetoothUpdateWorker;
 import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.wifi.slice.ContextualWifiScanWorker;
@@ -67,6 +68,7 @@
         final Context context = getContext();
         if (savedInstanceState == null) {
             FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
+            BluetoothUpdateWorker.initLocalBtManager(getContext());
         }
         mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
                 savedInstanceState);
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 8b74313..19de403 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -81,15 +81,12 @@
     private static boolean sBluetoothEnabling;
 
     private final Context mContext;
-    private final AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
-    private final SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
+    private AvailableMediaBluetoothDeviceUpdater mAvailableMediaBtDeviceUpdater;
+    private SavedBluetoothDeviceUpdater mSavedBtDeviceUpdater;
 
     public BluetoothDevicesSlice(Context context) {
         mContext = context;
-        mAvailableMediaBtDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(mContext,
-                null /* fragment */, null /* devicePreferenceCallback */);
-        mSavedBtDeviceUpdater = new SavedBluetoothDeviceUpdater(mContext,
-                null /* fragment */, null /* devicePreferenceCallback */);
+        BluetoothUpdateWorker.initLocalBtManager(context);
     }
 
     @Override
@@ -119,16 +116,8 @@
         // Add the header of Bluetooth on
         listBuilder.addRow(getBluetoothOnHeader());
 
-        // Get row builders of Bluetooth devices.
-        final List<ListBuilder.RowBuilder> rows = getBluetoothRowBuilders();
-
-        // Determine the displayable row count.
-        final int displayableCount = Math.min(rows.size(), DEFAULT_EXPANDED_ROW_COUNT);
-
-        // Add device rows up to the count.
-        for (int i = 0; i < displayableCount; i++) {
-            listBuilder.addRow(rows.get(i));
-        }
+        // Add row builders of Bluetooth devices.
+        getBluetoothRowBuilders().forEach(row -> listBuilder.addRow(row));
 
         return listBuilder.build();
     }
@@ -181,19 +170,18 @@
     List<CachedBluetoothDevice> getPairedBluetoothDevices() {
         final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();
 
-        // If Bluetooth is disable, skip to get the Bluetooth devices.
+        // If Bluetooth is disable, skip getting the Bluetooth devices.
         if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
             Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
             return bluetoothDeviceList;
         }
 
-        // Get the Bluetooth devices from LocalBluetoothManager.
-        final LocalBluetoothManager localBtManager =
-                com.android.settings.bluetooth.Utils.getLocalBtManager(mContext);
+        final LocalBluetoothManager localBtManager = BluetoothUpdateWorker.getLocalBtManager();
         if (localBtManager == null) {
-            Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is unsupported.");
+            Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is not ready.");
             return bluetoothDeviceList;
         }
+
         final Collection<CachedBluetoothDevice> cachedDevices =
                 localBtManager.getCachedDeviceManager().getCachedDevicesCopy();
 
@@ -292,8 +280,21 @@
 
     private List<ListBuilder.RowBuilder> getBluetoothRowBuilders() {
         final List<ListBuilder.RowBuilder> bluetoothRows = new ArrayList<>();
+        final List<CachedBluetoothDevice> pairedDevices = getPairedBluetoothDevices();
+        if (pairedDevices.isEmpty()) {
+            return bluetoothRows;
+        }
+
+        // Initialize updaters without being blocked after paired devices is available because
+        // LocalBluetoothManager is ready.
+        lazyInitUpdaters();
+
         // Create row builders based on paired devices.
-        for (CachedBluetoothDevice device : getPairedBluetoothDevices()) {
+        for (CachedBluetoothDevice device : pairedDevices) {
+            if (bluetoothRows.size() >= DEFAULT_EXPANDED_ROW_COUNT) {
+                break;
+            }
+
             String summary = device.getConnectionSummary();
             if (summary == null) {
                 summary = mContext.getString(
@@ -321,6 +322,18 @@
         return bluetoothRows;
     }
 
+    private void lazyInitUpdaters() {
+        if (mAvailableMediaBtDeviceUpdater == null) {
+            mAvailableMediaBtDeviceUpdater = new AvailableMediaBluetoothDeviceUpdater(mContext,
+                    null /* fragment */, null /* devicePreferenceCallback */);
+        }
+
+        if (mSavedBtDeviceUpdater == null) {
+            mSavedBtDeviceUpdater = new SavedBluetoothDeviceUpdater(mContext,
+                    null /* fragment */, null /* devicePreferenceCallback */);
+        }
+    }
+
     @VisibleForTesting
     SliceAction buildPrimaryBluetoothAction(CachedBluetoothDevice bluetoothDevice) {
         final Intent intent = new Intent(getUri().toString())
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BluetoothUpdateWorker.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothUpdateWorker.java
index 1602f56..8f15f2c 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothUpdateWorker.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothUpdateWorker.java
@@ -18,9 +18,14 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Process;
 import android.util.Log;
 
-import com.android.settings.bluetooth.Utils;
+import androidx.annotation.Nullable;
+
 import com.android.settings.slices.SliceBackgroundWorker;
 import com.android.settingslib.bluetooth.BluetoothCallback;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -30,29 +35,46 @@
 
     private static final String TAG = "BluetoothUpdateWorker";
 
-    private final LocalBluetoothManager mLocalBluetoothManager;
+    private static LocalBluetoothManager sLocalBluetoothManager;
+
+    private LoadBtManagerHandler mLoadBtManagerHandler;
 
     public BluetoothUpdateWorker(Context context, Uri uri) {
         super(context, uri);
-        mLocalBluetoothManager = Utils.getLocalBtManager(context);
+        mLoadBtManagerHandler = LoadBtManagerHandler.getInstance(context);
+        if (sLocalBluetoothManager == null) {
+            mLoadBtManagerHandler.startLoadingBtManager(this);
+        }
+    }
+
+    /** Initialize {@link LocalBluetoothManager} in the background */
+    public static void initLocalBtManager(Context context) {
+        if (sLocalBluetoothManager == null) {
+            LoadBtManagerHandler.getInstance(context).startLoadingBtManager();
+        }
+    }
+
+    @Nullable
+    static LocalBluetoothManager getLocalBtManager() {
+        return sLocalBluetoothManager;
     }
 
     @Override
     protected void onSlicePinned() {
-        if (mLocalBluetoothManager == null) {
-            Log.i(TAG, "onSlicePinned() Bluetooth is unsupported.");
+        final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
+        if (localBtManager == null) {
             return;
         }
-        mLocalBluetoothManager.getEventManager().registerCallback(this);
+        localBtManager.getEventManager().registerCallback(this);
     }
 
     @Override
     protected void onSliceUnpinned() {
-        if (mLocalBluetoothManager == null) {
-            Log.i(TAG, "onSliceUnpinned() Bluetooth is unsupported.");
+        final LocalBluetoothManager localBtManager = mLoadBtManagerHandler.getLocalBtManager();
+        if (localBtManager == null) {
             return;
         }
-        mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+        localBtManager.getEventManager().unregisterCallback(this);
     }
 
     @Override
@@ -84,4 +106,59 @@
             int bluetoothProfile) {
         notifySliceChange();
     }
+
+    private static class LoadBtManagerHandler extends Handler {
+
+        private static LoadBtManagerHandler sHandler;
+
+        private final Runnable mLoadBtManagerTask;
+        private final Context mContext;
+        private BluetoothUpdateWorker mWorker;
+
+        private static LoadBtManagerHandler getInstance(Context context) {
+            if (sHandler == null) {
+                final HandlerThread workerThread = new HandlerThread(TAG,
+                        Process.THREAD_PRIORITY_BACKGROUND);
+                workerThread.start();
+                sHandler = new LoadBtManagerHandler(context, workerThread.getLooper());
+            }
+            return sHandler;
+        }
+
+        private LoadBtManagerHandler(Context context, Looper looper) {
+            super(looper);
+            mContext = context;
+            mLoadBtManagerTask = () -> {
+                Log.d(TAG, "LoadBtManagerHandler: start loading...");
+                final long startTime = System.currentTimeMillis();
+                sLocalBluetoothManager = getLocalBtManager();
+                Log.d(TAG, "LoadBtManagerHandler took " + (System.currentTimeMillis() - startTime)
+                        + " ms");
+            };
+        }
+
+        private LocalBluetoothManager getLocalBtManager() {
+            if (sLocalBluetoothManager != null) {
+                return sLocalBluetoothManager;
+            }
+            return LocalBluetoothManager.getInstance(mContext,
+                    (context, btManager) -> {
+                        if (mWorker != null) {
+                            // notify change if the worker is ready
+                            mWorker.notifySliceChange();
+                        }
+                    });
+        }
+
+        private void startLoadingBtManager() {
+            if (!hasCallbacks(mLoadBtManagerTask)) {
+                post(mLoadBtManagerTask);
+            }
+        }
+
+        private void startLoadingBtManager(BluetoothUpdateWorker worker) {
+            mWorker = worker;
+            startLoadingBtManager();
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/network/ApnPreference.java b/src/com/android/settings/network/ApnPreference.java
index 2ec83d1..63e2838 100755
--- a/src/com/android/settings/network/ApnPreference.java
+++ b/src/com/android/settings/network/ApnPreference.java
@@ -27,6 +27,7 @@
 import android.view.View;
 import android.widget.CompoundButton;
 import android.widget.RadioButton;
+import android.widget.RelativeLayout;
 import android.widget.Toast;
 
 import androidx.preference.Preference;
@@ -34,19 +35,32 @@
 
 import com.android.settings.R;
 
-public class ApnPreference extends Preference implements CompoundButton.OnCheckedChangeListener {
+/**
+ * Preference of APN UI entry
+ */
+public class ApnPreference extends Preference implements CompoundButton.OnCheckedChangeListener,
+        View.OnClickListener {
     final static String TAG = "ApnPreference";
 
     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
+    /**
+     * Constructor of Preference
+     */
     public ApnPreference(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
     }
 
+    /**
+     * Constructor of Preference
+     */
     public ApnPreference(Context context, AttributeSet attrs) {
         this(context, attrs, R.attr.apnPreferenceStyle);
     }
 
+    /**
+     * Constructor of Preference
+     */
     public ApnPreference(Context context) {
         this(context, null);
     }
@@ -61,6 +75,9 @@
     public void onBindViewHolder(PreferenceViewHolder view) {
         super.onBindViewHolder(view);
 
+        final RelativeLayout textArea = (RelativeLayout) view.findViewById(R.id.text_layout);
+        textArea.setOnClickListener(this);
+
         final View widget = view.findViewById(R.id.apn_radiobutton);
         if ((widget != null) && widget instanceof RadioButton) {
             final RadioButton rb = (RadioButton) widget;
@@ -111,22 +128,25 @@
     }
 
     @Override
-    protected void onClick() {
+    public void onClick(View layoutView) {
         super.onClick();
         final Context context = getContext();
-        if (context != null) {
-            if (mHideDetails) {
-                Toast.makeText(context, context.getString(
-                        R.string.cannot_change_apn_toast), Toast.LENGTH_LONG).show();
-                return;
-            }
-            final int pos = Integer.parseInt(getKey());
-            final Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
-            final Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
-            editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
-            editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-            context.startActivity(editIntent);
+        final int pos = Integer.parseInt(getKey());
+        if (context == null) {
+            Log.w(TAG, "No context available for pos=" + pos);
+            return;
         }
+
+        if (mHideDetails) {
+            Toast.makeText(context, context.getString(
+                    R.string.cannot_change_apn_toast), Toast.LENGTH_LONG).show();
+            return;
+        }
+        final Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
+        final Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
+        editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
+        editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        context.startActivity(editIntent);
     }
 
     public void setSelectable(boolean selectable) {
diff --git a/src/com/android/settings/network/TetherProvisioningActivity.java b/src/com/android/settings/network/TetherProvisioningActivity.java
index 09efe48..bb61546 100644
--- a/src/com/android/settings/network/TetherProvisioningActivity.java
+++ b/src/com/android/settings/network/TetherProvisioningActivity.java
@@ -16,13 +16,19 @@
 
 package com.android.settings.network;
 
+import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
+import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
+import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
+import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
+import static android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
 import android.app.Activity;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.TetheringConstants;
-import android.net.TetheringManager;
 import android.os.Bundle;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
@@ -52,23 +58,19 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mResultReceiver = (ResultReceiver)getIntent().getParcelableExtra(
-                ConnectivityManager.EXTRA_PROVISION_CALLBACK);
+        mResultReceiver = (ResultReceiver) getIntent().getParcelableExtra(EXTRA_PROVISION_CALLBACK);
 
-        final int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
-                ConnectivityManager.TETHERING_INVALID);
+        final int tetherType = getIntent().getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);
 
-        final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID,
-                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        final int tetherSubId = getIntent().getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
         final int subId = SubscriptionManager.getActiveDataSubscriptionId();
         if (tetherSubId != subId) {
             Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
-            mResultReceiver.send(TetheringManager.TETHER_ERROR_PROVISIONING_FAILED, null);
+            mResultReceiver.send(TETHER_ERROR_PROVISIONING_FAILED, null);
             finish();
             return;
         }
-        String[] provisionApp = getIntent().getStringArrayExtra(
-                TetheringConstants.EXTRA_RUN_PROVISION);
+        String[] provisionApp = getIntent().getStringArrayExtra(EXTRA_RUN_PROVISION);
         if (provisionApp == null || provisionApp.length < 2) {
             final Resources res = Utils.getResourcesForSubId(this, subId);
             provisionApp = res.getStringArray(
@@ -77,8 +79,8 @@
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.setClassName(provisionApp[0], provisionApp[1]);
         intent.putExtra(EXTRA_TETHER_TYPE, tetherType);
-        intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
-        intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, mResultReceiver);
+        intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
+        intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
         if (DEBUG) {
             Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]);
         }
@@ -86,7 +88,7 @@
         if (getPackageManager().queryIntentActivities(intent,
                 PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
             Log.e(TAG, "Provisioning app is configured, but not available.");
-            mResultReceiver.send(TetheringManager.TETHER_ERROR_PROVISIONING_FAILED, null);
+            mResultReceiver.send(TETHER_ERROR_PROVISIONING_FAILED, null);
             finish();
             return;
         }
@@ -99,9 +101,8 @@
         super.onActivityResult(requestCode, resultCode, intent);
         if (requestCode == PROVISION_REQUEST) {
             if (DEBUG) Log.d(TAG, "Got result from app: " + resultCode);
-            int result = resultCode == Activity.RESULT_OK ?
-                    TetheringManager.TETHER_ERROR_NO_ERROR :
-                    TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
+            int result = resultCode == Activity.RESULT_OK
+                    ? TETHER_ERROR_NO_ERROR : TETHER_ERROR_PROVISIONING_FAILED;
             mResultReceiver.send(result, null);
             finish();
         }
diff --git a/src/com/android/settings/network/telephony/CellInfoUtil.java b/src/com/android/settings/network/telephony/CellInfoUtil.java
index 7412428..d7d2b18 100644
--- a/src/com/android/settings/network/telephony/CellInfoUtil.java
+++ b/src/com/android/settings/network/telephony/CellInfoUtil.java
@@ -33,6 +33,9 @@
 import android.text.TextDirectionHeuristics;
 import android.text.TextUtils;
 
+import com.android.internal.telephony.OperatorInfo;
+
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
@@ -99,6 +102,35 @@
         return cellId;
     }
 
+    /**
+     * Creates a CellInfo object from OperatorInfo. GsmCellInfo is used here only because
+     * operatorInfo does not contain technology type while CellInfo is an abstract object that
+     * requires to specify technology type. It doesn't matter which CellInfo type to use here, since
+     * we only want to wrap the operator info and PLMN to a CellInfo object.
+     */
+    public static CellInfo convertOperatorInfoToCellInfo(OperatorInfo operatorInfo) {
+        final String operatorNumeric = operatorInfo.getOperatorNumeric();
+        String mcc = null;
+        String mnc = null;
+        if (operatorNumeric != null && operatorNumeric.matches("^[0-9]{5,6}$")) {
+            mcc = operatorNumeric.substring(0, 3);
+            mnc = operatorNumeric.substring(3);
+        }
+        final CellIdentityGsm cig = new CellIdentityGsm(
+                Integer.MAX_VALUE /* lac */,
+                Integer.MAX_VALUE /* cid */,
+                Integer.MAX_VALUE /* arfcn */,
+                Integer.MAX_VALUE /* bsic */,
+                mcc,
+                mnc,
+                operatorInfo.getOperatorAlphaLong(),
+                operatorInfo.getOperatorAlphaShort(),
+                Collections.emptyList());
+
+        final CellInfoGsm ci = new CellInfoGsm();
+        ci.setCellIdentity(cig);
+        return ci;
+    }
 
     /** Convert a list of cellInfos to readable string without sensitive info. */
     public static String cellInfoListToString(List<CellInfo> cellInfos) {
diff --git a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
index 7173ccc..97894b1 100644
--- a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
+++ b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
@@ -57,6 +57,7 @@
     private List<String> mForbiddenPlmns;
     private int mLevel = LEVEL_NONE;
     private boolean mShow4GForLTE;
+    private boolean mUseNewApi;
 
     public NetworkOperatorPreference(Context context, CellInfo cellinfo,
             List<String> forbiddenPlmns, boolean show4GForLTE) {
@@ -75,6 +76,8 @@
         super(context);
         mForbiddenPlmns = forbiddenPlmns;
         mShow4GForLTE = show4GForLTE;
+        mUseNewApi = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
     }
 
     /**
@@ -215,7 +218,7 @@
     }
 
     private void updateIcon(int level) {
-        if (level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) {
+        if (!mUseNewApi || level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) {
             return;
         }
         final Context context = getContext();
diff --git a/src/com/android/settings/network/telephony/NetworkScanHelper.java b/src/com/android/settings/network/telephony/NetworkScanHelper.java
index fe5b9e1..524a737 100644
--- a/src/com/android/settings/network/telephony/NetworkScanHelper.java
+++ b/src/com/android/settings/network/telephony/NetworkScanHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.network.telephony;
 
+import android.annotation.IntDef;
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.CellInfo;
 import android.telephony.NetworkScan;
@@ -25,9 +26,21 @@
 import android.telephony.TelephonyScanManager;
 import android.util.Log;
 
+import com.android.internal.telephony.CellNetworkScanResult;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CancellationException;
 import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
 
 /**
  * A helper class that builds the common interface and performs the network scan for two different
@@ -70,6 +83,33 @@
         void onError(int errorCode);
     }
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS, NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS})
+    public @interface NetworkQueryType {}
+
+    /**
+     * Performs the network scan using {@link TelephonyManager#getAvailableNetworks()}. The network
+     * scan results won't be returned to the caller until the network scan is completed.
+     *
+     * <p> This is typically used when the modem doesn't support the new network scan api
+     * {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
+     */
+    public static final int NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS = 1;
+
+    /**
+     * Performs the network scan using {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
+     * results will be returned to the caller periodically in a small time window until the network
+     * scan is completed. The complete results should be returned in the last called of
+     * {@link NetworkScanCallback#onResults(List)}.
+     *
+     * <p> This is recommended to be used if modem supports the new network scan api
+     * {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+     */
+    public static final int NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS = 2;
+
     /** The constants below are used in the async network scan. */
     private static final boolean INCREMENTAL_RESULTS = true;
     private static final int SEARCH_PERIODICITY_SEC = 5;
@@ -83,6 +123,9 @@
 
     private NetworkScan mNetworkScanRequester;
 
+    /** Callbacks for sync network scan */
+    private ListenableFuture<List<CellInfo>> mNetworkScanFuture;
+
     public NetworkScanHelper(TelephonyManager tm, NetworkScanCallback callback, Executor executor) {
         mTelephonyManager = tm;
         mNetworkScanCallback = callback;
@@ -139,38 +182,63 @@
     }
 
     /**
-     * Request a network scan.
+     * Performs a network scan for the given type {@code type}.
+     * {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
+     * {@link TelephonyManager#requestNetworkScan(
+     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
      *
-     * Performs the network scan using {@link TelephonyManager#requestNetworkScan(
-     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)} The network scan
-     * results will be returned to the caller periodically in a small time window until the network
-     * scan is completed. The complete results should be returned in the last called of
-     * {@link NetworkScanCallback#onResults(List)}.
+     * @param type used to tell which network scan API should be used.
      */
-    public void startNetworkScan() {
-        if (mNetworkScanRequester != null) {
-            return;
-        }
-        mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
-                createNetworkScanForPreferredAccessNetworks(),
-                mExecutor,
-                mInternalNetworkScanCallback);
-        if (mNetworkScanRequester == null) {
-            onError(NetworkScan.ERROR_RADIO_INTERFACE_ERROR);
+    public void startNetworkScan(@NetworkQueryType int type) {
+        if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
+            mNetworkScanFuture = SettableFuture.create();
+            Futures.addCallback(mNetworkScanFuture, new FutureCallback<List<CellInfo>>() {
+                @Override
+                public void onSuccess(List<CellInfo> result) {
+                    onResults(result);
+                    onComplete();
+                }
+
+                @Override
+                public void onFailure(Throwable t) {
+                    if (t instanceof CancellationException) {
+                        return;
+                    }
+                    int errCode = Integer.parseInt(t.getMessage());
+                    onError(errCode);
+                }
+            }, MoreExecutors.directExecutor());
+            mExecutor.execute(new NetworkScanSyncTask(
+                    mTelephonyManager, (SettableFuture) mNetworkScanFuture));
+        } else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
+            if (mNetworkScanRequester != null) {
+                return;
+            }
+            mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
+                    createNetworkScanForPreferredAccessNetworks(),
+                    mExecutor,
+                    mInternalNetworkScanCallback);
+            if (mNetworkScanRequester == null) {
+                onError(NetworkScan.ERROR_RADIO_INTERFACE_ERROR);
+            }
         }
     }
 
     /**
-     * Stops the network scan.
-     *
-     * Use this method to stop an ongoing scan. When user requests a new scan, a {@link NetworkScan}
-     * object will be returned, and the user can stop the scan by calling this method.
+     * The network scan of type {@link #NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS} can't be stopped,
+     * however, the result of the current network scan won't be returned to the callback after
+     * calling this method.
      */
     public void stopNetworkQuery() {
         if (mNetworkScanRequester != null) {
             mNetworkScanRequester.stopScan();
             mNetworkScanRequester = null;
         }
+
+        if (mNetworkScanFuture != null) {
+            mNetworkScanFuture.cancel(true /* mayInterruptIfRunning */);
+            mNetworkScanFuture = null;
+        }
     }
 
     private void onResults(List<CellInfo> cellInfos) {
@@ -185,6 +253,23 @@
         mNetworkScanCallback.onError(errCode);
     }
 
+    /**
+     * Converts the status code of {@link CellNetworkScanResult} to one of the
+     * {@link NetworkScan.ScanErrorCode}.
+     * @param errCode status code from {@link CellNetworkScanResult}.
+     *
+     * @return one of the scan error code from {@link NetworkScan.ScanErrorCode}.
+     */
+    private static int convertToScanErrorCode(int errCode) {
+        switch (errCode) {
+            case CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE:
+                return NetworkScan.ERROR_RADIO_INTERFACE_ERROR;
+            case CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE:
+            default:
+                return NetworkScan.ERROR_MODEM_ERROR;
+        }
+    }
+
     private final class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback {
         public void onResults(List<CellInfo> results) {
             Log.d(TAG, "Async scan onResults() results = "
@@ -202,4 +287,35 @@
             NetworkScanHelper.this.onError(errCode);
         }
     }
+
+    private static final class NetworkScanSyncTask implements Runnable {
+        private final SettableFuture<List<CellInfo>> mCallback;
+        private final TelephonyManager mTelephonyManager;
+
+        NetworkScanSyncTask(
+                TelephonyManager telephonyManager, SettableFuture<List<CellInfo>> callback) {
+            mTelephonyManager = telephonyManager;
+            mCallback = callback;
+        }
+
+        @Override
+        public void run() {
+            final CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
+            if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
+                final List<CellInfo> cellInfos = result.getOperators()
+                        .stream()
+                        .map(operatorInfo
+                                -> CellInfoUtil.convertOperatorInfoToCellInfo(operatorInfo))
+                        .collect(Collectors.toList());
+                Log.d(TAG, "Sync network scan completed, cellInfos = "
+                        + CellInfoUtil.cellInfoListToString(cellInfos));
+                mCallback.set(cellInfos);
+            } else {
+                final Throwable error = new Throwable(
+                        Integer.toString(convertToScanErrorCode(result.getStatus())));
+                mCallback.setException(error);
+                Log.d(TAG, "Sync network scan error, ex = " + error);
+            }
+        }
+    }
 }
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index 7877063..3f18928 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -93,6 +93,8 @@
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
 
+        mUseNewApi = getContext().getResources().getBoolean(
+                com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
         mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID);
 
         mPreferenceCategory = findPreference(PREF_KEY_NETWORK_OPERATORS);
@@ -464,7 +466,10 @@
         if (mNetworkScanHelper != null) {
             mRequestIdManualNetworkScan = getNewRequestId();
             mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
-            mNetworkScanHelper.startNetworkScan();
+            mNetworkScanHelper.startNetworkScan(
+                    mUseNewApi
+                            ? NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS
+                            : NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
         }
     }
 
diff --git a/src/com/android/settings/notification/RemoteVolumeGroupController.java b/src/com/android/settings/notification/RemoteVolumeGroupController.java
index 4b045e2..6d3c96d 100644
--- a/src/com/android/settings/notification/RemoteVolumeGroupController.java
+++ b/src/com/android/settings/notification/RemoteVolumeGroupController.java
@@ -20,7 +20,6 @@
 import android.content.Intent;
 import android.media.RoutingSessionInfo;
 import android.text.TextUtils;
-import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -136,11 +135,6 @@
 
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
-        final MediaDevice device = mLocalMediaManager.getMediaDeviceById(preference.getKey());
-        if (device == null) {
-            Log.e(TAG, "Unable to find " + preference.getKey() + " to set volume");
-            return false;
-        }
         ThreadUtils.postOnBackgroundThread(() -> {
             mLocalMediaManager.adjustSessionVolume(preference.getKey(), (int) newValue);
         });
@@ -184,6 +178,5 @@
 
     @Override
     public void onSelectedDeviceStateChanged(MediaDevice device, int state) {
-
     }
 }
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index 536dc77..6f5cf90 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -95,6 +95,7 @@
     private ImageView mTitleIcon;
     private TextView mHeaderTitle;
     private TextView mHeaderSubtitle;
+    private int mMaxHeight;
 
     private final Map<Uri, LiveData<Slice>> mSliceLiveData = new LinkedHashMap<>();
 
@@ -105,6 +106,18 @@
         return false;
     };
 
+    private final ViewTreeObserver.OnGlobalLayoutListener mPanelLayoutListener =
+            new ViewTreeObserver.OnGlobalLayoutListener() {
+                @Override
+                public void onGlobalLayout() {
+                    if (mLayoutView.getHeight() > mMaxHeight) {
+                        final ViewGroup.LayoutParams params = mLayoutView.getLayoutParams();
+                        params.height = mMaxHeight;
+                        mLayoutView.setLayoutParams(params);
+                    }
+                }
+            };
+
     private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
             new ViewTreeObserver.OnGlobalLayoutListener() {
                 @Override
@@ -123,6 +136,9 @@
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
         mLayoutView = inflater.inflate(R.layout.panel_layout, container, false);
+        mLayoutView.getViewTreeObserver()
+                .addOnGlobalLayoutListener(mPanelLayoutListener);
+        mMaxHeight = getResources().getDimensionPixelSize(R.dimen.output_switcher_slice_max_height);
         createPanelContent();
         return mLayoutView;
     }
@@ -164,6 +180,9 @@
             activity.finish();
             return;
         }
+        final ViewGroup.LayoutParams params = mLayoutView.getLayoutParams();
+        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+        mLayoutView.setLayoutParams(params);
 
         mPanelSlices = mLayoutView.findViewById(R.id.panel_parent_layout);
         mSeeMoreButton = mLayoutView.findViewById(R.id.see_more);
@@ -220,6 +239,12 @@
             mHeaderSubtitle.setText(mPanel.getSubTitle());
             if (mPanel.getHeaderIconIntent() != null) {
                 mTitleIcon.setOnClickListener(getHeaderIconListener());
+                mTitleIcon.setLayoutParams(new LinearLayout.LayoutParams(
+                        ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+            } else {
+                final int size = getResources().getDimensionPixelSize(
+                        R.dimen.output_switcher_panel_icon_size);
+                mTitleIcon.setLayoutParams(new LinearLayout.LayoutParams(size, size));
             }
         }
         mSeeMoreButton.setOnClickListener(getSeeMoreListener());
@@ -384,6 +409,9 @@
             mPanelClosedKey = PanelClosedKeys.KEY_OTHERS;
         }
 
+        if (mLayoutView != null) {
+            mLayoutView.getViewTreeObserver().removeOnGlobalLayoutListener(mPanelLayoutListener);
+        }
         mMetricsProvider.action(
                 0 /* attribution */,
                 SettingsEnums.PAGE_HIDE,
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 81d5036..04ee1b8 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -821,6 +821,14 @@
         @Override
         public void onDestroy() {
             super.onDestroy();
+            if (mUserPassword != null) {
+                mUserPassword.zeroize();
+            }
+            // Force a garbage collection immediately to remove remnant of user password shards
+            // from memory.
+            System.gc();
+            System.runFinalization();
+            System.gc();
         }
 
         @Override
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index cdc03f9..19cc9c8 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -530,6 +530,19 @@
             }
         }
 
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            if (mCurrentCredential != null) {
+                mCurrentCredential.zeroize();
+            }
+            // Force a garbage collection immediately to remove remnant of user password shards
+            // from memory.
+            System.gc();
+            System.runFinalization();
+            System.gc();
+        }
+
         protected int getStageType() {
             return mForFingerprint ? Stage.TYPE_FINGERPRINT :
                     mForFace ? Stage.TYPE_FACE :
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index ece3da8..27fc9f0 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -617,6 +617,19 @@
             }
         }
 
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            if (mCurrentCredential != null) {
+                mCurrentCredential.zeroize();
+            }
+            // Force a garbage collection immediately to remove remnant of user password shards
+            // from memory.
+            System.gc();
+            System.runFinalization();
+            System.gc();
+        }
+
         protected Intent getRedactionInterstitialIntent(Context context) {
             return RedactionInterstitial.createStartIntent(context, mUserId);
         }
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
index eaea2ea..383ae4f 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
@@ -158,6 +158,16 @@
     }
 
     @Override
+    public void onDestroy() {
+        super.onDestroy();
+        // Force a garbage collection immediately to remove remnant of user password shards
+        // from memory.
+        System.gc();
+        System.runFinalization();
+        System.gc();
+    }
+
+    @Override
     public void finish() {
         super.finish();
         if (getIntent().getBooleanExtra(
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index 6f8dbfd..8aa44e9 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -217,6 +217,17 @@
             }
         }
 
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            mPasswordEntry.setText(null);
+            // Force a garbage collection immediately to remove remnant of user password shards
+            // from memory.
+            System.gc();
+            System.runFinalization();
+            System.gc();
+        }
+
         private int getDefaultHeader() {
             if (mFrp) {
                 return mIsAlpha ? R.string.lockpassword_confirm_your_password_header_frp
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogActivity.java b/src/com/android/settings/wifi/NetworkRequestDialogActivity.java
index fb1b87b..af82645a 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogActivity.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogActivity.java
@@ -217,13 +217,12 @@
 
     @Override
     public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
-        if (mIsSpecifiedSsid) {
-            showSingleSsidRequestDialog(
-                    WifiInfo.sanitizeSsid(mMatchedConfig.SSID), true /* isTryAgain */);
-            return;
+        if (!isFinishing()) {
+            Toast.makeText(this, R.string.network_connection_connect_failure, Toast.LENGTH_SHORT)
+                    .show();
+            setResult(RESULT_OK);
+            finish();
         }
-
-        mDialogFragment.onUserSelectionConnectFailure(wificonfiguration);
     }
 
     // Called when user click "Connect" button. Called by
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogBaseFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogBaseFragment.java
index c17bacd..f2e24ae 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogBaseFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogBaseFragment.java
@@ -21,7 +21,6 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.net.wifi.ScanResult;
-import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 
 import androidx.annotation.NonNull;
@@ -91,7 +90,4 @@
 
     protected void onMatch(List<ScanResult> scanResults) {
     }
-
-    protected void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
-    }
 }
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index edaa4d9..f179df0 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -324,11 +324,6 @@
         }
     }
 
-    @Override
-    public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
-        // Do nothing when selection is failed, let user could try again easily.
-    }
-
     @VisibleForTesting
     final class FilterWifiTracker {
         private final List<String> mAccessPointKeys;
diff --git a/src/com/android/settings/wifi/tether/HotspotOffReceiver.java b/src/com/android/settings/wifi/tether/HotspotOffReceiver.java
deleted file mode 100644
index fcbf888..0000000
--- a/src/com/android/settings/wifi/tether/HotspotOffReceiver.java
+++ /dev/null
@@ -1,55 +0,0 @@
-
-package com.android.settings.wifi.tether;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
-import android.util.Log;
-
-/**
- * This receiver catches when quick settings turns off the hotspot, so we can
- * cancel the alarm in that case.  All other cancels are handled in tethersettings.
- */
-public class HotspotOffReceiver extends BroadcastReceiver {
-
-    private static final String TAG = "HotspotOffReceiver";
-    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private Context mContext;
-    private boolean mRegistered;
-
-    public HotspotOffReceiver(Context context) {
-        mContext = context;
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
-            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-            if (wifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED) {
-                if (DEBUG) Log.d(TAG, "TetherService.cancelRecheckAlarmIfNecessary called");
-                // The hotspot has been turned off, we don't need to recheck tethering.
-                TetherService.cancelRecheckAlarmIfNecessary(
-                        context, ConnectivityManager.TETHERING_WIFI);
-            }
-        }
-    }
-
-    public void register() {
-        if (!mRegistered) {
-            mContext.registerReceiver(this,
-                new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION));
-            mRegistered = true;
-        }
-    }
-
-    public void unregister() {
-        if (mRegistered) {
-            mContext.unregisterReceiver(this);
-            mRegistered = false;
-        }
-    }
-}
diff --git a/src/com/android/settings/wifi/tether/TetherService.java b/src/com/android/settings/wifi/tether/TetherService.java
index e01a246..72ea1a9 100644
--- a/src/com/android/settings/wifi/tether/TetherService.java
+++ b/src/com/android/settings/wifi/tether/TetherService.java
@@ -16,15 +16,24 @@
 
 package com.android.settings.wifi.tether;
 
+import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
+import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
+import static android.net.TetheringConstants.EXTRA_REM_TETHER_TYPE;
+import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
+import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
+import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
+import static android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
 import android.app.Activity;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
 import android.app.Service;
 import android.app.usage.UsageStatsManager;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothPan;
-import android.bluetooth.BluetoothProfile;
-import android.bluetooth.BluetoothProfile.ServiceListener;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -33,10 +42,9 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.net.ConnectivityManager;
+import android.net.TetheringManager;
 import android.os.IBinder;
 import android.os.ResultReceiver;
-import android.os.SystemClock;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -74,7 +82,6 @@
     private TetherServiceWrapper mWrapper;
     private ArrayList<Integer> mCurrentTethers;
     private ArrayMap<Integer, List<ResultReceiver>> mPendingCallbacks;
-    private HotspotOffReceiver mHotspotReceiver;
 
     @Override
     public IBinder onBind(Intent intent) {
@@ -93,18 +100,16 @@
         mCurrentTethers = stringToTethers(prefs.getString(KEY_TETHERS, ""));
         mCurrentTypeIndex = 0;
         mPendingCallbacks = new ArrayMap<>(3);
-        mPendingCallbacks.put(ConnectivityManager.TETHERING_WIFI, new ArrayList<ResultReceiver>());
-        mPendingCallbacks.put(ConnectivityManager.TETHERING_USB, new ArrayList<ResultReceiver>());
-        mPendingCallbacks.put(
-                ConnectivityManager.TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
-        mHotspotReceiver = new HotspotOffReceiver(this);
+        mPendingCallbacks.put(TETHERING_WIFI, new ArrayList<ResultReceiver>());
+        mPendingCallbacks.put(TETHERING_USB, new ArrayList<ResultReceiver>());
+        mPendingCallbacks.put(TETHERING_BLUETOOTH, new ArrayList<ResultReceiver>());
+        mPendingCallbacks.put(TETHERING_ETHERNET, new ArrayList<ResultReceiver>());
     }
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         if (intent.hasExtra(EXTRA_SUBID)) {
-            final int tetherSubId = intent.getIntExtra(EXTRA_SUBID,
-                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+            final int tetherSubId = intent.getIntExtra(EXTRA_SUBID, INVALID_SUBSCRIPTION_ID);
             final int subId = getTetherServiceWrapper().getActiveDataSubscriptionId();
             if (tetherSubId != subId) {
                 Log.e(TAG, "This Provisioning request is outdated, current subId: " + subId);
@@ -114,18 +119,16 @@
                 return START_NOT_STICKY;
             }
         }
-        if (intent.hasExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE)) {
-            int type = intent.getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE,
-                    ConnectivityManager.TETHERING_INVALID);
-            ResultReceiver callback =
-                    intent.getParcelableExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK);
+        if (intent.hasExtra(EXTRA_ADD_TETHER_TYPE)) {
+            int type = intent.getIntExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_INVALID);
+            ResultReceiver callback = intent.getParcelableExtra(EXTRA_PROVISION_CALLBACK);
             if (callback != null) {
                 List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
                 if (callbacksForType != null) {
                     callbacksForType.add(callback);
                 } else {
                     // Invalid tether type. Just ignore this request and report failure.
-                    callback.send(ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE, null);
+                    callback.send(TETHER_ERROR_UNKNOWN_IFACE, null);
                     stopSelf();
                     return START_NOT_STICKY;
                 }
@@ -137,30 +140,20 @@
             }
         }
 
-        if (intent.hasExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE)) {
+        if (intent.hasExtra(EXTRA_REM_TETHER_TYPE)) {
             if (!mInProvisionCheck) {
-                int type = intent.getIntExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE,
-                        ConnectivityManager.TETHERING_INVALID);
+                int type = intent.getIntExtra(EXTRA_REM_TETHER_TYPE, TETHERING_INVALID);
                 int index = mCurrentTethers.indexOf(type);
                 if (DEBUG) Log.d(TAG, "Removing tether " + type + ", index " + index);
                 if (index >= 0) {
                     removeTypeAtIndex(index);
                 }
-                cancelAlarmIfNecessary();
             } else {
-                if (DEBUG) Log.d(TAG, "Don't cancel alarm during provisioning");
+                if (DEBUG) Log.d(TAG, "Don't remove tether type during provisioning");
             }
         }
 
-        // Only set the alarm if we have one tether, meaning the one just added,
-        // to avoid setting it when it was already set previously for another
-        // type.
-        if (intent.getBooleanExtra(ConnectivityManager.EXTRA_SET_ALARM, false)
-                && mCurrentTethers.size() == 1) {
-            scheduleAlarm();
-        }
-
-        if (intent.getBooleanExtra(ConnectivityManager.EXTRA_RUN_PROVISION, false)) {
+        if (intent.getBooleanExtra(EXTRA_RUN_PROVISION, false)) {
             startProvisioning(mCurrentTypeIndex);
         } else if (!mInProvisionCheck) {
             // If we aren't running any provisioning, no reason to stay alive.
@@ -182,16 +175,11 @@
         SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
         prefs.edit().putString(KEY_TETHERS, tethersToString(mCurrentTethers)).commit();
 
-        unregisterReceivers();
+        unregisterReceiver(mReceiver);
         if (DEBUG) Log.d(TAG, "Destroying TetherService");
         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
@@ -202,11 +190,6 @@
         }
     }
 
-    @VisibleForTesting
-    void setHotspotOffReceiver(HotspotOffReceiver receiver) {
-        mHotspotReceiver = receiver;
-    }
-
     private ArrayList<Integer> stringToTethers(String tethersStr) {
         ArrayList<Integer> ret = new ArrayList<Integer>();
         if (TextUtils.isEmpty(tethersStr)) return ret;
@@ -231,32 +214,9 @@
         return buffer.toString();
     }
 
-    private void disableWifiTethering() {
-        ConnectivityManager cm =
-                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
-        cm.stopTethering(ConnectivityManager.TETHERING_WIFI);
-    }
-
-    private void disableUsbTethering() {
-        ConnectivityManager cm =
-                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
-        cm.setUsbTethering(false);
-    }
-
-    private void disableBtTethering() {
-        final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        if (adapter != null) {
-            adapter.getProfileProxy(this, new ServiceListener() {
-                @Override
-                public void onServiceDisconnected(int profile) { }
-
-                @Override
-                public void onServiceConnected(int profile, BluetoothProfile proxy) {
-                    ((BluetoothPan) proxy).setBluetoothTethering(false);
-                    adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
-                }
-            }, BluetoothProfile.PAN);
-        }
+    private void disableTethering(final int tetheringType) {
+        final TetheringManager tm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
+        tm.stopTethering(tetheringType);
     }
 
     private void startProvisioning(int index) {
@@ -279,7 +239,7 @@
         Intent intent = new Intent(provisionAction);
         int type = mCurrentTethers.get(index);
         intent.putExtra(TETHER_CHOICE, type);
-        intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+        intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
         intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
                 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
 
@@ -304,55 +264,13 @@
         }
     }
 
-    @VisibleForTesting
-    void scheduleAlarm() {
-        Intent intent = new Intent(this, TetherService.class);
-        intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
-
-        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
-        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
-        int period = getResourceForActiveDataSubId().getInteger(
-                com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
-        long periodMs = period * MS_PER_HOUR;
-        long firstTime = SystemClock.elapsedRealtime() + periodMs;
-        if (DEBUG) Log.d(TAG, "Scheduling alarm at interval " + periodMs);
-        alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, firstTime, periodMs,
-                pendingIntent);
-        mHotspotReceiver.register();
-    }
-
-    /**
-     * Cancels the recheck alarm only if no tethering is currently active.
-     *
-     * Runs in the background, to get access to bluetooth service that takes time to bind.
-     */
-    public static void cancelRecheckAlarmIfNecessary(final Context context, int type) {
-        Intent intent = new Intent(context, TetherService.class);
-        intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
-        context.startService(intent);
-    }
-
-    @VisibleForTesting
-    void cancelAlarmIfNecessary() {
-        if (mCurrentTethers.size() != 0) {
-            if (DEBUG) Log.d(TAG, "Tethering still active, not cancelling alarm");
-            return;
-        }
-        Intent intent = new Intent(this, TetherService.class);
-        PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
-        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
-        alarmManager.cancel(pendingIntent);
-        if (DEBUG) Log.d(TAG, "Tethering no longer active, canceling recheck");
-        mHotspotReceiver.unregister();
-    }
-
     private void fireCallbacksForType(int type, int result) {
         List<ResultReceiver> callbacksForType = mPendingCallbacks.get(type);
         if (callbacksForType == null) {
             return;
         }
-        int errorCode = result == RESULT_OK ? ConnectivityManager.TETHER_ERROR_NO_ERROR :
-                ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+        int errorCode = result == RESULT_OK ? TETHER_ERROR_NO_ERROR :
+                TETHER_ERROR_PROVISIONING_FAILED;
         for (ResultReceiver callback : callbacksForType) {
           if (DEBUG) Log.d(TAG, "Firing result: " + errorCode + " to callback");
           callback.send(errorCode, null);
@@ -375,19 +293,7 @@
                 int checkType = mCurrentTethers.get(mCurrentTypeIndex);
                 mInProvisionCheck = false;
                 int result = intent.getIntExtra(EXTRA_RESULT, RESULT_DEFAULT);
-                if (result != RESULT_OK) {
-                    switch (checkType) {
-                        case ConnectivityManager.TETHERING_WIFI:
-                            disableWifiTethering();
-                            break;
-                        case ConnectivityManager.TETHERING_BLUETOOTH:
-                            disableBtTethering();
-                            break;
-                        case ConnectivityManager.TETHERING_USB:
-                            disableUsbTethering();
-                            break;
-                    }
-                }
+                if (result != RESULT_OK) disableTethering(checkType);
                 fireCallbacksForType(checkType, result);
 
                 if (++mCurrentTypeIndex >= mCurrentTethers.size()) {
diff --git a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
index 3517702..2027ace 100644
--- a/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppStorageSettingsTest.java
@@ -16,9 +16,9 @@
 
 package com.android.settings.applications;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
@@ -28,6 +28,10 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ModuleInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.view.View;
 import android.widget.Button;
 
@@ -51,6 +55,8 @@
     private AppStorageSettings mSettings;
     private Button mLeftButton;
     private Button mRightButton;
+    @Mock
+    private PackageManager mPackageManager;
 
     @Before
     public void setUp() {
@@ -58,6 +64,8 @@
         mLeftButton = new Button(RuntimeEnvironment.application);
         mRightButton = new Button(RuntimeEnvironment.application);
         mSettings = spy(new AppStorageSettings());
+        mSettings.mPm = mPackageManager;
+        mSettings.mPackageName = "Package";
         mSettings.mSizeController = mSizesController;
         mButtonsPref = createMock();
         mSettings.mButtonsPref = mButtonsPref;
@@ -77,7 +85,9 @@
     }
 
     @Test
-    public void updateUiWithSize_noAppStats_shouldDisableClearButtons() {
+    public void updateUiWithSize_noAppStats_shouldDisableClearButtons()
+            throws PackageManager.NameNotFoundException {
+        mockMainlineModule(mSettings.mPackageName, false /* isMainlineModule */);
         mSettings.updateUiWithSize(null);
 
         verify(mSizesController).updateUi(nullable(Context.class));
@@ -86,12 +96,15 @@
     }
 
     @Test
-    public void updateUiWithSize_hasDataAndCache_shouldEnableClearButtons() {
+    public void updateUiWithSize_hasDataAndCache_shouldEnableClearButtons()
+            throws PackageManager.NameNotFoundException {
         final AppStorageStats stats = mock(AppStorageStats.class);
         when(stats.getCacheBytes()).thenReturn(5000L);
         when(stats.getDataBytes()).thenReturn(10000L);
         doNothing().when(mSettings).handleClearCacheClick();
         doNothing().when(mSettings).handleClearDataClick();
+        mockMainlineModule(mSettings.mPackageName, false /* isMainlineModule */);
+
 
         mSettings.updateUiWithSize(stats);
         verify(mButtonsPref).setButton1Enabled(true);
@@ -105,6 +118,22 @@
         verify(mSettings).handleClearCacheClick();
     }
 
+    @Test
+    public void updateUiWithSize_mainlineModule_shouldDisableClearButtons()
+            throws PackageManager.NameNotFoundException {
+        final AppStorageStats stats = mock(AppStorageStats.class);
+        when(stats.getCacheBytes()).thenReturn(5000L);
+        when(stats.getDataBytes()).thenReturn(10000L);
+        doNothing().when(mSettings).handleClearCacheClick();
+        doNothing().when(mSettings).handleClearDataClick();
+        mockMainlineModule(mSettings.mPackageName, true /* isMainlineModule */);
+
+
+        mSettings.updateUiWithSize(stats);
+        verify(mButtonsPref).setButton1Enabled(false);
+        verify(mButtonsPref).setButton2Enabled(false);
+    }
+
     private ActionButtonsPreference createMock() {
         final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
         when(pref.setButton1Text(anyInt())).thenReturn(pref);
@@ -121,5 +150,23 @@
 
         return pref;
     }
+
+    private void mockMainlineModule(String packageName, boolean isMainlineModule)
+            throws PackageManager.NameNotFoundException {
+        final PackageInfo packageInfo = new PackageInfo();
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.sourceDir = "apex";
+        packageInfo.applicationInfo = applicationInfo;
+
+        if (isMainlineModule) {
+            when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenReturn(
+                    new ModuleInfo());
+        } else {
+            when(mPackageManager.getPackageInfo(packageName, 0 /* flags */)).thenReturn(
+                    packageInfo);
+            when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenThrow(
+                    new PackageManager.NameNotFoundException());
+        }
+    }
 }
 
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
index c2bcd1c..a5ac209 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
@@ -543,6 +543,19 @@
         assertThat(i.getBooleanExtra(KEY_REMOVE_TASK_WHEN_FINISHING, false)).isFalse();
     }
 
+    @Test
+    @Config(shadows = ShadowAppUtils.class)
+    public void isAvailable_nonMainlineModule_isTrue() {
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    @Config(shadows = ShadowAppUtils.class)
+    public void isAvailable_mainlineModule_isFalse() {
+        ShadowAppUtils.addMainlineModule(mController.mPackageName);
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
     /**
      * The test fragment which implements
      * {@link ButtonActionDialogFragment.AppButtonsDialogListener}
@@ -597,16 +610,22 @@
     public static class ShadowAppUtils {
 
         public static Set<String> sSystemModules = new ArraySet<>();
+        public static Set<String> sMainlineModules = new ArraySet<>();
 
         @Resetter
         public static void reset() {
             sSystemModules.clear();
+            sMainlineModules.clear();
         }
 
         public static void addHiddenModule(String pkg) {
             sSystemModules.add(pkg);
         }
 
+        public static void addMainlineModule(String pkg) {
+            sMainlineModules.add(pkg);
+        }
+
         @Implementation
         protected static boolean isInstant(ApplicationInfo info) {
             return false;
@@ -616,5 +635,10 @@
         protected static boolean isSystemModule(Context context, String packageName) {
             return sSystemModules.contains(packageName);
         }
+
+        @Implementation
+        protected static boolean isMainlineModule(PackageManager pm, String packageName) {
+            return sMainlineModules.contains(packageName);
+        }
     }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceControllerTest.java
index 00bd5f8..d37a685 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppInstallerInfoPreferenceControllerTest.java
@@ -99,12 +99,15 @@
     }
 
     @Test
-    public void getAvailabilityStatus_hasAppLabel_shouldReturnAvailable() {
+    public void getAvailabilityStatus_hasAppLabel_shouldReturnAvailable()
+            throws PackageManager.NameNotFoundException {
+        final String packageName = "Package1";
         when(mUserManager.isManagedProfile()).thenReturn(false);
         when(mAppInfo.loadLabel(mPackageManager)).thenReturn("Label1");
         mController = new AppInstallerInfoPreferenceController(mContext, "test_key");
-        mController.setPackageName("Package1");
+        mController.setPackageName(packageName);
         mController.setParentFragment(mFragment);
+        mockMainlineModule(packageName, false /* isMainlineModule */);
 
         assertThat(mController.getAvailabilityStatus())
                 .isEqualTo(BasePreferenceController.AVAILABLE);
@@ -153,12 +156,31 @@
     @Test
     public void getAvailabilityStatus_isMainlineModule_shouldReturnDisabled()
             throws PackageManager.NameNotFoundException {
+        final String packageName = "Package";
         when(mUserManager.isManagedProfile()).thenReturn(false);
         when(mAppInfo.loadLabel(mPackageManager)).thenReturn("Label");
-        mController.setPackageName("Package");
-        when(mPackageManager.getModuleInfo("Package", 0 /* flags */)).thenReturn(new ModuleInfo());
+        mController.setPackageName(packageName);
+        mockMainlineModule(packageName, true /* isMainlineModule */);
 
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.DISABLED_FOR_USER);
     }
+
+    private void mockMainlineModule(String packageName, boolean isMainlineModule)
+            throws PackageManager.NameNotFoundException {
+        final PackageInfo packageInfo = new PackageInfo();
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.sourceDir = "apex";
+        packageInfo.applicationInfo = applicationInfo;
+
+        if (isMainlineModule) {
+            when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenReturn(
+                    new ModuleInfo());
+        } else {
+            when(mPackageManager.getPackageInfo(packageName, 0 /* flags */)).thenReturn(
+                    packageInfo);
+            when(mPackageManager.getModuleInfo(packageName, 0 /* flags */)).thenThrow(
+                    new PackageManager.NameNotFoundException());
+        }
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/development/ForcePeakRefreshRatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ForcePeakRefreshRatePreferenceControllerTest.java
new file mode 100644
index 0000000..2e93d5e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/ForcePeakRefreshRatePreferenceControllerTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.development;
+
+import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.DEFAULT_REFRESH_RATE;
+import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.NO_CONFIG;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import android.util.Log;
+
+@RunWith(RobolectricTestRunner.class)
+public class ForcePeakRefreshRatePreferenceControllerTest {
+
+    @Mock
+    private SwitchPreference mPreference;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private Context mContext;
+    private ForcePeakRefreshRatePreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = new ForcePeakRefreshRatePreferenceController(mContext);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+        when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+        mController.displayPreference(mScreen);
+    }
+
+    @Test
+    public void onPreferenceChange_preferenceChecked_shouldEnableForcePeak() {
+        mController.mPeakRefreshRate = 88f;
+
+        mController.onPreferenceChange(mPreference, true);
+
+        assertThat(Settings.System.getFloat(mContext.getContentResolver(),
+                Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(88f);
+    }
+
+    @Test
+    public void onPreferenceChange_preferenceUnchecked_shouldDisableForcePeak() {
+        mController.mPeakRefreshRate = 88f;
+
+        mController.onPreferenceChange(mPreference, false);
+
+        assertThat(Settings.System.getFloat(mContext.getContentResolver(),
+                Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(NO_CONFIG);
+    }
+
+    @Test
+    public void updateState_enableForcePeak_shouldCheckedToggle() {
+        mController.mPeakRefreshRate = 88f;
+        mController.forcePeakRefreshRate(true);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(true);
+    }
+
+    @Test
+    public void updateState_disableForcePeak_shouldUncheckedToggle() {
+        mController.mPeakRefreshRate = 88f;
+        mController.forcePeakRefreshRate(false);
+
+        mController.updateState(mPreference);
+
+        verify(mPreference).setChecked(false);
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void isAvailable_withConfigNoShow_returnUnsupported() {
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_refreshRateLargerThanDefault_returnTrue() {
+        mController.mPeakRefreshRate = DEFAULT_REFRESH_RATE + 1;
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void getAvailabilityStatus_refreshRateEqualToDefault_returnFalse() {
+        mController.mPeakRefreshRate = DEFAULT_REFRESH_RATE;
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void onDeveloperOptionsDisabled_shouldDisablePreference() {
+        mController.onDeveloperOptionsSwitchDisabled();
+
+        assertThat(Settings.System.getFloat(mContext.getContentResolver(),
+                Settings.System.MIN_REFRESH_RATE, -1f)).isEqualTo(NO_CONFIG);
+        assertThat(mPreference.isChecked()).isFalse();
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/NetworkScanHelperTest.java b/tests/robotests/src/com/android/settings/network/telephony/NetworkScanHelperTest.java
index 19ae6ff..1e7bfaf 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/NetworkScanHelperTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/NetworkScanHelperTest.java
@@ -164,7 +164,8 @@
     }
 
     private void startNetworkScan_incremental(boolean waitForCompletion) {
-        mNetworkScanHelper.startNetworkScan();
+        mNetworkScanHelper.startNetworkScan(
+                NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS);
         if (!waitForCompletion) {
             mNetworkScanHelper.stopNetworkQuery();
         }
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
index 9f6e7a3..094e282 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
@@ -230,4 +230,13 @@
         assertThat(mActivity.mProgressDialog).isNull();
         assertThat(mActivity.mDialogFragment).isNull();
     }
+
+    @Test
+    public void updateAccessPointList_onUserSelectionConnectFailure_shouldFinishActivity() {
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "Test AP 3";
+        mActivity.onUserSelectionConnectFailure(config);
+
+        verify(mActivity).finish();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/TetherServiceTest.java b/tests/robotests/src/com/android/settings/wifi/tether/TetherServiceTest.java
deleted file mode 100644
index 61b9b5b..0000000
--- a/tests/robotests/src/com/android/settings/wifi/tether/TetherServiceTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.wifi.tether;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.net.wifi.WifiManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowApplication.Wrapper;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.ArrayList;
-
-@RunWith(RobolectricTestRunner.class)
-public class TetherServiceTest {
-
-    private static final int CHECK_PERIOD_HOURS = 24;
-
-    @Mock
-    private Context mContext;
-    @Mock
-    private Resources mResources;
-
-    private Context mAppContext;
-    private TetherService mService;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mAppContext = RuntimeEnvironment.application;
-        mService = spy(new TetherService());
-        ReflectionHelpers.setField(mService, "mBase", mAppContext);
-        mService.setHotspotOffReceiver(new HotspotOffReceiver(mContext));
-        doReturn(CHECK_PERIOD_HOURS).when(mResources).getInteger(
-                com.android.internal.R.integer.config_mobile_hotspot_provision_check_period);
-        doReturn(mResources).when(mService).getResourceForActiveDataSubId();
-    }
-
-    @Test
-    public void scheduleAlarm_shouldRegisterReceiver() {
-        mService.setHotspotOffReceiver(new HotspotOffReceiver(mAppContext));
-
-        mService.scheduleAlarm();
-
-        boolean found = false;
-        for (Wrapper wrapper : ShadowApplication.getInstance().getRegisteredReceivers()) {
-            if (wrapper.intentFilter.matchAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
-                found = true;
-                break;
-            }
-        }
-
-        assertThat(found).isTrue();
-    }
-
-    @Test
-    public void cancelAlarmIfNecessary_hasActiveTethers_shouldNotUnregisterReceiver() {
-        mService.scheduleAlarm();
-        final ArrayList<Integer> tethers = new ArrayList<>();
-        tethers.add(1);
-        ReflectionHelpers.setField(mService, "mCurrentTethers", tethers);
-
-        mService.cancelAlarmIfNecessary();
-
-        verify(mContext, never()).unregisterReceiver(any(HotspotOffReceiver.class));
-    }
-
-    @Test
-    public void cancelAlarmIfNecessary_noActiveTethers_shouldUnregisterReceiver() {
-        final ArrayList<Integer> tethers = new ArrayList<>();
-        ReflectionHelpers.setField(mService, "mCurrentTethers", tethers);
-        mService.scheduleAlarm();
-
-        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/wifi/tether/TetherServiceTest.java b/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
index 6891441..19f29c0 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/TetherServiceTest.java
@@ -16,27 +16,23 @@
 
 package com.android.settings.wifi.tether;
 
-import static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE;
-import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK;
-import static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE;
-import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
-import static android.net.ConnectivityManager.EXTRA_SET_ALARM;
-import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
-import static android.net.ConnectivityManager.TETHERING_INVALID;
-import static android.net.ConnectivityManager.TETHERING_USB;
-import static android.net.ConnectivityManager.TETHERING_WIFI;
-import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
-import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
+import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
+import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
+import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
+import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_USB;
+import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
-import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.app.usage.UsageStatsManager;
 import android.content.BroadcastReceiver;
@@ -51,7 +47,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
-import android.net.ConnectivityManager;
+import android.net.TetheringManager;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -92,8 +88,7 @@
     private ProvisionReceiver mProvisionReceiver;
     private Receiver mResultReceiver;
 
-    @Mock private AlarmManager mAlarmManager;
-    @Mock private ConnectivityManager mConnectivityManager;
+    @Mock private TetheringManager mTetheringManager;
     @Mock private PackageManager mPackageManager;
     @Mock private WifiManager mWifiManager;
     @Mock private SharedPreferences mPrefs;
@@ -158,15 +153,6 @@
         super.tearDown();
     }
 
-    private void cancelAllProvisioning() {
-        int[] types = new int[]{TETHERING_BLUETOOTH, TETHERING_WIFI, TETHERING_USB};
-        for (int type : types) {
-            Intent intent = new Intent();
-            intent.putExtra(EXTRA_REM_TETHER_TYPE, type);
-            startService(intent);
-        }
-    }
-
     public void testStartForProvision() {
         runProvisioningForType(TETHERING_WIFI);
 
@@ -184,19 +170,6 @@
         assertTrue(mWrapper.isAppInactive(FAKE_PACKAGE_NAME));
     }
 
-    public void testScheduleRechecks() {
-        Intent intent = new Intent();
-        intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
-        intent.putExtra(EXTRA_SET_ALARM, true);
-        startService(intent);
-
-        long period = TEST_CHECK_PERIOD * MS_PER_HOUR;
-        verify(mAlarmManager).setRepeating(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
-                eq(period), mPiCaptor.capture());
-        PendingIntent pi = mPiCaptor.getValue();
-        assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
-    }
-
     public void testStartMultiple() {
         runProvisioningForType(TETHERING_WIFI);
 
@@ -235,9 +208,9 @@
         runProvisioningForType(TETHERING_WIFI);
 
         assertTrue(waitForProvisionRequest(TETHERING_WIFI));
-        assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
+        assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISIONING_FAILED));
 
-        verify(mConnectivityManager).stopTethering(ConnectivityManager.TETHERING_WIFI);
+        verify(mTetheringManager).stopTethering(TETHERING_WIFI);
     }
 
     public void testFailureStopsTethering_Usb() {
@@ -246,24 +219,9 @@
         runProvisioningForType(TETHERING_USB);
 
         assertTrue(waitForProvisionRequest(TETHERING_USB));
-        assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
+        assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISIONING_FAILED));
 
-        verify(mConnectivityManager).setUsbTethering(eq(false));
-    }
-
-    public void testCancelAlarm() {
-        runProvisioningForType(TETHERING_WIFI);
-
-        assertTrue(waitForProvisionRequest(TETHERING_WIFI));
-        assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
-
-        Intent intent = new Intent();
-        intent.putExtra(EXTRA_REM_TETHER_TYPE, TETHERING_WIFI);
-        startService(intent);
-
-        verify(mAlarmManager).cancel(mPiCaptor.capture());
-        PendingIntent pi = mPiCaptor.getValue();
-        assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
+        verify(mTetheringManager).stopTethering(TETHERING_USB);
     }
 
     public void testIgnoreOutdatedRequest() {
@@ -387,10 +345,8 @@
 
         @Override
         public Object getSystemService(String name) {
-            if (ALARM_SERVICE.equals(name)) {
-                return mAlarmManager;
-            } else if (CONNECTIVITY_SERVICE.equals(name)) {
-                return mConnectivityManager;
+            if (TETHERING_SERVICE.equals(name)) {
+                return mTetheringManager;
             } else if (WIFI_SERVICE.equals(name)) {
                 return mWifiManager;
             }