Merge "Create the Note Task shortcut using the SystemUI Context" into udc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a95afc9..6fe6832 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -4575,7 +4575,7 @@
                   android:launchMode="singleInstance"
                   android:excludeFromRecents="true"
                   android:exported="true"
-                  android:configChanges="orientation|keyboardHidden|screenSize">
+                  android:configChanges="orientation|keyboard|keyboardHidden|screenSize|smallestScreenSize|screenLayout">
             <intent-filter>
                 <action android:name="android.settings.WIFI_ADD_NETWORKS" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/res/drawable/ic_modifier_keys_reset.xml b/res/drawable/ic_modifier_keys_reset.xml
index 7758be8..5345c25 100644
--- a/res/drawable/ic_modifier_keys_reset.xml
+++ b/res/drawable/ic_modifier_keys_reset.xml
@@ -21,7 +21,7 @@
         android:height="24.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
-        android:tint="?androidprv:attr/materialColorPrimaryContainer">
+        android:tint="?androidprv:attr/materialColorPrimary">
     <path
         android:fillColor="@android:color/white"
         android:pathData="M18,4C13.58,0.69 7.31,1.58 4,6V4H2v6h6V8H5.09c1.44,-2.47 4.09,-3.98 6.94,-3.97c4.42,0.02 7.99,3.61 7.97,8.03s-3.61,7.99 -8.03,7.97C7.55,20.01 3.98,16.42 4,12H2c0,3.15 1.48,6.11 4,8c4.42,3.31 10.69,2.42 14,-2C23.31,13.58 22.42,7.31 18,4z"/>
diff --git a/res/drawable/modifier_key_bordered.xml b/res/drawable/modifier_key_bordered.xml
index 976a3eb..29316796 100644
--- a/res/drawable/modifier_key_bordered.xml
+++ b/res/drawable/modifier_key_bordered.xml
@@ -25,7 +25,7 @@
                 <solid android:color="@android:color/transparent"/>
                 <stroke
                     android:width="1dp"
-                    android:color="?androidprv:attr/materialColorPrimaryContainer"/>
+                    android:color="?androidprv:attr/materialColorPrimary"/>
             </shape>
         </item>
     </ripple>
diff --git a/res/drawable/modifier_key_colored.xml b/res/drawable/modifier_key_colored.xml
index 2bb033b..995d733 100644
--- a/res/drawable/modifier_key_colored.xml
+++ b/res/drawable/modifier_key_colored.xml
@@ -22,7 +22,7 @@
         <item>
             <shape android:shape="rectangle">
                 <corners android:radius="24dp"/>
-                <solid android:color="?androidprv:attr/colorAccentPrimary"/>
+                <solid android:color="?androidprv:attr/materialColorPrimary"/>
             </shape>
         </item>
     </ripple>
diff --git a/res/drawable/modifier_key_lisetview_background.xml b/res/drawable/modifier_key_lisetview_background.xml
index 4e12b62..3353cfd 100644
--- a/res/drawable/modifier_key_lisetview_background.xml
+++ b/res/drawable/modifier_key_lisetview_background.xml
@@ -22,7 +22,7 @@
         <item>
             <shape android:shape="rectangle">
                 <corners android:radius="24dp"/>
-                <solid android:color="?androidprv:attr/materialColorSurfaceContainerHigh"/>
+                <solid android:color="?androidprv:attr/materialColorSurfaceContainerHighest"/>
             </shape>
         </item>
     </ripple>
diff --git a/res/layout/modifier_key_item.xml b/res/layout/modifier_key_item.xml
index 51ba027..a189479 100644
--- a/res/layout/modifier_key_item.xml
+++ b/res/layout/modifier_key_item.xml
@@ -32,7 +32,7 @@
         android:ellipsize="marquee"
         android:fadingEdge="horizontal"
         android:src="@drawable/ic_check_24dp"
-        android:tint="?androidprv:attr/materialColorPrimaryContainer"/>
+        android:tint="?androidprv:attr/materialColorPrimary"/>
 
     <TextView
         android:id="@+id/modifier_key_text"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2a891c8..b38552f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7097,8 +7097,8 @@
     <!-- List of synonyms for the font size, used to match in settings search [CHAR LIMIT=NONE] -->
     <string name="keywords_font_size">text size, large print, large font, large text, low vision, make text bigger, font enlarger, font enlargement</string>
 
-    <!-- List of synonyms for the always show time and info [CHAR LIMIT=NONE] -->
-    <string name="keywords_always_show_time_info">always on display, AOD</string>
+    <!-- List of synonyms for the always show time and info, used to match in settings search [CHAR LIMIT=NONE] -->
+    <string name="keywords_always_show_time_info">always on ambient display, AOD</string>
 
     <!-- List of synonyms for the nfc tag apps control [CHAR LIMIT=NONE] -->
     <string name="keywords_change_nfc_tag_apps_state">nfc, tag, reader</string>
@@ -10248,8 +10248,10 @@
     <string name="default_autofill_app">Default autofill service</string>
     <!-- Preference category for showing auto-fill services with saved passwords. [CHAR LIMIT=60] -->
     <string name="autofill_passwords">Passwords</string>
-    <!-- Preference category for showing credman services with saved credentials. [CHAR LIMIT=60] -->
-    <string name="credman_credentials">Passwords, passkeys and data services</string>
+    <!-- Preference category for showing autofill and credman services with saved credentials. [CHAR LIMIT=60] -->
+    <string name="credman_chosen_app_title">Passwords, passkeys and data services</string>
+    <!-- Preference category for showing additional credential providers. [CHAR LIMIT=60] -->
+    <string name="credman_credentials">Additional providers</string>
     <!-- Summary for passwords settings that shows how many passwords are saved for each autofill
          service. [CHAR LIMIT=NONE] -->
     <string name="autofill_passwords_count">{count, plural,
diff --git a/res/xml/accounts_dashboard_settings_credman.xml b/res/xml/accounts_dashboard_settings_credman.xml
index 38f3f55..4f278b6 100644
--- a/res/xml/accounts_dashboard_settings_credman.xml
+++ b/res/xml/accounts_dashboard_settings_credman.xml
@@ -24,12 +24,12 @@
     <PreferenceCategory
         android:key="default_service_category"
         android:order="10"
-        android:title="@string/default_autofill_app">
+        android:title="@string/credman_chosen_app_title">
 
         <com.android.settings.widget.GearPreference
             android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
             android:key="default_autofill_main"
-            android:title="@string/default_autofill_app"
+            android:title="@string/credman_chosen_app_title"
             settings:keywords="@string/autofill_keywords">
             <extra
                 android:name="for_work"
diff --git a/res/xml/accounts_personal_dashboard_settings_credman.xml b/res/xml/accounts_personal_dashboard_settings_credman.xml
index c3f061d..891bb7c 100644
--- a/res/xml/accounts_personal_dashboard_settings_credman.xml
+++ b/res/xml/accounts_personal_dashboard_settings_credman.xml
@@ -25,12 +25,12 @@
     <PreferenceCategory
         android:key="default_service_category"
         android:order="10"
-        android:title="@string/default_autofill_app">
+        android:title="@string/credman_chosen_app_title">
 
         <com.android.settings.widget.GearPreference
             android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
             android:key="default_autofill_main"
-            android:title="@string/default_autofill_app"
+            android:title="@string/credman_chosen_app_title"
             settings:keywords="@string/autofill_keywords">
             <extra
                 android:name="for_work"
diff --git a/res/xml/accounts_work_dashboard_settings_credman.xml b/res/xml/accounts_work_dashboard_settings_credman.xml
index 2946a21..0d4b742 100644
--- a/res/xml/accounts_work_dashboard_settings_credman.xml
+++ b/res/xml/accounts_work_dashboard_settings_credman.xml
@@ -25,12 +25,12 @@
     <PreferenceCategory
         android:key="default_service_category"
         android:order="10"
-        android:title="@string/default_autofill_app">
+        android:title="@string/credman_chosen_app_title">
 
         <com.android.settings.widget.GearPreference
             android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
             android:key="default_autofill_work"
-            android:title="@string/default_autofill_app"
+            android:title="@string/credman_chosen_app_title"
             settings:searchable="false">
             <extra
                 android:name="for_work"
diff --git a/src/com/android/settings/display/AlwaysOnDisplaySlice.java b/src/com/android/settings/display/AlwaysOnDisplaySlice.java
index c66f4ed..003c603 100644
--- a/src/com/android/settings/display/AlwaysOnDisplaySlice.java
+++ b/src/com/android/settings/display/AlwaysOnDisplaySlice.java
@@ -28,6 +28,7 @@
 import android.net.Uri;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.text.TextUtils;
 
 import androidx.slice.Slice;
 import androidx.slice.builders.ListBuilder;
@@ -40,6 +41,10 @@
 import com.android.settings.slices.CustomSliceRegistry;
 import com.android.settings.slices.CustomSliceable;
 
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 /**
  * Custom {@link Slice} for Always on Display.
  * <p>
@@ -75,6 +80,7 @@
         return new ListBuilder(mContext, CustomSliceRegistry.ALWAYS_ON_SLICE_URI,
                 ListBuilder.INFINITY)
                 .setAccentColor(color)
+                .setKeywords(getKeywords())
                 .addRow(new ListBuilder.RowBuilder()
                         .setTitle(mContext.getText(R.string.doze_always_on_title))
                         .setSubtitle(mContext.getText(R.string.doze_always_on_summary))
@@ -84,6 +90,13 @@
                 .build();
     }
 
+    private Set<String> getKeywords() {
+        final String keywords = mContext.getString(R.string.keywords_always_show_time_info);
+        return Arrays.stream(TextUtils.split(keywords, ","))
+                .map(String::trim)
+                .collect(Collectors.toSet());
+    }
+
     @Override
     public Uri getUri() {
         return CustomSliceRegistry.ALWAYS_ON_SLICE_URI;
diff --git a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
index e0e25df..5d95ddb 100644
--- a/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
+++ b/src/com/android/settings/display/AmbientDisplayAlwaysOnPreferenceController.java
@@ -22,7 +22,6 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.text.TextUtils;
 
 import androidx.preference.Preference;
 
@@ -59,7 +58,7 @@
 
     @Override
     public boolean isSliceable() {
-        return TextUtils.equals(getPreferenceKey(), "ambient_display_always_on");
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
index 15d8c99..4a8f98b 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
@@ -19,6 +19,7 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Parcel;
 import android.util.Log;
 
 import androidx.preference.Preference;
@@ -43,6 +44,10 @@
         mIsPluggedIn = isPluggedIn;
     }
 
+    private BatteryDefenderTip(Parcel in) {
+        super(in);
+    }
+
     @Override
     public CharSequence getTitle(Context context) {
         return context.getString(R.string.battery_tip_limited_temporarily_title);
@@ -113,4 +118,14 @@
 
         Log.i(TAG, "send resume charging broadcast intent=" + intent);
     }
+
+    public static final Creator CREATOR = new Creator() {
+        public BatteryTip createFromParcel(Parcel in) {
+            return new BatteryDefenderTip(in);
+        }
+
+        public BatteryTip[] newArray(int size) {
+            return new BatteryDefenderTip[size];
+        }
+    };
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
index 134cfa0..327f974 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
@@ -19,6 +19,7 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Parcel;
 import android.util.Log;
 
 import androidx.preference.Preference;
@@ -43,6 +44,10 @@
         mMode = mode;
     }
 
+    private DockDefenderTip(Parcel in) {
+        super(in);
+    }
+
     public int getMode() {
         return mMode;
     }
@@ -157,4 +162,14 @@
 
         Log.i(TAG, "send resume charging broadcast intent=" + intent);
     }
+
+    public static final Creator CREATOR = new Creator() {
+        public BatteryTip createFromParcel(Parcel in) {
+            return new DockDefenderTip(in);
+        }
+
+        public BatteryTip[] newArray(int size) {
+            return new DockDefenderTip[size];
+        }
+    };
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java
index dc9b804..1c5616f 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java
@@ -18,7 +18,7 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.content.Intent;
+import android.os.Parcel;
 import android.util.Log;
 
 import androidx.preference.Preference;
@@ -36,6 +36,10 @@
         super(TipType.INCOMPATIBLE_CHARGER, state, /* showDialog */ false);
     }
 
