Merge "Update title string for Nfc Tag App Preference" into udc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d82fc94..dc519e9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3073,7 +3073,8 @@
             android:name="Settings$PowerUsageSummaryActivity"
             android:label="@string/power_usage_summary_title"
             android:exported="true"
-            android:icon="@drawable/ic_homepage_battery">
+            android:icon="@drawable/ic_homepage_battery"
+            android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize">
             <intent-filter android:priority="1">
                 <action android:name="android.intent.action.POWER_USAGE_SUMMARY" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/res/values/config.xml b/res/values/config.xml
index 43643d3..ef786be 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -363,6 +363,9 @@
     <!-- Whether Wi-Fi hotspot settings should be shown or not. -->
     <bool name="config_show_wifi_hotspot_settings">true</bool>
 
+    <!-- Whether Wi-Fi hotspot speed should be shown or not. -->
+    <bool name="config_show_wifi_hotspot_speed">false</bool>
+
     <!-- Whether toggle_airplane is available or not. -->
     <bool name="config_show_toggle_airplane">true</bool>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2470e38..0da2371 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2015,6 +2015,16 @@
     <string name="wifi_hotspot_maximize_compatibility_single_ap_summary">Helps other devices find this hotspot. Reduces hotspot connection speed.</string>
     <!-- Summary for the toggle to show the maximize compatibility warning message in dual AP device [CHAR LIMIT=NONE]-->
     <string name="wifi_hotspot_maximize_compatibility_dual_ap_summary">Helps other devices find this hotspot. Increases battery usage.</string>
+    <!-- Title for Wifi hotspot speed [CHAR LIMIT=NONE]-->
+    <string name="wifi_hotspot_speed_title">Speed &amp; compatibility</string>
+    <!-- Summary for Wifi hotspot speed to 2.4 GHz band [CHAR LIMIT=NONE]-->
+    <string name="wifi_hotspot_speed_2g_summary">2.4 GHz / Any device can connect</string>
+    <!-- Summary for Wifi hotspot speed to 5 GHz band [CHAR LIMIT=NONE]-->
+    <string name="wifi_hotspot_speed_5g_summary">5 GHz / Most devices can connect</string>
+    <!-- Summary for Wifi hotspot speed to 6 GHz band [CHAR LIMIT=NONE]-->
+    <string name="wifi_hotspot_speed_6g_summary">6 GHz / Few devices can connect</string>
+    <!-- Summary for Wifi hotspot speed to 6 GHz band [CHAR LIMIT=NONE]-->
+    <string name="wifi_hotspot_speed_2g_and_5g_summary">2.4 and 5 GHz / Any device can connect</string>
 
     <!-- Summary text when turning hotspot on -->
     <string name="wifi_tether_starting">Turning hotspot on\u2026</string>
diff --git a/res/xml/wifi_tether_settings.xml b/res/xml/wifi_tether_settings.xml
index 21f347b..1cd5f48 100644
--- a/res/xml/wifi_tether_settings.xml
+++ b/res/xml/wifi_tether_settings.xml
@@ -45,4 +45,10 @@
     <SwitchPreference
         android:key="wifi_tether_maximize_compatibility"
         android:title="@string/wifi_hotspot_maximize_compatibility"/>
+
+    <Preference
+        android:key="wifi_hotspot_speed"
+        android:title="@string/wifi_hotspot_speed_title"
+        android:summary="@string/summary_placeholder"
+        settings:isPreferenceVisible="@bool/config_show_wifi_hotspot_speed"/>
 </PreferenceScreen>
diff --git a/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdater.java b/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdater.java
index 46ef3fb..da6e178 100644
--- a/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdater.java
+++ b/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdater.java
@@ -22,7 +22,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.SystemClock;
 import android.util.Log;
 import android.view.InputDevice;
 
@@ -57,11 +56,11 @@
     private final InputManager mInputManager;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
 
-    private long mLastUsiSeenTime = 0;
     private Context mContext;
 
     @VisibleForTesting
     Integer mLastDetectedUsiId;
+    BatteryState mLastBatteryState;
 
     @VisibleForTesting
     Preference mUsiPreference;
@@ -75,7 +74,6 @@
         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
         mContext = context;
         mInputManager = context.getSystemService(InputManager.class);
-
     }
 
     /**
@@ -132,13 +130,8 @@
     @Override
     public void onBatteryStateChanged(int deviceId, long eventTimeMillis,
             @NonNull BatteryState batteryState) {
-        if (batteryState.isPresent()) {
-            mLastUsiSeenTime = eventTimeMillis;
-            mLastDetectedUsiId = deviceId;
-        } else {
-            mLastUsiSeenTime = -1;
-            mLastDetectedUsiId = null;
-        }
+        mLastBatteryState = batteryState;
+        mLastDetectedUsiId = deviceId;
         forceUpdate();
     }
 
@@ -184,7 +177,7 @@
     }
 
     private boolean shouldShowUsiPreference() {
-        return isUsiConnectionValid() && !hasConnectedBluetoothStylusDevice();
+        return isUsiBatteryValid() && !hasConnectedBluetoothStylusDevice();
     }
 
     @VisibleForTesting
@@ -206,11 +199,9 @@
     }
 
     @VisibleForTesting
-    boolean isUsiConnectionValid() {
-        // battery listener uses uptimeMillis as its eventTime
-        long currentTime = SystemClock.uptimeMillis();
-        long usiValidityDuration = 60 * 60 * 1000; // 1 hour
-        return mLastUsiSeenTime > 0 && currentTime - usiValidityDuration <= mLastUsiSeenTime;
+    boolean isUsiBatteryValid() {
+        return mLastBatteryState != null
+                && mLastBatteryState.isPresent() && mLastBatteryState.getCapacity() > 0f;
     }
 
     private void launchDeviceDetails() {
diff --git a/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java b/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java
index ecc4ea0..81a15ca 100644
--- a/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java
+++ b/src/com/android/settings/fuelgauge/BatteryBroadcastReceiver.java
@@ -116,12 +116,21 @@
             return;
         }
         final String action = intent.getAction();
+        Log.d(TAG, "updateBatteryStatus: action=" + action);
         if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
             final String batteryLevel = Utils.getBatteryPercentage(intent);
             final String batteryStatus =
                     Utils.getBatteryStatus(mContext, intent, /* compactStatus= */ false);
             final int batteryHealth = intent.getIntExtra(
                     BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN);
+            Log.d(
+                    TAG,
+                    "Battery changed: level="
+                            + batteryLevel
+                            + ", status="
+                            + batteryStatus
+                            + ", health="
+                            + batteryHealth);
             if (!Utils.isBatteryPresent(intent)) {
                 Log.w(TAG, "Problem reading the battery meter.");
                 mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT);
