Merge "Support configurable multi-stage UDFPS enrollment" into sc-v2-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1c91216..54e6894 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -883,6 +883,9 @@
     <!-- Note: Update FingerprintEnrollParentalConsent.CONSENT_STRING_RESOURCES when any _consent_ strings are added or removed. -->
     <!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
     <string name="security_settings_fingerprint_preference_title">Fingerprint</string>
+    <!-- Fingerprint enrollment and settings --><skip />
+    <!-- Title shown for work menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
+    <string name="security_settings_work_fingerprint_preference_title">Fingerprint for work</string>
     <!-- Fingerprint managment category title - configuration options for managing enrolled fingerprints [CHAR LIMIT=22] -->
     <string name="fingerprint_manage_category_title">Manage fingerprints</string>
     <!-- Fingerprint category title - configuration options for managing fingerprint enrollment [CHAR LIMIT=22] -->
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index 23d2b6b..5b687af 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -155,7 +155,7 @@
 
         <com.android.settingslib.RestrictedPreference
             android:key="fingerprint_settings_profile"
-            android:title="@string/security_settings_fingerprint_preference_title"
+            android:title="@string/security_settings_work_fingerprint_preference_title"
             android:summary="@string/summary_placeholder" />
 
         <com.android.settingslib.RestrictedPreference
diff --git a/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java
index 1e2a2b4..c7a9b10 100644
--- a/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityControlTimeoutPreferenceFragment.java
@@ -69,7 +69,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return SettingsEnums.ACCESSIBILITY;
+        return SettingsEnums.ACCESSIBILITY_TIMEOUT;
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java
index 4334cd0..9ca1f19 100644
--- a/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java
@@ -33,7 +33,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SCREEN_READER;
+        return SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK;
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index be1ea31..c067094 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -19,8 +19,8 @@
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.settings.SettingsEnums;
 import android.app.backup.BackupManager;
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -361,18 +361,20 @@
         final String stateString;
         final String footerString;
 
-        if (!mBatteryOptimizeUtils.isValidPackageName()) {
-            //Present optimized only string when the package name is invalid.
+        if (!mBatteryOptimizeUtils.isValidPackageName()
+                || mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
+            // Present optimized only string when the package name is invalid or
+            // it's in allow list not idle app.
             stateString = context.getString(R.string.manager_battery_usage_optimized_only);
             footerString = context.getString(
                     R.string.manager_battery_usage_footer_limited, stateString);
         } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
-            //Present unrestricted only string when the package is system or default active app.
+            // Present unrestricted only string when the package is system or default active app.
             stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
             footerString = context.getString(
                     R.string.manager_battery_usage_footer_limited, stateString);
         } else {
-            //Present default string to normal app.
+            // Present default string to normal app.
             footerString = context.getString(R.string.manager_battery_usage_footer);
         }
         mFooterPreference.setTitle(footerString);
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
index db29ac6..11528a6 100644
--- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
@@ -130,6 +130,13 @@
                 || mPowerAllowListBackend.isDefaultActiveApp(mPackageName);
     }
 
+    /**
+     * Return {@code true} if this package is in allow list except idle app.
+     */
+    public boolean isAllowlistedExceptIdleApp() {
+        return mPowerAllowListBackend.isAllowlistedExceptIdle(mPackageName);
+    }
+
     String getPackageName() {
         return mPackageName == null ? UNKNOWN_PACKAGE : mPackageName;
     }
diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
index ffec50d..ef23397 100644
--- a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
@@ -57,6 +57,10 @@
             Log.d(TAG, "is system or default app, disable pref");
             ((RadioButtonPreference) preference).setChecked(false);
             preference.setEnabled(false);