+    private IncompatibleChargerTip(Parcel in) {
+        super(in);
+    }
+
     @Override
     public CharSequence getTitle(Context context) {
         return context.getString(R.string.battery_tip_incompatible_charging_title);
@@ -84,4 +88,14 @@
         cardPreference.setPrimaryButtonContentDescription(context.getString(
                 R.string.battery_tip_incompatible_charging_content_description));
     }
+
+    public static final Creator CREATOR = new Creator() {
+        public BatteryTip createFromParcel(Parcel in) {
+            return new IncompatibleChargerTip(in);
+        }
+
+        public BatteryTip[] newArray(int size) {
+            return new IncompatibleChargerTip[size];
+        }
+    };
 }
diff --git a/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java b/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java
index 14578af..949e656 100644
--- a/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java
+++ b/src/com/android/settings/inputmethod/ModifierKeysPickerDialogFragment.java
@@ -139,7 +139,7 @@
             } else {
                 itemSummary = new SpannableString(selectedItem);
                 itemSummary.setSpan(
-                        new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
+                        new ForegroundColorSpan(getColorOfMaterialColorPrimary()),
                         0, itemSummary.length(), 0);
                 int[] fromKeys = mRemappableKeyMap.get(mKeyDefaultName);
                 int[] toKeys = mRemappableKeyMap.get(selectedItem);
@@ -222,7 +222,7 @@
             textView.setText(mList.get(i));
             if (mCurrentItem == i) {
                 mKeyFocus = mList.get(i);
-                textView.setTextColor(getColorOfColorAccentPrimaryVariant());
+                textView.setTextColor(getColorOfMaterialColorPrimary());
                 checkIcon.setImageAlpha(255);
                 view.setBackground(
                         mActivity.getDrawable(R.drawable.modifier_key_lisetview_background));
@@ -251,8 +251,8 @@
         return Utils.getColorAttrDefaultColor(mActivity, android.R.attr.textColorSecondary);
     }
 
-    private int getColorOfColorAccentPrimaryVariant() {
+    private int getColorOfMaterialColorPrimary() {
         return Utils.getColorAttrDefaultColor(
-                mActivity, com.android.internal.R.attr.materialColorPrimaryContainer);
+                mActivity, com.android.internal.R.attr.materialColorPrimary);
     }
 }
diff --git a/src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java b/src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java
index 91caf29..5d8149a 100644
--- a/src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java
+++ b/src/com/android/settings/inputmethod/ModifierKeysPreferenceController.java
@@ -150,14 +150,14 @@
     private Spannable changeSummaryColor(String summary) {
         Spannable spannableSummary = new SpannableString(summary);
         spannableSummary.setSpan(
-                new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
+                new ForegroundColorSpan(getColorOfMaterialColorPrimary()),
                 0, spannableSummary.length(), 0);
         return spannableSummary;
     }
 
-    private int getColorOfColorAccentPrimaryVariant() {
+    private int getColorOfMaterialColorPrimary() {
         return Utils.getColorAttrDefaultColor(
-                mContext, com.android.internal.R.attr.materialColorPrimaryContainer);
+                mContext, com.android.internal.R.attr.materialColorPrimary);
     }
 
     private static boolean isCtrl(int keyCode) {
diff --git a/src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java b/src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java
index 3171487..4bb1069 100644
--- a/src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java
+++ b/src/com/android/settings/inputmethod/ModifierKeysRestorePreferenceController.java
@@ -82,13 +82,13 @@
         Spannable title = new SpannableString(
                 mParent.getActivity().getString(R.string.modifier_keys_reset_title));
         title.setSpan(
-                new ForegroundColorSpan(getColorOfColorAccentPrimaryVariant()),
+                new ForegroundColorSpan(getColorOfMaterialColorPrimary()),
                 0, title.length(), 0);
         preference.setTitle(title);
     }
 
-    private int getColorOfColorAccentPrimaryVariant() {
+    private int getColorOfMaterialColorPrimary() {
         return Utils.getColorAttrDefaultColor(
-                mParent.getActivity(), com.android.internal.R.attr.materialColorPrimaryContainer);
+                mParent.getActivity(), com.android.internal.R.attr.materialColorPrimary);
     }
 }
diff --git a/src/com/android/settings/location/BluetoothScanningMainSwitchPreferenceController.java b/src/com/android/settings/location/BluetoothScanningMainSwitchPreferenceController.java
index b491ec9..78e3184 100644
--- a/src/com/android/settings/location/BluetoothScanningMainSwitchPreferenceController.java
+++ b/src/com/android/settings/location/BluetoothScanningMainSwitchPreferenceController.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.provider.Settings;
 import android.widget.Switch;
+import android.os.UserManager;
 
 import androidx.preference.PreferenceScreen;
 
@@ -33,9 +34,11 @@
         implements OnMainSwitchChangeListener {
 
     private static final String KEY_BLUETOOTH_SCANNING_SWITCH = "bluetooth_always_scanning_switch";
+    private final UserManager mUserManager;
 
     public BluetoothScanningMainSwitchPreferenceController(Context context) {
         super(context, KEY_BLUETOOTH_SCANNING_SWITCH);
+        mUserManager = UserManager.get(context);
     }
 
     @Override
@@ -49,7 +52,9 @@
     @Override
     public int getAvailabilityStatus() {
         return mContext.getResources().getBoolean(R.bool.config_show_location_scanning)
-                ? AVAILABLE
+                ? (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_LOCATION)
+                        ? DISABLED_DEPENDENT_SETTING
+                        : AVAILABLE)
                 : UNSUPPORTED_ON_DEVICE;
     }
 
diff --git a/src/com/android/settings/location/WifiScanningMainSwitchPreferenceController.java b/src/com/android/settings/location/WifiScanningMainSwitchPreferenceController.java
index 546f1e1..e22b0a0 100644
--- a/src/com/android/settings/location/WifiScanningMainSwitchPreferenceController.java
+++ b/src/com/android/settings/location/WifiScanningMainSwitchPreferenceController.java
@@ -18,6 +18,7 @@
 import android.content.Context;
 import android.net.wifi.WifiManager;
 import android.widget.Switch;
+import android.os.UserManager;
 
 import androidx.preference.PreferenceScreen;
 
@@ -34,10 +35,12 @@
 
     private static final String KEY_WIFI_SCANNING_SWITCH = "wifi_always_scanning_switch";
     private final WifiManager mWifiManager;
+    private final UserManager mUserManager;
 
     public WifiScanningMainSwitchPreferenceController(Context context) {
         super(context, KEY_WIFI_SCANNING_SWITCH);
         mWifiManager = context.getSystemService(WifiManager.class);
+        mUserManager = UserManager.get(context);
     }
 
     @Override
@@ -52,7 +55,9 @@
     @Override
     public int getAvailabilityStatus() {
         return mContext.getResources().getBoolean(R.bool.config_show_location_scanning)
-                ? AVAILABLE
+                ? (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_LOCATION)
+                       ? DISABLED_DEPENDENT_SETTING
+                       : AVAILABLE)
                 : UNSUPPORTED_ON_DEVICE;
     }
 
