Merge "Add a flow to keep special apps in the battery unrestricted mode" into main
diff --git a/aconfig/settings_accessibility_flag_declarations.aconfig b/aconfig/settings_accessibility_flag_declarations.aconfig
index 10b536d..246f983 100644
--- a/aconfig/settings_accessibility_flag_declarations.aconfig
+++ b/aconfig/settings_accessibility_flag_declarations.aconfig
@@ -20,9 +20,16 @@
 }
 
 flag {
-  name: "separate_accessibility_vibration_settings_fragments"
-  namespace: "accessibility"
-  description: "Splits VibrationSettings into two fragments, one per XML resource"
-  bug: "289967175"
+    name: "separate_accessibility_vibration_settings_fragments"
+    namespace: "accessibility"
+    description: "Splits VibrationSettings into two fragments, one per XML resource"
+    bug: "289967175"
+}
+
+flag {
+    name: "new_hearing_device_pairing_page"
+    namespace: "accessibility"
+    description: "New hearing device pairing page with deny list method"
+    bug: "307473972"
 }
 
diff --git a/res/drawable/ic_audio_calls_and_alarms.xml b/res/drawable/ic_audio_calls_and_alarms.xml
new file mode 100644
index 0000000..5da27c6
--- /dev/null
+++ b/res/drawable/ic_audio_calls_and_alarms.xml
@@ -0,0 +1,32 @@
+<!--
+  Copyright (C) 2018 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:pathData="M3,15V9H7L12,4V20L7,15H3ZM10,15.17V8.83L7.83,11H5V13H7.83L10,15.17Z"
+        android:fillType="evenOdd"
+        android:fillColor="?android:attr/colorPrimary"/>
+    <path
+        android:pathData="M16.5,12C16.5,10.23 15.48,8.71 14,7.97V16.02C15.48,15.29 16.5,13.77 16.5,12Z"
+        android:fillColor="?android:attr/colorPrimary"/>
+    <path
+        android:pathData="M14,3.23V5.29C16.89,6.15 19,8.83 19,12C19,15.17 16.89,17.85 14,18.71V20.77C18.01,19.86 21,16.28 21,12C21,7.72 18.01,4.14 14,3.23Z"
+        android:fillColor="?android:attr/colorPrimary"/>
+</vector>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1938873..304ea55 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -292,6 +292,8 @@
     <string name="audio_sharing_title">Audio sharing</string>
     <!-- Title for audio sharing primary switch [CHAR LIMIT=none]-->
     <string name="audio_sharing_switch_title">Share audio</string>
+    <!-- Title for calls and alarms device on audio sharing page [CHAR LIMIT=none]-->
+    <string name="calls_and_alarms_device_title">Calls and alarms</string>
 
     <!-- Date & time settings screen title -->
     <string name="date_and_time">Date &amp; time</string>
@@ -2594,7 +2596,7 @@
     <!-- Display settings screen, peak refresh rate settings title [CHAR LIMIT=30] -->
     <string name="peak_refresh_rate_title">Smooth Display</string>
     <!-- Display settings screen, peak refresh rate settings summary [CHAR LIMIT=NONE] -->
-    <string name="peak_refresh_rate_summary">Automatically raises the refresh rate from 60 to <xliff:g name="refresh_rate" example="120">%1$s</xliff:g> Hz for some content. Increases battery usage.</string>
+    <string name="peak_refresh_rate_summary">Automatically raises the refresh rate up to <xliff:g name="refresh_rate" example="120">%1$d</xliff:g> Hz for some content. Increases battery usage.</string>
     <!-- Display developer settings: Force to the highest refresh rate [CHAR LIMIT=NONE] -->
     <string name="force_high_refresh_rate_toggle">Force peak refresh rate</string>
     <!-- Display developer settings: Force to the highest refresh rate description [CHAR LIMIT=NONE]-->
@@ -4633,6 +4635,8 @@
     <string name="accessibility_tutorial_dialog_title_volume">Hold volume keys to open</string>
     <!-- Title for the accessibility tutorial dialog in accessibility service with triple tap. [CHAR LIMIT=100] -->
     <string name="accessibility_tutorial_dialog_title_triple">Triple tap screen to open</string>
