Merge "Fix settings flakiness bug" into main
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index 2f04b62..4fc0e16 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -46,6 +46,7 @@
 import android.service.autofill.AutofillServiceInfo;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.view.View;
 import android.widget.CompoundButton;
 
@@ -77,6 +78,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Executor;
 
@@ -114,7 +116,7 @@
     private @Nullable String mFlagOverrideForTest = null;
     private @Nullable PreferenceScreen mPreferenceScreen = null;
 
-    private boolean mVisibility = false;
+    private Optional<Boolean> mSimulateHiddenForTests = Optional.empty();
     private boolean mIsWorkProfile = false;
     private boolean mSimulateConnectedForTests = false;
 
@@ -159,7 +161,9 @@
             return UNSUPPORTED_ON_DEVICE;
         }
 
-        if (!mVisibility) {
+        // If there is no top provider or any providers in the list then
+        // we should hide this pref.
+        if (isHiddenDueToNoProviderSet()) {
             return CONDITIONALLY_UNAVAILABLE;
         }
 
@@ -378,20 +382,29 @@
     }
 
     @VisibleForTesting
-    public void setVisibility(boolean newVisibility) {
-        if (newVisibility == mVisibility) {
-            return;
-        }
-
-        mVisibility = newVisibility;
+    public void forceDelegateRefresh() {
         if (mDelegate != null) {
             mDelegate.forceDelegateRefresh();
         }
     }
 
     @VisibleForTesting
-    public boolean getVisibility() {
-        return mVisibility;
+    public void setSimulateHiddenForTests(Optional<Boolean> simulateHiddenForTests) {
+        mSimulateHiddenForTests = simulateHiddenForTests;
+    }
+
+    @VisibleForTesting
+    public boolean isHiddenDueToNoProviderSet() {
+        return isHiddenDueToNoProviderSet(getProviders());
+    }
+
+    private boolean isHiddenDueToNoProviderSet(
+            Pair<List<CombinedProviderInfo>, CombinedProviderInfo> providerPair) {
+        if (mSimulateHiddenForTests.isPresent()) {
+            return mSimulateHiddenForTests.get();
+        }
+
+        return (providerPair.first.size() == 0 || providerPair.second == null);
     }
 
     @VisibleForTesting
@@ -459,10 +472,11 @@
         return preference;
     }
 
-    /** Aggregates the list of services and builds a list of UI prefs to show. */
-    @VisibleForTesting
-    public Map<String, CombiPreference> buildPreferenceList(
-            Context context, PreferenceGroup group) {
+    /**
+     * Returns a pair that contains a list of the providers in the first position and the top
+     * provider in the second position.
+     */
+    private Pair<List<CombinedProviderInfo>, CombinedProviderInfo> getProviders() {
         // Get the selected autofill provider. If it is the placeholder then replace it with an
         // empty string.
         String selectedAutofillProvider =
@@ -475,15 +489,25 @@
         // Get the list of combined providers.
         List<CombinedProviderInfo> providers =
                 CombinedProviderInfo.buildMergedList(
-                        AutofillServiceInfo.getAvailableServices(context, getUser()),
+                        AutofillServiceInfo.getAvailableServices(mContext, getUser()),
                         mServices,
                         selectedAutofillProvider);
+        return new Pair<>(providers, CombinedProviderInfo.getTopProvider(providers));
+    }
 
-        // Get the provider that is displayed at the top. If there is none then hide
-        // everything.
-        CombinedProviderInfo topProvider = CombinedProviderInfo.getTopProvider(providers);
-        if (topProvider == null) {
-            setVisibility(false);
+    /** Aggregates the list of services and builds a list of UI prefs to show. */
+    @VisibleForTesting
+    public @NonNull Map<String, CombiPreference> buildPreferenceList(
+            @NonNull Context context, @NonNull PreferenceGroup group) {
+        // Get the providers and extract the values.
+        Pair<List<CombinedProviderInfo>, CombinedProviderInfo> providerPair = getProviders();
+        CombinedProviderInfo topProvider = providerPair.second;
+        List<CombinedProviderInfo> providers = providerPair.first;
+
+        // If the provider is set to "none" or there are no providers then we should not
+        // return any providers.
+        if (isHiddenDueToNoProviderSet(providerPair)) {
+            forceDelegateRefresh();
             return new HashMap<>();
         }
 
@@ -520,7 +544,7 @@
         }
 
         // Set the visibility if we have services.
-        setVisibility(!output.isEmpty());
+        forceDelegateRefresh();
 
         return output;
     }
diff --git a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
index acf590b..b5aeac7 100644
--- a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.applications.credentials;
 
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -55,6 +56,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 @RunWith(AndroidJUnit4.class)
@@ -121,17 +123,34 @@
                 createControllerWithServices(Lists.newArrayList(createCredentialProviderInfo()));
         controller.setSimulateConnectedForTests(true);
         assertThat(controller.isConnected()).isTrue();
-        controller.setVisibility(true);
-        assertThat(controller.getVisibility()).isTrue();
+        controller.setSimulateHiddenForTests(Optional.of(false));
+        assertThat(controller.isHiddenDueToNoProviderSet()).isFalse();
         assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
     }
 
     @Test
+    public void getAvailabilityStatus_isHidden_returnsConditionallyUnavailable() {
+        CredentialManagerPreferenceController controller =
+                createControllerWithServices(Lists.newArrayList(createCredentialProviderInfo()));
+        controller.setSimulateConnectedForTests(true);
+        assertThat(controller.isConnected()).isTrue();
+        controller.setSimulateHiddenForTests(Optional.of(true));
+        assertThat(controller.isHiddenDueToNoProviderSet()).isTrue();
+        assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+    }
+
+    @Test
     public void displayPreference_withServices_preferencesAdded() {
         CredentialManagerPreferenceController controller =
                 createControllerWithServices(Lists.newArrayList(createCredentialProviderInfo()));
+        controller.setSimulateConnectedForTests(true);
+        controller.setSimulateHiddenForTests(Optional.of(false));
+
+        assertThat(controller.isHiddenDueToNoProviderSet()).isFalse();
+        assertThat(controller.isConnected()).isTrue();
+        assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+
         controller.displayPreference(mScreen);
-        assertThat(controller.isConnected()).isFalse();
         assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(1);
 
         Preference pref = mCredentialsPreferenceCategory.getPreference(0);
@@ -150,8 +169,8 @@
                 createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
         controller.setSimulateConnectedForTests(true);
         assertThat(controller.isConnected()).isTrue();
-        controller.setVisibility(true);
-        assertThat(controller.getVisibility()).isTrue();
+        controller.setSimulateHiddenForTests(Optional.of(false));
+        assertThat(controller.isHiddenDueToNoProviderSet()).isFalse();
         assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
 
         // Test the data is correct.
@@ -194,8 +213,8 @@
                                 createCredentialProviderInfo("com.android.provider6", "ClassA")));
         controller.setSimulateConnectedForTests(true);
         assertThat(controller.isConnected()).isTrue();