diff --git a/src/com/android/settings/notification/app/ChannelListPreferenceController.java b/src/com/android/settings/notification/app/ChannelListPreferenceController.java
index 8db3b21..61ee024 100644
--- a/src/com/android/settings/notification/app/ChannelListPreferenceController.java
+++ b/src/com/android/settings/notification/app/ChannelListPreferenceController.java
@@ -236,13 +236,16 @@
             @NonNull PreferenceGroup groupPrefGroup) {
         int initialPrefCount = groupPrefGroup.getPreferenceCount();
         List<Preference> finalOrderedPrefs = new ArrayList<>();
+        Preference appDefinedGroupToggle;
         if (group.getId() == null) {
             // For the 'null' group, set the "Other" title.
             groupPrefGroup.setTitle(R.string.notification_channels_other);
+            appDefinedGroupToggle = null;
         } else {
             // For an app-defined group, set their name and create a row to toggle 'isBlocked'.
             groupPrefGroup.setTitle(group.getName());
-            finalOrderedPrefs.add(addOrUpdateGroupToggle(groupPrefGroup, group));
+            appDefinedGroupToggle = addOrUpdateGroupToggle(groupPrefGroup, group);
+            finalOrderedPrefs.add(appDefinedGroupToggle);
         }
         // Here "empty" means having no channel rows; the group toggle is ignored for this purpose.
         boolean initiallyEmpty = groupPrefGroup.getPreferenceCount() == finalOrderedPrefs.size();
@@ -268,13 +271,25 @@
         // remove all preferences and re-add them all.
         // This is required to ensure proper ordering of inserted channels, and it simplifies logic
         // at the cost of computation in the rare case that the list is changing.
+        // As an optimization, keep the app-defined-group toggle. That way it doesn't "flicker"
+        // (due to remove+add) when toggling the group.
         int numFinalGroups = finalOrderedPrefs.size();
         boolean hasInsertions = !initiallyEmpty && initialPrefCount != numFinalGroups;
         boolean requiresRemoval = postAddPrefCount != numFinalGroups;
+        boolean keepGroupToggle =
+                appDefinedGroupToggle != null && groupPrefGroup.getPreferenceCount() > 0
+                        && groupPrefGroup.getPreference(0) == appDefinedGroupToggle
+                        && finalOrderedPrefs.get(0) == appDefinedGroupToggle;
         if (hasInsertions || requiresRemoval) {
-            groupPrefGroup.removeAll();
-            for (Preference preference : finalOrderedPrefs) {
-                groupPrefGroup.addPreference(preference);
+            if (keepGroupToggle) {
+                while (groupPrefGroup.getPreferenceCount() > 1) {
+                    groupPrefGroup.removePreference(groupPrefGroup.getPreference(1));
+                }
+            } else {
+                groupPrefGroup.removeAll();
+            }
+            for (int i = (keepGroupToggle ? 1 : 0); i < finalOrderedPrefs.size(); i++) {
+                groupPrefGroup.addPreference(finalOrderedPrefs.get(i));
             }
         }
     }
@@ -322,7 +337,7 @@
         if (channel.getImportance() > IMPORTANCE_LOW) {
             channelPref.setIcon(getAlertingIcon());
         } else {
-            channelPref.setIcon(R.drawable.empty_icon);
+            channelPref.setIcon(mContext.getDrawable(R.drawable.empty_icon));
         }
         channelPref.setIconSize(PrimarySwitchPreference.ICON_SIZE_SMALL);
         channelPref.setTitle(channel.getName());
diff --git a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
index 6612476..c61cf51 100644
--- a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
+++ b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.net.TetheringManager;
 import android.net.wifi.WifiManager;
 import android.util.Log;
 
@@ -40,6 +41,7 @@
 
     private final Context mAppContext;
     private WifiManager mWifiManager;
+    private TetheringManager mTetheringManager;
     private WifiVerboseLogging mWifiVerboseLogging;
     private WifiHotspotRepository mWifiHotspotRepository;
 
@@ -48,7 +50,7 @@
     }
 
     /**
-     * Get WifiManager
+     * Gets WifiManager
      */
     public WifiManager getWifiManager() {
         if (mWifiManager == null) {
@@ -58,7 +60,18 @@
     }
 
     /**
-     * Get WifiVerboseLogging
+     * Gets TetheringManager
+     */
+    public TetheringManager getTetheringManager() {
+        if (mTetheringManager == null) {
+            mTetheringManager = mAppContext.getSystemService(TetheringManager.class);
+            verboseLog(TAG, "getTetheringManager():" + mTetheringManager);
+        }
+        return mTetheringManager;
+    }
+
+    /**
+     * Gets WifiVerboseLogging
      */
     public WifiVerboseLogging getWifiVerboseLogging() {
         if (mWifiVerboseLogging == null) {
@@ -68,25 +81,26 @@
     }
 
     /**
-     * Get WifiHotspotRepository
+     * Gets WifiHotspotRepository
      */
     public WifiHotspotRepository getWifiHotspotRepository() {
         if (mWifiHotspotRepository == null) {
-            mWifiHotspotRepository = new WifiHotspotRepository(mAppContext, getWifiManager());
+            mWifiHotspotRepository = new WifiHotspotRepository(mAppContext, getWifiManager(),
+                    getTetheringManager());
             verboseLog(TAG, "getWifiHotspotRepository():" + mWifiHotspotRepository);
         }
         return mWifiHotspotRepository;
     }
 
     /**
-     * Get WifiTetherViewModel
+     * Gets WifiTetherViewModel
      */
     public WifiTetherViewModel getWifiTetherViewModel(@NotNull ViewModelStoreOwner owner) {
         return new ViewModelProvider(owner).get(WifiTetherViewModel.class);
     }
 
     /**
-     * Get WifiHotspotSecurityViewModel
+     * Gets WifiHotspotSecurityViewModel
      */
     public WifiHotspotSecurityViewModel getWifiHotspotSecurityViewModel(
             @NotNull ViewModelStoreOwner owner) {
@@ -97,7 +111,7 @@
     }
 
     /**
-     * Get WifiHotspotSpeedViewModel
+     * Gets WifiHotspotSpeedViewModel
      */
     public WifiHotspotSpeedViewModel getWifiHotspotSpeedViewModel(
             @NotNull ViewModelStoreOwner owner) {
diff --git a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
index c96896f..c46fb2b 100644
--- a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
+++ b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
@@ -16,14 +16,18 @@
 
 package com.android.settings.wifi.repository;
 
+import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.wifi.SoftApConfiguration.BAND_2GHZ;
 import static android.net.wifi.SoftApConfiguration.BAND_5GHZ;
 import static android.net.wifi.SoftApConfiguration.BAND_6GHZ;
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_OPEN;
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE;
 import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
 
 import android.content.Context;
+import android.net.TetheringManager;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiAvailableChannel;
 import android.net.wifi.WifiManager;
@@ -51,6 +55,8 @@
 public class WifiHotspotRepository {
     private static final String TAG = "WifiHotspotRepository";
 
+    private static final int RESTART_INTERVAL_MS = 100;
+
     /** Wi-Fi hotspot band unknown. */
     public static final int BAND_UNKNOWN = 0;
     /** Wi-Fi hotspot band 2.4GHz and 5GHz. */
@@ -79,8 +85,9 @@
         sSpeedMap.put(BAND_2GHZ_5GHZ, SPEED_2GHZ_5GHZ);
     }
 
-    protected final Context mAppContext;
-    protected final WifiManager mWifiManager;
+    private final Context mAppContext;
+    private final WifiManager mWifiManager;
+    private final TetheringManager mTetheringManager;
 
     protected String mLastPassword;
     protected LastPasswordListener mLastPasswordListener = new LastPasswordListener();
@@ -102,9 +109,24 @@
     Boolean mIsConfigShowSpeed;
     private Boolean mIsSpeedFeatureAvailable;
 
-    public WifiHotspotRepository(@NonNull Context appContext, @NonNull WifiManager wifiManager) {
+    @VisibleForTesting
+    SoftApCallback mSoftApCallback = new SoftApCallback();
+    @VisibleForTesting
+    StartTetheringCallback mStartTetheringCallback;
+    @VisibleForTesting
+    int mWifiApState = WIFI_AP_STATE_DISABLED;
+
+    @VisibleForTesting
+    boolean mIsRestarting;
+    @VisibleForTesting
+    MutableLiveData<Boolean> mRestarting;
+
+    public WifiHotspotRepository(@NonNull Context appContext, @NonNull WifiManager wifiManager,
+            @NonNull TetheringManager tetheringManager) {
         mAppContext = appContext;
         mWifiManager = wifiManager;
+        mTetheringManager = tetheringManager;
+        mWifiManager.registerSoftApCallback(mAppContext.getMainExecutor(), mSoftApCallback);
     }
 
     /**
@@ -126,6 +148,15 @@
         return !TextUtils.isEmpty(mLastPassword) ? mLastPassword : generateRandomPassword();
     }
 
+    @VisibleForTesting
+    String generatePassword(SoftApConfiguration config) {
+        String password = config.getPassphrase();
+        if (TextUtils.isEmpty(password)) {
+            password = generatePassword();
+        }
+        return password;
+    }
+
     private class LastPasswordListener implements Consumer<String> {
         @Override
         public void accept(String password) {
@@ -140,13 +171,27 @@
     }
 
     /**
+     * Gets the Wi-Fi tethered AP Configuration.
+     *
+     * @return AP details in {@link SoftApConfiguration}
+     */
+    public SoftApConfiguration getSoftApConfiguration() {
+        return mWifiManager.getSoftApConfiguration();
+    }
+
+    /**
      * Sets the tethered Wi-Fi AP Configuration.
      *
      * @param config A valid SoftApConfiguration specifying the configuration of the SAP.
      */
     public void setSoftApConfiguration(@NonNull SoftApConfiguration config) {
+        if (mIsRestarting) {
+            Log.e(TAG, "Skip setSoftApConfiguration because hotspot is restarting.");
+            return;
+        }
         mWifiManager.setSoftApConfiguration(config);
         refresh();
+        restartTetheringIfNeeded();
     }
 
     /**
@@ -217,13 +262,7 @@
             return;
         }
         SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder(config);
-        String passphrase = null;
-        if (securityType != SECURITY_TYPE_OPEN) {
-            passphrase = config.getPassphrase();
-            if (TextUtils.isEmpty(passphrase)) {
-                passphrase = generatePassword();
-            }
-        }
+        String passphrase = (securityType == SECURITY_TYPE_OPEN) ? null : generatePassword(config);
         configBuilder.setPassphrase(passphrase, securityType);
         setSoftApConfiguration(configBuilder.build());
 
@@ -302,7 +341,7 @@
             configBuilder.setBand(BAND_2GHZ_5GHZ_6GHZ);
             if (config.getSecurityType() != SECURITY_TYPE_WPA3_SAE) {
                 log("setSpeedType(), setPassphrase(SECURITY_TYPE_WPA3_SAE)");
-                configBuilder.setPassphrase(generatePassword(), SECURITY_TYPE_WPA3_SAE);
+                configBuilder.setPassphrase(generatePassword(config), SECURITY_TYPE_WPA3_SAE);
             }
         } else if (speedType == SPEED_5GHZ) {
             log("setSpeedType(), setBand(BAND_2GHZ_5GHZ)");
@@ -543,6 +582,84 @@
         }
     }
 
+    /**
+     * Gets Restarting LiveData
+     */
+    public LiveData<Boolean> getRestarting() {
+        if (mRestarting == null) {
+            mRestarting = new MutableLiveData<>();
+            mRestarting.setValue(mIsRestarting);
+        }
+        return mRestarting;
+    }
+
+    private void setRestarting(boolean isRestarting) {
+        log("setRestarting(), isRestarting:" + isRestarting);
+        mIsRestarting = isRestarting;
+        if (mRestarting != null) {
+            mRestarting.setValue(mIsRestarting);
+        }
+    }
+
+    @VisibleForTesting
+    void restartTetheringIfNeeded() {
+        if (mWifiApState != WIFI_AP_STATE_ENABLED) {
+            return;
+        }
+        log("restartTetheringIfNeeded()");
+        mAppContext.getMainThreadHandler().postDelayed(() -> {
+            setRestarting(true);
+            stopTethering();
+        }, RESTART_INTERVAL_MS);
+    }
+
+    private void startTethering() {
+        if (mStartTetheringCallback == null) {
+            mStartTetheringCallback = new StartTetheringCallback();
+        }
+        log("startTethering()");
+        mTetheringManager.startTethering(TETHERING_WIFI, mAppContext.getMainExecutor(),
+                mStartTetheringCallback);
+    }
+
+    private void stopTethering() {
+        log("startTethering()");
+        mTetheringManager.stopTethering(TETHERING_WIFI);
+    }
+
+    @VisibleForTesting
+    class SoftApCallback implements WifiManager.SoftApCallback {
+        @Override
+        public void onStateChanged(int state, int failureReason) {
+            log("onStateChanged(), state:" + state + ", failureReason:" + failureReason);
+            mWifiApState = state;
+            if (!mIsRestarting) {
+                return;
+            }
+            if (state == WIFI_AP_STATE_DISABLED) {
+                mAppContext.getMainThreadHandler().postDelayed(() -> startTethering(),
+                        RESTART_INTERVAL_MS);
+                return;
+            }
+            if (state == WIFI_AP_STATE_ENABLED) {
+                refresh();
+                setRestarting(false);
+            }
+        }
+    }
+
+    private class StartTetheringCallback implements TetheringManager.StartTetheringCallback {
+        @Override
+        public void onTetheringStarted() {
+            log("onTetheringStarted()");
+        }
+
+        @Override
+        public void onTetheringFailed(int error) {
+            log("onTetheringFailed(), error:" + error);
+        }
+    }
+
     private void log(String msg) {
         FeatureFactory.getFactory(mAppContext).getWifiFeatureProvider().verboseLog(TAG, msg);
     }
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java b/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
index 8ff2689..0dc1605 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettings.java
@@ -19,6 +19,7 @@
 import android.app.settings.SettingsEnums;
 import android.os.Bundle;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.LiveData;
 
 import com.android.settings.R;
@@ -72,6 +73,7 @@
             SelectorWithWidgetPreference preference = findPreference(viewItem.mKey);
             preference.setOnClickListener(this);
         }
+        mWifiHotspotSecurityViewModel.getRestarting().observe(this, this::onRestartingChanged);
     }
 
     protected void onViewItemListDataChanged(
@@ -96,6 +98,12 @@
         }
     }
 
+    @VisibleForTesting
+    void onRestartingChanged(Boolean restarting) {
+        log("onRestartingChanged(), restarting:" + restarting);
+        setLoading(restarting, false);
+    }
+
     @Override
     public void onRadioButtonClicked(SelectorWithWidgetPreference emiter) {
         String key = emiter.getKey();
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java b/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
index 422e40b..7c8554c 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModel.java
@@ -130,6 +130,13 @@
     }
 
     /**
+     * Gets Restarting LiveData
+     */
+    public LiveData<Boolean> getRestarting() {
+        return mWifiHotspotRepository.getRestarting();
+    }
+
+    /**
      * Wi-Fi Hotspot View Item
      */
     public static final class ViewItem {
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java b/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java
index 467d394..f5066bd 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettings.java
@@ -24,6 +24,8 @@
 import android.app.settings.SettingsEnums;
 import android.os.Bundle;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.overlay.FeatureFactory;
@@ -80,6 +82,7 @@
         onSpeedInfoMapDataChanged(mWifiHotspotSpeedViewModel.getSpeedInfoMapData().getValue());
         mWifiHotspotSpeedViewModel.getSpeedInfoMapData()
                 .observe(this, this::onSpeedInfoMapDataChanged);
+        mWifiHotspotSpeedViewModel.getRestarting().observe(this, this::onRestartingChanged);
     }
 
     protected void loadPreferences() {
@@ -117,6 +120,12 @@
         }
     }
 