diff --git a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
index 7f314d1..5bec7bd 100644
--- a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -34,6 +35,8 @@
 public class TopLevelBatteryPreferenceController extends BasePreferenceController implements
         LifecycleObserver, OnStart, OnStop, BatteryPreferenceController {
 
+    private static final String TAG = "TopLvBatteryPrefControl";
+
     @VisibleForTesting
     protected boolean mIsBatteryPresent = true;
     @VisibleForTesting
@@ -47,6 +50,7 @@
         super(context, preferenceKey);
         mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext);
         mBatteryBroadcastReceiver.setBatteryChangedListener(type -> {
+            Log.d(TAG, "onBatteryChanged: type=" + type);
             if (type == BatteryBroadcastReceiver.BatteryUpdateType.BATTERY_NOT_PRESENT) {
                 mIsBatteryPresent = false;
             }
@@ -101,6 +105,8 @@
             return null;
         }
 
+        Log.d(TAG, "getDashboardLabel: batteryStatusUpdate=" + batteryStatusUpdate);
+
         if (batteryStatusUpdate) {
             setSummaryAsync(info);
         }
@@ -137,6 +143,7 @@
     /**
      * Callback which receives text for the label.
      */
+    @Override
     public void updateBatteryStatus(String label, BatteryInfo info) {
         mBatteryStatusLabel = label; // Null if adaptive charging is not active
 
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index a1cd09f..020b725 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -22,7 +22,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.KeyguardManager;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -145,7 +145,7 @@
         private boolean mAllowAnyUserId;
         private boolean mForceVerifyPath;
         private boolean mRemoteLockscreenValidation;
-        @Nullable private StartLockscreenValidationRequest mStartLockscreenValidationRequest;
+        @Nullable private RemoteLockscreenValidationSession mRemoteLockscreenValidationSession;
         @Nullable private ComponentName mRemoteLockscreenValidationServiceComponent;
         boolean mRequestGatekeeperPasswordHandle;
 
@@ -272,7 +272,7 @@
 
         /**
          * @param isRemoteLockscreenValidation if true, remote device validation flow will be
-         *                                 started. {@link #setStartLockscreenValidationRequest} and
+         *                                 started. {@link #setRemoteLockscreenValidationSession},
          *                                 {@link #setRemoteLockscreenValidationServiceComponent}
          *                                 must also be used to set the required data.
          */
@@ -283,14 +283,14 @@
         }
 
         /**
-         * @param startLockScreenValidationRequest contains information necessary to perform remote
+         * @param remoteLockscreenValidationSession contains information necessary to perform remote
          *                                         lockscreen validation such as the remote device's
          *                                         lockscreen type, public key to be used for
          *                                         encryption, and remaining attempts.
          */
-        @NonNull public Builder setStartLockscreenValidationRequest(
-                StartLockscreenValidationRequest startLockScreenValidationRequest) {
-            mStartLockscreenValidationRequest = startLockScreenValidationRequest;
+        @NonNull public Builder setRemoteLockscreenValidationSession(
+                RemoteLockscreenValidationSession remoteLockscreenValidationSession) {
+            mRemoteLockscreenValidationSession = remoteLockscreenValidationSession;
             return this;
         }
 
@@ -369,7 +369,7 @@
                 mBuilder.mDescription, mBuilder.mReturnCredentials, mBuilder.mExternal,
                 mBuilder.mForceVerifyPath, mBuilder.mUserId, mBuilder.mAlternateButton,
                 mBuilder.mCheckBoxLabel, mBuilder.mRemoteLockscreenValidation,
-                mBuilder.mStartLockscreenValidationRequest,
+                mBuilder.mRemoteLockscreenValidationSession,
                 mBuilder.mRemoteLockscreenValidationServiceComponent, mBuilder.mAllowAnyUserId,
                 mBuilder.mForegroundOnly, mBuilder.mRequestGatekeeperPasswordHandle);
     }
@@ -379,18 +379,18 @@
             boolean returnCredentials, boolean external, boolean forceVerifyPath,
             int userId, @Nullable CharSequence alternateButton,
             @Nullable CharSequence checkboxLabel, boolean remoteLockscreenValidation,
-            @Nullable StartLockscreenValidationRequest startLockScreenValidationRequest,
+            @Nullable RemoteLockscreenValidationSession remoteLockscreenValidationSession,
             @Nullable ComponentName remoteLockscreenValidationServiceComponent,
             boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
         Optional<Class<?>> activityClass = determineAppropriateActivityClass(
-                returnCredentials, forceVerifyPath, userId, startLockScreenValidationRequest);
+                returnCredentials, forceVerifyPath, userId, remoteLockscreenValidationSession);
         if (activityClass.isEmpty()) {
             return false;
         }
 
         return launchConfirmationActivity(request, title, header, description, activityClass.get(),
                 returnCredentials, external, forceVerifyPath, userId, alternateButton,
-                checkboxLabel, remoteLockscreenValidation, startLockScreenValidationRequest,
+                checkboxLabel, remoteLockscreenValidation, remoteLockscreenValidationSession,
                 remoteLockscreenValidationServiceComponent, allowAnyUser, foregroundOnly,
                 requestGatekeeperPasswordHandle);
     }
@@ -400,7 +400,7 @@
             boolean external, boolean forceVerifyPath, int userId,
             @Nullable CharSequence alternateButton, @Nullable CharSequence checkbox,
             boolean remoteLockscreenValidation,
-            @Nullable StartLockscreenValidationRequest startLockScreenValidationRequest,
+            @Nullable RemoteLockscreenValidationSession remoteLockscreenValidationSession,
             @Nullable ComponentName remoteLockscreenValidationServiceComponent,
             boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle) {
         final Intent intent = new Intent();
@@ -419,8 +419,8 @@
         intent.putExtra(Intent.EXTRA_USER_ID, userId);
         intent.putExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL, alternateButton);
         intent.putExtra(KeyguardManager.EXTRA_CHECKBOX_LABEL, checkbox);
-        intent.putExtra(KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                startLockScreenValidationRequest);
+        intent.putExtra(KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                remoteLockscreenValidationSession);
         intent.putExtra(Intent.EXTRA_COMPONENT_NAME, remoteLockscreenValidationServiceComponent);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOREGROUND_ONLY, foregroundOnly);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, allowAnyUser);