+        } else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
+            Log.d(TAG, "in allow list not idle app, optimized states only");
+            preference.setEnabled(true);
+            ((RadioButtonPreference) preference).setChecked(true);
         } else if (mBatteryOptimizeUtils.getAppOptimizationMode()
                 == BatteryOptimizeUtils.MODE_OPTIMIZED) {
             Log.d(TAG, "is optimized states");
diff --git a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
index d50926e..230b1fc 100644
--- a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
@@ -55,6 +55,9 @@
             Log.d(TAG, "is system or default app, disable pref");
             ((RadioButtonPreference) preference).setChecked(false);
             preference.setEnabled(false);
+        } else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
+            Log.d(TAG, "in allow list not idle app, disable perf");
+            preference.setEnabled(false);
         } else if (mBatteryOptimizeUtils.getAppOptimizationMode()
                 == BatteryOptimizeUtils.MODE_RESTRICTED) {
             Log.d(TAG, "is restricted states");
diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
index 1d66c6c..f8ee651 100644
--- a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
@@ -53,6 +53,9 @@
         if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
             Log.d(TAG, "is system or default app, unrestricted states only");
             ((RadioButtonPreference) preference).setChecked(true);
+        } else if (mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()) {
+            Log.d(TAG, "in allow list not idle app, disable perf");
+            preference.setEnabled(false);
         } else if (mBatteryOptimizeUtils.getAppOptimizationMode()
                 == BatteryOptimizeUtils.MODE_UNRESTRICTED) {
             Log.d(TAG, "is unrestricted states");
diff --git a/src/com/android/settings/network/MobileNetworkListFragment.java b/src/com/android/settings/network/MobileNetworkListFragment.java
index 1767c1c..03e5a01 100644
--- a/src/com/android/settings/network/MobileNetworkListFragment.java
+++ b/src/com/android/settings/network/MobileNetworkListFragment.java
@@ -65,14 +65,12 @@
 
         if (Utils.isProviderModelEnabled(getContext())) {
             NetworkProviderSimsCategoryController simCategoryPrefCtrl =
-                    new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM);
-            simCategoryPrefCtrl.init(getSettingsLifecycle());
+                    new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM,
+                            getSettingsLifecycle());
             controllers.add(simCategoryPrefCtrl);