+    @VisibleForTesting
+    void onRestartingChanged(Boolean restarting) {
+        log("onRestartingChanged(), restarting:" + restarting);
+        setLoading(restarting, false);
+    }
+
     @Override
     public void onRadioButtonClicked(SelectorWithWidgetPreference emiter) {
         String key = emiter.getKey();
diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java b/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java
index c30174e..f04669a 100644
--- a/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java
+++ b/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModel.java
@@ -131,6 +131,13 @@
     }
 
     /**
+     * Gets Restarting LiveData
+     */
+    public LiveData<Boolean> getRestarting() {
+        return mWifiHotspotRepository.getRestarting();
+    }
+
+    /**
      * Wi-Fi Hotspot Speed Information
      */
     public static final class SpeedInfo {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index 174ccb0..2774be6 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -17,6 +17,8 @@
 package com.android.settings.wifi.tether;
 
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
 
 import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot;
 
@@ -26,7 +28,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.wifi.SoftApConfiguration;
-import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.UserManager;
 import android.util.FeatureFlagUtils;
@@ -76,6 +77,8 @@
     @VisibleForTesting
     static final String KEY_WIFI_HOTSPOT_SPEED = "wifi_hotspot_speed";
 
+    @VisibleForTesting
+    SettingsMainSwitchBar mMainSwitchBar;
     private WifiTetherSwitchBarController mSwitchBarController;
     private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
     private WifiTetherPasswordPreferenceController mPasswordPreferenceController;
@@ -83,8 +86,6 @@
     private WifiTetherMaximizeCompatibilityPreferenceController mMaxCompatibilityPrefController;
     private WifiTetherAutoOffPreferenceController mWifiTetherAutoOffPreferenceController;
 
-    private WifiManager mWifiManager;
-    private boolean mRestartWifiApAfterConfigChange;
     private boolean mUnavailable;
     private WifiRestriction mWifiRestriction;
     @VisibleForTesting
@@ -138,6 +139,7 @@
                 .getWifiTetherViewModel(this);
         if (mWifiTetherViewModel != null) {
             setupSpeedFeature(mWifiTetherViewModel.isSpeedFeatureAvailable());
+            mWifiTetherViewModel.getRestarting().observe(this, this::onRestartingChanged);
         }
     }
 
@@ -159,7 +161,6 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
         mTetherChangeReceiver = new TetherChangeReceiver();
 
         mSSIDPreferenceController = use(WifiTetherSSIDPreferenceController.class);
@@ -179,11 +180,11 @@
         // Assume we are in a SettingsActivity. This is only safe because we currently use
         // SettingsActivity as base for all preference fragments.
         final SettingsActivity activity = (SettingsActivity) getActivity();
-        final SettingsMainSwitchBar switchBar = activity.getSwitchBar();
-        switchBar.setTitle(getContext().getString(R.string.use_wifi_hotsopt_main_switch_title));
-        mSwitchBarController = new WifiTetherSwitchBarController(activity, switchBar);
+        mMainSwitchBar = activity.getSwitchBar();
+        mMainSwitchBar.setTitle(getString(R.string.use_wifi_hotsopt_main_switch_title));
+        mSwitchBarController = new WifiTetherSwitchBarController(activity, mMainSwitchBar);
         getSettingsLifecycle().addObserver(mSwitchBarController);
-        switchBar.show();
+        mMainSwitchBar.show();
     }
 
     @Override
@@ -259,40 +260,34 @@
         final SoftApConfiguration config = buildNewConfig();
         mPasswordPreferenceController.setSecurityType(config.getSecurityType());
 
-        /**
-         * if soft AP is stopped, bring up
-         * else restart with new config
-         * TODO: update config on a running access point when framework support is added
-         */
-        if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
-            Log.d("TetheringSettings",
-                    "Wifi AP config changed while enabled, stop and restart");
-            mRestartWifiApAfterConfigChange = true;
-            mSwitchBarController.stopTether();
-        }
         mWifiTetherViewModel.setSoftApConfiguration(config);
     }
 
+    @VisibleForTesting
+    void onRestartingChanged(Boolean restarting) {
+        mMainSwitchBar.setVisibility((restarting) ? INVISIBLE : VISIBLE);
+        setLoading(restarting, false);
+    }
+
     private SoftApConfiguration buildNewConfig() {
-        final SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
-        final int securityType = mSecurityPreferenceController.getSecurityType();
+        SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
+        int securityType = (mWifiTetherViewModel.isSpeedFeatureAvailable())
+                ? mWifiTetherViewModel.getSoftApConfiguration().getSecurityType()
+                : mSecurityPreferenceController.getSecurityType();
         configBuilder.setSsid(mSSIDPreferenceController.getSSID());
         if (securityType != SoftApConfiguration.SECURITY_TYPE_OPEN) {
             configBuilder.setPassphrase(
                     mPasswordPreferenceController.getPasswordValidated(securityType),
                     securityType);
         }
-        mMaxCompatibilityPrefController.setupMaximizeCompatibility(configBuilder);
+        if (!mWifiTetherViewModel.isSpeedFeatureAvailable()) {
+            mMaxCompatibilityPrefController.setupMaximizeCompatibility(configBuilder);
+        }
         configBuilder.setAutoShutdownEnabled(
                 mWifiTetherAutoOffPreferenceController.isEnabled());
         return configBuilder.build();
     }
 
-    private void startTether() {
-        mRestartWifiApAfterConfigChange = false;
-        mSwitchBarController.startTether();
-    }
-
     private void updateDisplayWithNewConfig() {
         use(WifiTetherSSIDPreferenceController.class).updateDisplay();
         use(WifiTetherSecurityPreferenceController.class).updateDisplay();
@@ -369,13 +364,6 @@
             String action = intent.getAction();
             Log.d(TAG, "updating display config due to receiving broadcast action " + action);
             updateDisplayWithNewConfig();
-            if (action.equals(WIFI_AP_STATE_CHANGED_ACTION)) {
-                int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0);
-                if (state == WifiManager.WIFI_AP_STATE_DISABLED
-                        && mRestartWifiApAfterConfigChange) {
-                    startTether();
-                }
-            }
         }
     }
 }
diff --git a/src/com/android/settings/wifi/tether/WifiTetherViewModel.java b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
index dd4ca28..fb2160f 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
@@ -101,6 +101,15 @@
     }
 
     /**
+     * Gets the Wi-Fi tethered AP Configuration.
+     *
+     * @return AP details in {@link SoftApConfiguration}
+     */
+    public SoftApConfiguration getSoftApConfiguration() {
+        return mWifiHotspotRepository.getSoftApConfiguration();
+    }
+
+    /**
      * Sets the tethered Wi-Fi AP Configuration.
      *
      * @param config A valid SoftApConfiguration specifying the configuration of the SAP.
@@ -153,4 +162,11 @@
         }
         mSpeedSummary.setValue(resId);
     }
+
+    /**
+     * Gets Restarting LiveData
+     */
+    public LiveData<Boolean> getRestarting() {
+        return mWifiHotspotRepository.getRestarting();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java
index ec8cfe8..969f992 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiHotspotSpeedSettingsTest.java
@@ -25,6 +25,9 @@
 import static com.android.settings.wifi.tether.WifiHotspotSpeedSettings.KEY_SPEED_5GHZ;
 import static com.android.settings.wifi.tether.WifiHotspotSpeedSettings.KEY_SPEED_6GHZ;
 
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -80,7 +83,7 @@
         WifiFeatureProvider provider = FakeFeatureFactory.setupForTest().getWifiFeatureProvider();
         when(provider.getWifiHotspotSpeedViewModel(mViewModelStoreOwner)).thenReturn(mViewModel);
 
-        mSettings = new WifiHotspotSpeedSettings();
+        mSettings = spy(new WifiHotspotSpeedSettings());
         mSettings.mWifiHotspotSpeedViewModel = mViewModel;
     }
 
@@ -181,6 +184,24 @@
     }
 
     @Test
+    public void onRestartingChanged_restartingTrue_setLoadingTrue() {
+        doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+        mSettings.onRestartingChanged(true);
+
+        verify(mSettings).setLoading(true, false);
+    }
+
+    @Test
+    public void onRestartingChanged_restartingFalse_setLoadingFalse() {
+        doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+        mSettings.onRestartingChanged(false);
+
+        verify(mSettings).setLoading(false, false);
+    }
+
+    @Test
     public void onRadioButtonClicked_toSpeed2g_setSpeedType2g() {
         when(mRadioButton.getKey()).thenReturn(KEY_SPEED_2GHZ);
 
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
index e264177..0a54c88 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.wifi.tether;
 
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
 import static com.android.settings.wifi.WifiUtils.setCanShowWifiHotspotCached;
 import static com.android.settings.wifi.tether.WifiTetherSettings.KEY_WIFI_HOTSPOT_SECURITY;
 import static com.android.settings.wifi.tether.WifiTetherSettings.KEY_WIFI_HOTSPOT_SPEED;
@@ -25,6 +28,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -55,6 +59,7 @@
 import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settings.widget.SettingsMainSwitchBar;
 import com.android.settings.wifi.factory.WifiFeatureProvider;
 import com.android.settings.wifi.repository.WifiHotspotRepository;
 
@@ -110,6 +115,8 @@
     private Preference mWifiHotspotSpeed;
     @Mock
     private LiveData<Integer> mSpeedSummary;
+    @Mock
+    private SettingsMainSwitchBar mMainSwitchBar;
 
     private WifiTetherSettings mSettings;
 
@@ -135,6 +142,7 @@
         when(mWifiTetherViewModel.getSpeedSummary()).thenReturn(mSpeedSummary);
 
         mSettings = spy(new WifiTetherSettings(mWifiRestriction));
+        mSettings.mMainSwitchBar = mMainSwitchBar;
         mSettings.mWifiTetherViewModel = mWifiTetherViewModel;
         when(mSettings.findPreference(KEY_WIFI_HOTSPOT_SECURITY)).thenReturn(mWifiHotspotSecurity);
         when(mSettings.findPreference(KEY_WIFI_HOTSPOT_SPEED)).thenReturn(mWifiHotspotSpeed);
@@ -308,6 +316,26 @@
         verify(mSpeedSummary, never()).observe(any(), any());
     }
 
+    @Test
+    public void onRestartingChanged_restartingTrue_setLoadingTrue() {
+        doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+        mSettings.onRestartingChanged(true);
+
+        verify(mMainSwitchBar).setVisibility(INVISIBLE);
+        verify(mSettings).setLoading(true, false);
+    }
+
+    @Test
+    public void onRestartingChanged_restartingFalse_setLoadingFalse() {
+        doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+        mSettings.onRestartingChanged(false);
+
+        verify(mMainSwitchBar).setVisibility(VISIBLE);
+        verify(mSettings).setLoading(false, false);
+    }
+
     private void spyWifiTetherSettings() {
         mSettings = spy(new WifiTetherSettings(mWifiRestriction));
         final FragmentActivity activity = mock(FragmentActivity.class);
diff --git a/tests/legacy_unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
similarity index 86%
rename from tests/legacy_unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
index 015addc..4aae76c 100644
--- a/tests/legacy_unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/notification/app/ChannelListPreferenceControllerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -22,7 +22,6 @@
 
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertFalse;
-import static junit.framework.TestCase.assertNotNull;
 import static junit.framework.TestCase.assertNull;
 import static junit.framework.TestCase.assertTrue;
 
@@ -37,6 +36,7 @@
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -65,15 +65,14 @@
 
     @Before
     public void setUp() throws Exception {
+        mContext = ApplicationProvider.getApplicationContext();
         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
-        mContext = instrumentation.getTargetContext();
-
         instrumentation.runOnMainSync(() -> {
             mBackend = new NotificationBackend();
             mAppRow = mBackend.loadAppRow(mContext,
                     mContext.getPackageManager(), mContext.getApplicationInfo());
             mController = new ChannelListPreferenceController(mContext, mBackend);
-            mController.onResume(mAppRow, null, null, null, null, null);
+            mController.onResume(mAppRow, null, null, null, null, null, null);
             mPreferenceManager = new PreferenceManager(mContext);
             mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
             mGroupList = new PreferenceCategory(mContext);
@@ -103,9 +102,10 @@
             assertEquals("group1", group1.getKey());
             assertEquals(2, group1.getPreferenceCount());
             assertNull(group1.getPreference(0).getKey());
-            assertEquals("All \"Group 1\" notifications", group1.getPreference(0).getTitle());
+            assertEquals("All \"Group 1\" notifications",
+                    group1.getPreference(0).getTitle().toString());
             assertEquals("ch1a", group1.getPreference(1).getKey());
-            assertEquals("Channel 1A", group1.getPreference(1).getTitle());
+            assertEquals("Channel 1A", group1.getPreference(1).getTitle().toString());
         }
 
         // Test that adding a channel works -- no dupes or omissions
@@ -117,11 +117,12 @@
             assertEquals("group1", group1.getKey());
             assertEquals(3, group1.getPreferenceCount());
             assertNull(group1.getPreference(0).getKey());
-            assertEquals("All \"Group 1\" notifications", group1.getPreference(0).getTitle());
+            assertEquals("All \"Group 1\" notifications",
+                    group1.getPreference(0).getTitle().toString());
             assertEquals("ch1a", group1.getPreference(1).getKey());
-            assertEquals("Channel 1A", group1.getPreference(1).getTitle());
+            assertEquals("Channel 1A", group1.getPreference(1).getTitle().toString());
             assertEquals("ch1b", group1.getPreference(2).getKey());
-            assertEquals("Channel 1B", group1.getPreference(2).getTitle());
+            assertEquals("Channel 1B", group1.getPreference(2).getTitle().toString());
         }
 
         // Test that renaming a channel does in fact rename the preferences
@@ -133,11 +134,12 @@
             assertEquals("group1", group1.getKey());
             assertEquals(3, group1.getPreferenceCount());
             assertNull(group1.getPreference(0).getKey());
-            assertEquals("All \"Group 1\" notifications", group1.getPreference(0).getTitle());
+            assertEquals("All \"Group 1\" notifications",
+                    group1.getPreference(0).getTitle().toString());
             assertEquals("ch1a", group1.getPreference(1).getKey());
-            assertEquals("Channel 1A", group1.getPreference(1).getTitle());
+            assertEquals("Channel 1A", group1.getPreference(1).getTitle().toString());
             assertEquals("ch1b", group1.getPreference(2).getKey());
-            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle());
+            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle().toString());
         }
 
         // Test that adding a group works and results in the correct sorting.