@@ -477,10 +477,10 @@
 
     private Optional<Class<?>> determineAppropriateActivityClass(boolean returnCredentials,
             boolean forceVerifyPath, int userId,
-            @Nullable StartLockscreenValidationRequest startLockscreenValidationRequest) {
+            @Nullable RemoteLockscreenValidationSession remoteLockscreenValidationSession) {
         int lockType;
-        if (startLockscreenValidationRequest != null) {
-            lockType = startLockscreenValidationRequest.getLockscreenUiType();
+        if (remoteLockscreenValidationSession != null) {
+            lockType = remoteLockscreenValidationSession.getLockType();
         } else {
             final int effectiveUserId = UserManager
                     .get(mActivity).getCredentialOwnerProfile(userId);
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index 31d9c74..328e440 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -28,7 +28,7 @@
 
 import android.app.Activity;
 import android.app.KeyguardManager;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.ComponentName;
@@ -235,10 +235,10 @@
                     .setUserId(LockPatternUtils.USER_FRP)
                     .show();
         } else if (remoteValidation) {
-            StartLockscreenValidationRequest startLockScreenValidationRequest =
+            RemoteLockscreenValidationSession remoteLockscreenValidationSession =
                     intent.getParcelableExtra(
-                            KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                            StartLockscreenValidationRequest.class);
+                            KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                            RemoteLockscreenValidationSession.class);
             ComponentName remoteLockscreenValidationServiceComponent =
                     intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME, ComponentName.class);
 
@@ -247,7 +247,7 @@
                     new ChooseLockSettingsHelper.Builder(this);
             launchedCDC = builder
                     .setRemoteLockscreenValidation(true)
-                    .setStartLockscreenValidationRequest(startLockScreenValidationRequest)
+                    .setRemoteLockscreenValidationSession(remoteLockscreenValidationSession)
                     .setRemoteLockscreenValidationServiceComponent(
                             remoteLockscreenValidationServiceComponent)
                     .setHeader(mTitle) // Show the title in the header location
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
index 7c3df61..1bb6df0 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
@@ -25,7 +25,7 @@
 import android.app.Dialog;
 import android.app.KeyguardManager;
 import android.app.RemoteLockscreenValidationResult;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.app.admin.DevicePolicyManager;
 import android.app.admin.ManagedSubscriptionsPolicy;
 import android.content.ComponentName;
@@ -107,7 +107,7 @@
     protected boolean mRemoteValidation;
     protected CharSequence mAlternateButtonText;
     protected BiometricManager mBiometricManager;
-    @Nullable protected StartLockscreenValidationRequest mStartLockscreenValidationRequest;
+    @Nullable protected RemoteLockscreenValidationSession mRemoteLockscreenValidationSession;
     /** Credential saved so the credential can be set for device if remote validation passes */
     @Nullable protected LockscreenCredential mDeviceCredentialGuess;
     @Nullable protected RemoteLockscreenValidationClient mRemoteLockscreenValidationClient;
@@ -141,12 +141,12 @@
             }
         }
         if (mRemoteValidation) {
-            mStartLockscreenValidationRequest = intent.getParcelableExtra(
-                    KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                    StartLockscreenValidationRequest.class);
-            if (mStartLockscreenValidationRequest == null
-                    || mStartLockscreenValidationRequest.getRemainingAttempts() == 0) {
-                Log.e(TAG, "StartLockscreenValidationRequest is null or "
+            mRemoteLockscreenValidationSession = intent.getParcelableExtra(
+                    KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                    RemoteLockscreenValidationSession.class);
+            if (mRemoteLockscreenValidationSession == null
+                    || mRemoteLockscreenValidationSession.getRemainingAttempts() == 0) {
+                Log.e(TAG, "RemoteLockscreenValidationSession is null or "
                         + "no more attempts for remote lockscreen validation.");
                 getActivity().finish();
             }
@@ -437,7 +437,7 @@
 
     private byte[] encryptDeviceCredentialGuess(byte[] guess) {
         try {
-            byte[] encodedPublicKey = mStartLockscreenValidationRequest.getSourcePublicKey();
+            byte[] encodedPublicKey = mRemoteLockscreenValidationSession.getSourcePublicKey();
             PublicKey publicKey = SecureBox.decodePublicKey(encodedPublicKey);
             return SecureBox.encrypt(
                     publicKey,
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index 83dc85c..427b4ff 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -166,7 +166,7 @@
             mErrorTextView = (TextView) view.findViewById(R.id.errorText);
 
             if (mRemoteValidation) {
-                mIsAlpha = mStartLockscreenValidationRequest.getLockscreenUiType()
+                mIsAlpha = mRemoteLockscreenValidationSession.getLockType()
                         == KeyguardManager.PASSWORD;
                 // ProgressBar visibility is set to GONE until interacted with.
                 // Set progress bar to INVISIBLE, so the EditText does not get bumped down later.
@@ -633,6 +633,9 @@
                     break;
                 case RemoteLockscreenValidationResult.RESULT_NO_REMAINING_ATTEMPTS:
                     getActivity().finish();
+                    break;
+                case RemoteLockscreenValidationResult.RESULT_SESSION_EXPIRED:
+                    getActivity().finish();
             }
             mGlifLayout.setProgressBarShown(false);
         }
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index 0013d7a..c664daf 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -646,6 +646,9 @@
                     break;
                 case RemoteLockscreenValidationResult.RESULT_NO_REMAINING_ATTEMPTS:
                     getActivity().finish();
+                    break;
+                case RemoteLockscreenValidationResult.RESULT_SESSION_EXPIRED:
+                    getActivity().finish();
             }
             mGlifLayout.setProgressBarShown(false);
         }
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index b14a4d7..cd096ec 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -126,16 +126,24 @@
                 true /* finishSecondaryWithPrimary */,
                 false /* clearTop */);
 
-        toolbar.setOnClickListener(tb -> {
-            FeatureFactory.getFactory(context).getSlicesFeatureProvider()
-                    .indexSliceDataAsync(context);
+        toolbar.setOnClickListener(tb -> startSearchActivity(context, activity, pageId, intent));
 
-            FeatureFactory.getFactory(context).getMetricsFeatureProvider()
-                    .logSettingsTileClick(KEY_HOMEPAGE_SEARCH_BAR, pageId);
+        toolbar.setHandwritingDelegatorCallback(
+                () -> startSearchActivity(context, activity, pageId, intent));
+        toolbar.setAllowedHandwritingDelegatePackage(intent.getPackage());
+    }
 
-            final Bundle bundle = ActivityOptions.makeSceneTransitionAnimation(activity).toBundle();
-            activity.startActivity(intent, bundle);
-        });
+    /** Start the search activity. */
+    private static void startSearchActivity(
+            Context context, FragmentActivity activity, int pageId, Intent intent) {
+        FeatureFactory.getFactory(context).getSlicesFeatureProvider()
+                .indexSliceDataAsync(context);
+
+        FeatureFactory.getFactory(context).getMetricsFeatureProvider()
+                .logSettingsTileClick(KEY_HOMEPAGE_SEARCH_BAR, pageId);
+
+        final Bundle bundle = ActivityOptions.makeSceneTransitionAnimation(activity).toBundle();
+        activity.startActivity(intent, bundle);
     }
 
     Intent buildSearchIntent(Context context, int pageId);
diff --git a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
index 2f5f3ea..433ff0c 100644
--- a/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
+++ b/src/com/android/settings/wifi/factory/WifiFeatureProvider.java
@@ -20,8 +20,13 @@
 import android.net.wifi.WifiManager;
 
 import androidx.annotation.NonNull;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.lifecycle.ViewModelStoreOwner;
 
 import com.android.settings.wifi.repository.WifiHotspotRepository;
+import com.android.settings.wifi.tether.WifiTetherViewModel;
+
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Wi-Fi Feature Provider
@@ -55,5 +60,13 @@
         }
         return mWifiHotspotRepository;
     }
+
+    /**
+     * Get WifiTetherViewModel
+     */
+    public WifiTetherViewModel getWifiTetherViewModel(@NotNull ViewModelStoreOwner owner) {
+        return new ViewModelProvider(owner).get(WifiTetherViewModel.class);
+    }
+
 }
 
diff --git a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
index b8a25dc..ee1ceea 100644
--- a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
+++ b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
@@ -16,13 +16,27 @@
 
 package com.android.settings.wifi.repository;
 
+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.WifiAvailableChannel.OP_MODE_SAP;
+
 import android.content.Context;
 import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.WifiAvailableChannel;
 import android.net.wifi.WifiManager;
+import android.net.wifi.WifiScanner;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Transformations;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 import java.util.function.Consumer;
 