-        controller.setVisibility(true);
-        assertThat(controller.getVisibility()).isTrue();
+        controller.setSimulateHiddenForTests(Optional.of(false));
+        assertThat(controller.isHiddenDueToNoProviderSet()).isFalse();
         assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
 
         // Ensure that we stay under 5 providers.
@@ -263,8 +282,8 @@
                 createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
         controller.setSimulateConnectedForTests(true);
         assertThat(controller.isConnected()).isTrue();
-        controller.setVisibility(true);
-        assertThat(controller.getVisibility()).isTrue();
+        controller.setSimulateHiddenForTests(Optional.of(false));
+        assertThat(controller.isHiddenDueToNoProviderSet()).isFalse();
         assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
 
         // Test the data is correct.
@@ -316,9 +335,14 @@
         CredentialManagerPreferenceController controller =
                 createControllerWithServices(
                         Lists.newArrayList(serviceA1, serviceB1, serviceC1, serviceC2, serviceC3));
-        controller.displayPreference(mScreen);
+        controller.setSimulateConnectedForTests(true);
+        controller.setSimulateHiddenForTests(Optional.of(false));
 
-        assertThat(controller.isConnected()).isFalse();
+        assertThat(controller.isHiddenDueToNoProviderSet()).isFalse();
+        assertThat(controller.isConnected()).isTrue();
+        assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+
+        controller.displayPreference(mScreen);
         assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(3);
 
         Map<String, CredentialManagerPreferenceController.CombiPreference> prefs =