@@ -152,18 +154,20 @@
             assertEquals("group0", group0.getKey());
             assertEquals(2, group0.getPreferenceCount());
             assertNull(group0.getPreference(0).getKey());
-            assertEquals("All \"Group 0\" notifications", group0.getPreference(0).getTitle());
+            assertEquals("All \"Group 0\" notifications",
+                    group0.getPreference(0).getTitle().toString());
             assertEquals("ch0b", group0.getPreference(1).getKey());
-            assertEquals("Channel 0B", group0.getPreference(1).getTitle());
+            assertEquals("Channel 0B", group0.getPreference(1).getTitle().toString());
             PreferenceGroup group1 = (PreferenceGroup) mGroupList.getPreference(1);
             assertEquals("group1", group1.getKey());
             assertEquals(3, group1.getPreferenceCount());
             assertNull(group1.getPreference(0).getKey());
-            assertEquals("All \"Group 1\" notifications", group1.getPreference(0).getTitle());
+            assertEquals("All \"Group 1\" notifications",
+                    group1.getPreference(0).getTitle().toString());
             assertEquals("ch1a", group1.getPreference(1).getKey());
-            assertEquals("Channel 1A", group1.getPreference(1).getTitle());
+            assertEquals("Channel 1A", group1.getPreference(1).getTitle().toString());
             assertEquals("ch1b", group1.getPreference(2).getKey());
-            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle());
+            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle().toString());
         }
 
         // Test that adding a channel that comes before another works and has correct ordering.
@@ -176,20 +180,22 @@
             assertEquals("group0", group0.getKey());
             assertEquals(3, group0.getPreferenceCount());
             assertNull(group0.getPreference(0).getKey());
-            assertEquals("All \"Group 0\" notifications", group0.getPreference(0).getTitle());
+            assertEquals("All \"Group 0\" notifications",
+                    group0.getPreference(0).getTitle().toString());
             assertEquals("ch0a", group0.getPreference(1).getKey());
-            assertEquals("Channel 0A", group0.getPreference(1).getTitle());
+            assertEquals("Channel 0A", group0.getPreference(1).getTitle().toString());
             assertEquals("ch0b", group0.getPreference(2).getKey());
-            assertEquals("Channel 0B", group0.getPreference(2).getTitle());
+            assertEquals("Channel 0B", group0.getPreference(2).getTitle().toString());
             PreferenceGroup group1 = (PreferenceGroup) mGroupList.getPreference(1);
             assertEquals("group1", group1.getKey());
             assertEquals(3, group1.getPreferenceCount());
             assertNull(group1.getPreference(0).getKey());
-            assertEquals("All \"Group 1\" notifications", group1.getPreference(0).getTitle());
+            assertEquals("All \"Group 1\" notifications",
+                    group1.getPreference(0).getTitle().toString());
             assertEquals("ch1a", group1.getPreference(1).getKey());
-            assertEquals("Channel 1A", group1.getPreference(1).getTitle());
+            assertEquals("Channel 1A", group1.getPreference(1).getTitle().toString());
             assertEquals("ch1b", group1.getPreference(2).getKey());
-            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle());
+            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle().toString());
         }
 
         // Test that the "Other" group works.
@@ -206,18 +212,19 @@
             assertEquals("group1", group1.getKey());
             assertEquals(3, group1.getPreferenceCount());
             assertNull(group1.getPreference(0).getKey());
-            assertEquals("All \"Group 1\" notifications", group1.getPreference(0).getTitle());
+            assertEquals("All \"Group 1\" notifications",
+                    group1.getPreference(0).getTitle().toString());
             assertEquals("ch1a", group1.getPreference(1).getKey());
-            assertEquals("Channel 1A", group1.getPreference(1).getTitle());
+            assertEquals("Channel 1A", group1.getPreference(1).getTitle().toString());
             assertEquals("ch1b", group1.getPreference(2).getKey());
-            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle());
+            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle().toString());
             PreferenceGroup groupOther = (PreferenceGroup) mGroupList.getPreference(1);
             assertEquals("categories", groupOther.getKey());
             assertEquals(2, groupOther.getPreferenceCount());
             assertEquals("chXa", groupOther.getPreference(0).getKey());
-            assertEquals("Other A", groupOther.getPreference(0).getTitle());
+            assertEquals("Other A", groupOther.getPreference(0).getTitle().toString());
             assertEquals("chXb", groupOther.getPreference(1).getKey());
-            assertEquals("Other B", groupOther.getPreference(1).getTitle());
+            assertEquals("Other B", groupOther.getPreference(1).getTitle().toString());
         }
 
         // Test that the removal of a channel works.
@@ -229,16 +236,17 @@
             assertEquals("group1", group1.getKey());
             assertEquals(3, group1.getPreferenceCount());
             assertNull(group1.getPreference(0).getKey());
-            assertEquals("All \"Group 1\" notifications", group1.getPreference(0).getTitle());
+            assertEquals("All \"Group 1\" notifications",
+                    group1.getPreference(0).getTitle().toString());
             assertEquals("ch1a", group1.getPreference(1).getKey());
-            assertEquals("Channel 1A", group1.getPreference(1).getTitle());
+            assertEquals("Channel 1A", group1.getPreference(1).getTitle().toString());
             assertEquals("ch1b", group1.getPreference(2).getKey());
-            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle());
+            assertEquals("Channel 1B - Renamed", group1.getPreference(2).getTitle().toString());
             PreferenceGroup groupOther = (PreferenceGroup) mGroupList.getPreference(1);
             assertEquals("categories", groupOther.getKey());
             assertEquals(1, groupOther.getPreferenceCount());
             assertEquals("chXb", groupOther.getPreference(0).getKey());
-            assertEquals("Other B", groupOther.getPreference(0).getTitle());
+            assertEquals("Other B", groupOther.getPreference(0).getTitle().toString());
         }
 
         // Test that we go back to the empty state when clearing all groups and channels.
@@ -269,15 +277,15 @@
             assertEquals(3, group.getPreferenceCount());
             SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
             assertNull(groupBlockPref.getKey());
-            assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle());
+            assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
             assertTrue(groupBlockPref.isChecked());
             PrimarySwitchPreference channelAPref = (PrimarySwitchPreference) group.getPreference(1);
             assertEquals("channelA", channelAPref.getKey());
-            assertEquals("Channel A", channelAPref.getTitle());
+            assertEquals("Channel A", channelAPref.getTitle().toString());
             assertEquals(Boolean.TRUE, channelAPref.getCheckedState());
             PrimarySwitchPreference channelBPref = (PrimarySwitchPreference) group.getPreference(2);
             assertEquals("channelB", channelBPref.getKey());
-            assertEquals("Channel B", channelBPref.getTitle());
+            assertEquals("Channel B", channelBPref.getTitle().toString());
             assertEquals(Boolean.FALSE, channelBPref.getCheckedState());
         }
 
@@ -291,7 +299,7 @@
             assertEquals(1, group.getPreferenceCount());
             SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
             assertNull(groupBlockPref.getKey());
-            assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle());
+            assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
             assertFalse(groupBlockPref.isChecked());
         }
 
@@ -305,15 +313,15 @@
             assertEquals(3, group.getPreferenceCount());
             SwitchPreference groupBlockPref = (SwitchPreference) group.getPreference(0);
             assertNull(groupBlockPref.getKey());
-            assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle());
+            assertEquals("All \"My Group\" notifications", groupBlockPref.getTitle().toString());
             assertTrue(groupBlockPref.isChecked());
             PrimarySwitchPreference channelAPref = (PrimarySwitchPreference) group.getPreference(1);
             assertEquals("channelA", channelAPref.getKey());
-            assertEquals("Channel A", channelAPref.getTitle());
+            assertEquals("Channel A", channelAPref.getTitle().toString());
             assertEquals(Boolean.TRUE, channelAPref.getCheckedState());
             PrimarySwitchPreference channelBPref = (PrimarySwitchPreference) group.getPreference(2);
             assertEquals("channelB", channelBPref.getKey());
-            assertEquals("Channel B", channelBPref.getTitle());
+            assertEquals("Channel B", channelBPref.getTitle().toString());
             assertEquals(Boolean.FALSE, channelBPref.getCheckedState());
         }
     }
@@ -347,19 +355,18 @@
             assertEquals("group", group.getKey());
             assertEquals(3, group.getPreferenceCount());
             assertNull(group.getPreference(0).getKey());
-            assertEquals("All \"Group\" notifications", group.getPreference(0).getTitle());
+            assertEquals("All \"Group\" notifications",
+                    group.getPreference(0).getTitle().toString());
             PrimarySwitchPreference channelAPref = (PrimarySwitchPreference) group.getPreference(1);
             assertEquals("channelA", channelAPref.getKey());
-            assertEquals("Channel A", channelAPref.getTitle());
+            assertEquals("Channel A", channelAPref.getTitle().toString());
             assertEquals(Boolean.TRUE, channelAPref.getCheckedState());
-            assertEquals("~2 notifications per day", channelAPref.getSummary());
-            assertNotNull(channelAPref.getIcon());
+            assertEquals("About 2 notifications per day", channelAPref.getSummary().toString());
             PrimarySwitchPreference channelBPref = (PrimarySwitchPreference) group.getPreference(2);
             assertEquals("channelB", channelBPref.getKey());
-            assertEquals("Channel B", channelBPref.getTitle());
+            assertEquals("Channel B", channelBPref.getTitle().toString());
             assertEquals(Boolean.FALSE, channelBPref.getCheckedState());
             assertNull(channelBPref.getSummary());
-            assertNull(channelBPref.getIcon());
         }
 
         channelA.setImportance(IMPORTANCE_NONE);
@@ -376,20 +383,18 @@
             assertEquals("group", group.getKey());
             assertEquals(3, group.getPreferenceCount());
             assertNull(group.getPreference(0).getKey());
