Merge "Fix face/fingerprint consent primary footer button logic" into sc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0a40c89..570b53d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -713,7 +713,8 @@
         <activity
             android:name="Settings$ManageAssistActivity"
             android:exported="true"
-            android:label="@string/assist_and_voice_input_title">
+            android:label="@string/assist_and_voice_input_title"
+            android:theme="@style/Theme.SubSettings">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.VOICE_INPUT_SETTINGS" />
                 <category android:name="android.intent.category.DEFAULT" />
diff --git a/res/drawable/ic_no_internet_airplane.xml b/res/drawable/ic_no_internet_airplane.xml
deleted file mode 100644
index 3b22811..0000000
--- a/res/drawable/ic_no_internet_airplane.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-    Copyright (C) 2021 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
-        android:fillAlpha="0.3"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M22,19.3v-0.9l-3.37,-2.25v-2.47C18.63,13.3 18.35,13 18,13s-0.63,0.3 -0.63,0.68v2.47L14,18.4v0.9l3.37,-1.12v2.48l-0.84,0.68V22L18,21.55L19.47,22v-0.67l-0.84,-0.68v-2.48L22,19.3z"/>
-</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_no_internet_unavailable.xml b/res/drawable/ic_no_internet_unavailable.xml
new file mode 100644
index 0000000..049034a
--- /dev/null
+++ b/res/drawable/ic_no_internet_unavailable.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright (C) 2021 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M2,12C2,6.48 6.47,2 11.99,2C17.52,2 22,6.48 22,12c0,0.34 -0.02,0.67 -0.05,1h-2.02c0.04,-0.33 0.07,-0.66 0.07,-1c0,-0.69 -0.1,-1.36 -0.26,-2h-3.38c0.08,0.66 0.14,1.32 0.14,2c0,0.34 -0.01,0.67 -0.04,1h-2.01c0.03,-0.33 0.05,-0.66 0.05,-1c0,-0.68 -0.07,-1.35 -0.16,-2H9.66c-0.09,0.65 -0.16,1.32 -0.16,2s0.07,1.34 0.16,2H13v2h-2.91c0.43,1.43 1.08,2.76 1.91,3.96V20h1v1.95C12.67,21.98 12.33,22 11.99,22C6.47,22 2,17.52 2,12zM15.97,8h2.95c-0.96,-1.65 -2.49,-2.93 -4.33,-3.56C15.19,5.55 15.65,6.75 15.97,8zM13.91,8C13.48,6.57 12.83,5.24 12,4.04c-0.83,1.2 -1.48,2.53 -1.91,3.96H13.91zM4,12c0,0.69 0.1,1.36 0.26,2h3.38c-0.08,-0.66 -0.14,-1.32 -0.14,-2s0.06,-1.34 0.14,-2H4.26C4.1,10.64 4,11.31 4,12zM8.03,16H5.08c0.96,1.66 2.49,2.93 4.33,3.56C8.81,18.45 8.35,17.25 8.03,16zM5.08,8h2.95c0.32,-1.25 0.78,-2.45 1.38,-3.56C7.57,5.07 6.04,6.34 5.08,8z"
+        android:fillAlpha="0.3"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+</vector>
diff --git a/res/layout/manage_apps_filter_spinner.xml b/res/layout/manage_apps_filter_spinner.xml
new file mode 100644
index 0000000..8283bb8
--- /dev/null
+++ b/res/layout/manage_apps_filter_spinner.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@android:color/transparent">
+
+    <com.android.settingslib.widget.settingsspinner.SettingsSpinner
+        android:id="@+id/filter_spinner"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginBottom="8dp"
+        android:theme="@style/Widget.PopupWindow.Settings"/>
+</FrameLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 90708da..60b8cd2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3166,8 +3166,8 @@
     <string name="wallpaper_settings_title">Wallpaper</string>
     <!-- Styles & Wallpapers settings title [CHAR LIMIT=30] -->
     <string name="style_and_wallpaper_settings_title">Wallpaper &amp; style</string>
-    <!-- Summary for the top level Styles & wallpapers Settings [CHAR LIMIT=NONE]-->
-    <string name="wallpaper_dashboard_summary">Colors, themed icons, app grid</string>
+    <!-- Summary for the top level wallpapers settings [CHAR LIMIT=NONE]-->
+    <string name="wallpaper_dashboard_summary">Home, lock screen</string>
     <!-- Wallpaper settings summary when default wallpaper is used [CHAR LIMIT=NONE] -->
     <string name="wallpaper_settings_summary_default">Default</string>
     <!-- Wallpaper settings summary when wallpaper has been updated [CHAR LIMIT=NONE] -->
@@ -11676,7 +11676,7 @@
     <string name="swipe_bottom_to_notifications_summary">Swipe down on the bottom edge of the screen to show your notifications.\nYou can\'t use one-handed mode when this feature is turned on.</string>
 
     <!-- Preference and settings suggestion title text for one handed [CHAR LIMIT=60] -->
-    <string name="one_handed_title">One-Handed mode</string>
+    <string name="one_handed_title">One-handed mode</string>
     <!-- Preference Switch for enabling one handed [CHAR LIMIT=60] -->
     <string name="one_handed_mode_enabled">Use one-handed mode</string>
     <!-- Preference Switch for app taps to exit one handed [CHAR LIMIT=60] -->
@@ -11691,6 +11691,19 @@
     <string name="one_handed_timeout_long">12 seconds</string>
     <!-- Search keywords for "One-Handed" settings [CHAR_LIMIT=NONE] -->
     <string name="keywords_one_handed">reachability</string>
+    <!-- Category title for one handed swipe down [CHAR_LIMIT=60] -->
+    <string name="one_handed_mode_swipe_down_category">Swipe down to</string>
+    <!-- One-handed mode Intro Text [CHAR_LIMIT=NONE] -->
+    <string name="one_handed_mode_intro_text">To use one handed mode, swipe down from the bottom edge of the screen. To use this feature, make sure gesture navigation is turned on in system navigation settings.</string>
+    <!-- One-handed mode pull down screen into reach action title [CHAR_LIMIT=60] -->
+    <string name="one_handed_action_pull_down_screen_title">Pull screen into reach</string>
+    <!-- One-handed mode pull down screen into reach action title [CHAR_LIMIT=NONE] -->
+    <string name="one_handed_action_pull_down_screen_summary">The top of the screen will move into reach of your thumb.</string>
+    <!-- One-handed mode show notification action [CHAR_LIMIT=60] -->
+    <string name="one_handed_action_show_notification_title">Show notifications</string>
+    <!-- One-handed mode show notification action [CHAR_LIMIT=NONE] -->
+    <string name="one_handed_action_show_notification_summary">Notification and settings will appear.</string>
+    <!-- One-handed mode Intro text for gesture navigation [CHAR_LIMIT=NONE] -->
 
     <!-- Summary text for ambient display double tap [CHAR LIMIT=NONE]-->
     <string name="ambient_display_summary">To check time, notifications, and other info, double-tap your screen.</string>
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index 1f4895e..6de9c1a 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -34,13 +34,6 @@
         settings:controller="com.android.settings.gestures.SwipeToNotificationPreferenceController" />
 
     <Preference
-        android:key="gesture_swipe_bottom_to_notification"
-        android:title="@string/swipe_bottom_to_notifications_title"
-        android:fragment="com.android.settings.gestures.SwipeBottomToNotificationSettings"
-        settings:searchable="false"
-        settings:controller="com.android.settings.gestures.SwipeBottomToNotificationPreferenceController" />
-
-    <Preference
         android:key="gesture_double_tap_power_input_summary"
         android:title="@string/double_tap_power_for_camera_title"
         android:fragment="com.android.settings.gestures.DoubleTapPowerSettings"
diff --git a/res/xml/one_handed_settings.xml b/res/xml/one_handed_settings.xml
index b2c7de9..f46b7ea 100644
--- a/res/xml/one_handed_settings.xml
+++ b/res/xml/one_handed_settings.xml
@@ -21,12 +21,6 @@
     android:persistent="false"
     android:title="@string/one_handed_title">
 
-    <com.android.settingslib.widget.MainSwitchPreference
-        android:key="gesture_one_handed_mode_enabled"
-        android:title="@string/one_handed_mode_enabled"
-        settings:keywords="@string/keywords_one_handed"
-        settings:controller="com.android.settings.gestures.OneHandedEnablePreferenceController"/>
-
     <com.android.settingslib.widget.LayoutPreference
         android:key="one_handed_header"
         android:layout="@layout/one_handed_header"
@@ -35,16 +29,31 @@
         settings:allowDividerBelow="false"
         settings:searchable="false"/>
 
-    <SwitchPreference
-        android:key="gesture_app_taps_to_exit"
-        android:title="@string/one_handed_app_taps_to_exit"
-        settings:controller="com.android.settings.gestures.OneHandedAppTapsExitPreferenceController"/>
+    <com.android.settingslib.widget.MainSwitchPreference
+        android:key="gesture_one_handed_mode_enabled_main_switch"
+        android:title="@string/one_handed_mode_enabled"
+        settings:keywords="@string/keywords_one_handed"
+        settings:controller="com.android.settings.gestures.OneHandedMainSwitchPreferenceController"/>
 
-    <ListPreference
-        android:key="gesture_one_handed_timeout"
-        android:entries="@array/one_handed_timeout_title"
-        android:entryValues="@array/one_handed_timeout_values"
-        android:persistent="false"
-        android:title="@string/one_handed_timeout_title"
-        settings:controller="com.android.settings.gestures.OneHandedTimeoutPreferenceController"/>
+    <com.android.settingslib.widget.TopIntroPreference
+        android:key="gesture_one_handed_mode_intro_text"
+        android:title="@string/one_handed_mode_intro_text"/>
+
+    <PreferenceCategory
+        android:key="gesture_one_handed_mode_swipe_down"
+        android:title="@string/one_handed_mode_swipe_down_category">
+
+        <com.android.settingslib.widget.RadioButtonPreference
+            android:key="gesture_one_handed_action_pull_screen_down"
+            android:title="@string/one_handed_action_pull_down_screen_title"
+            android:summary="@string/one_handed_action_pull_down_screen_summary"
+            settings:controller="com.android.settings.gestures.OneHandedActionPullDownPrefController"/>
+
+        <com.android.settingslib.widget.RadioButtonPreference
+            android:key="gesture_one_handed_action_show_notification"
+            android:title="@string/one_handed_action_show_notification_title"
+            android:summary="@string/one_handed_action_show_notification_summary"
+            settings:controller="com.android.settings.gestures.OneHandedActionShowNotificationPrefController"/>
+
+    </PreferenceCategory>
 </PreferenceScreen>