@@ -30,6 +44,36 @@
  * Wi-Fi Hotspot Repository
  */
 public class WifiHotspotRepository {
+    private static final String TAG = "WifiHotspotRepository";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    /** Wi-Fi hotspot band unknown. */
+    public static final int BAND_UNKNOWN = 0;
+    /** Wi-Fi hotspot band 2.4GHz and 5GHz. */
+    public static final int BAND_2GHZ_5GHZ = BAND_2GHZ | BAND_5GHZ;
+    /** Wi-Fi hotspot band 2.4GHz and 5GHz and 6GHz. */
+    public static final int BAND_2GHZ_5GHZ_6GHZ = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ;
+
+    /** Wi-Fi hotspot speed unknown. */
+    public static final int SPEED_UNKNOWN = 0;
+    /** Wi-Fi hotspot speed 2.4GHz. */
+    public static final int SPEED_2GHZ = 1;
+    /** Wi-Fi hotspot speed 5GHz. */
+    public static final int SPEED_5GHZ = 2;
+    /** Wi-Fi hotspot speed 2.4GHz and 5GHz. */
+    public static final int SPEED_2GHZ_5GHZ = 3;
+    /** Wi-Fi hotspot speed 6GHz. */
+    public static final int SPEED_6GHZ = 4;
+
+    protected static Map<Integer, Integer> sSpeedMap = new HashMap<>();
+
+    static {
+        sSpeedMap.put(BAND_UNKNOWN, SPEED_UNKNOWN);
+        sSpeedMap.put(BAND_2GHZ, SPEED_2GHZ);
+        sSpeedMap.put(BAND_5GHZ, SPEED_5GHZ);
+        sSpeedMap.put(BAND_6GHZ, SPEED_6GHZ);
+        sSpeedMap.put(BAND_2GHZ_5GHZ, SPEED_2GHZ_5GHZ);
+    }
 
     protected final Context mAppContext;
     protected final WifiManager mWifiManager;
@@ -37,6 +81,14 @@
     protected String mLastPassword;
     protected LastPasswordListener mLastPasswordListener = new LastPasswordListener();
 
+    protected MutableLiveData<Integer> mSpeedType;
+
+    protected Boolean mIsDualBand;
+    protected Boolean mIs5gAvailable;
+    protected Boolean mIs6gAvailable;
+    protected String mCurrentCountryCode;
+    protected ActiveCountryCodeChangedCallback mActiveCountryCodeChangedCallback;
+
     public WifiHotspotRepository(@NonNull Context appContext, @NonNull WifiManager wifiManager) {
         mAppContext = appContext;
         mWifiManager = wifiManager;
@@ -73,4 +125,167 @@
         //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
         return randomUUID.substring(0, 8) + randomUUID.substring(9, 13);
     }
+
+    /**
+     * Sets the tethered Wi-Fi AP Configuration.
+     *
+     * @param config A valid SoftApConfiguration specifying the configuration of the SAP.
+     */
+    public void setSoftApConfiguration(@NonNull SoftApConfiguration config) {
+        mWifiManager.setSoftApConfiguration(config);
+        refresh();
+    }
+
+    /**
+     * Refresh data from the SoftApConfiguration.
+     */
+    public void refresh() {
+        updateSpeedType();
+    }
+
+    /**
+     * Set to auto refresh data.
+     *
+     * @param enabled whether the auto refresh should be enabled or not.
+     */
+    public void setAutoRefresh(boolean enabled) {
+        if (enabled) {
+            startAutoRefresh();
+        } else {
+            stopAutoRefresh();
+        }
+    }
+
+    /**
+     * Gets SpeedType LiveData
+     */
+    public LiveData<Integer> getSpeedType() {
+        if (mSpeedType == null) {
+            mSpeedType = new MutableLiveData<>();
+            updateSpeedType();
+        }
+        return Transformations.distinctUntilChanged(mSpeedType);
+    }
+
+    protected void updateSpeedType() {
+        if (mSpeedType == null) {
+            return;
+        }
+        SoftApConfiguration config = mWifiManager.getSoftApConfiguration();
+        if (config == null) {
+            mSpeedType.setValue(SPEED_UNKNOWN);
+            return;
+        }
+        int keyBand = config.getBand();
+        logd("updateSpeedType(), getBand():" + keyBand);
+        if (!is5gAvailable()) {
+            keyBand &= ~BAND_5GHZ;
+        }
+        if (!is6gAvailable()) {
+            keyBand &= ~BAND_6GHZ;
+        }
+        if ((keyBand & BAND_6GHZ) != 0) {
+            keyBand = BAND_6GHZ;
+        } else if (isDualBand() && is5gAvailable()) {
+            keyBand = BAND_2GHZ_5GHZ;
+        } else if ((keyBand & BAND_5GHZ) != 0) {
+            keyBand = BAND_5GHZ;
+        } else if ((keyBand & BAND_2GHZ) != 0) {
+            keyBand = BAND_2GHZ;
+        } else {
+            keyBand = 0;
+        }
+        logd("updateSpeedType(), keyBand:" + keyBand);
+        mSpeedType.setValue(sSpeedMap.get(keyBand));
+    }
+
+    protected boolean isDualBand() {
+        if (mIsDualBand == null) {
+            mIsDualBand = mWifiManager.isBridgedApConcurrencySupported();
+            logd("isDualBand():" + mIsDualBand);
+        }
+        return mIsDualBand;
+    }
+
+    protected boolean is5gAvailable() {
+        if (mIs5gAvailable == null) {
+            // TODO(b/272450463): isBandAvailable(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS) will
+            //  cause crash in the old model device, use a simple check to workaround it first.
+            mIs5gAvailable = (mWifiManager.is5GHzBandSupported() && mCurrentCountryCode != null);
+            logd("is5gAvailable():" + mIs5gAvailable);
+        }
+        return mIs5gAvailable;
+    }
+
+    protected boolean is6gAvailable() {
+        if (mIs6gAvailable == null) {
+            mIs6gAvailable = mWifiManager.is6GHzBandSupported()
+                    && isBandAvailable(WifiScanner.WIFI_BAND_6_GHZ);
+            logd("is6gAvailable():" + mIs6gAvailable);
+        }
+        return mIs6gAvailable;
+    }
+
+    /**
+     * Return whether the Hotspot band is available or not.
+     *
+     * @param band one of the following band constants defined in {@code WifiScanner#WIFI_BAND_*}
+     *             constants.
+     *             1. {@code WifiScanner#WIFI_BAND_5_GHZ_WITH_DFS}
+     *             2. {@code WifiScanner#WIFI_BAND_6_GHZ}
+     */
+    protected boolean isBandAvailable(int band) {
+        List<WifiAvailableChannel> channels = mWifiManager.getUsableChannels(band, OP_MODE_SAP);
+        return (channels != null && channels.size() > 0);
+    }
+
+    protected void purgeRefreshData() {
+        mIsDualBand = null;
+        mIs5gAvailable = null;
+        mIs6gAvailable = null;
+    }
+
+    protected void startAutoRefresh() {
+        if (mActiveCountryCodeChangedCallback != null) {
+            return;
+        }
+        logd("startMonitorSoftApConfiguration()");
+        mActiveCountryCodeChangedCallback = new ActiveCountryCodeChangedCallback();
+        mWifiManager.registerActiveCountryCodeChangedCallback(mAppContext.getMainExecutor(),
+                mActiveCountryCodeChangedCallback);
+    }
+
+    protected void stopAutoRefresh() {
+        if (mActiveCountryCodeChangedCallback == null) {
+            return;
+        }
+        logd("stopMonitorSoftApConfiguration()");
+        mWifiManager.unregisterActiveCountryCodeChangedCallback(mActiveCountryCodeChangedCallback);
+        mActiveCountryCodeChangedCallback = null;
+    }
+
+    protected class ActiveCountryCodeChangedCallback implements
+            WifiManager.ActiveCountryCodeChangedCallback {
+        @Override
+        public void onActiveCountryCodeChanged(String country) {
+            logd("onActiveCountryCodeChanged(), country:" + country);
+            mCurrentCountryCode = country;
+            purgeRefreshData();
+            refresh();
+        }
+
+        @Override
+        public void onCountryCodeInactive() {
+            logd("onCountryCodeInactive()");
+            mCurrentCountryCode = null;
+            purgeRefreshData();
+            refresh();
+        }
+    }
+
+    private static void logd(String msg) {
+        if (DEBUG) {
+            Log.d(TAG, msg);
+        }
+    }
 }
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index 47dba76..3a3691a 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -34,11 +34,13 @@
 
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SettingsMainSwitchBar;
 import com.android.settings.wifi.WifiUtils;