-            assertEquals("All \"Group\" notifications", group.getPreference(0).getTitle());
+            assertEquals("All \"Group\" notifications",
+                    group.getPreference(0).getTitle().toString());
             PrimarySwitchPreference channelAPref = (PrimarySwitchPreference) group.getPreference(1);
             assertEquals("channelA", channelAPref.getKey());
-            assertEquals("Channel A", channelAPref.getTitle());
+            assertEquals("Channel A", channelAPref.getTitle().toString());
             assertEquals(Boolean.FALSE, channelAPref.getCheckedState());
             assertNull(channelAPref.getSummary());
-            assertNull(channelAPref.getIcon());
             PrimarySwitchPreference channelBPref = (PrimarySwitchPreference) group.getPreference(2);
             assertEquals("channelB", channelBPref.getKey());
-            assertEquals("Channel B", channelBPref.getTitle());
+            assertEquals("Channel B", channelBPref.getTitle().toString());
             assertEquals(Boolean.TRUE, channelBPref.getCheckedState());
-            assertEquals("~2 notifications per week", channelBPref.getSummary());
-            assertNotNull(channelBPref.getIcon());
+            assertEquals("About 2 notifications per week", channelBPref.getSummary().toString());
         }
     }
-
 }
diff --git a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
index 6559c12..7110a1b 100644
--- a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
+++ b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
@@ -16,12 +16,15 @@
 
 package com.android.settings.wifi.repository;
 
+import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.wifi.SoftApConfiguration.BAND_2GHZ;
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_OPEN;
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA2_PSK;
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE;
 import static android.net.wifi.SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION;
 import static android.net.wifi.WifiAvailableChannel.OP_MODE_SAP;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
 
 import static com.android.settings.wifi.repository.WifiHotspotRepository.BAND_2GHZ_5GHZ;
 import static com.android.settings.wifi.repository.WifiHotspotRepository.BAND_2GHZ_5GHZ_6GHZ;
@@ -42,12 +45,17 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.net.TetheringManager;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiAvailableChannel;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiScanner;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.util.SparseIntArray;
 
+import androidx.annotation.NonNull;
 import androidx.lifecycle.MutableLiveData;
 import androidx.test.annotation.UiThreadTest;
 import androidx.test.core.app.ApplicationProvider;
@@ -81,30 +89,33 @@
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
     @Spy
-    Context mContext = ApplicationProvider.getApplicationContext();
+    private Context mContext = ApplicationProvider.getApplicationContext();
     @Mock
-    WifiManager mWifiManager;
+    private WifiManager mWifiManager;
     @Mock
-    MutableLiveData<Integer> mSecurityType;
+    private TetheringManager mTetheringManager;
     @Mock
-    MutableLiveData<Integer> mSpeedType;
+    private MutableLiveData<Integer> mSecurityType;
+    @Mock
+    private MutableLiveData<Integer> mSpeedType;
 
-    WifiHotspotRepository mWifiHotspotRepository;
-    SoftApConfiguration mSoftApConfiguration;
-    ArgumentCaptor<SoftApConfiguration> mSoftApConfigCaptor =
+    private WifiHotspotRepository mRepository;
+    private SoftApConfiguration mSoftApConfiguration = new SoftApConfiguration.Builder().build();
+    private ArgumentCaptor<SoftApConfiguration> mSoftApConfigCaptor =
             ArgumentCaptor.forClass(SoftApConfiguration.class);
 
     @Before
     public void setUp() {
+        doReturn(new TestHandler()).when(mContext).getMainThreadHandler();
         doReturn(SPEED_6GHZ).when(mSpeedType).getValue();
 
-        mWifiHotspotRepository = new WifiHotspotRepository(mContext, mWifiManager);
-        mWifiHotspotRepository.mSecurityType = mSecurityType;
-        mWifiHotspotRepository.mSpeedType = mSpeedType;
-        mWifiHotspotRepository.mCurrentCountryCode = WIFI_CURRENT_COUNTRY_CODE;
-        mWifiHotspotRepository.mIsDualBand = true;
-        mWifiHotspotRepository.mIs5gAvailable = true;
-        mWifiHotspotRepository.mIs6gAvailable = true;
+        mRepository = new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager);
+        mRepository.mSecurityType = mSecurityType;
+        mRepository.mSpeedType = mSpeedType;
+        mRepository.mCurrentCountryCode = WIFI_CURRENT_COUNTRY_CODE;
+        mRepository.mIsDualBand = true;
+        mRepository.mIs5gAvailable = true;
+        mRepository.mIs6gAvailable = true;
     }
 
     @Test
@@ -115,7 +126,7 @@
                 .build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(mSoftApConfiguration);
 
-        mWifiHotspotRepository.queryLastPasswordIfNeeded();
+        mRepository.queryLastPasswordIfNeeded();
 
         verify(mWifiManager).queryLastConfiguredTetheredApPassphraseSinceBoot(any(), any());
     }
@@ -128,7 +139,7 @@
                 .build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(mSoftApConfiguration);
 
-        mWifiHotspotRepository.queryLastPasswordIfNeeded();
+        mRepository.queryLastPasswordIfNeeded();
 
         verify(mWifiManager, never())
                 .queryLastConfiguredTetheredApPassphraseSinceBoot(any(), any());
@@ -136,46 +147,74 @@
 
     @Test
     public void generatePassword_haveLastPassword_returnLastPassword() {
-        mWifiHotspotRepository.mLastPassword = WIFI_PASSWORD;
+        mRepository.mLastPassword = WIFI_PASSWORD;
 
-        assertThat(mWifiHotspotRepository.generatePassword()).isEqualTo(WIFI_PASSWORD);
+        assertThat(mRepository.generatePassword()).isEqualTo(WIFI_PASSWORD);
     }
 
     @Test
     public void generatePassword_noLastPassword_returnRandomPassword() {
-        mWifiHotspotRepository.mLastPassword = "";
+        mRepository.mLastPassword = "";
 
-        String password = mWifiHotspotRepository.generatePassword();
-
-        assertThat(password).isNotEqualTo(WIFI_PASSWORD);
-        assertThat(password.length()).isNotEqualTo(0);
+        assertThat(mRepository.generatePassword().length()).isNotEqualTo(0);
     }
 
     @Test
-    public void setSoftApConfiguration_setConfigByWifiManager() {
-        SoftApConfiguration config = new SoftApConfiguration.Builder().build();
+    public void generatePassword_configPasswordIsNotEmpty_returnConfigPassword() {
+        mSoftApConfiguration = new SoftApConfiguration.Builder()
+                .setPassphrase(WIFI_PASSWORD, SECURITY_TYPE_WPA2_PSK)
+                .build();
 
-        mWifiHotspotRepository.setSoftApConfiguration(config);
+        assertThat(mRepository.generatePassword(mSoftApConfiguration)).isEqualTo(WIFI_PASSWORD);
+    }
 
-        verify(mWifiManager).setSoftApConfiguration(config);
+    @Test
+    public void generatePassword_configPasswordIsEmpty_returnConfigPassword() {
+        mSoftApConfiguration = new SoftApConfiguration.Builder().build();
+        mRepository.mLastPassword = WIFI_PASSWORD;
+
+        assertThat(mRepository.generatePassword(mSoftApConfiguration)).isEqualTo(WIFI_PASSWORD);
+    }
+
+    @Test
+    public void getSoftApConfiguration_getConfigFromWifiManager() {
+        mRepository.getSoftApConfiguration();
+
+        verify(mWifiManager).getSoftApConfiguration();
+    }
+
+    @Test
+    public void setSoftApConfiguration_setConfigToWifiManager() {
+        mRepository.setSoftApConfiguration(mSoftApConfiguration);
+
+        verify(mWifiManager).setSoftApConfiguration(mSoftApConfiguration);
+    }
+
+    @Test
+    public void setSoftApConfiguration_isRestarting_doNotSetConfig() {
+        mRepository.mIsRestarting = true;
+
+        mRepository.setSoftApConfiguration(mSoftApConfiguration);
+
+        verify(mWifiManager, never()).setSoftApConfiguration(mSoftApConfiguration);
     }
 
     @Test
     public void refresh_liveDataNotUsed_doNothing() {
         // If LiveData is not used then it's null.
-        mWifiHotspotRepository.mSecurityType = null;
-        mWifiHotspotRepository.mSpeedType = null;
+        mRepository.mSecurityType = null;
+        mRepository.mSpeedType = null;
 
-        mWifiHotspotRepository.refresh();
+        mRepository.refresh();
 
         verify(mWifiManager, never()).getSoftApConfiguration();
     }
 
     @Test
     public void refresh_liveDataIsUsed_getConfigAndUpdateLiveData() {
-        mWifiHotspotRepository.getSpeedType();
+        mRepository.getSpeedType();
 
-        mWifiHotspotRepository.refresh();
+        mRepository.refresh();
 
         verify(mWifiManager, atLeast(1)).getSoftApConfiguration();
         verify(mSpeedType).setValue(anyInt());
@@ -183,18 +222,18 @@
 
     @Test
     public void setAutoRefresh_setEnabled_registerCallback() {
-        mWifiHotspotRepository.mActiveCountryCodeChangedCallback = null;
+        mRepository.mActiveCountryCodeChangedCallback = null;
 
-        mWifiHotspotRepository.setAutoRefresh(true);
+        mRepository.setAutoRefresh(true);
 
         verify(mWifiManager).registerActiveCountryCodeChangedCallback(any(), any());
     }
 
     @Test
     public void setAutoRefresh_setDisabled_registerCallback() {
-        mWifiHotspotRepository.setAutoRefresh(true);
+        mRepository.setAutoRefresh(true);
 
-        mWifiHotspotRepository.setAutoRefresh(false);
+        mRepository.setAutoRefresh(false);
 
         verify(mWifiManager).unregisterActiveCountryCodeChangedCallback(any());
     }
@@ -203,17 +242,17 @@
     @UiThreadTest
     public void getSecurityType_shouldNotReturnNull() {
         // If LiveData is not used then it's null.
-        mWifiHotspotRepository.mSecurityType = null;
+        mRepository.mSecurityType = null;
         mockConfigSecurityType(SECURITY_TYPE_OPEN);
 
-        assertThat(mWifiHotspotRepository.getSecurityType()).isNotNull();
+        assertThat(mRepository.getSecurityType()).isNotNull();
     }
 
     @Test
     public void updateSecurityType_securityTypeOpen_setValueCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_OPEN);
 
-        mWifiHotspotRepository.updateSecurityType();
+        mRepository.updateSecurityType();
 
         verify(mSecurityType).setValue(SECURITY_TYPE_OPEN);
     }
@@ -222,7 +261,7 @@
     public void updateSecurityType_securityTypeWpa2_setValueCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_WPA2_PSK);
 
-        mWifiHotspotRepository.updateSecurityType();
+        mRepository.updateSecurityType();
 
         verify(mSecurityType).setValue(SECURITY_TYPE_WPA2_PSK);
     }
@@ -231,7 +270,7 @@
     public void updateSecurityType_securityTypeWpa2Wpa3_setValueCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
 
-        mWifiHotspotRepository.updateSecurityType();
+        mRepository.updateSecurityType();
 
         verify(mSecurityType).setValue(SECURITY_TYPE_WPA3_SAE_TRANSITION);
     }
@@ -240,7 +279,7 @@
     public void updateSecurityType_securityTypeWpa3_setValueCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
 
-        mWifiHotspotRepository.updateSecurityType();
+        mRepository.updateSecurityType();
 
         verify(mSecurityType).setValue(SECURITY_TYPE_WPA3_SAE);
     }
@@ -249,7 +288,7 @@
     public void setSecurityType_sameValue_doNotSetConfig() {
         mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
 
-        mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
+        mRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
 
         verify(mWifiManager, never()).setSoftApConfiguration(any());
     }
@@ -258,7 +297,7 @@
     public void setSecurityType_wpa3ToWpa2Wpa3_setConfigCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE);
 
-        mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
+        mRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -269,7 +308,7 @@
     public void setSecurityType_Wpa2Wpa3ToWpa2_setConfigCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_WPA3_SAE_TRANSITION);
 
