Merge "Clear recent access list when fragment is paused."
diff --git a/src/com/android/settings/FallbackHome.java b/src/com/android/settings/FallbackHome.java
index 40867aa..b70470b 100644
--- a/src/com/android/settings/FallbackHome.java
+++ b/src/com/android/settings/FallbackHome.java
@@ -42,7 +42,7 @@
 
 public class FallbackHome extends Activity {
     private static final String TAG = "FallbackHome";
-    private static final int PROGRESS_TIMEOUT = 2000;
+    private int mProgressTimeout;
 
     private boolean mProvisioned;
     private WallpaperManager mWallManager;
@@ -76,6 +76,12 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        mProgressTimeout = getResources().getInteger(
+            com.android.internal.R.integer.config_progressTimeoutFallbackHome);
+
+        if (mProgressTimeout <= 0) {
+            mProgressTimeout = 0;
+        }
 
         // Set ourselves totally black before the device is provisioned so that
         // we don't flash the wallpaper before SUW
@@ -107,7 +113,7 @@
     protected void onResume() {
         super.onResume();
         if (mProvisioned) {
-            mHandler.postDelayed(mProgressTimeoutRunnable, PROGRESS_TIMEOUT);
+            mHandler.postDelayed(mProgressTimeoutRunnable, mProgressTimeout);
         }
     }
 
diff --git a/src/com/android/settings/applications/appinfo/AppLocaleDetails.java b/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
index aee360e..164cfd9 100644
--- a/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
+++ b/src/com/android/settings/applications/appinfo/AppLocaleDetails.java
@@ -18,6 +18,7 @@
 import static com.android.settings.widget.EntityHeaderController.ActionType;
 
 import android.app.Activity;
+import android.app.LocaleConfig;
 import android.app.LocaleManager;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
@@ -289,12 +290,18 @@
 
         @VisibleForTesting
         void handleSupportedLocales() {
-            //TODO Waiting for PackageManager api
-            String[] languages = getAssetSystemLocales();
-
-            for (String language : languages) {
-                mSupportedLocales.add(Locale.forLanguageTag(language));
+            LocaleList localeList = getPackageLocales();
+            if (localeList == null) {
+                String[] languages = getAssetSystemLocales();
+                for (String language : languages) {
+                    mSupportedLocales.add(Locale.forLanguageTag(language));
+                }
+            } else {
+                for (int i = 0; i < localeList.size(); i++) {
+                    mSupportedLocales.add(localeList.get(i));
+                }
             }
+
             if (mSuggestedLocales != null || !mSuggestedLocales.isEmpty()) {
                 mSupportedLocales.removeAll(mSuggestedLocales);
             }
@@ -349,9 +356,23 @@
                         packageManager.getPackageInfo(mPackageName, PackageManager.MATCH_ALL)
                                 .applicationInfo).getAssets().getNonSystemLocales();
             } catch (PackageManager.NameNotFoundException e) {
-                Log.w(TAG, "Can not found the package name : " + e);
+                Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
             }
             return new String[0];
         }
+
+        @VisibleForTesting
+        LocaleList getPackageLocales() {
+            try {
+                LocaleConfig localeConfig =
+                        new LocaleConfig(mContext.createPackageContext(mPackageName, 0));
+                if (localeConfig.getStatus() == LocaleConfig.STATUS_SUCCESS) {
+                    return localeConfig.getSupportedLocales();
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Can not found the package name : " + mPackageName + " / " + e);
+            }
+            return null;
+        }
     }
 }
diff --git a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
index fb75695..bd8169a 100644
--- a/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceController.java
@@ -16,8 +16,9 @@
 
 package com.android.settings.development;
 
-import android.bluetooth.BluetoothManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.os.SystemProperties;
 
 import androidx.annotation.VisibleForTesting;
@@ -39,13 +40,20 @@
     static final String MAX_CONNECTED_AUDIO_DEVICES_PROPERTY =
             "persist.bluetooth.maxconnectedaudiodevices";
 