+    <!-- Title for the accessibility tutorial dialog in accessibility service with two finger triple tap. [CHAR LIMIT=100] -->
+    <string name="accessibility_tutorial_dialog_title_two_finger_triple">Two finger triple tap screen to open</string>
     <!-- Title for the accessibility tutorial dialog in accessibility service with gesture. [CHAR LIMIT=50] -->
     <string name="accessibility_tutorial_dialog_title_gesture">Use gesture to open</string>
     <!-- Title for the accessibility tutorial dialog in gesture navigation settings. [CHAR LIMIT=50] -->
@@ -4645,6 +4649,8 @@
     <string name="accessibility_tutorial_dialog_message_volume">To use this feature, press &amp; hold both volume keys.</string>
     <!-- Instruction for the accessibility tutorial dialog in accessibility service with triple tap. [CHAR LIMIT=100] -->
     <string name="accessibility_tutorial_dialog_message_triple">To start and stop magnification, triple-tap anywhere on your screen.</string>
+    <!-- Instruction for the accessibility tutorial dialog in accessibility service with two finger triple tap. [CHAR LIMIT=100] -->
+    <string name="accessibility_tutorial_dialog_message_two_finger_triple">To start and stop magnification, triple-tap anywhere on your screen with two fingers.</string>
     <!-- Message for the accessibility tutorial dialog when user enables an accessibility service while using gesture navigation and touch exploration is not enabled. [CHAR LIMIT=NONE] -->
     <string name="accessibility_tutorial_dialog_message_gesture">To use this feature, swipe up from the bottom of the screen with 2 fingers.\n\nTo switch between features, swipe up with 2 fingers and hold.</string>
     <!-- Message for the accessibility tutorial dialog when user enables an accessibility service while using gesture navigation and touch exploration is enabled. [CHAR LIMIT=NONE] -->
diff --git a/res/xml/bluetooth_audio_sharing.xml b/res/xml/bluetooth_audio_sharing.xml
index a90da72..bf7593a 100644
--- a/res/xml/bluetooth_audio_sharing.xml
+++ b/res/xml/bluetooth_audio_sharing.xml
@@ -19,4 +19,10 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/audio_sharing_title">
 
+    <Preference
+        android:key="calls_and_alarms"
+        android:title="@string/calls_and_alarms_device_title"
+        android:icon="@drawable/ic_audio_calls_and_alarms"
+        settings:controller="com.android.settings.connecteddevice.audiosharing.CallsAndAlarmsPreferenceController"
+        android:summary=""/>
 </PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
index ee2dc05..e90ed87 100644
--- a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
+++ b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
@@ -54,6 +54,7 @@
 import androidx.viewpager.widget.PagerAdapter;
 import androidx.viewpager.widget.ViewPager;
 
+import com.android.server.accessibility.Flags;
 import com.android.settings.R;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settingslib.widget.LottieColorUtils;
@@ -411,6 +412,23 @@
         return new TutorialPage(type, title, image, indicatorIcon, instruction);
     }
 
+    private static TutorialPage createTwoFingerTripleTapTutorialPage(@NonNull Context context) {
+        // TODO(b/308088945): Update tutorial string and image when UX provides them
+        final int type = UserShortcutType.TWOFINGERTRIPLETAP;
+        final CharSequence title =
+                context.getText(R.string.accessibility_tutorial_dialog_title_two_finger_triple);
+        final View image =
+                createIllustrationViewWithImageRawResource(context,
+                        R.raw.a11y_shortcut_type_triple_tap);
+        final CharSequence instruction =
+                context.getText(R.string.accessibility_tutorial_dialog_message_two_finger_triple);
+        final ImageView indicatorIcon =
+                createImageView(context, R.drawable.ic_accessibility_page_indicator);
+        indicatorIcon.setEnabled(false);
+
+        return new TutorialPage(type, title, image, indicatorIcon, instruction);
+    }
+
     @VisibleForTesting
     static List<TutorialPage> createShortcutTutorialPages(@NonNull Context context,
             int shortcutTypes) {
@@ -427,6 +445,13 @@
             tutorialPages.add(createTripleTapTutorialPage(context));
         }
 
