Fix the Wi-Fi detailed settings un-editable issue.

- The WifiEntry info might not be ready in early stage. (ex:
WifiEntry#canSetPrivacy())

- The Wi-Fi detailed setting listens to the WifiEntry callback to
refresh the preferences, it should first update the preference status to
be editable or not, and then display preferences to the UI.

- The privicy preference should be able to set back to selectable when
WifiEntry#canSetPrivicy() change from false to true.

Bug: 170148009
Test:
make RunSettingsRoboTests
ROBOTEST_FILTER=WifiNetworkDetailsFragment2Test
make RunSettingsRoboTests
ROBOTEST_FILTER=WifiPrivacyPreferenceController2Test

Change-Id: I567b2b80163631a01d165c0ac5c0aba392e014ef
diff --git a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
index 76a8c5f..d0708ea 100644
--- a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
+++ b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java
@@ -36,6 +36,7 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
@@ -78,7 +79,8 @@
     private HandlerThread mWorkerThread;
     private WifiDetailPreferenceController2 mWifiDetailPreferenceController2;
     private List<WifiDialog2.WifiDialog2Listener> mWifiDialogListeners = new ArrayList<>();
-    private List<AbstractPreferenceController> mControllers;
+    @VisibleForTesting
+    List<AbstractPreferenceController> mControllers;
 
     @Override
     public void onDestroy() {
@@ -255,6 +257,11 @@
      * API call for refreshing the preferences in this fragment.
      */
     public void refreshPreferences() {
+        updatePreferenceStates();
+        displayPreferenceControllers();
+    }
+
+    protected void displayPreferenceControllers() {
         final PreferenceScreen screen = getPreferenceScreen();
         for (AbstractPreferenceController controller : mControllers) {
             // WifiDetailPreferenceController2 gets the callback WifiEntryCallback#onUpdated,
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
index a0d4b16..d6e1b60 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
@@ -69,12 +69,13 @@
     public void updateState(Preference preference) {
         final DropDownPreference dropDownPreference = (DropDownPreference) preference;
         final int randomizationLevel = getRandomizationValue();
+        final boolean isSelectable = mWifiEntry.canSetPrivacy();
+        preference.setSelectable(isSelectable);
         dropDownPreference.setValue(Integer.toString(randomizationLevel));
         updateSummary(dropDownPreference, randomizationLevel);
 
-        // Makes preference not selectable, when this is a ephemeral network.
-        if (!mWifiEntry.canSetPrivacy()) {
-            preference.setSelectable(false);
+        // If the preference cannot be selectable, display a temporary network in the summary.
+        if (!isSelectable) {
             dropDownPreference.setSummary(R.string.wifi_privacy_settings_ephemeral_summary);
         }
     }
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java
index 4b1a8ca..e0fb578 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java
@@ -24,6 +24,7 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -32,14 +33,25 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.AbstractPreferenceController;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
 
 @RunWith(RobolectricTestRunner.class)
 public class WifiNetworkDetailsFragment2Test {
 
+    final String TEST_PREFERENCE_KEY = "TEST_PREFERENCE_KEY";
+
     private WifiNetworkDetailsFragment2 mFragment;
 
     @Before
@@ -73,4 +85,44 @@
 
         verify(menuItem).setIcon(com.android.internal.R.drawable.ic_mode_edit);
     }
+
+    @Test
+    public void refreshPreferences_controllerShouldUpdateStateAndDisplayPreference() {
+        final FakeFragment fragment = spy(new FakeFragment());
+        final PreferenceScreen screen = mock(PreferenceScreen.class);
+        final Preference preference = mock(Preference.class);
+        final TestController controller = mock(TestController.class);
+        doReturn(screen).when(fragment).getPreferenceScreen();
+        doReturn(preference).when(screen).findPreference(TEST_PREFERENCE_KEY);
+        doReturn(TEST_PREFERENCE_KEY).when(controller).getPreferenceKey();
+        fragment.mControllers = new ArrayList<>();
+        fragment.mControllers.add(controller);
+        fragment.addPreferenceController(controller);
+
+        fragment.refreshPreferences();
+
+        verify(controller).updateState(preference);
+        verify(controller).displayPreference(screen);
+    }
+
+    // Fake WifiNetworkDetailsFragment2 to override the protected method as public.
+    public class FakeFragment extends WifiNetworkDetailsFragment2 {
+
+        @Override
+        public void addPreferenceController(AbstractPreferenceController controller) {
+            super.addPreferenceController(controller);
+        }
+    }
+
+    public class TestController extends BasePreferenceController {
+
+        public TestController() {
+            super(RuntimeEnvironment.application, TEST_PREFERENCE_KEY);
+        }
+
+        @Override
+        public int getAvailabilityStatus() {
+            return AVAILABLE;
+        }
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
index 0414b1c..d3244fa 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2Test.java
@@ -89,7 +89,15 @@
     }
 
     @Test
-    public void testUpdateState_canSetPrivacy_shouldBeSelectable() {
+    public void testUpdateState_canSetPrivacyInNextUpdate_shouldBeSelectable() {
+        // Return false in WifiEntry#canSetPrivacy to make preference un-selectable first.
+        when(mMockWifiEntry.canSetPrivacy()).thenReturn(false);
+
+        mPreferenceController.updateState(mDropDownPreference);
+
+        assertThat(mDropDownPreference.isSelectable()).isFalse();
+
+        // Return true in WifiEntry#canSetPrivacy to verify preference back to selectable.
         when(mMockWifiEntry.canSetPrivacy()).thenReturn(true);
 
         mPreferenceController.updateState(mDropDownPreference);
@@ -98,7 +106,15 @@
     }
 
     @Test
-    public void testUpdateState_canNotSetPrivacy_shouldNotSelectable() {
+    public void testUpdateState_canNotSetPrivacyInNextUpdate_shouldNotBeSelectable() {
+        // Return true in WifiEntry#canSetPrivacy to make preference selectable first.
+        when(mMockWifiEntry.canSetPrivacy()).thenReturn(true);
+
+        mPreferenceController.updateState(mDropDownPreference);
+
+        assertThat(mDropDownPreference.isSelectable()).isTrue();
+
+        // Return false in WifiEntry#canSetPrivacy to verify preference back to un-selectable.
         when(mMockWifiEntry.canSetPrivacy()).thenReturn(false);
 
         mPreferenceController.updateState(mDropDownPreference);