-        mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA2_PSK);
+        mRepository.setSecurityType(SECURITY_TYPE_WPA2_PSK);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -280,7 +319,7 @@
     public void setSecurityType_Wpa2ToOpen_setConfigCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_WPA2_PSK);
 
-        mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_OPEN);
+        mRepository.setSecurityType(SECURITY_TYPE_OPEN);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -291,7 +330,7 @@
     public void setSecurityType_OpenToWpa3_setConfigCorrectly() {
         mockConfigSecurityType(SECURITY_TYPE_OPEN);
 
-        mWifiHotspotRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
+        mRepository.setSecurityType(SECURITY_TYPE_WPA3_SAE);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -302,109 +341,109 @@
     @UiThreadTest
     public void getSpeedType_shouldNotReturnNull() {
         // If LiveData is not used then it's null.
-        mWifiHotspotRepository.mSpeedType = null;
+        mRepository.mSpeedType = null;
         SoftApConfiguration config = new SoftApConfiguration.Builder().setBand(BAND_2GHZ).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        assertThat(mWifiHotspotRepository.getSpeedType()).isNotNull();
+        assertThat(mRepository.getSpeedType()).isNotNull();
     }
 
     @Test
     public void updateSpeedType_singleBand2g_get2gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = false;
+        mRepository.mIsDualBand = false;
         SoftApConfiguration config = new SoftApConfiguration.Builder().setBand(BAND_2GHZ).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_2GHZ);
     }
 
     @Test
     public void updateSpeedType_singleBand5gPreferred_get5gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = false;
+        mRepository.mIsDualBand = false;
         SoftApConfiguration config = new SoftApConfiguration.Builder()
                 .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_5GHZ);
     }
 
     @Test
     public void updateSpeedType_singleBand5gPreferredBut5gUnavailable_get2gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = false;
-        mWifiHotspotRepository.mIs5gAvailable = false;
+        mRepository.mIsDualBand = false;
+        mRepository.mIs5gAvailable = false;
         SoftApConfiguration config = new SoftApConfiguration.Builder()
                 .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_2GHZ);
     }
 
     @Test
     public void updateSpeedType_singleBand6gPreferred_get6gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = false;
+        mRepository.mIsDualBand = false;
         SoftApConfiguration config = new SoftApConfiguration.Builder()
                 .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_6GHZ);
     }
 
     @Test
     public void updateSpeedType_singleBand6gPreferredBut6gUnavailable_get5gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = false;
-        mWifiHotspotRepository.mIs6gAvailable = false;
+        mRepository.mIsDualBand = false;
+        mRepository.mIs6gAvailable = false;
         SoftApConfiguration config = new SoftApConfiguration.Builder()
                 .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_5GHZ);
     }
 
     @Test
     public void updateSpeedType_singleBand6gPreferredBut5gAnd6gUnavailable_get2gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = false;
-        mWifiHotspotRepository.mIs5gAvailable = false;
-        mWifiHotspotRepository.mIs6gAvailable = false;
+        mRepository.mIsDualBand = false;
+        mRepository.mIs5gAvailable = false;
+        mRepository.mIs6gAvailable = false;
         SoftApConfiguration config = new SoftApConfiguration.Builder()
                 .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_2GHZ);
     }
 
     @Test
     public void updateSpeedType_dualBand2gAnd5g_get2gAnd5gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = true;
+        mRepository.mIsDualBand = true;
         SoftApConfiguration config = new SoftApConfiguration.Builder()
                 .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_2GHZ_5GHZ);
     }
 
     @Test
     public void updateSpeedType_dualBand2gAnd5gBut5gUnavailable_get2gSpeedType() {
-        mWifiHotspotRepository.mIsDualBand = true;
-        mWifiHotspotRepository.mIs5gAvailable = false;
+        mRepository.mIsDualBand = true;
+        mRepository.mIs5gAvailable = false;
         SoftApConfiguration config = new SoftApConfiguration.Builder()
                 .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
         when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
 
-        mWifiHotspotRepository.updateSpeedType();
+        mRepository.updateSpeedType();
 
         verify(mSpeedType).setValue(SPEED_2GHZ);
     }
@@ -413,7 +452,7 @@
     public void setSpeedType_sameValue_doNotSetConfig() {
         doReturn(SPEED_6GHZ).when(mSpeedType).getValue();
 
-        mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+        mRepository.setSpeedType(SPEED_6GHZ);
 
         verify(mWifiManager, never()).setSoftApConfiguration(any());
     }
@@ -422,7 +461,7 @@
     public void setSpeedType_2g5ghzTo6ghz_setConfigBandTo6ghzPreferred() {
         mockConfigSpeedType(SPEED_2GHZ_5GHZ);
 
-        mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+        mRepository.setSpeedType(SPEED_6GHZ);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(BAND_2GHZ_5GHZ_6GHZ);
@@ -432,7 +471,7 @@
     public void setSpeedType_2g5ghzTo6ghz_setConfigSecurityToWpa3() {
         mockConfig(SPEED_2GHZ_5GHZ, SECURITY_TYPE_WPA3_SAE_TRANSITION);
 
-        mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+        mRepository.setSpeedType(SPEED_6GHZ);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
@@ -442,9 +481,9 @@
     @Test
     public void setSpeedType_6ghzTo2g5ghz_setConfigBandsTo2g5ghz() {
         mockConfigSpeedType(SPEED_6GHZ);
-        mWifiHotspotRepository.mIsDualBand = true;
+        mRepository.mIsDualBand = true;
 
-        mWifiHotspotRepository.setSpeedType(SPEED_2GHZ_5GHZ);
+        mRepository.setSpeedType(SPEED_2GHZ_5GHZ);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         SparseIntArray channels = mSoftApConfigCaptor.getValue().getChannels();
@@ -456,7 +495,7 @@
     public void setSpeedType_2ghzTo5ghz_setConfigBandTo5ghzPreferred() {
         mockConfigSpeedType(SPEED_2GHZ);
 
-        mWifiHotspotRepository.setSpeedType(SPEED_5GHZ);
+        mRepository.setSpeedType(SPEED_5GHZ);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(WIFI_5GHZ_BAND_PREFERRED);
@@ -466,7 +505,7 @@
     public void setSpeedType_5ghzTo6ghz_setConfigBandTo6ghzPreferred() {
         mockConfigSpeedType(SPEED_5GHZ);
 
-        mWifiHotspotRepository.setSpeedType(SPEED_6GHZ);
+        mRepository.setSpeedType(SPEED_6GHZ);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(WIFI_6GHZ_BAND_PREFERRED);
@@ -476,7 +515,7 @@
     public void setSpeedType_6ghzTo2ghz_setConfigBandTo2ghz() {
         mockConfigSpeedType(SPEED_6GHZ);
 
-        mWifiHotspotRepository.setSpeedType(SPEED_2GHZ);
+        mRepository.setSpeedType(SPEED_2GHZ);
 
         verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getBand()).isEqualTo(BAND_2GHZ);
@@ -485,171 +524,227 @@
     @Test
     public void isDualBand_resultSameAsWifiManager() {
         // Reset mIsDualBand to trigger an update
-        mWifiHotspotRepository.mIsDualBand = null;
+        mRepository.mIsDualBand = null;
         when(mWifiManager.isBridgedApConcurrencySupported()).thenReturn(true);
 
-        assertThat(mWifiHotspotRepository.isDualBand()).isTrue();
+        assertThat(mRepository.isDualBand()).isTrue();
 
         // Reset mIsDualBand to trigger an update
-        mWifiHotspotRepository.mIsDualBand = null;
+        mRepository.mIsDualBand = null;
         when(mWifiManager.isBridgedApConcurrencySupported()).thenReturn(false);
 
-        assertThat(mWifiHotspotRepository.isDualBand()).isFalse();
+        assertThat(mRepository.isDualBand()).isFalse();
     }
 
     @Test
     public void is5GHzBandSupported_resultSameAsWifiManager() {
         // Reset mIs5gBandSupported to trigger an update
-        mWifiHotspotRepository.mIs5gBandSupported = null;
+        mRepository.mIs5gBandSupported = null;
         when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
 
-        assertThat(mWifiHotspotRepository.is5GHzBandSupported()).isTrue();
+        assertThat(mRepository.is5GHzBandSupported()).isTrue();
 
         // Reset mIs5gBandSupported to trigger an update
-        mWifiHotspotRepository.mIs5gBandSupported = null;
+        mRepository.mIs5gBandSupported = null;
         when(mWifiManager.is5GHzBandSupported()).thenReturn(false);
 
-        assertThat(mWifiHotspotRepository.is5GHzBandSupported()).isFalse();
+        assertThat(mRepository.is5GHzBandSupported()).isFalse();
     }
 
     @Test
     public void is5gAvailable_hasUsableChannels_returnTrue() {
-        mWifiHotspotRepository.mIs5gBandSupported = true;
+        mRepository.mIs5gBandSupported = true;
         // Reset mIs5gAvailable to trigger an update
-        mWifiHotspotRepository.mIs5gAvailable = null;
+        mRepository.mIs5gAvailable = null;
         List<WifiAvailableChannel> channels =
                 Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP));
         when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
                 .thenReturn(channels);
 
-        assertThat(mWifiHotspotRepository.is5gAvailable()).isTrue();
+        assertThat(mRepository.is5gAvailable()).isTrue();
     }
 
     @Test
     public void is5gAvailable_noUsableChannels_returnFalse() {
-        mWifiHotspotRepository.mIs5gBandSupported = true;
+        mRepository.mIs5gBandSupported = true;
         // Reset mIs5gAvailable to trigger an update
-        mWifiHotspotRepository.mIs5gAvailable = null;
+        mRepository.mIs5gAvailable = null;
         when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP))
                 .thenReturn(null);
 
-        assertThat(mWifiHotspotRepository.is5gAvailable()).isFalse();
+        assertThat(mRepository.is5gAvailable()).isFalse();
     }
 
     @Test
     @UiThreadTest
     public void get5gAvailable_shouldNotReturnNull() {
         // Reset m5gAvailable to trigger an update
-        mWifiHotspotRepository.m5gAvailable = null;
+        mRepository.m5gAvailable = null;
 
-        assertThat(mWifiHotspotRepository.get5gAvailable()).isNotNull();
+        assertThat(mRepository.get5gAvailable()).isNotNull();
     }
 
     @Test
     public void is6GHzBandSupported_resultSameAsWifiManager() {
         // Reset mIs6gBandSupported to trigger an update
-        mWifiHotspotRepository.mIs6gBandSupported = null;
+        mRepository.mIs6gBandSupported = null;
         when(mWifiManager.is6GHzBandSupported()).thenReturn(true);
 
-        assertThat(mWifiHotspotRepository.is6GHzBandSupported()).isTrue();
+        assertThat(mRepository.is6GHzBandSupported()).isTrue();
 
         // Reset mIs6gBandSupported to trigger an update
-        mWifiHotspotRepository.mIs6gBandSupported = null;
+        mRepository.mIs6gBandSupported = null;
         when(mWifiManager.is6GHzBandSupported()).thenReturn(false);
 
-        assertThat(mWifiHotspotRepository.is6GHzBandSupported()).isFalse();
+        assertThat(mRepository.is6GHzBandSupported()).isFalse();
     }
 
     @Test
     public void is6gAvailable_hasUsableChannels_returnTrue() {
-        mWifiHotspotRepository.mIs6gBandSupported = true;
+        mRepository.mIs6gBandSupported = true;
         // Reset mIs6gAvailable to trigger an update
-        mWifiHotspotRepository.mIs6gAvailable = null;
+        mRepository.mIs6gAvailable = null;
         List<WifiAvailableChannel> channels =
                 Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP));
         when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
                 .thenReturn(channels);
 