@@ -69,6 +71,8 @@
     @VisibleForTesting
     static final String KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY =
             WifiTetherMaximizeCompatibilityPreferenceController.PREF_KEY;
+    @VisibleForTesting
+    static final String KEY_WIFI_HOTSPOT_SPEED = "wifi_hotspot_speed";
 
     private WifiTetherSwitchBarController mSwitchBarController;
     private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
@@ -84,6 +88,11 @@
     @VisibleForTesting
     TetherChangeReceiver mTetherChangeReceiver;
 
+    @VisibleForTesting
+    WifiTetherViewModel mWifiTetherViewModel;
+    @VisibleForTesting
+    Preference mWifiHotspotSpeed;
+
     static {
         TETHER_STATE_CHANGE_FILTER = new IntentFilter(WIFI_AP_STATE_CHANGED_ACTION);
     }
@@ -120,6 +129,13 @@
 
         setIfOnlyAvailableForAdmins(true);
         mUnavailable = isUiRestricted() || !mWifiRestriction.isHotspotAvailable(getContext());
+
+        mWifiTetherViewModel = FeatureFactory.getFactory(getContext()).getWifiFeatureProvider()
+                .getWifiTetherViewModel(this);
+        mWifiHotspotSpeed = findPreference(KEY_WIFI_HOTSPOT_SPEED);
+        if (mWifiHotspotSpeed != null && mWifiHotspotSpeed.isVisible()) {
+            mWifiTetherViewModel.getSpeedSummary().observe(this, this::onSpeedSummaryChanged);
+        }
     }
 
     @Override
@@ -175,6 +191,7 @@
             // Handle the initial state after register the receiver.
             updateDisplayWithNewConfig();
         }
+        mWifiTetherViewModel.refresh();
     }
 
     @Override
@@ -189,6 +206,9 @@
         }
     }
 
+    protected void onSpeedSummaryChanged(Integer summaryResId) {
+        mWifiHotspotSpeed.setSummary(summaryResId);
+    }
 
     @Override
     protected int getPreferenceScreenResId() {
@@ -228,7 +248,7 @@
             mRestartWifiApAfterConfigChange = true;
             mSwitchBarController.stopTether();
         }