-
             NetworkProviderDownloadedSimsCategoryController downloadedSimsCategoryCtrl =
                     new NetworkProviderDownloadedSimsCategoryController(context,
-                            KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
-            downloadedSimsCategoryCtrl.init(getSettingsLifecycle());
+                            KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, getSettingsLifecycle());
             controllers.add(downloadedSimsCategoryCtrl);
         } else {
             controllers.add(new MobileNetworkListController(getContext(), getLifecycle()));
diff --git a/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java b/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java
index f7c70f2..f5176b0 100644
--- a/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java
+++ b/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryController.java
@@ -1,8 +1,8 @@
 package com.android.settings.network;
 
 import android.content.Context;
+import android.util.Log;
 
-import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
@@ -15,23 +15,17 @@
 public class NetworkProviderDownloadedSimsCategoryController extends
         PreferenceCategoryController implements LifecycleObserver {
 
+    private static final String LOG_TAG = "NetworkProviderDownloadedSimsCategoryController";
     private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM =
             "provider_model_downloaded_sim_category";
     private PreferenceCategory mPreferenceCategory;
     private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController;
 
-    public NetworkProviderDownloadedSimsCategoryController(Context context, String key) {
-        super(context, key);
-    }
-
-    public void init(Lifecycle lifecycle) {
-        mNetworkProviderDownloadedSimListController = createDownloadedSimListController(lifecycle);
-    }
-
-    @VisibleForTesting
-    protected NetworkProviderDownloadedSimListController createDownloadedSimListController(
+    public NetworkProviderDownloadedSimsCategoryController(Context context, String key,
             Lifecycle lifecycle) {
-        return new NetworkProviderDownloadedSimListController(mContext, lifecycle);
+        super(context, key);
+        mNetworkProviderDownloadedSimListController =
+                new NetworkProviderDownloadedSimListController(mContext, lifecycle);
     }
 
     @Override
@@ -47,15 +41,23 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
+        mNetworkProviderDownloadedSimListController.displayPreference(screen);
         mPreferenceCategory = screen.findPreference(
                 KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
+        if (mPreferenceCategory == null) {
+            Log.d(LOG_TAG, "displayPreference(), Can not find the category.");
+            return;
+        }
         mPreferenceCategory.setVisible(isAvailable());
-        mNetworkProviderDownloadedSimListController.displayPreference(screen);
     }
 
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
+        if (mPreferenceCategory == null) {
+            Log.d(LOG_TAG, "updateState(), Can not find the category.");
+            return;
+        }
         int count = mPreferenceCategory.getPreferenceCount();
         String title = mContext.getString(count > 1
                 ? R.string.downloaded_sims_category_title
diff --git a/src/com/android/settings/network/NetworkProviderSimListController.java b/src/com/android/settings/network/NetworkProviderSimListController.java
index 814a461..8fb6cb6 100644
--- a/src/com/android/settings/network/NetworkProviderSimListController.java
+++ b/src/com/android/settings/network/NetworkProviderSimListController.java
@@ -172,7 +172,6 @@
         for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
             if (!info.isEmbedded()) {
                 subList.add(info);
-                break;
             }
         }
         return subList;
diff --git a/src/com/android/settings/network/NetworkProviderSimsCategoryController.java b/src/com/android/settings/network/NetworkProviderSimsCategoryController.java
index e27575a..06035a9 100644
--- a/src/com/android/settings/network/NetworkProviderSimsCategoryController.java
+++ b/src/com/android/settings/network/NetworkProviderSimsCategoryController.java
@@ -17,33 +17,28 @@
 package com.android.settings.network;
 
 import android.content.Context;
+import android.util.Log;
 
-import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
 import com.android.settings.widget.PreferenceCategoryController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 
 public class NetworkProviderSimsCategoryController extends PreferenceCategoryController implements
         LifecycleObserver {
-
+    private static final String LOG_TAG = "NetworkProviderSimsCategoryController";
     private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category";
     private NetworkProviderSimListController mNetworkProviderSimListController;
+    private PreferenceCategory mPreferenceCategory;
 
-    public NetworkProviderSimsCategoryController(Context context, String key) {
+    public NetworkProviderSimsCategoryController(Context context, String key, Lifecycle lifecycle) {
         super(context, key);
-    }
-
-    public void init(Lifecycle lifecycle) {
-        mNetworkProviderSimListController = createSimListController(lifecycle);
-    }
-
-    @VisibleForTesting
-    protected NetworkProviderSimListController createSimListController(
-            Lifecycle lifecycle) {
-        return new NetworkProviderSimListController(mContext, lifecycle);
+        mNetworkProviderSimListController =
+                new NetworkProviderSimListController(mContext, lifecycle);
     }
 
     @Override
@@ -59,8 +54,26 @@
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        PreferenceCategory preferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM);
-        preferenceCategory.setVisible(isAvailable());
         mNetworkProviderSimListController.displayPreference(screen);
+        mPreferenceCategory = screen.findPreference(KEY_PREFERENCE_CATEGORY_SIM);
+        if (mPreferenceCategory == null) {
+            Log.d(LOG_TAG, "displayPreference(), Can not find the category.");
+            return;
+        }
+        mPreferenceCategory.setVisible(isAvailable());
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        if (mPreferenceCategory == null) {
+            Log.d(LOG_TAG, "updateState(), Can not find the category.");
+            return;
+        }
+        int count = mPreferenceCategory.getPreferenceCount();
+        String title = mContext.getString(count > 1
+                ? R.string.provider_network_settings_title
+                : R.string.sim_category_title);
+        mPreferenceCategory.setTitle(title);
     }
 }
diff --git a/src/com/android/settings/wifi/WifiConfigController2.java b/src/com/android/settings/wifi/WifiConfigController2.java
index e8f2384..011c970 100644
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -484,7 +484,7 @@
     }
 
     boolean isValidSaePassword(String password) {
-        if (password.length() >= 1 && password.length() <= 63) {
+        if (password.length() >= 1 && password.length() <= 128) {
             return true;
         }
         return false;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index a2e78c3..ac85d97 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -746,6 +746,16 @@
     }
 
     @Test
+    public void testInitPreferenceForTriState_isAllowlistedExceptIdleApp_hasCorrectString() {
+        when(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
+
+        mFragment.initPreferenceForTriState(mContext);
+
+        assertThat(mFooterPreference.getTitle().toString())
+                .isEqualTo("This app requires optimized battery usage.");
+    }
+
+    @Test
     public void testInitPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() {
         when(mBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
         when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
index 53101c0..c32be18 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryOptimizeUtilsTest.java
@@ -125,6 +125,18 @@
     }
 
     @Test
+    public void testIsAllowlistedExpectIdle_isAllowlistedExceptIdle_returnTrue() {
+        when(mMockBackend.isAllowlistedExceptIdle(anyString())).thenReturn(true);
+
+        assertThat(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).isTrue();
+    }
+
+    @Test
+    public void testIsAllowlistedExpectIdle_notAllowlistedExpectIdle_returnFalse() {
+        assertThat(mBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).isFalse();
+    }
+
+    @Test
     public void testSetAppOptimizationMode_Restricted_verifyAction() {
         // Sets the current mode as MODE_UNRESTRICTED.
         mBatteryOptimizeUtils.mAllowListed = false;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
index 9df3ac9..923855d 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
@@ -94,6 +94,16 @@
     }
 
     @Test
+    public void testUpdateState_isAllowlistedExceptIdleApp_prefEnabled() {
+        when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
     public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
         mPreference.setKey(mController.KEY_OPTIMIZED_PREF);
         mController.handlePreferenceTreeClick(mPreference);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
index 0986153..7b4271f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
@@ -102,6 +102,16 @@
     }
 
     @Test
+    public void testUpdateState_isAllowlistedExceptIdleApp_prefDisabled() {
+        when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
     public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
         mPreference.setKey(mController.KEY_RESTRICTED_PREF);
         mController.handlePreferenceTreeClick(mPreference);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
index 004e97c..5052784 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
@@ -102,6 +102,16 @@
     }
 
     @Test
+    public void testUpdateState_isAllowlistedExceptIdleApp_prefDisabled() {
+        when(mockBatteryOptimizeUtils.isAllowlistedExceptIdleApp()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
     public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
         mPreference.setKey(mController.KEY_UNRESTRICTED_PREF);
         mController.handlePreferenceTreeClick(mPreference);
diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java
index e34b489..9045502 100644
--- a/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/NetworkProviderDownloadedSimsCategoryControllerTest.java
@@ -26,9 +26,12 @@
 
 import android.content.Context;
 import android.os.Looper;
+import android.telephony.SubscriptionInfo;
 
+import com.android.settings.testutils.ResourcesUtils;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
@@ -41,38 +44,39 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+
 @RunWith(AndroidJUnit4.class)
 public class NetworkProviderDownloadedSimsCategoryControllerTest {
 
     private static final String KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM =
             "provider_model_downloaded_sim_category";
+    private static final String KEY_ADD_MORE = "add_more";
+    private static final String SUB_1 = "SUB_1";
+    private static final String SUB_2 = "SUB_2";
+    private static final int SUB_ID_1 = 1;
+    private static final int SUB_ID_2 = 2;
 
     @Mock
-    private NetworkProviderDownloadedSimListController mNetworkProviderDownloadedSimListController;
-    @Mock
-    private PreferenceCategory mPreferenceCategory;
-    @Mock
     private Lifecycle mLifecycle;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo1;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo2;
 
     private Context mContext;
     private NetworkProviderDownloadedSimsCategoryController mCategoryController;
-
+    private PreferenceCategory mPreferenceCategory;
     private PreferenceManager mPreferenceManager;
     private PreferenceScreen mPreferenceScreen;
+    private Preference mAddMorePreference;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
         mContext = spy(ApplicationProvider.getApplicationContext());
-        mCategoryController = new NetworkProviderDownloadedSimsCategoryController(
-                mContext, KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM) {
-            @Override
-            protected NetworkProviderDownloadedSimListController createDownloadedSimListController(
-                    Lifecycle lifecycle) {
-                return mNetworkProviderDownloadedSimListController;
-            }
-        };
 
         if (Looper.myLooper() == null) {
             Looper.prepare();
@@ -80,14 +84,21 @@
 
         mPreferenceManager = new PreferenceManager(mContext);
         mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
-        when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
-        when(mPreferenceCategory.getPreferenceCount()).thenReturn(1);
+        mPreferenceCategory = new PreferenceCategory(mContext);
+        mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM);
+        mAddMorePreference = new Preference(mContext);
+        mAddMorePreference.setKey(KEY_ADD_MORE);
+        mAddMorePreference.setVisible(true);
         mPreferenceScreen.addPreference(mPreferenceCategory);
+        mPreferenceScreen.addPreference(mAddMorePreference);
+
+        mCategoryController = new NetworkProviderDownloadedSimsCategoryController(mContext,
+                KEY_PREFERENCE_CATEGORY_DOWNLOADED_SIM, mLifecycle);
     }
 
     @Test
     public void getAvailabilityStatus_returnUnavailable() {
-        mNetworkProviderDownloadedSimListController = null;
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>());
 
         assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo(
                 CONDITIONALLY_UNAVAILABLE);
@@ -95,10 +106,46 @@
 
     @Test
     public void displayPreference_isVisible() {
-        when(mNetworkProviderDownloadedSimListController.isAvailable()).thenReturn(true);
-        mCategoryController.init(mLifecycle);
+        setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
         mCategoryController.displayPreference(mPreferenceScreen);
 
         assertEquals(mPreferenceCategory.isVisible(), true);
     }
+
+
+    @Test
+    public void updateState_setTitle_withTwoDownloadedSims_returnDownloadedSims() {
+        setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
+        setUpSubscriptionInfoForDownloadedSim(SUB_ID_2, SUB_2, mSubscriptionInfo2);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(
+                Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2));
+
+        mCategoryController.displayPreference(mPreferenceScreen);
+        mCategoryController.updateState(mPreferenceCategory);
+
+        assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
+        assertThat(mPreferenceCategory.getTitle()).isEqualTo(
+                ResourcesUtils.getResourcesString(mContext, "downloaded_sims_category_title"));
+    }
+
+    @Test
+    public void updateState_setTitle_withOneDownloadedSim_returnDownloadedSim() {
+        setUpSubscriptionInfoForDownloadedSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
+
+        mCategoryController.displayPreference(mPreferenceScreen);
+        mCategoryController.updateState(mPreferenceCategory);
+
+        assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
+        assertThat(mPreferenceCategory.getTitle()).isEqualTo(
+                ResourcesUtils.getResourcesString(mContext, "downloaded_sim_category_title"));
+    }
+
+    private void setUpSubscriptionInfoForDownloadedSim(int subId, String displayName,
+            SubscriptionInfo subscriptionInfo) {
+        when(subscriptionInfo.isEmbedded()).thenReturn(true);
+        when(subscriptionInfo.getSubscriptionId()).thenReturn(subId);
+        when(subscriptionInfo.getDisplayName()).thenReturn(displayName);
+    }
 }
diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java
index 3b0a40a..066cf6b 100644
--- a/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/NetworkProviderSimListControllerTest.java
@@ -16,10 +16,14 @@
 
 package com.android.settings.network;
 
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.google.common.truth.Truth.assertThat;
+
 import static androidx.lifecycle.Lifecycle.Event;
 
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
@@ -170,7 +174,6 @@
         assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary));
     }
 
-
     @Test
     @UiThreadTest
     public void getSummary_inactivePSim() {
@@ -227,4 +230,18 @@
         assertTrue(TextUtils.equals(mController.getSummary(SUB_ID_1, DISPLAY_NAME_1), summary));
     }
 
+    @Test
+    @UiThreadTest
+    public void getAvailablePhysicalSubscription_withTwoPhysicalSims_returnTwo() {
+        final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+        when(info1.isEmbedded()).thenReturn(false);
+        final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+        when(info2.isEmbedded()).thenReturn(false);
+        when(mSubscriptionManager.getAvailableSubscriptionInfoList()).thenReturn(
+                Arrays.asList(info1,  info2));
+        displayPreferenceWithLifecycle();
+
+        assertThat(mController.getAvailablePhysicalSubscription().size()).isEqualTo(2);
+    }
+
 }