diff --git a/res/xml/swipe_bottom_to_notification_settings.xml b/res/xml/swipe_bottom_to_notification_settings.xml
deleted file mode 100644
index 2a75c14..0000000
--- a/res/xml/swipe_bottom_to_notification_settings.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 The Android Open Source Project
-  ~
-  ~ Licensed under the Apache License, Version 2.0 (the "License");
-  ~ you may not use this file except in compliance with the License.
-  ~ You may obtain a copy of the License at
-  ~
-  ~      http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  -->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
-    android:title="@string/swipe_bottom_to_notifications_title">
-
-    <com.android.settingslib.widget.LayoutPreference
-        android:key="one_handed_header"
-        android:layout="@layout/one_handed_header"
-        android:persistent="false"
-        android:selectable="false"
-        settings:allowDividerBelow="false"
-        settings:searchable="false"/>
-
-    <SwitchPreference
-        android:key="gesture_swipe_bottom_to_notification"
-        android:title="@string/swipe_bottom_to_notifications_title"
-        android:summary="@string/swipe_bottom_to_notifications_summary"
-        settings:controller="com.android.settings.gestures.SwipeBottomToNotificationPreferenceController"
-        settings:allowDividerAbove="true" />
-
-</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
index fe08d6b..98090ac 100644
--- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
@@ -78,10 +78,12 @@
         // Settings animated image.
         final int animatedImageRes = arguments.getInt(
                 AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES);
-        mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                .authority(mComponentName.getPackageName())
-                .appendPath(String.valueOf(animatedImageRes))
-                .build();
+        if (animatedImageRes > 0) {
+            mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                    .authority(mComponentName.getPackageName())
+                    .appendPath(String.valueOf(animatedImageRes))
+                    .build();
+        }
 
         // Settings html description.
         mHtmlDescription = arguments.getCharSequence(AccessibilitySettings.EXTRA_HTML_DESCRIPTION);
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index 9d94858..9349071 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -396,10 +396,12 @@
         // Settings animated image.
         final int animatedImageRes = arguments.getInt(
                 AccessibilitySettings.EXTRA_ANIMATED_IMAGE_RES);
-        mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
-                .authority(mComponentName.getPackageName())
-                .appendPath(String.valueOf(animatedImageRes))
-                .build();
+        if (animatedImageRes > 0) {
+            mImageUri = new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                    .authority(mComponentName.getPackageName())
+                    .appendPath(String.valueOf(animatedImageRes))
+                    .build();
+        }
 
         // Get Accessibility service name.
         mPackageName = getAccessibilityServiceInfo().getResolveInfo().loadLabel(
diff --git a/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java b/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
index b4dbf3d..238e937 100644
--- a/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
+++ b/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
@@ -17,16 +17,19 @@
 package com.android.settings.accounts;
 
 import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
 
 import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.widget.FooterPreference;
 
 public class EnterpriseDisclosurePreferenceController extends BasePreferenceController {
-
     private final EnterprisePrivacyFeatureProvider mFeatureProvider;
 
     public EnterpriseDisclosurePreferenceController(Context context, String key) {
@@ -37,6 +40,16 @@
     }
 
     @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        final CharSequence disclosure = getDisclosure();
+        if (disclosure == null) {
+            return;
+        }
+        updateFooterPreference(screen, disclosure);
+    }
+
+    @Override
     public int getAvailabilityStatus() {
         if (getDisclosure() == null) {
             return UNSUPPORTED_ON_DEVICE;
@@ -49,12 +62,18 @@
         return mFeatureProvider.getDeviceOwnerDisclosure();
     }
 
-    @Override
-    public void updateState(Preference preference) {
-        final CharSequence disclosure = getDisclosure();
-        if (disclosure == null) {
-            return;
-        }
-        preference.setTitle(disclosure);
+    void updateFooterPreference(PreferenceScreen screen, CharSequence disclosure) {
+        final FooterPreference footerPreference = screen.findPreference(getPreferenceKey());
+        footerPreference.setTitle(disclosure);
+        footerPreference.setLearnMoreAction(view -> {
+            mContext.startActivity(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS));
+        });
+        final String learnMoreContentDescription = mContext.getString(
+                R.string.footer_learn_more_content_description, getLabelName());
+        footerPreference.setLearnMoreContentDescription(learnMoreContentDescription);
+    }
+
+    private String getLabelName() {
+        return mContext.getString(R.string.header_add_an_account);
     }
 }
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 62513db..7509a78 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -434,7 +434,7 @@
         final Activity activity = getActivity();
         final FrameLayout pinnedHeader = mRootView.findViewById(R.id.pinned_header);
         mSpinnerHeader = activity.getLayoutInflater()
-                .inflate(R.layout.apps_filter_spinner, pinnedHeader, false);
+                .inflate(R.layout.manage_apps_filter_spinner, pinnedHeader, false);
         mFilterSpinner = mSpinnerHeader.findViewById(R.id.filter_spinner);
         mFilterAdapter = new FilterSpinnerAdapter(this);
         mFilterSpinner.setAdapter(mFilterAdapter);
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 0de86f5..a03a4f9 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -360,6 +360,11 @@
         // Icon provided by the content provider overrides any static icon.
         if (tile.getMetaData() != null
                 && tile.getMetaData().containsKey(META_DATA_PREFERENCE_ICON_URI)) {
+            // Set a transparent color before starting to fetch the real icon, this is necessary
+            // to avoid preference padding change.
+            setPreferenceIcon(preference, tile, forceRoundedIcon, mContext.getPackageName(),
+                    Icon.createWithResource(mContext, android.R.color.transparent));
+
             ThreadUtils.postOnBackgroundThread(() -> {
                 final Intent intent = tile.getIntent();
                 String packageName = null;
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index f461fe1..7d722fc 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -100,9 +100,6 @@
         } else {
             disclosure.append(mResources.getString(R.string.do_disclosure_generic));
         }
-        disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
-        disclosure.append(mResources.getString(R.string.learn_more),
-                new EnterprisePrivacySpan(mContext), 0);
         return disclosure;
     }
 
diff --git a/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java
new file mode 100644
index 0000000..84ea8b6
--- /dev/null
+++ b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 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.gestures;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+/**
+ * The controller to handle one-handed mode pull screen into reach preference.
+ **/
+public class OneHandedActionPullDownPrefController extends BasePreferenceController
+        implements OneHandedSettingsUtils.TogglesCallback, LifecycleObserver, OnStart, OnStop {
+
+    private final OneHandedSettingsUtils mUtils;
+
+    private Preference mPreference;
+
+    public OneHandedActionPullDownPrefController(Context context, String key) {
+        super(context, key);
+        mUtils = new OneHandedSettingsUtils(context);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        if (preference instanceof RadioButtonPreference) {
+            ((RadioButtonPreference) preference).setChecked(
+                    !OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext));
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return  (OneHandedSettingsUtils.isSupportOneHandedMode()
+                && OneHandedSettingsUtils.canEnableController(mContext))
+                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!getPreferenceKey().equals(preference.getKey())) {
+            return false;
+        }
+        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, false);
+        if (preference instanceof RadioButtonPreference) {
+            ((RadioButtonPreference) preference).setChecked(true);
+        }
+        return true;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public void onStart() {
+        mUtils.registerToggleAwareObserver(this);
+    }
+
+    @Override
+    public void onStop() {
+        mUtils.unregisterToggleAwareObserver();
+    }
+
+    @Override
+    public void onChange(Uri uri) {
+        if (mPreference == null) {
+            return;
+        }
+        if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI)) {
+            mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext));
+        } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) {
+            updateState(mPreference);
+        }
+    }
+}
diff --git a/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java
new file mode 100644
index 0000000..5644299
--- /dev/null
+++ b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2021 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.gestures;
+
+import android.content.Context;
+import android.net.Uri;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+/**
+ * The controller to handle one-handed mode show notification preference.
+ **/
+public class OneHandedActionShowNotificationPrefController extends BasePreferenceController
+        implements OneHandedSettingsUtils.TogglesCallback, LifecycleObserver, OnStart, OnStop {
+
+    private final OneHandedSettingsUtils mUtils;
+
+    private Preference mPreference;
+
+    public OneHandedActionShowNotificationPrefController(Context context, String key) {
+        super(context, key);
+        mUtils = new OneHandedSettingsUtils(context);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        if (preference instanceof RadioButtonPreference) {
+            ((RadioButtonPreference) preference).setChecked(
+                    OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext));
+        }
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return  (OneHandedSettingsUtils.isSupportOneHandedMode()
+                && OneHandedSettingsUtils.canEnableController(mContext))
+                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!getPreferenceKey().equals(preference.getKey())) {
+            return false;
+        }
+        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, true);
+        if (preference instanceof RadioButtonPreference) {
+            ((RadioButtonPreference) preference).setChecked(true);
+        }
+        return true;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+    }
+
+    @Override
+    public void onStart() {
+        mUtils.registerToggleAwareObserver(this);
+    }
+
+    @Override
+    public void onStop() {
+        mUtils.unregisterToggleAwareObserver();
+    }
+
+    @Override
+    public void onChange(Uri uri) {
+        if (mPreference == null) {
+            return;
+        }
+        if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI)) {
+            mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext));
+        } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) {
+            updateState(mPreference);
+        }
+    }
+}
diff --git a/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceController.java b/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceController.java
deleted file mode 100644
index 1cc7911..0000000
--- a/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceController.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import android.content.Context;
-import android.net.Uri;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.core.TogglePreferenceController;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-/**
- * The Controller to handle app taps to exit of one-handed mode
- */
-public class OneHandedAppTapsExitPreferenceController extends TogglePreferenceController implements
-        LifecycleObserver, OnStart, OnStop, OneHandedSettingsUtils.TogglesCallback {
-
-    private final OneHandedSettingsUtils mUtils;
-
-    private Preference mPreference;
-
-    public OneHandedAppTapsExitPreferenceController(Context context, String key) {
-        super(context, key);
-
-        mUtils = new OneHandedSettingsUtils(context);
-
-        // By default, app taps to stop one-handed is enabled, this will get default value once.
-        OneHandedSettingsUtils.setTapsAppToExitEnabled(mContext, isChecked());
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)
-                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mPreference = screen.findPreference(getPreferenceKey());
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        super.updateState(preference);
-
-        final int availabilityStatus = getAvailabilityStatus();
-        preference.setEnabled(
-                availabilityStatus == AVAILABLE || availabilityStatus == AVAILABLE_UNSEARCHABLE);
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        return OneHandedSettingsUtils.setTapsAppToExitEnabled(mContext, isChecked);
-    }
-
-    @Override
-    public boolean isChecked() {
-        return OneHandedSettingsUtils.isTapsAppToExitEnabled(mContext);
-    }
-
-    @Override
-    public void onStart() {
-        mUtils.registerToggleAwareObserver(this);
-    }
-
-    @Override
-    public void onStop() {
-        mUtils.unregisterToggleAwareObserver();
-    }
-
-    @Override
-    public void onChange(Uri uri) {
-        updateState(mPreference);
-    }
-}
diff --git a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
index 1e9c240..e388585 100644
--- a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
+++ b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java
@@ -19,38 +19,25 @@
 import android.content.Context;
 
 import com.android.settings.R;
