Merge "[Settings] Refactor AirplaneModeEnabler"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ab3be11..74f4621 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1763,7 +1763,8 @@
     <string name="tx_link_speed"><xliff:g id="Transmit link speed" example="150 Mbps">%1$d</xliff:g> Mbps</string>
     <!-- Receive Link speed on Wifi Status screen [CHAR LIMIT=32] -->
     <string name="rx_link_speed"><xliff:g id="Receive link speed" example="54 Mbps">%1$d</xliff:g> Mbps</string>
-
+    <!-- Link speed on Wifi Status screen [CHAR LIMIT=32] -->
+    <string name="link_speed"><xliff:g id="Link speed" example="54 Mbps">%1$d</xliff:g> Mbps</string>
     <!-- This string asks the user whether or not to allow an app to enable WiFi. [CHAR LIMIT=NONE] -->
     <string name="wifi_ask_enable"><xliff:g id="requester" example="FancyApp">%s</xliff:g> wants to turn on Wi-Fi</string>
     <!-- This string asks the user whether or not to allow an app to disable WiFi. [CHAR LIMIT=NONE] -->
@@ -1974,6 +1975,8 @@
     <string name="tx_wifi_speed">Transmit link speed</string>
     <!-- Label for the receive link speed of the connection. [CHAR LIMIT=32] -->
     <string name="rx_wifi_speed">Receive link speed</string>
+    <!-- Label for the link speed of the connection. [CHAR LIMIT=32] -->
+    <string name="wifi_speed">Link speed</string>
     <!-- Label for the frequency band of the connection -->
     <string name="wifi_frequency">Frequency</string>
     <!-- Label for the IP address of the connection -->
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index cd05512..cc45a96 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -71,17 +71,19 @@
         android:title="@string/security_settings_face_preference_title">
         <com.android.settingslib.widget.LayoutPreference
             android:key="security_settings_face_delete_faces_container"
+            android:title="@string/security_settings_face_settings_remove_face_data"
             android:selectable="false"
             android:layout="@layout/face_remove_button"
             settings:allowDividerBelow="true"/>
 
         <com.android.settingslib.widget.LayoutPreference
             android:key="security_settings_face_enroll_faces_container"
+            android:title="@string/security_settings_face_settings_enroll"
             android:selectable="false"
-            android:layout="@layout/face_enroll_button "
+            android:layout="@layout/face_enroll_button"
             settings:allowDividerBelow="true"/>
     </PreferenceCategory>
 
     <com.android.settingslib.widget.FooterPreference
         settings:allowDividerAbove="true"/>
-</PreferenceScreen>
\ No newline at end of file
+</PreferenceScreen>
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index ca51f18..5795e65 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -56,6 +56,11 @@
     private static final String TAG = "FaceSettings";
     private static final String KEY_TOKEN = "hw_auth_token";
 
+    private static final String PREF_KEY_DELETE_FACE_DATA =
+            "security_settings_face_delete_faces_container";
+    private static final String PREF_KEY_ENROLL_FACE_UNLOCK =
+            "security_settings_face_enroll_faces_container";
+
     private UserManager mUserManager;
     private FaceManager mFaceManager;
     private int mUserId;
@@ -309,6 +314,15 @@
                 protected boolean isPageSearchEnabled(Context context) {
                     return isAvailable(context);
                 }
-            };
 
+                @Override
+                public List<String> getNonIndexableKeys(Context context) {
+                    final List<String> keys = super.getNonIndexableKeys(context);
+                    final FaceManager faceManager = context.getSystemService(FaceManager.class);
+                    final boolean hasEnrolled = faceManager.hasEnrolledTemplates(
+                            UserHandle.myUserId());
+                    keys.add(hasEnrolled ? PREF_KEY_ENROLL_FACE_UNLOCK : PREF_KEY_DELETE_FACE_DATA);
+                    return keys;
+                }
+            };
 }
diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java
index 3e8a42c..c6b4702 100644
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -366,7 +366,7 @@
             } else {
                 final String signalLevel = getSignalString();
 
-                if (mWifiEntry.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED
+                if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED
                             && signalLevel != null) {
                     mConfigUi.setSubmitButton(res.getString(R.string.wifi_connect));
                 } else {
@@ -388,16 +388,10 @@
                     }
 
                     final ConnectedInfo info = mWifiEntry.getConnectedInfo();
-                    // TODO(b/143326832): Replace it with ConnectedInfo#linkSpeedMbps.
-                   //if (info != null && info.getTxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) {
-                    //    addRow(group, R.string.tx_wifi_speed, String.format(
-                   //            res.getString(R.string.tx_link_speed), info.getTxLinkSpeedMbps()));
-                    //}
-
-                   //if (info != null && info.getRxLinkSpeedMbps() != WifiInfo.LINK_SPEED_UNKNOWN) {
-                    //    addRow(group, R.string.rx_wifi_speed, String.format(
-                   //            res.getString(R.string.rx_link_speed), info.getRxLinkSpeedMbps()));
-                    //}
+                    if (info != null && info.linkSpeedMbps >= 0) {
+                        addRow(group, R.string.wifi_speed, String.format(
+                                res.getString(R.string.link_speed), info.linkSpeedMbps));
+                    }
 
                     if (info != null && info.frequencyMhz != WifiEntry.FREQUENCY_UNKNOWN) {
                         final int frequency = info.frequencyMhz;
diff --git a/src/com/android/settings/wifi/WifiSettings2.java b/src/com/android/settings/wifi/WifiSettings2.java
index ac5e31c..bd79b3f 100644
--- a/src/com/android/settings/wifi/WifiSettings2.java
+++ b/src/com/android/settings/wifi/WifiSettings2.java
@@ -142,6 +142,19 @@
     private String mDialogWifiEntryKey;
     private WifiEntry mDialogWifiEntry;
 
+    // This boolean extra specifies whether to enable the Next button when connected. Used by
+    // account creation outside of setup wizard.
+    private static final String EXTRA_ENABLE_NEXT_ON_CONNECT = "wifi_enable_next_on_connect";
+
+    // Enable the Next button when a Wi-Fi network is connected.
+    private boolean mEnableNextOnConnection;
+
+    // This string extra specifies a network to open the connect dialog on, so the user can enter
+    // network credentials.  This is used by quick settings for secured networks, among other
+    // things.
+    private static final String EXTRA_START_CONNECT_SSID = "wifi_start_connect_ssid";
+    private String mOpenSsid;
+
     private static boolean isVerboseLoggingEnabled() {
         return WifiPickerTracker.isVerboseLoggingEnabled();
     }
@@ -329,6 +342,15 @@
                 }
             }
         }
+
+        // If we're supposed to enable/disable the Next button based on our current connection
+        // state, start it off in the right state.
+        final Intent intent = getActivity().getIntent();
+        mEnableNextOnConnection = intent.getBooleanExtra(EXTRA_ENABLE_NEXT_ON_CONNECT, false);
+
+        if (intent.hasExtra(EXTRA_START_CONNECT_SSID)) {
+            mOpenSsid = intent.getStringExtra(EXTRA_START_CONNECT_SSID);
+        }
     }
 
     @Override
@@ -384,6 +406,23 @@
         if (mWifiEnabler != null) {
             mWifiEnabler.resume(activity);
         }
+
+        changeNextButtonState(mWifiPickerTracker.getConnectedWifiEntry() != null);
+
+        // Edit the Wi-Fi network of specified SSID.
+        if (mOpenSsid != null) {
+            Optional<WifiEntry> matchedWifiEntry = mWifiPickerTracker.getWifiEntries().stream()
+                    .filter(wifiEntry -> TextUtils.equals(mOpenSsid, wifiEntry.getSsid()))
+                    .filter(wifiEntry -> wifiEntry.getSecurity() != WifiEntry.SECURITY_NONE
+                            && wifiEntry.getSecurity() != WifiEntry.SECURITY_OWE)
+                    .filter(wifiEntry -> !wifiEntry.isSaved()
+                            || isDisabledByWrongPassword(wifiEntry))
+                    .findFirst();
+            if (matchedWifiEntry.isPresent()) {
+                mOpenSsid = null;
+                launchConfigNewNetworkFragment(matchedWifiEntry.get());
+            }
+        }
     }
 
     @Override
@@ -626,6 +665,7 @@
     @Override
     public void onWifiEntriesChanged() {
         updateWifiEntryPreferencesDelayed();
+        changeNextButtonState(mWifiPickerTracker.getConnectedWifiEntry() != null);
     }
 
     @Override
@@ -882,6 +922,19 @@
         return R.string.help_url_wifi;
     }
 