+        if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
+            if ((shortcutTypes & UserShortcutType.TWOFINGERTRIPLETAP)
+                    == UserShortcutType.TWOFINGERTRIPLETAP) {
+                tutorialPages.add(createTwoFingerTripleTapTutorialPage(context));
+            }
+        }
+
         return tutorialPages;
     }
 
diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
index 370b69a..b9ef8f4 100644
--- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDashboardFragment.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.connecteddevice.audiosharing;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.os.Bundle;
 
@@ -36,8 +37,7 @@
 
     @Override
     public int getMetricsCategory() {
-        // TODO: update category id.
-        return 0;
+        return SettingsEnums.AUDIO_SHARING_SETTINGS;
     }
 
     @Override
@@ -63,6 +63,7 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
+        use(CallsAndAlarmsPreferenceController.class).init(this);
     }
 
     @Override
diff --git a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragment.java
new file mode 100644
index 0000000..0577f70
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsDialogFragment.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.flags.Flags;
+
+/** Provides a dialog to choose the active device for calls and alarms. */
+public class CallsAndAlarmsDialogFragment extends InstrumentedDialogFragment {
+    private static final String TAG = "CallsAndAlarmsDialog";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_AUDIO_SHARING_SWITCH_ACTIVE;
+    }
+
+    /**
+     * Display the {@link CallsAndAlarmsDialogFragment} dialog.
+     *
+     * @param host The Fragment this dialog will be hosted.
+     */
+    public static void show(Fragment host) {
+        if (!Flags.enableLeAudioSharing()) return;
+        final FragmentManager manager = host.getChildFragmentManager();
+        if (manager.findFragmentByTag(TAG) == null) {
+            final CallsAndAlarmsDialogFragment dialog = new CallsAndAlarmsDialogFragment();
+            dialog.show(manager, TAG);
+        }
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        // TODO: use real device names
+        String[] choices = {"Buds 1", "Buds 2"};
+        AlertDialog.Builder builder =
+                new AlertDialog.Builder(getActivity())
+                        .setTitle(R.string.calls_and_alarms_device_title)
+                        .setSingleChoiceItems(
+                                choices,
+                                0, // TODO: set to current active device.
+                                (dialog, which) -> {
+                                    // TODO: set device to active device for calls and alarms.
+                                });
+        return builder.create();
+    }
+}
diff --git a/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java b/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java
new file mode 100644
index 0000000..480b257
--- /dev/null
+++ b/src/com/android/settings/connecteddevice/audiosharing/CallsAndAlarmsPreferenceController.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.audiosharing;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
+
+/** PreferenceController to control the dialog to choose the active device for calls and alarms */
+public class CallsAndAlarmsPreferenceController extends BasePreferenceController {
+
+    private static final String TAG = "CallsAndAlarmsPreferenceController";
+
+    private static final String PREF_KEY = "calls_and_alarms";
+
+    private Preference mPreference;
+    private DashboardFragment mFragment;
+
+    public CallsAndAlarmsPreferenceController(Context context) {
+        super(context, PREF_KEY);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return Flags.enableLeAudioSharing() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return PREF_KEY;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mPreference = screen.findPreference(getPreferenceKey());
+        mPreference.setOnPreferenceClickListener(
+                preference -> {
+                    if (mFragment != null) {
+                        CallsAndAlarmsDialogFragment.show(mFragment);
+                    } else {
+                        Log.w(TAG, "Dialog fail to show due to null host.");
+                    }
+                    return true;
+                });
+    }
+
+    /**
+     * Initialize the controller.
+     *
+     * @param fragment The fragment to host the {@link CallsAndAlarmsDialogFragment} dialog.
+     */
+    public void init(DashboardFragment fragment) {
+        this.mFragment = fragment;
+    }
+}
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index 793fecc..bc271ca 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -49,9 +49,11 @@
 import android.view.View;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
+import androidx.core.view.MenuProvider;
 import androidx.fragment.app.Fragment;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
@@ -249,6 +251,8 @@
     ConnectedEthernetNetworkController mConnectedEthernetNetworkController;
     @VisibleForTesting
     FooterPreference mWifiStatusMessagePreference;