-import com.android.settings.widget.SettingsMainSwitchPreferenceController;
+import com.android.settings.core.BasePreferenceController;
 
 /**
  * The controller to handle one-handed mode enable or disable state.
  **/
-public class OneHandedEnablePreferenceController extends SettingsMainSwitchPreferenceController {
+public class OneHandedEnablePreferenceController extends BasePreferenceController {
 
-    public OneHandedEnablePreferenceController(Context context, String key) {
-        super(context, key);
+    public OneHandedEnablePreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
     }
 
-    @Override
     public int getAvailabilityStatus() {
-        return OneHandedSettingsUtils.isFeatureAvailable(mContext)
-                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, isChecked);
-        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, !isChecked);
-        return true;
-    }
-
-    @Override
-    public boolean isChecked() {
-        return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext);
+        return OneHandedSettingsUtils.isSupportOneHandedMode() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
     public CharSequence getSummary() {
         return mContext.getText(
-                isChecked() ? R.string.gesture_setting_on : R.string.gesture_setting_off);
+                OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)
+                        ? R.string.gesture_setting_on : R.string.gesture_setting_off);
     }
 }
diff --git a/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceController.java b/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceController.java
new file mode 100644
index 0000000..043588e
--- /dev/null
+++ b/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceController.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 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.gestures;
+
+import android.content.Context;
+
+import com.android.settings.widget.SettingsMainSwitchPreferenceController;
+
+/**
+ * The controller to handle one-handed mode main switch enable or disable state.
+ **/
+public class OneHandedMainSwitchPreferenceController extends
+        SettingsMainSwitchPreferenceController {
+
+    public OneHandedMainSwitchPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return (OneHandedSettingsUtils.isSupportOneHandedMode()
+                && OneHandedSettingsUtils.getNavigationBarMode(mContext) != 0 /* 3-button mode */)
+                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+    }
+
+    @Override
+    public boolean isChecked() {
+        return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext);
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        if (isChecked) {
+            // Set default value for TapsAppToExit and Timeout
+            OneHandedSettingsUtils.setTapsAppToExitEnabled(mContext, true);
+            OneHandedSettingsUtils.setTimeoutValue(mContext,
+                    OneHandedSettingsUtils.OneHandedTimeout.MEDIUM.getValue());
+        }
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, isChecked);
+        return true;
+    }
+}
diff --git a/src/com/android/settings/gestures/OneHandedSettingsUtils.java b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
index 21998a6..a931129 100644
--- a/src/com/android/settings/gestures/OneHandedSettingsUtils.java
+++ b/src/com/android/settings/gestures/OneHandedSettingsUtils.java
@@ -26,6 +26,8 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 
+import androidx.annotation.VisibleForTesting;
+
 /**
  * The Util to query one-handed mode settings config
  */
@@ -34,6 +36,10 @@
     static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
     static final int OFF = 0;
     static final int ON = 1;
+    static final Uri ONE_HANDED_MODE_ENABLED_URI =
+            Settings.Secure.getUriFor(Settings.Secure.ONE_HANDED_MODE_ENABLED);
+    static final Uri SHOW_NOTIFICATION_ENABLED_URI =
+            Settings.Secure.getUriFor(Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED);
 
     public enum OneHandedTimeout {
         NEVER(0), SHORT(4), MEDIUM(8), LONG(12);
@@ -177,6 +183,21 @@
     }
 
     /**
+     * Set NavigationBar mode flag to Settings provider.
+     * @param context App context
+     * @param value Navigation bar mode:
+     *  0 = 3 button
+     *  1 = 2 button
+     *  2 = fully gestural
+     * @return true if the value was set, false on database errors.
+     */
+    @VisibleForTesting
+    public boolean setNavigationBarMode(Context context, String value) {
+        return Settings.Secure.putStringForUser(context.getContentResolver(),
+                Settings.Secure.NAVIGATION_MODE, value, UserHandle.myUserId());
+    }
+
+    /**
      * Get NavigationBar mode flag from Settings provider.
      * @param context App context
      * @return Navigation bar mode:
@@ -190,12 +211,17 @@
     }
 
     /**
-     *
+     * Check if One-handed mode settings controllers can enabled or disabled.
      * @param context App context
-     * @return Support One-Handed mode feature or not.
+     * @return true if controllers are able to enabled, false otherwise.
+     *
+     * Note: For better UX experience, just disabled controls that let users know to use
+     * this feature, they need to make sure gesture navigation is turned on in system
+     * navigation settings.
      */
-    public static boolean isFeatureAvailable(Context context) {
-        return isSupportOneHandedMode() && getNavigationBarMode(context) != 0;
+    public static boolean canEnableController(Context context) {
+        return (OneHandedSettingsUtils.isOneHandedModeEnabled(context)
+                && OneHandedSettingsUtils.getNavigationBarMode(context) != 0 /* 3-button mode */);
     }
 
     /**
@@ -218,9 +244,6 @@
     private final class SettingsObserver extends ContentObserver {
         private TogglesCallback mCallback;
 
-        private final Uri mOneHandedEnabledAware = Settings.Secure.getUriFor(
-                Settings.Secure.ONE_HANDED_MODE_ENABLED);
-
         SettingsObserver(Handler handler) {
             super(handler);
         }
@@ -231,7 +254,8 @@
 
         public void observe() {
             final ContentResolver resolver = mContext.getContentResolver();
-            resolver.registerContentObserver(mOneHandedEnabledAware, true, this);
+            resolver.registerContentObserver(ONE_HANDED_MODE_ENABLED_URI, true, this);
+            resolver.registerContentObserver(SHOW_NOTIFICATION_ENABLED_URI, true, this);
         }
 
         @Override
diff --git a/src/com/android/settings/gestures/OneHandedTimeoutPreferenceController.java b/src/com/android/settings/gestures/OneHandedTimeoutPreferenceController.java
deleted file mode 100644
index 8ce0e86..0000000
--- a/src/com/android/settings/gestures/OneHandedTimeoutPreferenceController.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import android.content.Context;
-import android.net.Uri;
-
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnStart;
-import com.android.settingslib.core.lifecycle.events.OnStop;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The Controller to handle one-handed mode timeout state.
- **/
-public class OneHandedTimeoutPreferenceController extends BasePreferenceController implements
-        Preference.OnPreferenceChangeListener, LifecycleObserver, OnStart, OnStop,
-        OneHandedSettingsUtils.TogglesCallback {
-
-    private final Map<String, String> mTimeoutMap;
-    private final OneHandedSettingsUtils mUtils;
-
-    private Preference mTimeoutPreference;
-
-    public OneHandedTimeoutPreferenceController(Context context, String preferenceKey) {
-        super(context, preferenceKey);
-
-        mTimeoutMap = new HashMap<>();
-        initTimeoutMap();
-        mUtils = new OneHandedSettingsUtils(context);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)
-                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
-    }
-
-    @Override
-    public boolean onPreferenceChange(Preference preference, Object object) {
-        if (!(preference instanceof ListPreference)) {
-            return false;
-        }
-        final int newValue = Integer.parseInt((String) object);
-        OneHandedSettingsUtils.setTimeoutValue(mContext, newValue);
-        updateState(preference);
-        return true;
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        super.updateState(preference);
-        if (!(preference instanceof ListPreference)) {
-            return;
-        }
-        final ListPreference listPreference = (ListPreference) preference;
-        listPreference.setValue(getTimeoutValue());
-
-        final int availabilityStatus = getAvailabilityStatus();
-        preference.setEnabled(
-                availabilityStatus == AVAILABLE || availabilityStatus == AVAILABLE_UNSEARCHABLE);
-    }
-
-    @Override
-    public CharSequence getSummary() {
-        if (OneHandedSettingsUtils.getTimeoutValue(mContext) == 0) {
-            return mContext.getResources().getString(R.string.screensaver_settings_summary_never);
-        }
-        return String.format(mContext.getResources().getString(
-                R.string.screen_timeout_summary), mTimeoutMap.get(getTimeoutValue()));
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mTimeoutPreference = screen.findPreference(mPreferenceKey);
-    }
-
-    @Override
-    public void onStart() {
-        mUtils.registerToggleAwareObserver(this);
-    }
-
-    @Override
-    public void onStop() {
-        mUtils.unregisterToggleAwareObserver();
-    }
-
-    @Override
-    public void onChange(Uri uri) {
-        updateState(mTimeoutPreference);
-    }
-
-    private String getTimeoutValue() {
-        return String.valueOf(OneHandedSettingsUtils.getTimeoutValue(mContext));
-    }
-
-    private void initTimeoutMap() {
-        if (mTimeoutMap.size() != 0) {
-            return;
-        }
-
-        final String[] timeoutValues = mContext.getResources().getStringArray(
-                R.array.one_handed_timeout_values);
-        final String[] timeoutTitles = mContext.getResources().getStringArray(
-                R.array.one_handed_timeout_title);
-
-        if (timeoutValues.length != timeoutTitles.length) {
-            return;
-        }
-
-        for (int i = 0; i < timeoutValues.length; i++) {
-            mTimeoutMap.put(timeoutValues[i], timeoutTitles[i]);
-        }
-    }
-}
diff --git a/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java
deleted file mode 100644
index ec81482..0000000
--- a/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceController.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.core.TogglePreferenceController;
-
-/**
- * Handles swipe bottom to expand notification panel gesture.
- **/
-public class SwipeBottomToNotificationPreferenceController extends TogglePreferenceController {
-
-    public SwipeBottomToNotificationPreferenceController(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return OneHandedSettingsUtils.isFeatureAvailable(mContext)
-                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
-    }
-
-    @Override
-    public boolean isSliceable() {
-        return true;
-    }
-
-    @Override
-    public boolean isPublicSlice() {
-        return true;
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        if (isChecked) {
-            OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-        }
-        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, isChecked);
-        return true;
-    }
-
-    @Override
-    public boolean isChecked() {
-        return OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext);
-    }
-
-    @Override
-    public CharSequence getSummary() {
-        // This toggle preference summary will be updated in gesture preference page since we bound
-        // it with entry preference in gesture.xml
-        return mContext.getText(
-                isChecked() ? R.string.gesture_setting_on : R.string.gesture_setting_off);
-    }
-}
diff --git a/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java b/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java
deleted file mode 100644
index 9d85f11..0000000
--- a/src/com/android/settings/gestures/SwipeBottomToNotificationSettings.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-
-/**
- * The Fragment for swipe bottom to notification gesture settings.
- */
-public class SwipeBottomToNotificationSettings extends DashboardFragment {
-
-    private static final String TAG = "SwipeBottomToNotificationSettings";
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.SETTINGS_SWIPE_BOTTOM_TO_NOTIFICATION;
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.swipe_bottom_to_notification_settings;
-    }
-
-    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider(R.xml.swipe_bottom_to_notification_settings) {
-
-                @Override
-                protected boolean isPageSearchEnabled(Context context) {
-                    if (!OneHandedSettingsUtils.isSupportOneHandedMode()) {
-                        return false;
-                    }
-                    return !OneHandedSettingsUtils.isOneHandedModeEnabled(context);
-                }
-            };
-}
diff --git a/src/com/android/settings/network/InternetPreferenceController.java b/src/com/android/settings/network/InternetPreferenceController.java
index 639bab5..a58e69a 100644
--- a/src/com/android/settings/network/InternetPreferenceController.java
+++ b/src/com/android/settings/network/InternetPreferenceController.java
@@ -65,7 +65,7 @@
     @VisibleForTesting
     static Map<Integer, Integer> sIconMap = new HashMap<>();
     static {
-        sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_airplane);
+        sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_unavailable);
         sIconMap.put(INTERNET_NETWORKS_AVAILABLE, R.drawable.ic_no_internet_available);
         sIconMap.put(INTERNET_WIFI, R.drawable.ic_wifi_signal_4);
         sIconMap.put(INTERNET_CELLULAR, R.drawable.ic_network_cell);