+    /**
+     * Renames/replaces "Next" button when appropriate. "Next" button usually exists in
+     * Wi-Fi setup screens, not in usual wifi settings screen.
+     *
+     * @param enabled true when the device is connected to a wifi network.
+     */
+    @VisibleForTesting
+    void changeNextButtonState(boolean enabled) {
+        if (mEnableNextOnConnection && hasNextButton()) {
+            getNextButton().setEnabled(enabled);
+        }
+    }
+
     @Override
     public void onForget(WifiDialog2 dialog) {
         forget(mDialogWifiEntry);
@@ -1014,16 +1067,7 @@
                 if (mEditIfNoConfig) {
                     // Edit an unsaved secure Wi-Fi network.
                     if (mFullScreenEdit) {
-                        final Bundle bundle = new Bundle();
-                        bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY,
-                                mConnectWifiEntry.getKey());
-                        new SubSettingLauncher(getContext())
-                                .setTitleText(mConnectWifiEntry.getTitle())
-                                .setDestination(ConfigureWifiEntryFragment.class.getName())
-                                .setArguments(bundle)
-                                .setSourceMetricsCategory(getMetricsCategory())
-                                .setResultListener(WifiSettings2.this, CONFIG_NETWORK_REQUEST)
-                                .launch();
+                        launchConfigNewNetworkFragment(mConnectWifiEntry);
                     } else {
                         showDialog(mConnectWifiEntry, WifiConfigUiBase2.MODE_MODIFY);
                     }
@@ -1053,4 +1097,32 @@
     private boolean isFisishingOrDestroyed(Activity activity) {
         return activity == null || activity.isFinishing() || activity.isDestroyed();
     }
+
+    private void launchConfigNewNetworkFragment(WifiEntry wifiEntry) {
+        final Bundle bundle = new Bundle();
+        bundle.putString(WifiNetworkDetailsFragment2.KEY_CHOSEN_WIFIENTRY_KEY,
+                wifiEntry.getKey());
+        new SubSettingLauncher(getContext())
+                .setTitleText(wifiEntry.getTitle())
+                .setDestination(ConfigureWifiEntryFragment.class.getName())
+                .setArguments(bundle)
+                .setSourceMetricsCategory(getMetricsCategory())
+                .setResultListener(WifiSettings2.this, CONFIG_NETWORK_REQUEST)
+                .launch();
+    }
+
+    /** Helper method to return whether an WifiEntry is disabled due to a wrong password */
+    private static boolean isDisabledByWrongPassword(WifiEntry wifiEntry) {
+        WifiConfiguration config = wifiEntry.getWifiConfiguration();
+        if (config == null) {
+            return false;
+        }
+        WifiConfiguration.NetworkSelectionStatus networkStatus =
+                config.getNetworkSelectionStatus();
+        if (networkStatus == null || networkStatus.isNetworkEnabled()) {
+            return false;
+        }
+        int reason = networkStatus.getNetworkSelectionDisableReason();
+        return WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD == reason;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java b/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java
index aeec19a..eb4f326 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettings2Test.java
@@ -18,6 +18,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
@@ -278,4 +279,11 @@
         verify(menu).add(anyInt(), eq(WifiSettings2.MENU_ID_FORGET), anyInt(), anyInt());
         verify(menu).add(anyInt(), eq(WifiSettings2.MENU_ID_DISCONNECT), anyInt(), anyInt());
     }
+
+    @Test
+    public void onWifiEntriesChanged_shouldChangeNextButtonState() {
+        mWifiSettings2.onWifiEntriesChanged();
+
+        verify(mWifiSettings2).changeNextButtonState(anyBoolean());
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
index f81efc7..36279cb 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
@@ -35,7 +35,6 @@
 import com.android.settings.R;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -88,7 +87,6 @@
     }
 
     @Test
-    @Ignore
     public void display_5GhzSupported_shouldDisplayFullList() {
         when(mWifiManager.getCountryCode()).thenReturn("US");
         when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
@@ -128,7 +126,6 @@
     }
 
     @Test
-    @Ignore
     public void changePreference_noDualModeWith5G_shouldUpdateValue() {
         when(mWifiManager.getCountryCode()).thenReturn("US");
         when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
@@ -156,7 +153,6 @@
     }
 
     @Test
-    @Ignore
     public void changePreference_dualModeWith5G_shouldUpdateValue() {
         when(mWifiManager.getCountryCode()).thenReturn("US");
         when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
@@ -187,7 +183,6 @@
     }
 
     @Test
-    @Ignore
     public void updateDisplay_shouldUpdateValue() {
         when(mWifiManager.getCountryCode()).thenReturn("US");
         when(mWifiManager.is5GHzBandSupported()).thenReturn(true);