-        assertThat(mWifiHotspotRepository.is6gAvailable()).isTrue();
+        assertThat(mRepository.is6gAvailable()).isTrue();
     }
 
     @Test
     public void is6gAvailable_noUsableChannels_returnFalse() {
-        mWifiHotspotRepository.mIs6gBandSupported = true;
+        mRepository.mIs6gBandSupported = true;
         // Reset mIs6gAvailable to trigger an update
-        mWifiHotspotRepository.mIs6gAvailable = null;
+        mRepository.mIs6gAvailable = null;
         when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP))
                 .thenReturn(null);
 
-        assertThat(mWifiHotspotRepository.is6gAvailable()).isFalse();
+        assertThat(mRepository.is6gAvailable()).isFalse();
     }
 
     @Test
     @UiThreadTest
     public void get6gAvailable_shouldNotReturnNull() {
         // Reset m6gAvailable to trigger an update
-        mWifiHotspotRepository.m6gAvailable = null;
+        mRepository.m6gAvailable = null;
 
-        assertThat(mWifiHotspotRepository.get6gAvailable()).isNotNull();
+        assertThat(mRepository.get6gAvailable()).isNotNull();
     }
 
     @Test
     public void isSpeedFeatureAvailable_configNotShow_returnFalse() {
-        mWifiHotspotRepository.mIsConfigShowSpeed = false;
+        mRepository.mIsConfigShowSpeed = false;
 
-        assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
     }
 
     @Test
     public void isSpeedFeatureAvailable_5gBandNotSupported_returnFalse() {
-        mWifiHotspotRepository.mIsConfigShowSpeed = true;
-        mWifiHotspotRepository.mIs5gBandSupported = false;
+        mRepository.mIsConfigShowSpeed = true;
+        mRepository.mIs5gBandSupported = false;
 
-        assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
     }
 
     @Test
     public void isSpeedFeatureAvailable_throwExceptionWhenGet5gSapChannel_returnFalse() {
-        mWifiHotspotRepository.mIsConfigShowSpeed = true;
-        mWifiHotspotRepository.mIs5gBandSupported = true;
+        mRepository.mIsConfigShowSpeed = true;
+        mRepository.mIs5gBandSupported = true;
         doThrow(IllegalArgumentException.class).when(mWifiManager)
                 .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
 
-        assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
 
         doThrow(UnsupportedOperationException.class).when(mWifiManager)
                 .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
 
-        assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
     }
 
     @Test
     public void isSpeedFeatureAvailable_throwExceptionWhenGet6gSapChannel_returnFalse() {
-        mWifiHotspotRepository.mIsConfigShowSpeed = true;
-        mWifiHotspotRepository.mIs5gBandSupported = true;
+        mRepository.mIsConfigShowSpeed = true;
+        mRepository.mIs5gBandSupported = true;
         doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
                 .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
         doThrow(IllegalArgumentException.class).when(mWifiManager)
                 .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
 
-        assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
 
         doThrow(UnsupportedOperationException.class).when(mWifiManager)
                 .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
 
-        assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isFalse();
+        assertThat(mRepository.isSpeedFeatureAvailable()).isFalse();
     }
 
     @Test
     public void isSpeedFeatureAvailable_conditionsAreReady_returnTrue() {
-        mWifiHotspotRepository.mIsConfigShowSpeed = true;
-        mWifiHotspotRepository.mIs5gBandSupported = true;
+        mRepository.mIsConfigShowSpeed = true;
+        mRepository.mIs5gBandSupported = true;
         doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager)
                 .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP);
         doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP))).when(mWifiManager)
                 .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP);
 
-        assertThat(mWifiHotspotRepository.isSpeedFeatureAvailable()).isTrue();
+        assertThat(mRepository.isSpeedFeatureAvailable()).isTrue();
+    }
+
+    @Test
+    @UiThreadTest
+    public void getRestarting_shouldNotReturnNull() {
+        // Reset mIsRestarting to trigger an update
+        mRepository.mRestarting = null;
+
+        assertThat(mRepository.getRestarting()).isNotNull();
+    }
+
+    @Test
+    public void restartTetheringIfNeeded_stateDisabled_doNotStopTethering() {
+        mRepository.mWifiApState = WIFI_AP_STATE_DISABLED;
+
+        mRepository.restartTetheringIfNeeded();
+
+        verify(mTetheringManager, never()).stopTethering(TETHERING_WIFI);
+    }
+
+    @Test
+    public void restartTetheringIfNeeded_stateEnabled_stopTethering() {
+        mRepository.mWifiApState = WIFI_AP_STATE_ENABLED;
+
+        mRepository.restartTetheringIfNeeded();
+
+        verify(mTetheringManager).stopTethering(TETHERING_WIFI);
+    }
+
+    @Test
+    public void onStateChanged_stateDisabledAndRestartingFalse_doNotStartTethering() {
+        mRepository.mIsRestarting = false;
+
+        mRepository.mSoftApCallback.onStateChanged(WIFI_AP_STATE_DISABLED, 0);
+
+        verify(mTetheringManager, never()).startTethering(TETHERING_WIFI,
+                mContext.getMainExecutor(), mRepository.mStartTetheringCallback);
+    }
+
+    @Test
+    public void onStateChanged_stateDisabledAndRestartingTrue_startTethering() {
+        mRepository.mIsRestarting = true;
+
+        mRepository.mSoftApCallback.onStateChanged(WIFI_AP_STATE_DISABLED, 0);
+
+        verify(mTetheringManager).startTethering(TETHERING_WIFI, mContext.getMainExecutor(),
+                mRepository.mStartTetheringCallback);
+    }
+
+    @Test
+    public void onStateChanged_stateEnabledAndRestartingTrue_setRestartingFalse() {
+        mRepository.mIsRestarting = true;
+
+        mRepository.mSoftApCallback.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+
+        assertThat(mRepository.mIsRestarting).isFalse();
     }
 
     private void mockConfigSecurityType(int securityType) {
@@ -669,12 +764,12 @@
 
         // Speed Type
         doReturn(speedType).when(mSpeedType).getValue();
-        mWifiHotspotRepository.mIsDualBand = true;
+        mRepository.mIsDualBand = true;
         if (speedType == SPEED_2GHZ) {
-            mWifiHotspotRepository.mIsDualBand = false;
+            mRepository.mIsDualBand = false;
             configBuilder.setBand(BAND_2GHZ);
         } else if (speedType == SPEED_5GHZ) {
-            mWifiHotspotRepository.mIsDualBand = false;
+            mRepository.mIsDualBand = false;
             configBuilder.setBand(BAND_2GHZ_5GHZ);
         } else if (speedType == SPEED_2GHZ_5GHZ) {
             int[] bands = {BAND_2GHZ, BAND_2GHZ_5GHZ};
@@ -684,4 +779,17 @@
         }
         when(mWifiManager.getSoftApConfiguration()).thenReturn(configBuilder.build());
     }
+
+    private static class TestHandler extends Handler {
+
+        TestHandler() {
+            super(Looper.getMainLooper());
+        }
+
+        @Override
+        public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
+            msg.getCallback().run();
+            return true;
+        }
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
index 511240e..9743253 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecuritySettingsTest.java
@@ -26,6 +26,8 @@
 import static com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_WPA2_WPA3;
 import static com.android.settings.wifi.tether.WifiHotspotSecurityViewModel.KEY_SECURITY_WPA3;
 
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -144,6 +146,24 @@
     }
 
     @Test
+    public void onRestartingChanged_restartingTrue_setLoadingTrue() {
+        doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+        mSettings.onRestartingChanged(true);
+
+        verify(mSettings).setLoading(true, false);
+    }
+
+    @Test
+    public void onRestartingChanged_restartingFalse_setLoadingFalse() {
+        doNothing().when(mSettings).setLoading(anyBoolean(), anyBoolean());
+
+        mSettings.onRestartingChanged(false);
+
+        verify(mSettings).setLoading(false, false);
+    }
+
+    @Test
     public void onRadioButtonClicked_clickedWpa3_setSecurityTypeCorrectly() {
         mSettings.onRadioButtonClicked(mRadioButtonWpa3);
 
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
index db768c7..401678c 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSecurityViewModelTest.java
@@ -65,6 +65,8 @@
     MutableLiveData<Integer> mSecurityType;
     @Mock
     MutableLiveData<Integer> mSpeedType;
+    @Mock
+    private MutableLiveData<Boolean> mRestarting;
 
     WifiHotspotSecurityViewModel mViewModel;
 
@@ -75,6 +77,7 @@
                 .thenReturn(mWifiHotspotRepository);
         when(mWifiHotspotRepository.getSecurityType()).thenReturn(mSecurityType);
         when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
+        when(mWifiHotspotRepository.getRestarting()).thenReturn(mRestarting);
 
         mViewModel = new WifiHotspotSecurityViewModel((Application) mContext);
     }
@@ -185,6 +188,11 @@
         assertThat(mViewModel.getViewItemListData()).isNotNull();
     }
 
+    @Test
+    public void getRestarting_shouldNotReturnNull() {
+        assertThat(mViewModel.getRestarting()).isNotNull();
+    }
+
     private void assertItemChecked(boolean checkedWpa3, boolean checkedWpa2Wpa3,
             boolean checkedWpa2, boolean checkedNone) {
         assertThat(mViewModel.mViewItemMap.get(SECURITY_TYPE_WPA3_SAE).mIsChecked)
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java
index 7308161..3a1a927 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiHotspotSpeedViewModelTest.java
@@ -64,6 +64,8 @@
     MutableLiveData<Boolean> m6gAvailable;
     @Mock
     MutableLiveData<Map<Integer, WifiHotspotSpeedViewModel.SpeedInfo>> mSpeedInfoMapData;
+    @Mock
+    private MutableLiveData<Boolean> mRestarting;
 
     WifiHotspotSpeedViewModel mViewModel;
 
@@ -77,6 +79,7 @@
         when(mWifiHotspotRepository.get5gAvailable()).thenReturn(m5gAvailable);
         when(mWifiHotspotRepository.is6GHzBandSupported()).thenReturn(true);
         when(mWifiHotspotRepository.get6gAvailable()).thenReturn(m6gAvailable);
+        when(mWifiHotspotRepository.getRestarting()).thenReturn(mRestarting);
 
         mViewModel = new WifiHotspotSpeedViewModel((Application) mContext);
         mViewModel.mSpeedInfoMapData = mSpeedInfoMapData;
@@ -284,4 +287,9 @@
 
         assertThat(mViewModel.getSpeedInfoMapData()).isNotNull();
     }
+
+    @Test
+    public void getRestarting_shouldNotReturnNull() {
+        assertThat(mViewModel.getRestarting()).isNotNull();
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
index 36da390..af1f62b 100644
--- a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
@@ -55,6 +55,8 @@
     MutableLiveData<Integer> mSecurityType;
     @Mock
     MutableLiveData<Integer> mSpeedType;
+    @Mock
+    private MutableLiveData<Boolean> mRestarting;
 
     WifiTetherViewModel mViewModel;
 
@@ -67,6 +69,7 @@
                 .thenReturn(mWifiHotspotRepository);
         when(mWifiHotspotRepository.getSecurityType()).thenReturn(mSecurityType);
         when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
+        when(mWifiHotspotRepository.getRestarting()).thenReturn(mRestarting);
 
         mViewModel = new WifiTetherViewModel(mApplication);
     }
@@ -83,6 +86,13 @@
     }
 
     @Test
+    public void getSoftApConfiguration_getConfigFromRepository() {
+        mViewModel.getSoftApConfiguration();
+
+        verify(mWifiHotspotRepository).getSoftApConfiguration();
+    }
+
+    @Test
     public void setSoftApConfiguration_setConfigByRepository() {
         SoftApConfiguration config = new SoftApConfiguration.Builder().build();
 
@@ -126,4 +136,9 @@
 
         verify(mWifiHotspotRepository).isSpeedFeatureAvailable();
     }
+
+    @Test
+    public void getRestarting_shouldNotReturnNull() {
+        assertThat(mViewModel.getRestarting()).isNotNull();
+    }
 }