-        mWifiManager.setSoftApConfiguration(config);
+        mWifiTetherViewModel.setSoftApConfiguration(config);
     }
 
     private SoftApConfiguration buildNewConfig() {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherViewModel.java b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
new file mode 100644
index 0000000..4abca02
--- /dev/null
+++ b/src/com/android/settings/wifi/tether/WifiTetherViewModel.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.tether;
+
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ_5GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_5GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_6GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_UNKNOWN;
+
+import android.app.Application;
+import android.net.wifi.SoftApConfiguration;
+
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Transformations;
+
+import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.wifi.repository.WifiHotspotRepository;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Wi-Fi Hotspot ViewModel
+ */
+public class WifiTetherViewModel extends AndroidViewModel {
+    private static final String TAG = "WifiTetherViewModel";
+
+    protected static Map<Integer, Integer> sSpeedSummaryResMap = new HashMap<>();
+
+    static {
+        sSpeedSummaryResMap.put(SPEED_UNKNOWN, R.string.summary_placeholder);
+        sSpeedSummaryResMap.put(SPEED_2GHZ, R.string.wifi_hotspot_speed_2g_summary);
+        sSpeedSummaryResMap.put(SPEED_5GHZ, R.string.wifi_hotspot_speed_5g_summary);
+        sSpeedSummaryResMap.put(SPEED_6GHZ, R.string.wifi_hotspot_speed_6g_summary);
+        sSpeedSummaryResMap.put(SPEED_2GHZ_5GHZ, R.string.wifi_hotspot_speed_2g_and_5g_summary);
+    }
+
+    protected final WifiHotspotRepository mWifiHotspotRepository;
+    protected MutableLiveData<Integer> mSpeedSummary;
+
+    public WifiTetherViewModel(@NotNull Application application) {
+        super(application);
+        mWifiHotspotRepository = FeatureFactory.getFactory(application).getWifiFeatureProvider()
+                .getWifiHotspotRepository();
+        mWifiHotspotRepository.setAutoRefresh(true);
+    }
+
+    @Override
+    protected void onCleared() {
+        mWifiHotspotRepository.setAutoRefresh(false);
+    }
+
+    /**
+     * Sets the tethered Wi-Fi AP Configuration.
+     *
+     * @param config A valid SoftApConfiguration specifying the configuration of the SAP.
+     */
+    public void setSoftApConfiguration(SoftApConfiguration config) {
+        mWifiHotspotRepository.setSoftApConfiguration(config);
+    }
+
+    /**
+     * Refresh data from the SoftApConfiguration.
+     */
+    public void refresh() {
+        mWifiHotspotRepository.refresh();
+    }
+
+    /**
+     * Gets SpeedSummary LiveData
+     */
+    public LiveData<Integer> getSpeedSummary() {
+        if (mSpeedSummary == null) {
+            mSpeedSummary = new MutableLiveData<>();
+            mWifiHotspotRepository.getSpeedType().observeForever(this::onSpeedTypeChanged);
+        }
+        return Transformations.distinctUntilChanged(mSpeedSummary);
+    }
+
+    protected void onSpeedTypeChanged(Integer speedType) {
+        mSpeedSummary.setValue(sSpeedSummaryResMap.get(speedType));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdaterTest.java
index 10f3727..7fb17e2 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdaterTest.java
@@ -127,7 +127,7 @@
     @Test
     public void click_usiPreference_launchUsiDetailsPage() {
         doReturn(mSettingsActivity).when(mDashboardFragment).getContext();
-        doReturn(true).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(true).when(mStylusDeviceUpdater).isUsiBatteryValid();
         doReturn(false).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
         mStylusDeviceUpdater.forceUpdate();
         mStylusDeviceUpdater.mLastDetectedUsiId = 1;
@@ -144,7 +144,7 @@
 
     @Test
     public void forceUpdate_addsUsiPreference_validUsiDevice() {
-        doReturn(true).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(true).when(mStylusDeviceUpdater).isUsiBatteryValid();
         doReturn(false).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
 
         mStylusDeviceUpdater.forceUpdate();
@@ -154,7 +154,7 @@
 
     @Test
     public void forceUpdate_doesNotAddPreference_invalidUsiDevice() {
-        doReturn(false).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(false).when(mStylusDeviceUpdater).isUsiBatteryValid();
         doReturn(false).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
 
         mStylusDeviceUpdater.forceUpdate();
@@ -164,12 +164,12 @@
 
     @Test
     public void forceUpdate_removesUsiPreference_existingPreference_invalidUsiDevice() {
-        doReturn(true).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(true).when(mStylusDeviceUpdater).isUsiBatteryValid();
         doReturn(false).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
 
         mStylusDeviceUpdater.forceUpdate();
 
-        doReturn(false).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(false).when(mStylusDeviceUpdater).isUsiBatteryValid();
         mStylusDeviceUpdater.forceUpdate();
 
         assertThat(mStylusDeviceUpdater.mUsiPreference).isNull();
@@ -177,7 +177,7 @@
 
     @Test
     public void forceUpdate_doesNotAddUsiPreference_bluetoothStylusConnected() {
-        doReturn(true).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(true).when(mStylusDeviceUpdater).isUsiBatteryValid();
         doReturn(true).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
 
         mStylusDeviceUpdater.forceUpdate();
@@ -187,7 +187,7 @@
 
     @Test
     public void forceUpdate_addsUsiPreference_bluetoothStylusDisconnected() {
-        doReturn(true).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(true).when(mStylusDeviceUpdater).isUsiBatteryValid();
         doReturn(true).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
         mStylusDeviceUpdater.forceUpdate();
 
@@ -199,7 +199,7 @@
 
     @Test
     public void forceUpdate_removesUsiPreference_existingPreference_bluetoothStylusConnected() {
-        doReturn(true).when(mStylusDeviceUpdater).isUsiConnectionValid();
+        doReturn(true).when(mStylusDeviceUpdater).isUsiBatteryValid();
         doReturn(false).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
         mStylusDeviceUpdater.forceUpdate();
         doReturn(true).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
@@ -218,7 +218,7 @@
         mStylusDeviceUpdater.onBatteryStateChanged(1, SystemClock.uptimeMillis(),
                 batteryState);
 
-        assertThat(mStylusDeviceUpdater.isUsiConnectionValid()).isTrue();
+        assertThat(mStylusDeviceUpdater.isUsiBatteryValid()).isTrue();
     }
 
     @Test
@@ -230,19 +230,7 @@
         mStylusDeviceUpdater.onBatteryStateChanged(1, SystemClock.uptimeMillis(),
                 batteryState);
 
-        assertThat(mStylusDeviceUpdater.isUsiConnectionValid()).isFalse();
-    }
-
-    @Test
-    public void onBatteryStateChanged_ddetectsInvalidUsi_staleBatteryEventTime() {
-        doReturn(false).when(mStylusDeviceUpdater).hasConnectedBluetoothStylusDevice();
-        BatteryState batteryState = mock(BatteryState.class);
-        doReturn(true).when(batteryState).isPresent();
-        doReturn(0.5f).when(batteryState).getCapacity();
-
-        mStylusDeviceUpdater.onBatteryStateChanged(1, 0, batteryState);
-
-        assertThat(mStylusDeviceUpdater.isUsiConnectionValid()).isFalse();
+        assertThat(mStylusDeviceUpdater.isUsiBatteryValid()).isFalse();
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockSettingsHelperTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockSettingsHelperTest.java
index 2777529..fcab797 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockSettingsHelperTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockSettingsHelperTest.java
@@ -2,7 +2,7 @@
 
 import static com.android.settings.password.TestUtils.COMPONENT_NAME;
 import static com.android.settings.password.TestUtils.VALID_REMAINING_ATTEMPTS;
-import static com.android.settings.password.TestUtils.createStartLockscreenValidationRequest;
+import static com.android.settings.password.TestUtils.createRemoteLockscreenValidationSession;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -15,7 +15,7 @@
 
 import android.app.Activity;
 import android.app.KeyguardManager;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -170,13 +170,13 @@
     public void launchConfirmPassword_remoteValidation_passwordLockType() throws Exception {
         Activity activity = Robolectric.setupActivity(Activity.class);
         ShadowActivity shadowActivity = Shadows.shadowOf(activity);
-        StartLockscreenValidationRequest request = createStartLockscreenValidationRequest(
+        RemoteLockscreenValidationSession request = createRemoteLockscreenValidationSession(
                 KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS);
 
         ChooseLockSettingsHelper chooseLockSettingsHelper = getChooseLockSettingsHelper(
                 new ChooseLockSettingsHelper.Builder(activity)
                         .setRemoteLockscreenValidation(true)
-                        .setStartLockscreenValidationRequest(request)
+                        .setRemoteLockscreenValidationSession(request)
                         .setRemoteLockscreenValidationServiceComponent(COMPONENT_NAME));
         chooseLockSettingsHelper.launch();
 
@@ -187,8 +187,8 @@
                 ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, false)
         ).isTrue();
         assertThat(startedIntent.getParcelableExtra(
-                KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                StartLockscreenValidationRequest.class)
+                KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                RemoteLockscreenValidationSession.class)
         ).isEqualTo(request);
         assertThat(startedIntent.getParcelableExtra(
                 Intent.EXTRA_COMPONENT_NAME, ComponentName.class)
@@ -199,13 +199,13 @@
     public void launchConfirmPassword_remoteValidation_pinLockType() throws Exception {
         Activity activity = Robolectric.setupActivity(Activity.class);
         ShadowActivity shadowActivity = Shadows.shadowOf(activity);
-        StartLockscreenValidationRequest request = createStartLockscreenValidationRequest(
+        RemoteLockscreenValidationSession request = createRemoteLockscreenValidationSession(
                 KeyguardManager.PIN, VALID_REMAINING_ATTEMPTS);
 
         ChooseLockSettingsHelper chooseLockSettingsHelper = getChooseLockSettingsHelper(
                 new ChooseLockSettingsHelper.Builder(activity)
                         .setRemoteLockscreenValidation(true)
-                        .setStartLockscreenValidationRequest(request)
+                        .setRemoteLockscreenValidationSession(request)
                         .setRemoteLockscreenValidationServiceComponent(COMPONENT_NAME));
         chooseLockSettingsHelper.launch();
 
@@ -216,8 +216,8 @@
                 ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, false)
         ).isTrue();
         assertThat(startedIntent.getParcelableExtra(
-                KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                StartLockscreenValidationRequest.class)
+                KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                RemoteLockscreenValidationSession.class)
         ).isEqualTo(request);
         assertThat(startedIntent.getParcelableExtra(
                 Intent.EXTRA_COMPONENT_NAME, ComponentName.class)
@@ -228,13 +228,13 @@
     public void launchConfirmPattern_remoteValidation_patternLockType() throws Exception {
         Activity activity = Robolectric.setupActivity(Activity.class);
         ShadowActivity shadowActivity = Shadows.shadowOf(activity);
-        StartLockscreenValidationRequest request = createStartLockscreenValidationRequest(
+        RemoteLockscreenValidationSession request = createRemoteLockscreenValidationSession(
                 KeyguardManager.PATTERN, VALID_REMAINING_ATTEMPTS);
 
         ChooseLockSettingsHelper chooseLockSettingsHelper = getChooseLockSettingsHelper(
                 new ChooseLockSettingsHelper.Builder(activity)
                         .setRemoteLockscreenValidation(true)
-                        .setStartLockscreenValidationRequest(request)
+                        .setRemoteLockscreenValidationSession(request)
                         .setRemoteLockscreenValidationServiceComponent(COMPONENT_NAME));
         chooseLockSettingsHelper.launch();
 
@@ -245,8 +245,8 @@
                 ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, false)
         ).isTrue();
         assertThat(startedIntent.getParcelableExtra(
-                KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                StartLockscreenValidationRequest.class)
+                KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                RemoteLockscreenValidationSession.class)
         ).isEqualTo(request);
         assertThat(startedIntent.getParcelableExtra(
                 Intent.EXTRA_COMPONENT_NAME, ComponentName.class)
diff --git a/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java b/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java
index 40b359e..299b1eb 100644
--- a/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java
+++ b/tests/robotests/src/com/android/settings/password/ConfirmCredentialTest.java
@@ -23,7 +23,7 @@
 import static com.android.settings.password.TestUtils.buildConfirmDeviceCredentialBaseActivity;
 import static com.android.settings.password.TestUtils.createPackageInfoWithService;
 import static com.android.settings.password.TestUtils.createRemoteLockscreenValidationIntent;
-import static com.android.settings.password.TestUtils.createStartLockscreenValidationRequest;
+import static com.android.settings.password.TestUtils.createRemoteLockscreenValidationSession;
 import static com.android.settings.password.TestUtils.getConfirmDeviceCredentialBaseFragment;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -132,8 +132,8 @@
             throws Exception {
         Intent intentWithInvalidComponentName = new Intent()
                 .putExtra(ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, true)
-                .putExtra(KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                        createStartLockscreenValidationRequest(
+                .putExtra(KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                        createRemoteLockscreenValidationSession(
                                 KeyguardManager.PASSWORD, VALID_REMAINING_ATTEMPTS))
                 .putExtra(Intent.EXTRA_COMPONENT_NAME, new ComponentName("pkg", "cls"));
 
diff --git a/tests/robotests/src/com/android/settings/password/TestUtils.java b/tests/robotests/src/com/android/settings/password/TestUtils.java
index 246d926..ef08f05 100644
--- a/tests/robotests/src/com/android/settings/password/TestUtils.java
+++ b/tests/robotests/src/com/android/settings/password/TestUtils.java
@@ -18,7 +18,7 @@
 
 import android.app.KeyguardManager;
 import android.app.RemoteLockscreenValidationResult;
-import android.app.StartLockscreenValidationRequest;
+import android.app.RemoteLockscreenValidationSession;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -79,15 +79,15 @@
             int lockscreenType, int remainingAttempts) throws Exception {
         return new Intent()
                 .putExtra(ConfirmDeviceCredentialBaseFragment.IS_REMOTE_LOCKSCREEN_VALIDATION, true)
-                .putExtra(KeyguardManager.EXTRA_START_LOCKSCREEN_VALIDATION_REQUEST,
-                        createStartLockscreenValidationRequest(lockscreenType, remainingAttempts))
+                .putExtra(KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION,
+                        createRemoteLockscreenValidationSession(lockscreenType, remainingAttempts))
                 .putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME);
     }
 
-    public static StartLockscreenValidationRequest createStartLockscreenValidationRequest(
+    public static RemoteLockscreenValidationSession createRemoteLockscreenValidationSession(
             int lockscreenType, int remainingAttempts) throws NoSuchAlgorithmException {
-        return new StartLockscreenValidationRequest.Builder()
-                .setLockscreenUiType(lockscreenType)
+        return new RemoteLockscreenValidationSession.Builder()
+                .setLockType(lockscreenType)
                 .setRemainingAttempts(remainingAttempts)
                 .setSourcePublicKey(SecureBox.genKeyPair().getPublic().getEncoded())
                 .build();
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 7f8a06d..582f792 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -41,6 +41,8 @@
 import android.widget.TextView;
 
 import androidx.fragment.app.FragmentActivity;
+import androidx.lifecycle.ViewModelStoreOwner;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
 
@@ -49,6 +51,8 @@
 import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settings.wifi.factory.WifiFeatureProvider;
+import com.android.settings.wifi.repository.WifiHotspotRepository;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -90,6 +94,10 @@
     private PreferenceScreen mPreferenceScreen;
     @Mock
     private TextView mEmptyTextView;
+    @Mock
+    WifiTetherViewModel mWifiTetherViewModel;
+    @Mock
+    WifiHotspotRepository mWifiHotspotRepository;
 
     private WifiTetherSettings mWifiTetherSettings;
 
@@ -106,6 +114,11 @@
         when(mWifiRestriction.isTetherAvailable(mContext)).thenReturn(true);
         when(mWifiRestriction.isHotspotAvailable(mContext)).thenReturn(true);
 
+        WifiFeatureProvider provider = FakeFeatureFactory.setupForTest().getWifiFeatureProvider();
+        when(provider.getWifiHotspotRepository()).thenReturn(mWifiHotspotRepository);
+        when(provider.getWifiTetherViewModel(mock(ViewModelStoreOwner.class)))
+                .thenReturn(mWifiTetherViewModel);
+
         mWifiTetherSettings = new WifiTetherSettings(mWifiRestriction);
     }
 
@@ -143,6 +156,16 @@
     }
 
     @Test
+    public void onSpeedSummaryChanged_canNotShowWifiHotspot_returnFalse() {
+        int stringResId = R.string.wifi_hotspot_speed_6g_summary;
+        mWifiTetherSettings.mWifiHotspotSpeed = mock(Preference.class);
+
+        mWifiTetherSettings.onSpeedSummaryChanged(stringResId);
+
+        verify(mWifiTetherSettings.mWifiHotspotSpeed).setSummary(stringResId);
+    }
+
+    @Test
     public void createPreferenceControllers_getPreferenceControllersNotEmpty() {
         assertThat(WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.getPreferenceControllers(mContext))
                 .isNotEmpty();
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 58a9d1c..52f02f5 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,21 @@
 
 package com.android.settings.wifi.repository;
 
+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_WPA3_SAE;
 
+import static com.android.settings.wifi.repository.WifiHotspotRepository.BAND_2GHZ_5GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.BAND_2GHZ_5GHZ_6GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_2GHZ_5GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_5GHZ;
+import static com.android.settings.wifi.repository.WifiHotspotRepository.SPEED_6GHZ;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -30,6 +39,8 @@
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiManager;
 
+import androidx.lifecycle.MutableLiveData;
+import androidx.test.annotation.UiThreadTest;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
@@ -46,6 +57,10 @@
 public class WifiHotspotRepositoryTest {
     static final String WIFI_SSID = "wifi_ssid";
     static final String WIFI_PASSWORD = "wifi_password";
+    static final String WIFI_CURRENT_COUNTRY_CODE = "US";
+
+    static final int WIFI_5GHZ_BAND_PREFERRED = BAND_2GHZ_5GHZ;
+    static final int WIFI_6GHZ_BAND_PREFERRED = BAND_2GHZ_5GHZ_6GHZ;
 
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -53,6 +68,8 @@
     Context mContext = ApplicationProvider.getApplicationContext();
     @Mock
     WifiManager mWifiManager;
+    @Mock
+    MutableLiveData<Integer> mSpeedType;
 
     WifiHotspotRepository mWifiHotspotRepository;
     SoftApConfiguration mSoftApConfiguration;
@@ -60,6 +77,10 @@
     @Before
     public void setUp() {
         mWifiHotspotRepository = new WifiHotspotRepository(mContext, mWifiManager);
+        mWifiHotspotRepository.mCurrentCountryCode = WIFI_CURRENT_COUNTRY_CODE;
+        mWifiHotspotRepository.mIsDualBand = true;
+        mWifiHotspotRepository.mIs5gAvailable = true;
+        mWifiHotspotRepository.mIs6gAvailable = true;
     }
 
     @Test
@@ -105,4 +126,171 @@
         assertThat(password).isNotEqualTo(WIFI_PASSWORD);
         assertThat(password.length()).isNotEqualTo(0);
     }
+
+    @Test
+    public void setSoftApConfiguration_setConfigByWifiManager() {
+        SoftApConfiguration config = new SoftApConfiguration.Builder().build();
+
+        mWifiHotspotRepository.setSoftApConfiguration(config);
+
+        verify(mWifiManager).setSoftApConfiguration(config);
+    }
+
+    @Test
+    public void refresh_liveDataNotUsed_doNothing() {
+        // If LiveData is not used then it's null.
+        mWifiHotspotRepository.mSpeedType = null;
+
+        mWifiHotspotRepository.refresh();
+
+        verify(mWifiManager, never()).getSoftApConfiguration();
+    }
+
+    @Test
+    public void refresh_liveDataIsUsed_getConfigAndUpdateLiveData() {
+        // If LiveData is used then it's not null.
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.refresh();
+
+        verify(mWifiManager).getSoftApConfiguration();
+        verify(mSpeedType).setValue(anyInt());
+    }
+
+    @Test
+    public void setAutoRefresh_setEnabled_registerCallback() {
+        mWifiHotspotRepository.mActiveCountryCodeChangedCallback = null;
+
+        mWifiHotspotRepository.setAutoRefresh(true);
+
+        verify(mWifiManager).registerActiveCountryCodeChangedCallback(any(), any());
+    }
+
+    @Test
+    public void setAutoRefresh_setDisabled_registerCallback() {
+        mWifiHotspotRepository.setAutoRefresh(true);
+
+        mWifiHotspotRepository.setAutoRefresh(false);
+
+        verify(mWifiManager).unregisterActiveCountryCodeChangedCallback(any());
+    }
+
+    @Test
+    @UiThreadTest
+    public void getSpeedType_shouldNotReturnNull() {
+        // If LiveData is not used then it's null.
+        mWifiHotspotRepository.mSpeedType = null;
+        SoftApConfiguration config = new SoftApConfiguration.Builder().setBand(BAND_2GHZ).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+
+        assertThat(mWifiHotspotRepository.getSpeedType()).isNotNull();
+    }
+
+    @Test
+    public void updateSpeedType_singleBand2g_get2gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = false;
+        SoftApConfiguration config = new SoftApConfiguration.Builder().setBand(BAND_2GHZ).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_2GHZ);
+    }
+
+    @Test
+    public void updateSpeedType_singleBand5gPreferred_get5gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = false;
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_5GHZ);
+    }
+
+    @Test
+    public void updateSpeedType_singleBand5gPreferredBut5gUnavailable_get2gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = false;
+        mWifiHotspotRepository.mIs5gAvailable = false;
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_2GHZ);
+    }
+
+    @Test
+    public void updateSpeedType_singleBand6gPreferred_get6gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = false;
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_6GHZ);
+    }
+
+    @Test
+    public void updateSpeedType_singleBand6gPreferredBut6gUnavailable_get5gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = false;
+        mWifiHotspotRepository.mIs6gAvailable = false;
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_5GHZ);
+    }
+
+    @Test
+    public void updateSpeedType_singleBand6gPreferredBut5gAnd6gUnavailable_get2gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = false;
+        mWifiHotspotRepository.mIs5gAvailable = false;
+        mWifiHotspotRepository.mIs6gAvailable = false;
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setBand(WIFI_6GHZ_BAND_PREFERRED).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_2GHZ);
+    }
+
+    @Test
+    public void updateSpeedType_dualBand2gAnd5g_get2gAnd5gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = true;
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_2GHZ_5GHZ);
+    }
+
+    @Test
+    public void updateSpeedType_dualBand2gAnd5gBut5gUnavailable_get2gSpeedType() {
+        mWifiHotspotRepository.mIsDualBand = true;
+        mWifiHotspotRepository.mIs5gAvailable = false;
+        SoftApConfiguration config = new SoftApConfiguration.Builder()
+                .setBand(WIFI_5GHZ_BAND_PREFERRED).build();
+        when(mWifiManager.getSoftApConfiguration()).thenReturn(config);
+        mWifiHotspotRepository.mSpeedType = mSpeedType;
+
+        mWifiHotspotRepository.updateSpeedType();
+
+        verify(mSpeedType).setValue(SPEED_2GHZ);
+    }
 }