diff --git a/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java
index cfa376b..c8d750c 100644
--- a/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/NetworkProviderSimsCategoryControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.network;
 
 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
@@ -25,7 +26,10 @@
 
 import android.content.Context;
 import android.os.Looper;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
 
+import com.android.settings.testutils.ResourcesUtils;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import androidx.preference.PreferenceCategory;
@@ -40,37 +44,35 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+
 @RunWith(AndroidJUnit4.class)
 public class NetworkProviderSimsCategoryControllerTest {
 
     private static final String KEY_PREFERENCE_CATEGORY_SIM = "provider_model_sim_category";
+    private static final String SUB_1 = "SUB_1";
+    private static final String SUB_2 = "SUB_2";
+    private static final int SUB_ID_1 = 1;
+    private static final int SUB_ID_2 = 2;
 
     @Mock
-    private NetworkProviderSimListController mNetworkProviderSimListController;
-    @Mock
-    private PreferenceCategory mPreferenceCategory;
-    @Mock
     private Lifecycle mLifecycle;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo1;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo2;
 
     private Context mContext;
     private NetworkProviderSimsCategoryController mCategoryController;
-
     private PreferenceManager mPreferenceManager;
     private PreferenceScreen mPreferenceScreen;
+    private PreferenceCategory mPreferenceCategory;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-
         mContext = spy(ApplicationProvider.getApplicationContext());
-        mCategoryController = new NetworkProviderSimsCategoryController(
-                mContext, KEY_PREFERENCE_CATEGORY_SIM) {
-            @Override
-            protected NetworkProviderSimListController createSimListController(
-                    Lifecycle lifecycle) {
-                return mNetworkProviderSimListController;
-            }
-        };
 
         if (Looper.myLooper() == null) {
             Looper.prepare();
@@ -78,14 +80,17 @@
 
         mPreferenceManager = new PreferenceManager(mContext);
         mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
-        when(mPreferenceCategory.getKey()).thenReturn(KEY_PREFERENCE_CATEGORY_SIM);
-        when(mPreferenceCategory.getPreferenceCount()).thenReturn(1);
+        mPreferenceCategory = new PreferenceCategory(mContext);
+        mPreferenceCategory.setKey(KEY_PREFERENCE_CATEGORY_SIM);
         mPreferenceScreen.addPreference(mPreferenceCategory);
+
+        mCategoryController = new NetworkProviderSimsCategoryController(
+                mContext, KEY_PREFERENCE_CATEGORY_SIM, mLifecycle);
     }
 
     @Test
     public void getAvailabilityStatus_returnUnavailable() {
-        mNetworkProviderSimListController = null;
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(new ArrayList<>());
 
         assertThat(mCategoryController.getAvailabilityStatus()).isEqualTo(
                 CONDITIONALLY_UNAVAILABLE);
@@ -93,10 +98,46 @@
 
     @Test
     public void displayPreference_isVisible() {
-        when(mNetworkProviderSimListController.isAvailable()).thenReturn(true);
-        mCategoryController.init(mLifecycle);
+        setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
         mCategoryController.displayPreference(mPreferenceScreen);
 
         assertEquals(mPreferenceCategory.isVisible(), true);
     }
+
+    @Test
+    public void updateState_setTitle_withTwoPhysicalSims_returnSims() {
+        setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
+        setUpSubscriptionInfoForPhysicalSim(SUB_ID_2, SUB_2, mSubscriptionInfo2);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(
+                Arrays.asList(mSubscriptionInfo1, mSubscriptionInfo2));
+
+        mCategoryController.displayPreference(mPreferenceScreen);
+        mCategoryController.updateState(mPreferenceCategory);
+
+        assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(2);
+        assertThat(mPreferenceCategory.getTitle()).isEqualTo(
+                ResourcesUtils.getResourcesString(mContext, "provider_network_settings_title"));
+    }
+
+    @Test
+    public void updateState_setTitle_withOnePhysicalSim_returnSim() {
+        setUpSubscriptionInfoForPhysicalSim(SUB_ID_1, SUB_1, mSubscriptionInfo1);
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscriptionInfo1));
+
+        mCategoryController.displayPreference(mPreferenceScreen);
+        mCategoryController.updateState(mPreferenceCategory);
+
+        assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1);
+        assertThat(mPreferenceCategory.getTitle()).isEqualTo(
+                ResourcesUtils.getResourcesString(mContext, "sim_category_title"));
+    }
+
+    private void setUpSubscriptionInfoForPhysicalSim(int subId, String displayName,
+            SubscriptionInfo subscriptionInfo) {
+        when(subscriptionInfo.isEmbedded()).thenReturn(false);
+        when(subscriptionInfo.getSubscriptionId()).thenReturn(subId);
+        when(subscriptionInfo.getDisplayName()).thenReturn(displayName);
+    }
+
 }