-    private final int mDefaultMaxConnectedAudioDevices;
+    private int mDefaultMaxConnectedAudioDevices = 0;
 
     public BluetoothMaxConnectedAudioDevicesPreferenceController(Context context) {
         super(context);
-        BluetoothManager mBluetoothManager = context.getSystemService(BluetoothManager.class);
-        mDefaultMaxConnectedAudioDevices = mBluetoothManager.getAdapter()
-                .getMaxConnectedAudioDevices();
+
+        try {
+            Resources res = context.getPackageManager().getResourcesForApplication(
+                    "com.android.bluetooth");
+            mDefaultMaxConnectedAudioDevices = res.getInteger(res.getIdentifier(
+                    "config_bluetooth_max_connected_audio_devices",
+                    "integer", "com.android.bluetooth"));
+        } catch (PackageManager.NameNotFoundException e) {
+            e.printStackTrace();
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/display/darkmode/BedtimeSettings.java b/src/com/android/settings/display/darkmode/BedtimeSettings.java
index 9714afa..d9a458c 100644
--- a/src/com/android/settings/display/darkmode/BedtimeSettings.java
+++ b/src/com/android/settings/display/darkmode/BedtimeSettings.java
@@ -16,19 +16,17 @@
 
 package com.android.settings.display.darkmode;
 
+import static android.provider.Settings.ACTION_BEDTIME_SETTINGS;
+
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 
 import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 
 /** Manages Digital Wellbeing bedtime settings' intents. */
 public final class BedtimeSettings {
-    @VisibleForTesting
-    public static final String ACTION_BEDTIME_SETTINGS = "android.settings.BEDTIME_SETTINGS";
-
     private final Context mContext;
     private final PackageManager mPackageManager;
     private final String mWellbeingPackage;
diff --git a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java
index e7c93dc..62f2780 100644
--- a/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java
+++ b/src/com/android/settings/fuelgauge/DebugEstimatesLoader.java
@@ -18,13 +18,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.os.BatteryStats;
 import android.os.BatteryStatsManager;
 import android.os.BatteryUsageStats;
 import android.os.SystemClock;
 import android.util.Log;
 
-import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.fuelgauge.Estimate;
 import com.android.settingslib.fuelgauge.EstimateKt;
@@ -37,11 +35,8 @@
 public class DebugEstimatesLoader extends AsyncLoaderCompat<List<BatteryInfo>> {
     private static final String TAG = "DebugEstimatesLoader";
 
-    private BatteryStatsHelper mStatsHelper;
-
-    public DebugEstimatesLoader(Context context, BatteryStatsHelper statsHelper) {
+    public DebugEstimatesLoader(Context context) {
         super(context);
-        mStatsHelper = statsHelper;
     }
 
     @Override
@@ -60,7 +55,6 @@
                 SystemClock.elapsedRealtime());
         Intent batteryBroadcast = getContext().registerReceiver(null,
                 new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
-        BatteryStats stats = mStatsHelper.getStats();
         BatteryUsageStats batteryUsageStats;
         try {
             batteryUsageStats = context.getSystemService(BatteryStatsManager.class)
diff --git a/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java b/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java
index 9524164..c6d1ea0 100644
--- a/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java
+++ b/src/com/android/settings/network/SwitchToEuiccSubscriptionSidecar.java
@@ -69,20 +69,15 @@
         }
     }
 
-    /** Starts calling EuiccManager#switchToSubscription to enable/disable the eSIM profile. */
-    // ToDo: delete this api and refactor the related code.
-    public void run(int subscriptionId) {
-        setState(State.RUNNING, Substate.UNUSED);
-        mCallbackIntent = createCallbackIntent();
-        mEuiccManager.switchToSubscription(subscriptionId, mCallbackIntent);
-    }
-
     /**
      * Starts calling EuiccManager#switchToSubscription to enable/disable the eSIM profile.
      *
      * @param subscriptionId the esim's subscriptionId.
-     * @param port the esim's portId. If user wants to inactivate esim, then user must to assign the
-     *             the port. If user wants to activate esim, then the port can be -1.
+     * @param port the esim's portId. If user wants to inactivate esim, then user must to assign
+     *             the corresponding port. If user wants to activate esim, then the port can be
+     *             {@link UiccSlotUtil#INVALID_PORT_ID}. When it is
+     *             {@link UiccSlotUtil#INVALID_PORT_ID}, the system will reassign a corresponding
+     *             port id.
      * @param removedSubInfo if the all of slots have sims, it should remove the one of active sim.
      *                       If the removedSubInfo is null, then use the default value.
      *                       The default value is the esim slot and portId 0.
diff --git a/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java b/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java
index 9b9c0dd..e98b405 100644
--- a/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java
+++ b/src/com/android/settings/network/SwitchToRemovableSlotSidecar.java
@@ -81,29 +81,6 @@
     }
 
     /**
-     * Starts switching to the removable slot. It disables the active eSIM profile before switching
-     * if there is one.
-     *
-     * @param physicalSlotId removable physical SIM slot ID.
-     */
-    // ToDo: delete this api and refactor the related code.
-    public void run(int physicalSlotId) {
-        mPhysicalSlotId = physicalSlotId;
-        SubscriptionManager subscriptionManager =
-                getContext().getSystemService(SubscriptionManager.class);
-        if (SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream()
-                .anyMatch(SubscriptionInfo::isEmbedded)) {
-            // In SS mode, the esim is active, then inactivate the esim.
-            Log.i(TAG, "There is an active eSIM profile. Disable the profile first.");
-            // Use INVALID_SUBSCRIPTION_ID to disable the only active profile.
-            mSwitchToSubscriptionSidecar.run(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 0, null);
-        } else {
-            Log.i(TAG, "There is no active eSIM profiles. Start to switch to removable slot.");
-            mSwitchSlotSidecar.runSwitchToRemovableSlot(mPhysicalSlotId, null);
-        }
-    }
-
-    /**
      * Starts switching to the removable slot.
      *
      * @param physicalSlotId removable physical SIM slot ID.
diff --git a/src/com/android/settings/sim/ChooseSimActivity.java b/src/com/android/settings/sim/ChooseSimActivity.java
index d0ccc4c..cebc1ba 100644
--- a/src/com/android/settings/sim/ChooseSimActivity.java
+++ b/src/com/android/settings/sim/ChooseSimActivity.java
@@ -159,11 +159,12 @@
         mSelectedItemIndex = subItem.getId();
         if (mSelectedItemIndex == INDEX_PSIM) {
             Log.i(TAG, "Ready to switch to pSIM slot.");
-            mSwitchToRemovableSlotSidecar.run(UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID);
+            mSwitchToRemovableSlotSidecar.run(UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID, null);
         } else {
             Log.i(TAG, "Ready to switch to eSIM subscription with index: " + mSelectedItemIndex);
             mSwitchToEuiccSubscriptionSidecar.run(
-                    mEmbeddedSubscriptions.get(mSelectedItemIndex).getSubscriptionId());
+                    mEmbeddedSubscriptions.get(mSelectedItemIndex).getSubscriptionId(),
+                    UiccSlotUtil.INVALID_PORT_ID, null);
         }
     }
 
diff --git a/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java b/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java
index be2fa2d..db6e1b4 100644
--- a/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java
+++ b/src/com/android/settings/sim/SwitchToEsimConfirmDialogActivity.java
@@ -23,6 +23,7 @@
 import com.android.settings.R;
 import com.android.settings.SidecarFragment;
 import com.android.settings.network.SwitchToEuiccSubscriptionSidecar;
+import com.android.settings.network.UiccSlotUtil;
 import com.android.settings.network.telephony.AlertDialogFragment;
 import com.android.settings.network.telephony.ConfirmDialogFragment;
 import com.android.settings.network.telephony.SubscriptionActionDialogActivity;
@@ -110,7 +111,8 @@
             return;
         }
         Log.i(TAG, "User confirmed to switch to embedded slot.");
-        mSwitchToEuiccSubscriptionSidecar.run(mSubToEnabled.getSubscriptionId());
+        mSwitchToEuiccSubscriptionSidecar.run(mSubToEnabled.getSubscriptionId(),
+                UiccSlotUtil.INVALID_PORT_ID, null);
         showProgressDialog(
                 getString(
                         R.string.sim_action_switch_sub_dialog_progress,
diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
index e0bc9cd..8c8964f 100644
--- a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
+++ b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
@@ -210,10 +210,11 @@
         }
 
         List<SubscriptionInfo> groupedEmbeddedSubscriptions = getGroupedEmbeddedSubscriptions();
-
         if (groupedEmbeddedSubscriptions.size() == 0 || !removableSlotInfo.getPorts().stream()
                 .findFirst().get().isActive()) {
-            Log.i(TAG, "eSIM slot is active or no subscriptions exist. Do nothing.");
+            Log.i(TAG, "eSIM slot is active or no subscriptions exist. Do nothing."
+                            + " The removableSlotInfo: " + removableSlotInfo
+                            + ", groupedEmbeddedSubscriptions: " + groupedEmbeddedSubscriptions);
             return;
         }
 
diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
index 68a8a86..09c5734 100644
--- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java
@@ -439,7 +439,6 @@
         assertThat(mFragment.mTemplate.getMatchRule())
                 .isEqualTo(NetworkTemplate.MATCH_WIFI);
         assertTrue(mFragment.mTemplate.getSubscriberIds().isEmpty());
-        assertThat(mFragment.mTemplate.getNetworkId())
-                .isEqualTo(NetworkTemplate.WIFI_NETWORKID_ALL);
+        assertTrue(mFragment.mTemplate.getWifiNetworkKeys().isEmpty());
     }
 }
diff --git a/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java b/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
index 8d994d0..70a1a38 100644
--- a/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
@@ -81,8 +81,8 @@
         when(mSubscriptionManager.isActiveSubscriptionId(SUB_ID)).thenReturn(false);
 
         final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
     }
 
     @Test
@@ -94,8 +94,8 @@
                 .thenReturn(new String[] {SUBSCRIBER_ID});
 
         final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isFalse();
     }
 
     @Test
@@ -107,7 +107,7 @@
                 .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
 
         final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
-        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.getSubscriberIds().contains(SUBSCRIBER_ID_2)).isTrue();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
index e5fbd65..72477b9 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothMaxConnectedAudioDevicesPreferenceControllerTest.java
@@ -24,9 +24,10 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.when;
 
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+
 import android.os.SystemProperties;
 
 import androidx.preference.ListPreference;
@@ -46,17 +47,12 @@
 @RunWith(RobolectricTestRunner.class)
 public class BluetoothMaxConnectedAudioDevicesPreferenceControllerTest {
 
-  private static final int TEST_MAX_CONNECTED_AUDIO_DEVICES = 3;
+  private static int TEST_MAX_CONNECTED_AUDIO_DEVICES = 5;
 
   @Mock
   private PreferenceScreen mPreferenceScreen;
   @Spy
   private Context mSpyContext = RuntimeEnvironment.application;
-  @Spy
-  private BluetoothManager mBluetoothManager =
-      mSpyContext.getSystemService(BluetoothManager.class);
-  @Spy
-  private BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
 
   private ListPreference mPreference;
   private BluetoothMaxConnectedAudioDevicesPreferenceController mController;
@@ -67,16 +63,19 @@
   @Before
   public void setup() {
     MockitoAnnotations.initMocks(this);
-    doReturn(mBluetoothManager).when(mSpyContext).getSystemService(BluetoothManager.class);
-    doReturn(mBluetoothAdapter).when(mBluetoothManager).getAdapter();
     // Get XML values without mock
     // Setup test list preference using XML values
     mPreference = new ListPreference(mSpyContext);
     mPreference.setEntries(R.array.bluetooth_max_connected_audio_devices);
     mPreference.setEntryValues(R.array.bluetooth_max_connected_audio_devices_values);
-    // Stub default max connected audio devices to a test controlled value
-    doReturn(TEST_MAX_CONNECTED_AUDIO_DEVICES).when(mBluetoothAdapter)
-        .getMaxConnectedAudioDevices();
+    // Retrieve default max connected audio devices to a test controlled value
+    try {
+      Resources res = mSpyContext.getPackageManager().getResourcesForApplication("com.android.bluetooth");
+      TEST_MAX_CONNECTED_AUDIO_DEVICES = res.getInteger(res.getIdentifier("config_bluetooth_max_connected_audio_devices", "integer", "com.android.bluetooth"));
+    } catch (PackageManager.NameNotFoundException e) {
+      e.printStackTrace();
+    }
+
     // Init the actual controller
     mController = new BluetoothMaxConnectedAudioDevicesPreferenceController(mSpyContext);
     // Construct preference in the controller via a mocked preference screen object
diff --git a/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java b/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java
index 6c1d3c2..59c501b 100644
--- a/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BedtimeSettingsUtils.java
@@ -16,7 +16,7 @@
 
 package com.android.settings.testutils;
 
-import static com.android.settings.display.darkmode.BedtimeSettings.ACTION_BEDTIME_SETTINGS;
+import static android.provider.Settings.ACTION_BEDTIME_SETTINGS;
 
 import static org.robolectric.Shadows.shadowOf;
 
diff --git a/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java b/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
index 1042a6a..ed4c127 100644
--- a/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
+++ b/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java
@@ -55,6 +55,7 @@
     private LocaleList mSystemLocales;
     private LocaleList mAppLocale;
     private String[] mAssetLocales;
+    private LocaleList mPackageLocales;
 
     @Before
     @UiThreadTest
@@ -67,11 +68,13 @@
         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
         when(mContext.getSystemService(LocaleManager.class)).thenReturn(mLocaleManager);
 
-        setupInitialLocales("en",
-                "tw",
-                "jp",
-                "en, uk, jp, ne",
-                new String[]{"en", "ne", "ms", "pa"});
+        setupInitialLocales(
+                /* appLocale= */ "en",
+                /* simCountry= */ "tw",
+                /* networkCountry= */ "jp",
+                /* systemLocales= */ "en, uk, jp, ne",
+                /* packageLocales= */ "pa, cn, tw, en",
+                /* assetLocales= */ new String[]{"en", "ne", "ms", "pa"});
     }
 
     @Test
@@ -105,11 +108,13 @@
     @UiThreadTest
     public void handleAllLocalesData_withoutAppLocale_1stSuggestedLocaleIsSimCountryLocale() {
         Locale simCountryLocale = new Locale("zh", "TW");
-        setupInitialLocales("",
-                "tw",
-                "",
-                "en, uk, jp, ne",
-                new String[]{"en", "ne", "ms", "pa"});
+        setupInitialLocales(
+                /* appLocale= */ "",
+                /* simCountry= */ "tw",
+                /* networkCountry= */ "",
+                /* systemLocales= */ "en, uk, jp, ne",
+                /* packageLocales= */ "",
+                /* assetLocales= */ new String[]{});
         DummyAppLocaleDetailsHelper helper =
                 new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
 
@@ -124,11 +129,13 @@
     @UiThreadTest
     public void handleAllLocalesData_withoutAppLocale_1stSuggestedLocaleIsNetworkCountryLocale() {
         Locale networkCountryLocale = new Locale("en", "GB");
-        setupInitialLocales("",
-                "",
-                "gb",
-                "en, uk, jp, ne",
-                new String[]{"en", "ne", "ms", "pa"});
+        setupInitialLocales(
+                /* appLocale= */ "",
+                /* simCountry= */ "",
+                /* networkCountry= */ "gb",
+                /* systemLocales= */ "en, uk, jp, ne",
+                /* packageLocales= */ "",
+                /* assetLocales= */ new String[]{});
         DummyAppLocaleDetailsHelper helper =
                 new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
 
@@ -142,11 +149,32 @@
     @Test
     @UiThreadTest
     public void handleAllLocalesData_noAppAndSimNetworkLocale_1stLocaleIsFirstOneInSystemLocales() {
-        setupInitialLocales("",
-                "",
-                "",
-                "en, uk, jp, ne",
-                new String[]{"en", "ne", "ms", "pa"});
+        setupInitialLocales(
+                /* appLocale= */ "",
+                /* simCountry= */ "",
+                /* networkCountry= */ "",
+                /* systemLocales= */ "en, uk, jp, ne",
+                /* packageLocales= */ "",
+                /* assetLocales= */ new String[]{});
+        DummyAppLocaleDetailsHelper helper =
+                new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
+
+        helper.handleAllLocalesData();
+
+        Locale locale = Iterables.get(helper.getSuggestedLocales(), 0);
+        assertTrue(locale.equals(mSystemLocales.get(0)));
+    }
+
+    @Test
+    @UiThreadTest
+    public void handleAllLocalesData_hasPackageAndSystemLocales_1stLocaleIs1stOneInSystemLocales() {
+        setupInitialLocales(
+                /* appLocale= */ "",
+                /* simCountry= */ "",
+                /* networkCountry= */ "",
+                /* systemLocales= */ "en, uk, jp, ne",
+                /* packageLocales= */ "pa, cn, tw, en",
+                /* assetLocales= */ new String[]{});
         DummyAppLocaleDetailsHelper helper =
                 new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME);
 
@@ -204,6 +232,11 @@
      *
      * @param systemLocales  System locales, a locale list by a multiple language tags with comma.
      *                       example: "en, uk, jp"
+     *
+     * @param packageLocales PackageManager locales, a locale list by a multiple language tags with
+     *                       comma.
+     *                       example: "en, uk, jp"
+     *
      * @param assetLocales   Asset locales, a locale list by a multiple language tags with String
      *                       array.
      *                       example: new String[] {"en", "ne", "ms", "pa"}
@@ -212,10 +245,12 @@
             String simCountry,
             String networkCountry,
             String systemLocales,
+            String packageLocales,
             String[] assetLocales) {
         mAppLocale = LocaleList.forLanguageTags(appLocale);
         mSystemLocales = LocaleList.forLanguageTags(systemLocales);
         mAssetLocales = assetLocales;
+        mPackageLocales = LocaleList.forLanguageTags(packageLocales);
         when(mTelephonyManager.getSimCountryIso()).thenReturn(simCountry);
         when(mTelephonyManager.getNetworkCountryIso()).thenReturn(networkCountry);
         when(mLocaleManager.getApplicationLocales(anyString())).thenReturn(mAppLocale);
@@ -237,6 +272,10 @@
         LocaleList getCurrentSystemLocales() {
             return mSystemLocales;
         }
-    }
 
+        @Override
+        LocaleList getPackageLocales() {
+            return mPackageLocales;
+        }
+    }
 }