diff --git a/src/com/android/settings/network/ProviderModelSlice.java b/src/com/android/settings/network/ProviderModelSlice.java
index cfaef53..1df77bc 100644
--- a/src/com/android/settings/network/ProviderModelSlice.java
+++ b/src/com/android/settings/network/ProviderModelSlice.java
@@ -20,6 +20,7 @@
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
 import static com.android.settings.slices.CustomSliceRegistry.PROVIDER_MODEL_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
 
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
@@ -64,7 +65,6 @@
 public class ProviderModelSlice extends WifiSlice {
 
     private static final String TAG = "ProviderModelSlice";
-    protected static final String ACTION_TITLE_CONNECT_TO_CARRIER = "Connect_To_Carrier";
 
     private final ProviderModelSliceHelper mHelper;
 
@@ -89,78 +89,77 @@
     @Override
     public Slice getSlice() {
         // The provider model slice step:
-        // First section:  Add a Wi-Fi item which state is connected.
-        // Second section:  Add a carrier item.
-        // Third section:  Add the Wi-Fi items which are not connected.
-        // Fourth section:  If device has connection problem, this row show the message for user.
-        @InternetUpdater.InternetType int internetType = getInternetType();
+        //  First section: Add the Ethernet item.
+        // Second section: Add the carrier item.
+        //  Third section: Add the Wi-Fi toggle item.
+        // Fourth section: Add the connected Wi-Fi item.
+        //  Fifth section: Add the Wi-Fi items which are not connected.
+        //  Sixth section: Add the See All item.
         final ListBuilder listBuilder = mHelper.createListBuilder(getUri());
-        if (mHelper.isAirplaneModeEnabled() && !mWifiManager.isWifiEnabled()
-                && internetType != InternetUpdater.INTERNET_ETHERNET) {
-            log("Airplane mode is enabled.");
-            return listBuilder.build();
-        }
-
         int maxListSize = 0;
-        List<WifiSliceItem> wifiList = null;
         final NetworkProviderWorker worker = getWorker();
         if (worker != null) {
-            // get Wi-Fi list.
-            wifiList = worker.getResults();
             maxListSize = worker.getApRowCount();
         } else {
             log("network provider worker is null.");
         }
 
-        final boolean hasCarrier = mHelper.hasCarrier();
-        log("hasCarrier: " + hasCarrier);
-
-        // First section:  Add a Ethernet or Wi-Fi item which state is connected.
-        boolean isConnectedWifiAddedTop = false;
-        final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList);
-        if (internetType == InternetUpdater.INTERNET_ETHERNET) {
+        // First section: Add the Ethernet item.
+        if (getInternetType() == InternetUpdater.INTERNET_ETHERNET) {
             log("get Ethernet item which is connected");
             listBuilder.addRow(createEthernetRow());
             maxListSize--;
-        } else {
-            if (connectedWifiItem != null && internetType == InternetUpdater.INTERNET_WIFI) {
-                log("get Wi-Fi item which is connected to internet");
-                listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem));
-                isConnectedWifiAddedTop = true;
+        }
+
+        // Second section: Add the carrier item.
+        if (!mHelper.isAirplaneModeEnabled()) {
+            final boolean hasCarrier = mHelper.hasCarrier();
+            log("hasCarrier: " + hasCarrier);
+            if (hasCarrier) {
+                mHelper.updateTelephony();
+                listBuilder.addRow(
+                        mHelper.createCarrierRow(
+                                worker != null ? worker.getNetworkTypeDescription() : ""));
                 maxListSize--;
             }
         }
 
-        // Second section:  Add a carrier item.
-        if (hasCarrier) {
-            mHelper.updateTelephony();
-            listBuilder.addRow(
-                    mHelper.createCarrierRow(
-                            worker != null ? worker.getNetworkTypeDescription() : ""));
-            maxListSize--;
+        // Third section: Add the Wi-Fi toggle item.
+        final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+        listBuilder.addRow(createWifiToggleRow(mContext, isWifiEnabled));
+        maxListSize--;
+        if (!isWifiEnabled) {
+            log("Wi-Fi is disabled");
+            return listBuilder.build();
+        }
+        List<WifiSliceItem> wifiList = (worker != null) ? worker.getResults() : null;
+        if (wifiList == null || wifiList.size() <= 0) {
+            log("Wi-Fi list is empty");
+            return listBuilder.build();
         }
 
-        // Third section:  Add the connected Wi-Fi item to Wi-Fi list if the Ethernet is connected.
-        if (connectedWifiItem != null && !isConnectedWifiAddedTop) {
+        // Fourth section: Add the connected Wi-Fi item.
+        final WifiSliceItem connectedWifiItem = mHelper.getConnectedWifiItem(wifiList);
+        if (connectedWifiItem != null) {
             log("get Wi-Fi item which is connected");
             listBuilder.addRow(getWifiSliceItemRow(connectedWifiItem));
             maxListSize--;
         }
 
-        // Fourth section:  Add the Wi-Fi items which are not connected.
-        if (wifiList != null && wifiList.size() > 0) {
-            log("get Wi-Fi items which are not connected. Wi-Fi items : " + wifiList.size());
-
-            final List<WifiSliceItem> disconnectedWifiList = wifiList.stream()
-                    .filter(wifiSliceItem -> wifiSliceItem.getConnectedState()
-                            != WifiEntry.CONNECTED_STATE_CONNECTED)
-                    .limit(maxListSize - 1)
-                    .collect(Collectors.toList());
-            for (WifiSliceItem item : disconnectedWifiList) {
-                listBuilder.addRow(getWifiSliceItemRow(item));
-            }
-            listBuilder.addRow(getSeeAllRow());
+        // Fifth section: Add the Wi-Fi items which are not connected.
+        log("get Wi-Fi items which are not connected. Wi-Fi items : " + wifiList.size());
+        final List<WifiSliceItem> disconnectedWifiList = wifiList.stream()
+                .filter(item -> item.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED)
+                .limit(maxListSize - 1)
+                .collect(Collectors.toList());
+        for (WifiSliceItem item : disconnectedWifiList) {
+            listBuilder.addRow(getWifiSliceItemRow(item));
         }
+
+        // Sixth section: Add the See All item.
+        log("add See-All");
+        listBuilder.addRow(getSeeAllRow());
+
         return listBuilder.build();
     }
 
@@ -269,6 +268,26 @@
                 .setSubtitle(mContext.getText(R.string.to_switch_networks_disconnect_ethernet));
     }
 
+    /**
+     * @return a {@link ListBuilder.RowBuilder} of the Wi-Fi toggle.
+     */
+    protected ListBuilder.RowBuilder createWifiToggleRow(Context context, boolean isWifiEnabled) {
+        final Intent intent = new Intent(WIFI_SLICE_URI.toString())
+                .setData(WIFI_SLICE_URI)
+                .setClass(context, SliceBroadcastReceiver.class)
+                .putExtra(EXTRA_TOGGLE_STATE, !isWifiEnabled)
+                // The FLAG_RECEIVER_FOREGROUND flag is necessary to avoid the intent delay of
+                // the first sending after the device restarts
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+        final SliceAction toggleSliceAction = SliceAction.createToggle(pendingIntent,
+                null /* actionTitle */, isWifiEnabled);
+        return new ListBuilder.RowBuilder()
+                .setTitle(context.getString(R.string.wifi_settings))
+                .setPrimaryAction(toggleSliceAction);
+    }
+
     protected ListBuilder.RowBuilder getSeeAllRow() {
         final CharSequence title = mContext.getText(R.string.previous_connected_see_all);
         final IconCompat icon = getSeeAllIcon();
@@ -295,31 +314,6 @@
     }
 
     @Override
-    protected ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
-        final CharSequence title = wifiSliceItem.getTitle();
-        final IconCompat levelIcon = getWifiSliceItemLevelIcon(wifiSliceItem);
-        final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
-                .setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
-                .setTitle(title)
-                .setSubtitle(wifiSliceItem.getSummary())
-                .setContentDescription(wifiSliceItem.getContentDescription());
-
-        final IconCompat endIcon;
-        if (wifiSliceItem.hasInternetAccess()) {
-            rowBuilder.setPrimaryAction(SliceAction.create(getBroadcastIntent(mContext),
-                    levelIcon, ListBuilder.ICON_IMAGE, ACTION_TITLE_CONNECT_TO_CARRIER));
-            endIcon = IconCompat.createWithResource(mContext, R.drawable.ic_settings_close);
-        } else {
-            rowBuilder.setPrimaryAction(getWifiEntryAction(wifiSliceItem, levelIcon, title));
-            endIcon = getEndIcon(wifiSliceItem);
-        }
-        if (endIcon != null) {
-            rowBuilder.addEndItem(endIcon, ListBuilder.ICON_IMAGE);
-        }
-        return rowBuilder;
-    }
-
-    @Override
     protected IconCompat getWifiSliceItemLevelIcon(WifiSliceItem wifiSliceItem) {
         if (wifiSliceItem.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED
                 && getInternetType() != InternetUpdater.INTERNET_WIFI) {
diff --git a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java
index d1c9f7b..4f64399 100644
--- a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java
@@ -31,6 +31,7 @@
 
 import com.android.settings.R;
 import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.network.ims.WifiCallingQueryImsState;
 
 import java.util.List;
 import java.util.Objects;
@@ -147,16 +148,20 @@
     }
 
     private boolean hasBackupCallingFeature(int subscriptionId) {
-        PersistableBundle carrierConfig = getCarrierConfigForSubId(subscriptionId);
-        Boolean featureEnableStatus = null;
-        if (carrierConfig != null) {
-            featureEnableStatus = carrierConfig.getBoolean(
-                    CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false);
+        return isCrossSimEnabledByPlatform(mContext, subscriptionId);
+    }
+
+    protected boolean isCrossSimEnabledByPlatform(Context context, int subscriptionId) {
+        // TODO : Change into API which created for accessing
+        //        com.android.ims.ImsManager#isCrossSimEnabledByPlatform()
+        if ((new WifiCallingQueryImsState(context, subscriptionId)).isWifiCallingSupported()) {
+            PersistableBundle bundle = getCarrierConfigForSubId(subscriptionId);
+            return (bundle != null) && bundle.getBoolean(
+                    CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL,
+                    false /*default*/);
         }
-        // TODO: remove log after fixing b/182326102
-        Log.d(LOG_TAG, "config " + CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL
-                + "=" + featureEnableStatus + " for subId=" + subscriptionId);
-        return (featureEnableStatus != null) && featureEnableStatus.booleanValue();
+        Log.d(LOG_TAG, "Not supported by framework. subId = " + subscriptionId);
+        return false;
     }
 
     private ImsMmTelManager getImsMmTelManager(int subId) {
diff --git a/src/com/android/settings/network/telephony/NetworkProviderWorker.java b/src/com/android/settings/network/telephony/NetworkProviderWorker.java
index 369218b..d4f0551 100644
--- a/src/com/android/settings/network/telephony/NetworkProviderWorker.java
+++ b/src/com/android/settings/network/telephony/NetworkProviderWorker.java
@@ -54,7 +54,7 @@
         DataConnectivityListener.Client, InternetUpdater.InternetChangeListener,
         SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
     private static final String TAG = "NetworkProviderWorker";
-    private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 5;
+    private static final int PROVIDER_MODEL_DEFAULT_EXPANDED_ROW_COUNT = 6;
     private DataContentObserver mMobileDataObserver;
     private SignalStrengthListener mSignalStrengthListener;
     private SubscriptionsChangeListener mSubscriptionsListener;
diff --git a/src/com/android/settings/panel/InternetConnectivityPanel.java b/src/com/android/settings/panel/InternetConnectivityPanel.java
index e6344d8..c735780 100644
--- a/src/com/android/settings/panel/InternetConnectivityPanel.java
+++ b/src/com/android/settings/panel/InternetConnectivityPanel.java
@@ -38,7 +38,6 @@
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
-import androidx.fragment.app.FragmentActivity;
 import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.OnLifecycleEvent;
 
@@ -84,12 +83,13 @@
             }
 
             if (TextUtils.equals(intent.getAction(), WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-                showProgressBar();
+                updateProgressBar();
                 updatePanelTitle();
                 return;
             }
 
             if (TextUtils.equals(intent.getAction(), WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                updateProgressBar();
                 updatePanelTitle();
             }
         }
@@ -110,13 +110,40 @@
     private int mDefaultDataSubid = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
     // Wi-Fi scanning progress bar
+    protected HandlerInjector mHandlerInjector;
     protected boolean mIsProgressBarVisible;
-    protected final Runnable mHideProgressBarRunnable = () -> {
+    protected boolean mIsScanningSubTitleShownOnce;
+    protected Runnable mHideProgressBarRunnable = () -> {
         setProgressBarVisible(false);
     };
+    protected Runnable mHideScanningSubTitleRunnable = () -> {
+        mIsScanningSubTitleShownOnce = true;
+        updatePanelTitle();
+    };
+
+    /**
+     * Wrapper for testing compatibility.
+     */
+    @VisibleForTesting
+    static class HandlerInjector {
+        protected final Handler mHandler;
+
+        HandlerInjector(Context context) {
+            mHandler = context.getMainThreadHandler();
+        }
+
+        public void postDelay(Runnable runnable) {
+            mHandler.postDelayed(runnable, 2000 /* delay millis */);
+        }
+
+        public void removeCallbacks(Runnable runnable) {
+            mHandler.removeCallbacks(runnable);
+        }
+    }
 
     private InternetConnectivityPanel(Context context) {
         mContext = context.getApplicationContext();
+        mHandlerInjector = new HandlerInjector(context);
         mIsProviderModelEnabled = Utils.isProviderModelEnabled(mContext);
         mInternetUpdater = new InternetUpdater(context, null /* Lifecycle */, this);
 
@@ -150,7 +177,7 @@
         mTelephonyManager.registerTelephonyCallback(
                 new HandlerExecutor(new Handler(Looper.getMainLooper())), mTelephonyCallback);
         mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter);
-        showProgressBar();
+        updateProgressBar();
         updatePanelTitle();
     }
 
@@ -165,7 +192,8 @@
         mConnectivityListener.stop();
         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
         mContext.unregisterReceiver(mWifiStateReceiver);
-        mContext.getMainThreadHandler().removeCallbacks(mHideProgressBarRunnable);
+        mHandlerInjector.removeCallbacks(mHideProgressBarRunnable);
+        mHandlerInjector.removeCallbacks(mHideScanningSubTitleRunnable);
     }
 
     /**
@@ -210,23 +238,6 @@
     }
 
     @Override
-    public boolean isCustomizedButtonUsed() {
-        return mIsProviderModelEnabled;
-    }
-
-    @Override
-    public CharSequence getCustomizedButtonTitle() {
-        return mContext.getText(
-                mInternetUpdater.isWifiEnabled() ? R.string.turn_off_wifi : R.string.turn_on_wifi);
-    }
-
-    @Override
-    public void onClickCustomizedButton(FragmentActivity panelActivity) {
-        // Don't finish the panel activity
-        mWifiManager.setWifiEnabled(!mInternetUpdater.isWifiEnabled());
-    }
-
-    @Override
     public boolean isProgressBarVisible() {
         return mIsProgressBarVisible;
     }
@@ -246,6 +257,7 @@
      */
     @Override
     public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
+        log("onAirplaneModeChanged: isAirplaneModeOn:" + isAirplaneModeOn);
         updatePanelTitle();
     }
 
@@ -254,6 +266,7 @@
      */
     @Override
     public void onWifiEnabledChanged(boolean enabled) {
+        log("onWifiEnabledChanged: enabled:" + enabled);
         updatePanelTitle();
     }
 
@@ -305,13 +318,6 @@
             return;
         }
 
-        if (mIsProgressBarVisible) {
-            // When the Wi-Fi scan result callback is received
-            //   Sub-Title: Searching for networks...
-            mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
-            return;
-        }
-
         if (mInternetUpdater.isAirplaneModeOn()) {
             return;
         }
@@ -319,11 +325,18 @@
         final List<ScanResult> wifiList = mWifiManager.getScanResults();
         if (wifiList != null && wifiList.size() != 0) {
             // When the Wi-Fi scan result is not empty
-            //   Sub-Title: Select the network you want to use for data
+            //   Sub-Title: Tap a network to connect
             mSubtitle = SUBTITLE_TEXT_TAP_A_NETWORK_TO_CONNECT;
             return;
         }
 
+        if (!mIsScanningSubTitleShownOnce && mIsProgressBarVisible) {
+            // When the Wi-Fi scan result callback is received
+            //   Sub-Title: Searching for networks...
+            mSubtitle = SUBTITLE_TEXT_SEARCHING_FOR_NETWORKS;
+            return;
+        }
+
         // Sub-Title:
         // show non_carrier_network_unavailable
         //   - while Wi-Fi on + no Wi-Fi item
@@ -353,7 +366,7 @@
         mSubtitle = SUBTITLE_TEXT_NON_CARRIER_NETWORK_UNAVAILABLE;
     }
 