diff --git a/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
new file mode 100644
index 0000000..6724dd5
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/tether/WifiTetherViewModelTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wifi.tether;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.net.wifi.SoftApConfiguration;
+
+import androidx.lifecycle.MutableLiveData;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.wifi.repository.WifiHotspotRepository;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiTetherViewModelTest {
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    Application mApplication;
+    @Mock
+    Executor mExecutor;
+    @Mock
+    WifiHotspotRepository mWifiHotspotRepository;
+    @Mock
+    MutableLiveData<Integer> mSpeedType;
+
+    WifiTetherViewModel mViewModel;
+
+    @Before
+    public void setUp() {
+        when(mApplication.getMainExecutor()).thenReturn(mExecutor);
+
+        FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
+        when(featureFactory.getWifiFeatureProvider().getWifiHotspotRepository())
+                .thenReturn(mWifiHotspotRepository);
+        when(mWifiHotspotRepository.getSpeedType()).thenReturn(mSpeedType);
+
+        mViewModel = new WifiTetherViewModel(mApplication);
+    }
+
+    @Test
+    public void constructor_setAutoRefreshTrue() {
+        verify(mWifiHotspotRepository).setAutoRefresh(true);
+    }
+
+    @Test
+    public void onCleared_setAutoRefreshFalse() {
+        mViewModel.onCleared();
+
+        verify(mWifiHotspotRepository).setAutoRefresh(false);
+    }
+
+    @Test
+    public void setSoftApConfiguration_setConfigByRepository() {
+        SoftApConfiguration config = new SoftApConfiguration.Builder().build();
+
+        mViewModel.setSoftApConfiguration(config);
+
+        verify(mWifiHotspotRepository).setSoftApConfiguration(config);
+    }
+
+    @Test
+    public void refresh_refreshByRepository() {
+        mViewModel.refresh();
+
+        verify(mWifiHotspotRepository).refresh();
+    }
+
+    @Test
+    @UiThreadTest
+    public void getSpeedSummary_returnNotNull() {
+        mViewModel.mSpeedSummary = null;
+
+        mViewModel.getSpeedSummary();
+
+        assertThat(mViewModel.mSpeedSummary).isNotNull();
+    }
+}