+    @VisibleForTesting
+    MenuProvider mMenuProvider;
 
     /**
      * Mobile networks list for provider model
@@ -306,6 +310,44 @@
 
         mIsRestricted = isUiRestricted();
         updateUserType();
+
+        mMenuProvider = new MenuProvider() {
+            @Override
+            public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
+                MenuItem fixConnectivityItem = menu.add(0, MENU_FIX_CONNECTIVITY, 0,
+                        R.string.fix_connectivity);
+                fixConnectivityItem.setIcon(R.drawable.ic_repair_24dp);
+                fixConnectivityItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+            }
+
+            @Override
+            public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
+                if (menuItem.getItemId() == MENU_FIX_CONNECTIVITY) {
+                    if (isPhoneOnCall()) {
+                        showResetInternetDialog();
+                        return true;
+                    }
+                    fixConnectivity();
+                    return true;
+                }
+                return false;
+            }
+
+            @Override
+            public void onPrepareMenu(@NonNull Menu menu) {
+                MenuProvider.super.onPrepareMenu(menu);
+
+                boolean isWifiEnabled = mWifiPickerTracker != null
+                        && mWifiPickerTracker.getWifiState() == WifiManager.WIFI_STATE_ENABLED;
+                boolean isAirplaneModeOn =
+                        mAirplaneModeEnabler != null && mAirplaneModeEnabler.isAirplaneModeOn();
+                MenuItem fixConnectivityItem = menu.findItem(MENU_FIX_CONNECTIVITY);
+                if (fixConnectivityItem == null) {
+                    return;
+                }
+                fixConnectivityItem.setVisible(!mIsGuest && (!isAirplaneModeOn || isWifiEnabled));
+            }
+        };
     }
 
     private void updateUserType() {
@@ -425,7 +467,6 @@
                 }
             }
         };
-        setHasOptionsMenu(true);
 
         if (savedInstanceState != null) {
             mDialogMode = savedInstanceState.getInt(SAVE_DIALOG_MODE);
@@ -444,12 +485,13 @@
         if (mNetworkMobileProviderController != null) {
             mNetworkMobileProviderController.setWifiPickerTrackerHelper(mWifiPickerTrackerHelper);
         }
+
+        requireActivity().addMenuProvider(mMenuProvider);
     }
 
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-
     }
 
     @Override
@@ -807,6 +849,9 @@
             return;
         }
 
+        // update the menu item
+        requireActivity().invalidateMenu();
+
         switch (wifiState) {
             case WifiManager.WIFI_STATE_ENABLED:
                 setWifiScanMessage(/* isWifiEnabled */ true);