-    protected void showProgressBar() {
+    protected void updateProgressBar() {
         if (mWifiManager == null || !mInternetUpdater.isWifiEnabled()) {
             setProgressBarVisible(false);
             return;
@@ -362,8 +375,9 @@
         setProgressBarVisible(true);
         List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
         if (wifiScanResults != null && wifiScanResults.size() > 0) {
-            mContext.getMainThreadHandler().postDelayed(mHideProgressBarRunnable,
-                    2000 /* delay millis */);
+            mHandlerInjector.postDelay(mHideProgressBarRunnable);
+        } else if (!mIsScanningSubTitleShownOnce) {
+            mHandlerInjector.postDelay(mHideScanningSubTitleRunnable);
         }
     }
 
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 28c4ba1..ca30952 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -20,8 +20,6 @@
 import android.os.Bundle;
 import android.provider.Settings;
 
-import com.android.settings.Utils;
-
 public class PanelFeatureProviderImpl implements PanelFeatureProvider {
 
     @Override
@@ -41,9 +39,6 @@
             case Settings.Panel.ACTION_NFC:
                 return NfcPanel.create(context);
             case Settings.Panel.ACTION_WIFI:
-                if (Utils.isProviderModelEnabled(context)) {
-                    return InternetConnectivityPanel.create(context);
-                }
                 return WifiPanel.create(context);
             case Settings.Panel.ACTION_VOLUME:
                 return VolumePanel.create(context);
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index ced198b..7bf680d 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -63,6 +63,7 @@
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceScreen;
+import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.net.module.util.Inet4AddressUtils;
 import com.android.settings.R;
@@ -513,6 +514,12 @@
 
     @Override
     public void onResume() {
+        // Disable the animation of the EntityHeaderController
+        final RecyclerView recyclerView = mFragment.getListView();
+        if (recyclerView != null) {
+            recyclerView.setItemAnimator(null);
+        }
+
         // Ensure mNetwork is set before any callbacks above are delivered, since our
         // NetworkCallback only looks at changes to mNetwork.
         updateNetworkInfo();
diff --git a/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
index b10a729..8860cfe 100644
--- a/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
@@ -19,20 +19,25 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 
-import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.FooterPreference;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
@@ -42,13 +47,18 @@
 
     private Context mContext;
     private EnterpriseDisclosurePreferenceController mController;
-    private Preference mPreference;
+    private FooterPreference mPreference;
+
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mController = spy(new EnterpriseDisclosurePreferenceController(mContext, "my_key"));
-        mPreference = spy(new Preference(mContext));
+        mPreference = spy(new FooterPreference(mContext));
+        when(mPreferenceScreen.findPreference(anyString())).thenReturn(mPreference);
     }
 
     @Test
@@ -68,19 +78,19 @@
     }
 
     @Test
-    public void updateState_hasDisclosure_shouldSetTitle() {
+    public void displayPreference_hasDisclosure_shouldSetTitle() {
         doReturn(TEST_DISCLOSURE).when(mController).getDisclosure();
 
-        mController.updateState(mPreference);
+        mController.displayPreference(mPreferenceScreen);
 
         assertThat(mPreference.getTitle()).isEqualTo(TEST_DISCLOSURE);
     }
 
     @Test
-    public void updateState_noDisclosure_shouldBeInvisible() {
+    public void displayPreference_noDisclosure_shouldBeInvisible() {
         doReturn(null).when(mController).getDisclosure();
 
-        mController.updateState(mPreference);
+        mController.displayPreference(mPreferenceScreen);
 
         verify(mPreference, never()).setTitle(any());
     }
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java
new file mode 100644
index 0000000..60398de
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2021 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class OneHandedActionPullDownPrefControllerTest {
+
+    private static final String KEY = "gesture_one_handed_action_pull_screen_down";
+
+    private Context mContext;
+    private OneHandedSettingsUtils mUtils;
+    private OneHandedActionPullDownPrefController mController;
+    private RadioButtonPreference mPreference;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mUtils = new OneHandedSettingsUtils(mContext);
+        mController = new OneHandedActionPullDownPrefController(mContext, KEY);
+        mPreference = new RadioButtonPreference(mContext);
+        OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
+    }
+
+    @Test
+    public void updateState_showNotificationEnabled_shouldUnchecked() {
+        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, true);
+
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void updateState_showNotificationDisabled_shouldChecked() {
+        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, false);
+
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void getAvailabilityStatus_setOneHandedModeDisabled_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+
+    @Test
+    public void getAvailabilityStatus_setNavi3ButtonMode_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+        mUtils.setNavigationBarMode(mContext, "0" /* 3 button */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+
+    @Test
+    public void getAvailabilityStatus_setNaviGesturalMode_shouldEnabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java
new file mode 100644
index 0000000..b56a4f7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class OneHandedActionShowNotificationPrefControllerTest {
+
+    private static final String KEY = "gesture_one_handed_action_show_notification";
+
+    private Context mContext;
+    private OneHandedSettingsUtils mUtils;
+    private OneHandedActionShowNotificationPrefController mController;
+    private RadioButtonPreference mPreference;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mUtils = new OneHandedSettingsUtils(mContext);
+        mController = new OneHandedActionShowNotificationPrefController(mContext, KEY);
+        mPreference = new RadioButtonPreference(mContext);
+        OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
+    }
+
+    @Test
+    public void updateState_setGesturalMode_shouldEnabled() {
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        mController.updateState(mPreference);
+        assertThat(mPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void updateState_ShowNotificationEnabled_shouldChecked() {
+        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, true);
+
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void updateState_showNotificationDisabled_shouldUnchecked() {
+        OneHandedSettingsUtils.setSwipeDownNotificationEnabled(mContext, false);
+
+        mController.updateState(mPreference);
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void getAvailabilityStatus_setOneHandedModeDisabled_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+
+    @Test
+    public void getAvailabilityStatus_setNavi3ButtonMode_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+        mUtils.setNavigationBarMode(mContext, "0" /* 3 button */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+
+    @Test
+    public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
+        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
index e5b8688..d0f6485 100644
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedEnablePreferenceControllerTest.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.provider.Settings;
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
@@ -48,20 +47,8 @@
     }
 
     @Test
-    public void setChecked_setBoolean_checkIsTrueOrFalse() {
-        mController.setChecked(false);
-        assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isFalse();
-        assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isTrue();
-
-        mController.setChecked(true);
-        assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isTrue();
-        assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isFalse();
-    }
-
-    @Test
     public void getAvailabilityStatus_setSupportOneHandedModeProperty_shouldAvailable() {
         SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
-        setNavigationBarMode(mContext, "2" /* fully gestural */);
 
         assertThat(mController.getAvailabilityStatus())
                 .isEqualTo(BasePreferenceController.AVAILABLE);
@@ -70,16 +57,6 @@
     @Test
     public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldUnsupported() {
         SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
-        setNavigationBarMode(mContext, "2" /* fully gestural */);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_set3ButtonModeProperty_shouldUnsupported() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
-        setNavigationBarMode(mContext, "0" /* 3-button */);
 
         assertThat(mController.getAvailabilityStatus())
                 .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
@@ -100,18 +77,4 @@
         assertThat(mController.getSummary())
                 .isEqualTo(mContext.getText(R.string.switch_off_text));
     }
-
-    /**
-     * Set NavigationBar mode flag to Settings provider.
-     * @param context App context
-     * @param value Navigation bar mode:
-     *  0 = 3 button
-     *  1 = 2 button
-     *  2 = fully gestural
-     * @return true if the value was set, false on database errors.
-     */
-    private boolean setNavigationBarMode(Context context, String value) {
-        return Settings.Secure.putStringForUser(context.getContentResolver(),
-                Settings.Secure.NAVIGATION_MODE, value, UserHandle.myUserId());
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceControllerTest.java
new file mode 100644
index 0000000..40cf795
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedMainSwitchPreferenceControllerTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class OneHandedMainSwitchPreferenceControllerTest {
+
+    private static final String KEY = "gesture_one_handed_mode_enabled_main_switch";
+
+    private Context mContext;
+    private OneHandedSettingsUtils mUtils;
+    private OneHandedMainSwitchPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mUtils = new OneHandedSettingsUtils(mContext);
+        mController = new OneHandedMainSwitchPreferenceController(mContext, KEY);
+        OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
+    }
+
+    @Test
+    public void setChecked_setBoolean_checkIsTrueOrFalse() {
+        mController.setChecked(false);
+        assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isFalse();
+
+        mController.setChecked(true);
+        assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isTrue();
+    }
+
+    @Test
+    public void getAvailabilityStatus_setSupportOneHandedModeProperty_shouldAvailable() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_unsetSupportOneHandedModeProperty_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
+        mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+
+    @Test
+    public void getAvailabilityStatus_set3ButtonMode_shouldDisabled() {
+        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
+        mUtils.setNavigationBarMode(mContext, "0" /* 3-button mode */);
+
+        assertThat(mController.getAvailabilityStatus())
+                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedTimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedTimeoutPreferenceControllerTest.java
deleted file mode 100644
index d278945..0000000
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedTimeoutPreferenceControllerTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.UserHandle;
-
-import androidx.preference.ListPreference;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class OneHandedTimeoutPreferenceControllerTest {
-
-    private static final String KEY = "gesture_one_handed_timeout";
-
-    private Context mContext;
-    private OneHandedTimeoutPreferenceController mController;
-    private ListPreference mPreference;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mController = new OneHandedTimeoutPreferenceController(mContext, KEY);
-        mPreference = new ListPreference(mContext);
-        mPreference.setKey(KEY);
-        OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
-    }
-
-    @Test
-    public void getAvailabilityStatus_enabledOneHanded_shouldAvailable() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_disableOneHanded_shouldUnavailable() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
-    }
-
-    @Test
-    public void updateState_enableOneHanded_switchShouldEnabled() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isEnabled()).isTrue();
-    }
-
-    @Test
-    public void updateState_disableOneHanded_switchShouldDisabled() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isEnabled()).isFalse();
-    }
-
-    @Test
-    public void getSummary_setTimeoutNever_shouldReturnNeverSummary() {
-        final String[] timeoutTitles = mContext.getResources().getStringArray(
-                R.array.one_handed_timeout_title);
-
-        OneHandedSettingsUtils.setTimeoutValue(mContext,
-                OneHandedSettingsUtils.OneHandedTimeout.NEVER.getValue());
-
-        assertThat(mController.getSummary()).isEqualTo(
-                timeoutTitles[OneHandedSettingsUtils.OneHandedTimeout.NEVER.ordinal()]);
-    }
-
-    @Test
-    public void getSummary_setTimeoutShort_shouldReturnShortSummary() {
-        final String[] timeoutTitles = mContext.getResources().getStringArray(
-                R.array.one_handed_timeout_title);
-
-        OneHandedSettingsUtils.setTimeoutValue(mContext,
-                OneHandedSettingsUtils.OneHandedTimeout.SHORT.getValue());
-
-        assertThat(mController.getSummary()).isEqualTo(String.format(
-                mContext.getResources().getString(R.string.screen_timeout_summary),
-                timeoutTitles[OneHandedSettingsUtils.OneHandedTimeout.SHORT.ordinal()]));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java
deleted file mode 100644
index 8f50006..0000000
--- a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationPreferenceControllerTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.provider.Settings;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class SwipeBottomToNotificationPreferenceControllerTest {
-
-    private static final String KEY = "gesture_swipe_bottom_to_notification";
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
-    private SwipeBottomToNotificationPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mController = new SwipeBottomToNotificationPreferenceController(mContext, KEY);
-    }
-
-    @Test
-    public void setChecked_toggledOn_enablesSwipeBottomToNotification() {
-        mController.setChecked(true);
-
-        assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isTrue();
-        assertThat(OneHandedSettingsUtils.isOneHandedModeEnabled(mContext)).isFalse();
-    }
-
-    @Test
-    public void setChecked_toggledOff_disablesSwipeBottomToNotification() {
-        mController.setChecked(false);
-
-        assertThat(OneHandedSettingsUtils.isSwipeDownNotificationEnabled(mContext)).isFalse();
-    }
-
-    @Test
-    public void getAvailabilityStatus_oneHandedUnsupported_returnsUnsupport() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
-        setNavigationBarMode(mContext, "2" /* fully gestural */);
-
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(
-                BasePreferenceController.UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_oneHandedSupported_returnsAvailable() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
-        setNavigationBarMode(mContext, "2" /* fully gestural */);
-
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_set3ButtonModeProperty_returnsUnsupport() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
-        setNavigationBarMode(mContext, "0" /* 3-button */);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    public void getSummary_gestureEnabled_returnsOnSummary() {
-        mController.setChecked(true);
-
-        assertThat(mController.getSummary()).isEqualTo(
-                mContext.getText(R.string.gesture_setting_on));
-    }
-
-    @Test
-    public void getSummary_gestureDisabled_returnsOffSummary() {
-        mController.setChecked(false);
-
-        assertThat(mController.getSummary()).isEqualTo(
-                mContext.getText(R.string.gesture_setting_off));
-    }
-
-    @Test
-    public void isChecked_getDefaultConfig_returnFalse() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
-        Settings.Secure.resetToDefaults(mContext.getContentResolver(),
-                Settings.Secure.ONE_HANDED_MODE_ENABLED);
-
-        assertThat(mController.isChecked()).isFalse();
-    }
-
-    /**
-     * Set NavigationBar mode flag to Settings provider.
-     * @param context App context
-     * @param value Navigation bar mode:
-     *  0 = 3 button
-     *  1 = 2 button
-     *  2 = fully gestural
-     * @return true if the value was set, false on database errors.
-     */
-    private boolean setNavigationBarMode(Context context, String value) {
-        return Settings.Secure.putStringForUser(context.getContentResolver(),
-                Settings.Secure.NAVIGATION_MODE, value, UserHandle.myUserId());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java
deleted file mode 100644
index a3c8a1e..0000000
--- a/tests/robotests/src/com/android/settings/gestures/SwipeBottomToNotificationSettingsTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.SystemProperties;
-import android.provider.SearchIndexableResource;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.util.ReflectionHelpers;
-
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class SwipeBottomToNotificationSettingsTest {
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
-    private SwipeBottomToNotificationSettings mSettings = new SwipeBottomToNotificationSettings();
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @Test
-    public void getPreferenceScreenResId_shouldReturnsXml() {
-        assertThat(mSettings.getPreferenceScreenResId())
-                .isEqualTo(R.xml.swipe_bottom_to_notification_settings);
-    }
-
-    @Test
-    public void searchIndexProvider_shouldIndexResource() {
-        final List<SearchIndexableResource> indexRes =
-                SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
-                        mContext, true /* enabled */);
-
-        assertThat(indexRes.get(0).xmlResId).isEqualTo(mSettings.getPreferenceScreenResId());
-    }
-
-    @Test
-    public void isPageSearchEnabled_oneHandedUnsupported_shouldReturnFalse() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "false");
-
-        final Object obj = ReflectionHelpers.callInstanceMethod(
-                SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
-                ReflectionHelpers.ClassParameter.from(Context.class, mContext));
-
-        final boolean isEnabled = (Boolean) obj;
-        assertThat(isEnabled).isFalse();
-    }
-
-    @Test
-    public void isPageSearchEnabled_oneHandedDisabled_shouldReturnTrue() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
-        final Object obj = ReflectionHelpers.callInstanceMethod(
-                SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
-                ReflectionHelpers.ClassParameter.from(Context.class, mContext));
-
-        final boolean isEnabled = (Boolean) obj;
-        assertThat(isEnabled).isTrue();
-    }
-
-    @Test
-    public void isPageSearchEnabled_oneHandedEnabled_shouldReturnFalse() {
-        SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true");
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
-        final Object obj = ReflectionHelpers.callInstanceMethod(
-                SwipeBottomToNotificationSettings.SEARCH_INDEX_DATA_PROVIDER, "isPageSearchEnabled",
-                ReflectionHelpers.ClassParameter.from(Context.class, mContext));
-
-        final boolean isEnabled = (Boolean) obj;
-        assertThat(isEnabled).isFalse();
-    }
-}
diff --git a/tests/unit/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceControllerTest.java b/tests/unit/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceControllerTest.java
deleted file mode 100644
index 980ca6e..0000000
--- a/tests/unit/src/com/android/settings/gestures/OneHandedAppTapsExitPreferenceControllerTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.os.UserHandle;
-
-import androidx.preference.SwitchPreference;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.core.TogglePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class OneHandedAppTapsExitPreferenceControllerTest {
-
-    private static final String KEY = "gesture_app_taps_to_exit";
-
-    private Context mContext;
-    private SwitchPreference mSwitchPreference;
-    private OneHandedAppTapsExitPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        mContext = ApplicationProvider.getApplicationContext();
-        mController = new OneHandedAppTapsExitPreferenceController(mContext, KEY);
-        mSwitchPreference = new SwitchPreference(mContext);
-        mSwitchPreference.setKey(KEY);
-        OneHandedSettingsUtils.setUserId(UserHandle.myUserId());
-    }
-
-    @Test
-    public void setChecked_setBoolean_checkIsTrueOrFalse() {
-        mController.setChecked(false);
-        assertThat(mController.isChecked()).isFalse();
-
-        mController.setChecked(true);
-        assertThat(mController.isChecked()).isTrue();
-    }
-
-    @Test
-    public void getAvailabilityStatus_enabledOneHanded_shouldAvailable() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(TogglePreferenceController.AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_disabledOneHanded_shouldUnavailable() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(TogglePreferenceController.DISABLED_DEPENDENT_SETTING);
-    }
-
-    @Test
-    public void updateState_enableOneHanded_switchShouldEnabled() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, true);
-
-        mController.updateState(mSwitchPreference);
-
-        assertThat(mSwitchPreference.isEnabled()).isTrue();
-    }
-
-    @Test
-    public void updateState_disableOneHanded_switchShouldDisabled() {
-        OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false);
-
-        mController.updateState(mSwitchPreference);
-
-        assertThat(mSwitchPreference.isEnabled()).isFalse();
-    }
-}
diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
index a96e7cf..85129f8 100644
--- a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
+++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.network;
 
-import static com.android.settings.network.ProviderModelSlice.ACTION_TITLE_CONNECT_TO_CARRIER;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -42,6 +40,8 @@
 import android.telephony.TelephonyManager;
 
 import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
 import androidx.slice.SliceProvider;
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.builders.SliceAction;
@@ -100,8 +100,6 @@
     ListBuilder.RowBuilder mMockCarrierRowBuild;
     @Mock
     WifiPickerTracker mWifiPickerTracker;
-    @Mock
-    WifiSliceItem mWifiSliceItem;
 
     private FakeFeatureFactory mFeatureFactory;
 
@@ -122,7 +120,7 @@
         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
         when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
-
+        when(mWifiManager.isWifiEnabled()).thenReturn(true);
 
         // Set-up specs for SliceMetadata.
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
@@ -182,7 +180,24 @@
 
     @Test
     @UiThreadTest
-    public void getSlice_haveTwoWifiAndOneCarrier_getCarrierAndTwoWiFiAndSeeAll() {
+    public void getSlice_airplaneModeIsOn_oneWifiToggle() {
+        mWifiList.clear();
+        mMockNetworkProviderWorker.updateSelfResults(null);
+        mockHelperCondition(true, false, false, null);
+
+        final Slice slice = mMockProviderModelSlice.getSlice();
+
+        assertThat(slice).isNotNull();
+        verify(mListBuilder, times(1)).addRow(any(ListBuilder.RowBuilder.class));
+        final SliceItem sliceTitle =
+                SliceMetadata.from(mContext, slice).getListContent().getHeader().getTitleItem();
+        assertThat(sliceTitle.getText()).isEqualTo(
+                ResourcesUtils.getResourcesString(mContext, "wifi_settings"));
+    }
+
+    @Test
+    @UiThreadTest
+    public void getSlice_haveTwoWifiAndOneCarrier_getFiveRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -197,13 +212,13 @@
 
         assertThat(slice).isNotNull();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveOneConnectedWifiAndTwoDisconnectedWifiAndNoCarrier_getFourRow() {
+    public void getSlice_haveOneConnectedWifiAndTwoDisconnectedWifiAndNoCarrier_getFiveRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -220,13 +235,13 @@
         final Slice slice = mMockProviderModelSlice.getSlice();
 
         assertThat(slice).isNotNull();
-        verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveTwoDisconnectedWifiAndNoCarrier_getThreeRow() {
+    public void getSlice_haveTwoDisconnectedWifiAndNoCarrier_getFourRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi1_key", true);
@@ -240,13 +255,13 @@
         final Slice slice = mMockProviderModelSlice.getSlice();
 
         assertThat(slice).isNotNull();
-        verify(mListBuilder, times(3)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(4)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveEthernetAndCarrierAndTwoDisconnectedWifi_getFiveRow() {
+    public void getSlice_haveEthernetAndCarrierAndTwoDisconnectedWifi_getSixRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_DISCONNECTED, "wifi1_key", true);
@@ -264,13 +279,13 @@
         assertThat(slice).isNotNull();
         assertThat(mMockProviderModelSlice.hasCreateEthernetRow()).isTrue();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(6)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
     @Test
     @UiThreadTest
-    public void getSlice_haveEthernetAndCarrierAndConnectedWifiAndDisconnectedWifi_getFiveRow() {
+    public void getSlice_haveEthernetAndCarrierAndConnectedWifiAndDisconnectedWifi_getSixRow() {
         mWifiList.clear();
         mockWifiItemCondition(mMockWifiSliceItem1, "wifi1", "wifi1",
                 WifiEntry.CONNECTED_STATE_CONNECTED, "wifi1_key", true);
@@ -288,7 +303,7 @@
         assertThat(slice).isNotNull();
         assertThat(mMockProviderModelSlice.hasCreateEthernetRow()).isTrue();
         verify(mListBuilder, times(1)).addRow(mMockCarrierRowBuild);
-        verify(mListBuilder, times(5)).addRow(any(ListBuilder.RowBuilder.class));
+        verify(mListBuilder, times(6)).addRow(any(ListBuilder.RowBuilder.class));
         assertThat(mMockProviderModelSlice.hasSeeAllRow()).isTrue();
     }
 
@@ -380,6 +395,11 @@
             return super.getSeeAllRow();
         }
 
+        @Override
+        public ListBuilder.RowBuilder getWifiSliceItemRow(WifiSliceItem wifiSliceItem) {
+            return super.getWifiSliceItemRow(wifiSliceItem);
+        }
+
         public boolean hasCreateEthernetRow() {
             return mHasCreateEthernetRow;
         }
@@ -420,29 +440,4 @@
 
         verify(mMockNetworkProviderWorker, never()).connectCarrierNetwork();
     }
-
-    @Test
-    public void getWifiSliceItemRow_wifiNoInternetAccess_actionConnectToWifiSsid() {
-        when(mWifiSliceItem.getKey()).thenReturn("wifi_key");
-        when(mWifiSliceItem.getTitle()).thenReturn("wifi_ssid");
-        when(mWifiSliceItem.hasInternetAccess()).thenReturn(false);
-
-        ListBuilder.RowBuilder rowBuilder =
-                mMockProviderModelSlice.getWifiSliceItemRow(mWifiSliceItem);
-
-        assertThat(rowBuilder.getPrimaryAction().getTitle())
-                .isEqualTo("wifi_ssid");
-    }
-
-    @Test
-    public void getWifiSliceItemRow_wifiHasInternetAccess_actionConnectToCarrier() {
-        when(mWifiSliceItem.getTitle()).thenReturn("wifi_ssid");
-        when(mWifiSliceItem.hasInternetAccess()).thenReturn(true);
-
-        ListBuilder.RowBuilder rowBuilder =
-                mMockProviderModelSlice.getWifiSliceItemRow(mWifiSliceItem);
-
-        assertThat(rowBuilder.getPrimaryAction().getTitle())
-                .isEqualTo(ACTION_TITLE_CONNECT_TO_CARRIER);
-    }
 }
diff --git a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java b/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
index e475e6f..9ad4a37 100644
--- a/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
+++ b/tests/unit/src/com/android/settings/panel/InternetConnectivityPanelTest.java
@@ -18,12 +18,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -32,9 +29,7 @@
 import android.net.Uri;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiManager;
-import android.os.Handler;
 
-import androidx.fragment.app.FragmentActivity;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
@@ -82,8 +77,6 @@
     @Rule
     public final MockitoRule mMocks = MockitoJUnit.rule();
     @Mock
-    Handler mMainThreadHandler;
-    @Mock
     PanelContentCallback mPanelContentCallback;
     @Mock
     InternetUpdater mInternetUpdater;
@@ -91,17 +84,34 @@
     private WifiManager mWifiManager;
     @Mock
     private ProviderModelSliceHelper mProviderModelSliceHelper;
-    @Mock
-    private FragmentActivity mPanelActivity;
 
     private Context mContext;
+    private FakeHandlerInjector mFakeHandlerInjector;
     private InternetConnectivityPanel mPanel;
 
+    private class FakeHandlerInjector extends InternetConnectivityPanel.HandlerInjector {
+
+        private Runnable mRunnable;
+
+        FakeHandlerInjector(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void postDelay(Runnable runnable) {
+            mRunnable = runnable;
+        }
+
+        public Runnable getRunnable() {
+            return mRunnable;
+        }
+    }
+
     @Before
     public void setUp() {
         mContext = spy(ApplicationProvider.getApplicationContext());
+        mFakeHandlerInjector = new FakeHandlerInjector(mContext);
         when(mContext.getApplicationContext()).thenReturn(mContext);
-        when(mContext.getMainThreadHandler()).thenReturn(mMainThreadHandler);
         when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
 
         mPanel = InternetConnectivityPanel.create(mContext);
@@ -109,6 +119,7 @@
         mPanel.mIsProviderModelEnabled = true;
         mPanel.mInternetUpdater = mInternetUpdater;
         mPanel.mProviderModelSliceHelper = mProviderModelSliceHelper;
+        mPanel.mHandlerInjector = mFakeHandlerInjector;
     }
 
     @Test
@@ -204,20 +215,6 @@
     }
 
     @Test
-    public void getCustomizedButtonTitle_wifiOff_turnOnWifi() {
-        doReturn(false).when(mInternetUpdater).isWifiEnabled();
-
-        assertThat(mPanel.getCustomizedButtonTitle()).isEqualTo(BUTTON_TURN_ON_WIFI);
-    }
-
-    @Test
-    public void getCustomizedButtonTitle_wifiOn_turnOffWifi() {
-        doReturn(true).when(mInternetUpdater).isWifiEnabled();
-
-        assertThat(mPanel.getCustomizedButtonTitle()).isEqualTo(BUTTON_TURN_OFF_WIFI);
-    }
-
-    @Test
     public void getSlices_providerModelDisabled_containsNecessarySlices() {
         mPanel.mIsProviderModelEnabled = false;
         List<Uri> uris = mPanel.getSlices();
@@ -241,31 +238,6 @@
     }
 
     @Test
-    public void onClickCustomizedButton_wifiOn_setWifiOff() {
-        doReturn(true).when(mInternetUpdater).isWifiEnabled();
-
-        mPanel.onClickCustomizedButton(mPanelActivity);
-
-        verify(mWifiManager).setWifiEnabled(false);
-    }
-
-    @Test
-    public void onClickCustomizedButton_wifiOff_setWifiOn() {
-        doReturn(false).when(mInternetUpdater).isWifiEnabled();
-
-        mPanel.onClickCustomizedButton(mPanelActivity);
-
-        verify(mWifiManager).setWifiEnabled(true);
-    }
-
-    @Test
-    public void onClickCustomizedButton_shouldNotFinishActivity() {
-        mPanel.onClickCustomizedButton(mPanelActivity);
-
-        verify(mPanelActivity, never()).finish();
-    }
-
-    @Test
     public void updatePanelTitle_onHeaderChanged() {
         clearInvocations(mPanelContentCallback);
 
@@ -295,36 +267,41 @@
     }
 
     @Test
-    public void showProgressBar_wifiDisabled_hideProgress() {
+    public void updateProgressBar_wifiDisabled_hideProgress() {
         mPanel.mIsProgressBarVisible = true;
         doReturn(false).when(mInternetUpdater).isWifiEnabled();
         clearInvocations(mPanelContentCallback);
 
-        mPanel.showProgressBar();
+        mPanel.updateProgressBar();
 
         assertThat(mPanel.isProgressBarVisible()).isFalse();
         verify(mPanelContentCallback).onProgressBarVisibleChanged();
     }
 
     @Test
-    public void showProgressBar_noWifiScanResults_showProgressForever() {
+    public void updateProgressBar_noWifiScanResults_showProgressForever() {
+        mPanel.mIsScanningSubTitleShownOnce = false;
         mPanel.mIsProgressBarVisible = false;
         doReturn(true).when(mInternetUpdater).isWifiEnabled();
         List<ScanResult> noWifiScanResults = new ArrayList<>();
         doReturn(noWifiScanResults).when(mWifiManager).getScanResults();
         clearInvocations(mPanelContentCallback);
 
-        mPanel.showProgressBar();
+        mPanel.updateProgressBar();
 
-        assertThat(mPanel.isProgressBarVisible()).isTrue();
+        assertThat(mPanel.mIsProgressBarVisible).isTrue();
         verify(mPanelContentCallback).onProgressBarVisibleChanged();
         verify(mPanelContentCallback).onHeaderChanged();
-        verify(mMainThreadHandler, never())
-                .postDelayed(any() /* mHideProgressBarRunnable */, anyLong());
+
+        assertThat(mFakeHandlerInjector.getRunnable())
+                .isEqualTo(mPanel.mHideScanningSubTitleRunnable);
+        mFakeHandlerInjector.getRunnable().run();
+        assertThat(mPanel.mIsScanningSubTitleShownOnce).isTrue();
+        assertThat(mPanel.mIsProgressBarVisible).isTrue();
     }
 
     @Test
-    public void showProgressBar_hasWifiScanResults_showProgressDelayedHide() {
+    public void updateProgressBar_hasWifiScanResults_showProgressDelayedHide() {
         mPanel.mIsProgressBarVisible = false;
         doReturn(true).when(mInternetUpdater).isWifiEnabled();
         List<ScanResult> hasWifiScanResults = mock(ArrayList.class);
@@ -332,11 +309,15 @@
         doReturn(hasWifiScanResults).when(mWifiManager).getScanResults();
         clearInvocations(mPanelContentCallback);
 
-        mPanel.showProgressBar();
+        mPanel.updateProgressBar();
 
         assertThat(mPanel.isProgressBarVisible()).isTrue();
         verify(mPanelContentCallback).onProgressBarVisibleChanged();
-        verify(mMainThreadHandler).postDelayed(any() /* mHideProgressBarRunnable */, anyLong());
+
+        assertThat(mFakeHandlerInjector.getRunnable())
+                .isEqualTo(mPanel.mHideProgressBarRunnable);
+        mFakeHandlerInjector.getRunnable().run();
+        assertThat(mPanel.mIsProgressBarVisible).isFalse();
     }
 
     @Test
diff --git a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
index 2199023..3b61a73 100644
--- a/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
+++ b/tests/unit/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
@@ -27,10 +27,7 @@
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.settings.testutils.FeatureFlagUtilsRule;
-
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -39,9 +36,6 @@
 
     private static final String TEST_PACKAGENAME = "com.test.packagename";
 
-    @Rule
-    public final FeatureFlagUtilsRule mFeatureFlagUtilsRule = new FeatureFlagUtilsRule();
-
     private Context mContext;
     private PanelFeatureProviderImpl mProvider;
     private Bundle mBundle;
@@ -71,24 +65,4 @@
 
         assertThat(panel).isInstanceOf(VolumePanel.class);
     }
-
-    @Test
-    public void getPanel_wifi_returnsWifiPanelWhenProviderModelDisable() {
-        mFeatureFlagUtilsRule.setProviderModelEnabled(false);
-        mBundle.putString(KEY_PANEL_TYPE_ARGUMENT, Settings.Panel.ACTION_WIFI);
-
-        final PanelContent panel = mProvider.getPanel(mContext, mBundle);
-
-        assertThat(panel).isInstanceOf(WifiPanel.class);
-    }
-
-    @Test
-    public void getPanel_wifi_returnsInternetConnectivityPanelWhenProviderModelDisable() {
-        mFeatureFlagUtilsRule.setProviderModelEnabled(true);
-        mBundle.putString(KEY_PANEL_TYPE_ARGUMENT, Settings.Panel.ACTION_WIFI);
-
-        final PanelContent panel = mProvider.getPanel(mContext, mBundle);
-
-        assertThat(panel).isInstanceOf(InternetConnectivityPanel.class);
-    }
 }
diff --git a/tests/unit/src/com/android/settings/testutils/FeatureFlagUtilsRule.java b/tests/unit/src/com/android/settings/testutils/FeatureFlagUtilsRule.java
deleted file mode 100644
index 910073e..0000000
--- a/tests/unit/src/com/android/settings/testutils/FeatureFlagUtilsRule.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.testutils;
-
-import android.content.Context;
-import android.util.FeatureFlagUtils;
-
-import androidx.test.core.app.ApplicationProvider;
-
-import org.junit.rules.ExternalResource;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A test rule that is used to automatically recover the FeatureFlagUtils resource after testing.
- *
- * Example:
- * <pre class="code"><code class="java">
- * public class ExampleTest {
- *
- *     &#064;Rule
- *     public final FeatureFlagUtilsRule mFeatureFlagUtilsRule = new FeatureFlagUtilsRule();
- *
- * }
- * </code></pre>
- */
-public class FeatureFlagUtilsRule extends ExternalResource {
-
-    private Context mContext;
-    private Map<String, Boolean> mBackupFeatureFlags = new HashMap<String, Boolean>();
-
-    @Override
-    protected void before() throws Throwable {
-        mContext = ApplicationProvider.getApplicationContext();
-    }
-
-    @Override
-    protected void after() {
-        mBackupFeatureFlags.forEach((k, v) -> FeatureFlagUtils.setEnabled(mContext, k, v));
-    }
-
-    public void setEnabled(String feature, boolean enabled) {
-        if (enabled == FeatureFlagUtils.isEnabled(mContext, feature)) {
-            return;
-        }
-        mBackupFeatureFlags.putIfAbsent(feature, !enabled);
-        FeatureFlagUtils.setEnabled(mContext, feature, enabled);
-    }
-
-    public void setProviderModelEnabled(boolean enabled) {
-        setEnabled(FeatureFlagUtils.SETTINGS_PROVIDER_MODEL, enabled);
-    }
-}