@@ -1397,29 +1442,6 @@
         return HelpUtils.getHelpIntent(context, helpUrlString, context.getClass().getName());
     }
 
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        if (!mIsGuest && !mAirplaneModeEnabler.isAirplaneModeOn()) {
-            MenuItem item = menu.add(0, MENU_FIX_CONNECTIVITY, 0, R.string.fix_connectivity);
-            item.setIcon(R.drawable.ic_repair_24dp);
-            item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
-        }
-        super.onCreateOptionsMenu(menu, inflater);
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem menuItem) {
-        if (menuItem.getItemId() == MENU_FIX_CONNECTIVITY) {
-            if (isPhoneOnCall()) {
-                showResetInternetDialog();
-                return true;
-            }
-            fixConnectivity();
-            return true;
-        }
-        return super.onOptionsItemSelected(menuItem);
-    }
-
     @VisibleForTesting
     void showResetInternetDialog() {
         AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
@@ -1462,6 +1484,8 @@
     @Override
     public void onAirplaneModeChanged(boolean isAirplaneModeOn) {
         updateAirplaneModeMsgPreference(isAirplaneModeOn /* visible */);
+        // update the menu item
+        requireActivity().invalidateMenu();
     }
 
     /**
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
index 5d3557f..d6a2492 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorialTest.java
@@ -32,11 +32,15 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.view.View;
 
 import androidx.appcompat.app.AlertDialog;
 import androidx.test.core.app.ApplicationProvider;
 
+import com.android.server.accessibility.Flags;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SubSettings;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -59,6 +63,8 @@
 
     @Rule
     public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
     @Mock
     private DialogInterface.OnClickListener mOnClickListener;
     @Mock
@@ -90,6 +96,19 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE)
+    public void createTutorialPages_turnOnTwoFingerTripleTapShortcut_hasOnePage() {
+        mShortcutTypes |= UserShortcutType.TWOFINGERTRIPLETAP;
+
+        final AlertDialog alertDialog =
+                createAccessibilityTutorialDialog(mContext, mShortcutTypes);
+
+        assertThat(createShortcutTutorialPages(mContext,
+                mShortcutTypes)).hasSize(/* expectedSize= */ 1);
+        assertThat(alertDialog).isNotNull();
+    }
+
+    @Test
     public void createTutorialPages_turnOnSoftwareShortcut_hasOnePage() {
         mShortcutTypes |= UserShortcutType.SOFTWARE;
 
diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
index a91af12..b1bd41d 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
@@ -286,7 +286,8 @@
 
     private void setUpForOnCreate() {
         final FragmentActivity activity = mock(FragmentActivity.class);
-        when(mNetworkProviderSettings.getActivity()).thenReturn(activity);
+        doReturn(activity).when(mNetworkProviderSettings).requireActivity();
+        doReturn(activity).when(mNetworkProviderSettings).getActivity();
         final Resources.Theme theme = mContext.getTheme();
         when(activity.getTheme()).thenReturn(theme);
         UserManager userManager = mock(UserManager.class);
@@ -484,59 +485,95 @@
         when(controller.getConfig()).thenReturn(config);
         WifiDialog2.WifiDialog2Listener listener = mock(WifiDialog2.WifiDialog2Listener.class);
         final WifiDialog2 wifiDialog2 = spy(new WifiDialog2(mContext, listener, mWifiEntry, mode));
-        when(wifiDialog2.getController()).thenReturn(controller);
+        doReturn(controller).when(wifiDialog2).getController();
         return wifiDialog2;
     }
 
-    @Test
-    public void onCreateOptionsMenu_isGuest_neverAddFixConnectivityMenu() {
-        mNetworkProviderSettings.mIsGuest = true;
+    private void mockMenuConditions(boolean isGuest, boolean isAirplaneModeOn, boolean isWifiOn) {
+        mNetworkProviderSettings.mIsGuest = isGuest;
+        doReturn(isAirplaneModeOn).when(mAirplaneModeEnabler).isAirplaneModeOn();
+        when(mMockWifiPickerTracker.getWifiState()).thenReturn(
+                isWifiOn ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED);
 
-        mNetworkProviderSettings.onCreateOptionsMenu(mMenu, null /* inflater */);
+        doReturn(mMenuItem).when(mMenu).findItem(MENU_FIX_CONNECTIVITY);
+        mNetworkProviderSettings.mAirplaneModeEnabler = mAirplaneModeEnabler;
+        mNetworkProviderSettings.mWifiPickerTracker = mMockWifiPickerTracker;
 
-        verify(mMenu, never()).add(anyInt(), eq(MENU_FIX_CONNECTIVITY), anyInt(), anyInt());
     }
 
     @Test
-    public void onCreateOptionsMenu_isNotGuest_addFixConnectivityMenu() {
-        mNetworkProviderSettings.mIsGuest = false;
+    public void onCreateOptionsMenu_isGuest_hideFixConnectivityMenu() {
+        setUpForOnCreate();
+        mNetworkProviderSettings.onCreate(null);
+        mockMenuConditions(/*isGuest=*/ true, /*isAirplaneModeOn=*/ false, /*isWifiOn=*/ true);
 
-        mNetworkProviderSettings.onCreateOptionsMenu(mMenu, null /* inflater */);
+        mNetworkProviderSettings.mMenuProvider.onPrepareMenu(mMenu);
 
-        verify(mMenu).add(anyInt(), eq(MENU_FIX_CONNECTIVITY), anyInt(), anyInt());
+        verify(mMenuItem).setVisible(false);
+
     }
 
     @Test
-    public void onCreateOptionsMenu_isAirplaneModeOn_neverAddFixConnectivityMenu() {
-        doReturn(true).when(mAirplaneModeEnabler).isAirplaneModeOn();
+    public void onCreateOptionsMenu_isNotGuest_showFixConnectivityMenu() {
+        setUpForOnCreate();
+        mNetworkProviderSettings.onCreate(null);
+        mockMenuConditions(/*isGuest=*/ false, /*isAirplaneModeOn=*/ false, /*isWifiOn=*/ true);
 
-        mNetworkProviderSettings.onCreateOptionsMenu(mMenu, null /* inflater */);
+        mNetworkProviderSettings.mMenuProvider.onPrepareMenu(mMenu);
 
-        verify(mMenu, never()).add(anyInt(), eq(MENU_FIX_CONNECTIVITY), anyInt(), anyInt());
+        verify(mMenuItem).setVisible(true);
+
     }
 
     @Test
-    public void onCreateOptionsMenu_isNotAirplaneModeOn_addFixConnectivityMenu() {
-        doReturn(false).when(mAirplaneModeEnabler).isAirplaneModeOn();
+    public void onCreateOptionsMenu_isAirplaneModeOnAndWifiOff_hideFixConnectivityMenu() {
+        setUpForOnCreate();
+        mNetworkProviderSettings.onCreate(null);
+        mockMenuConditions(/*isGuest=*/ false, /*isAirplaneModeOn=*/ true, /*isWifiOn=*/ false);
 
-        mNetworkProviderSettings.onCreateOptionsMenu(mMenu, null /* inflater */);
+        mNetworkProviderSettings.mMenuProvider.onPrepareMenu(mMenu);
 
-        verify(mMenu).add(anyInt(), eq(MENU_FIX_CONNECTIVITY), anyInt(), anyInt());
+        verify(mMenuItem).setVisible(false);
+    }
+
+    @Test
+    public void onCreateOptionsMenu_isAirplaneModeOnAndWifiOn_showFixConnectivityMenu() {
+        setUpForOnCreate();
+        mNetworkProviderSettings.onCreate(null);
+        mockMenuConditions(/*isGuest=*/ false, /*isAirplaneModeOn=*/ true, /*isWifiOn=*/ true);
+
+        mNetworkProviderSettings.mMenuProvider.onPrepareMenu(mMenu);
+
+        verify(mMenuItem).setVisible(true);
+    }
+
+    @Test
+    public void onCreateOptionsMenu_isNotAirplaneModeOn_showFixConnectivityMenu() {
+        setUpForOnCreate();
+        mNetworkProviderSettings.onCreate(null);
+        mockMenuConditions(/*isGuest=*/ false, /*isAirplaneModeOn=*/ false, /*isWifiOn=*/ true);
+
+        mNetworkProviderSettings.mMenuProvider.onPrepareMenu(mMenu);
+
+        verify(mMenuItem).setVisible(true);
     }
 
     @Test
     public void onOptionsItemSelected_fixConnectivity_restartInternet() {
-        mNetworkProviderSettings.mInternetResetHelper = mInternetResetHelper;
+        setUpForOnCreate();
         doReturn(false).when(mNetworkProviderSettings).isPhoneOnCall();
-        doReturn(NetworkProviderSettings.MENU_FIX_CONNECTIVITY).when(mMenuItem).getItemId();
+        doReturn(MENU_FIX_CONNECTIVITY).when(mMenuItem).getItemId();
+        mNetworkProviderSettings.onCreate(null);
+        mNetworkProviderSettings.mInternetResetHelper = mInternetResetHelper;
 
-        mNetworkProviderSettings.onOptionsItemSelected(mMenuItem);
+        mNetworkProviderSettings.mMenuProvider.onMenuItemSelected(mMenuItem);
 
         verify(mInternetResetHelper).restart();
     }
 
     @Test
     public void onAirplaneModeChanged_apmIsOn_showApmMsg() {
+        setUpForOnCreate();
         mNetworkProviderSettings.onAirplaneModeChanged(true);
 
         verify(mAirplaneModeMsgPreference).setVisible(true);
@@ -544,6 +581,7 @@
 
     @Test
     public void onAirplaneModeChanged_apmIsOff_hideApmMsg() {
+        setUpForOnCreate();
         mNetworkProviderSettings.onAirplaneModeChanged(false);
 
         verify(mAirplaneModeMsgPreference).setVisible(false);