From cfc5554068c627d19225709d070b34bb19343d12 Mon Sep 17 00:00:00 2001 From: tom hsu Date: Sat, 22 Jan 2022 03:20:24 +0800 Subject: [PATCH] [Panlingual] Add device default language to suggested group - Add default language preference - Polish unit test - Fix unsupported locale show on suggested group Bug: 209728327 Test: local test Test: atest pass Change-Id: I69778cb8d69b21314c75689f0d61c25294c7f9d2 --- res/values/strings.xml | 6 + res/xml/app_locale_details.xml | 9 +- .../appinfo/AppLocaleDetails.java | 177 +++++++++------ .../appinfo/AppLocaleDetailsTest.java | 211 ++++++++++++++---- 4 files changed, 291 insertions(+), 112 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index f071f5dd9c1..f5a3d6f1b31 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -491,6 +491,12 @@ All languages + + System language + + + System default - %1$s + The app is set to %1$s by default and doesn\u2019t support multiple languages. diff --git a/res/xml/app_locale_details.xml b/res/xml/app_locale_details.xml index 8056cbf2784..40ca58243ec 100644 --- a/res/xml/app_locale_details.xml +++ b/res/xml/app_locale_details.xml @@ -28,7 +28,14 @@ + android:title="@string/suggested_app_locales_title" > + + + + mSuggestedLocales = new ArrayList<>(); - private Collection mSupportedLocales = new ArrayList<>(); + private Collection mProcessedSuggestedLocales = new ArrayList<>(); + private Collection mProcessedSupportedLocales = new ArrayList<>(); + + private Collection mAppSupportedLocales = new ArrayList<>(); AppLocaleDetailsHelper(Context context, String packageName) { mContext = context; mPackageName = packageName; mTelephonyManager = context.getSystemService(TelephonyManager.class); mLocaleManager = context.getSystemService(LocaleManager.class); + mAppSupportedLocales = getAppSupportedLocales(); } /** Handle suggested and supported locales for UI display. */ @@ -225,49 +261,47 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen /** Gets suggested locales in the app. */ public Collection getSuggestedLocales() { - return mSuggestedLocales; + return mProcessedSuggestedLocales; } /** Gets supported locales in the app. */ public Collection getSupportedLocales() { - return mSupportedLocales; + return mProcessedSupportedLocales; } @VisibleForTesting void handleSuggestedLocales() { - LocaleList currentSystemLocales = getCurrentSystemLocales(); Locale appLocale = getAppDefaultLocale(mContext, mPackageName); + // 1st locale in suggested languages group. + for (Locale supportedlocale : mAppSupportedLocales) { + if (compareLocale(supportedlocale, appLocale)) { + mProcessedSuggestedLocales.add(appLocale); + break; + } + } + + // 2nd and 3rd locale in suggested languages group. String simCountry = mTelephonyManager.getSimCountryIso().toUpperCase(Locale.US); String networkCountry = mTelephonyManager.getNetworkCountryIso().toUpperCase(Locale.US); - // 1st locale in suggested languages group. - if (appLocale != null) { - mSuggestedLocales.add(appLocale); - } - // 2nd locale in suggested languages group. - final List localeInfos = LocalePicker.getAllAssetLocales(mContext, false); - for (LocaleInfo localeInfo : localeInfos) { - Locale locale = localeInfo.getLocale(); - String localeCountry = locale.getCountry().toUpperCase(Locale.US); - if (!compareLocale(locale, appLocale) + mAppSupportedLocales.forEach(supportedlocale -> { + String localeCountry = supportedlocale.getCountry().toUpperCase(Locale.US); + if (!compareLocale(supportedlocale, appLocale) && isCountrySuggestedLocale(localeCountry, simCountry, networkCountry)) { - mSuggestedLocales.add(locale); + mProcessedSuggestedLocales.add(supportedlocale); } - } + }); + // Other locales in suggested languages group. - for (int i = 0; i < currentSystemLocales.size(); i++) { - Locale locale = currentSystemLocales.get(i); - boolean isInSuggestedLocales = false; - for (int j = 0; j < mSuggestedLocales.size(); j++) { - Locale suggestedLocale = Iterables.get(mSuggestedLocales, j); - if (compareLocale(locale, suggestedLocale)) { - isInSuggestedLocales = true; - break; + Collection supportedSystemLocales = new ArrayList<>(); + getCurrentSystemLocales().forEach(systemLocale -> { + mAppSupportedLocales.forEach(supportedLocale -> { + if (compareLocale(systemLocale, supportedLocale)) { + supportedSystemLocales.add(supportedLocale); } - } - if (!isInSuggestedLocales) { - mSuggestedLocales.add(locale); - } - } + }); + }); + supportedSystemLocales.removeAll(mProcessedSuggestedLocales); + mProcessedSuggestedLocales.addAll(supportedSystemLocales); } @VisibleForTesting @@ -290,26 +324,34 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen @VisibleForTesting void handleSupportedLocales() { - 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)); - } - } + mProcessedSupportedLocales.addAll(mAppSupportedLocales); - if (mSuggestedLocales != null || !mSuggestedLocales.isEmpty()) { - mSupportedLocales.removeAll(mSuggestedLocales); + if (mProcessedSuggestedLocales != null || !mProcessedSuggestedLocales.isEmpty()) { + mProcessedSuggestedLocales.retainAll(mProcessedSupportedLocales); + mProcessedSupportedLocales.removeAll(mProcessedSuggestedLocales); } } private void clearLocalesData() { - mSuggestedLocales.clear(); - mSupportedLocales.clear(); + mProcessedSuggestedLocales.clear(); + mProcessedSupportedLocales.clear(); + } + + private Collection getAppSupportedLocales() { + Collection appSupportedLocales = new ArrayList<>(); + LocaleList localeList = getPackageLocales(); + + if (localeList != null && localeList.size() > 0) { + for (int i = 0; i < localeList.size(); i++) { + appSupportedLocales.add(localeList.get(i)); + } + } else { + String[] languages = getAssetLocales(); + for (String language : languages) { + appSupportedLocales.add(Locale.forLanguageTag(language)); + } + } + return appSupportedLocales; } /** Gets per app's default locale */ @@ -317,8 +359,8 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen LocaleManager localeManager = context.getSystemService(LocaleManager.class); try { LocaleList localeList = (localeManager == null) - ? new LocaleList() : localeManager.getApplicationLocales(packageName); - return localeList.isEmpty() ? null : localeList.get(0); + ? null : localeManager.getApplicationLocales(packageName); + return localeList == null ? null : localeList.get(0); } catch (IllegalArgumentException e) { Log.w(TAG, "package name : " + packageName + " is not correct. " + e); } @@ -344,12 +386,17 @@ public class AppLocaleDetails extends AppInfoBase implements RadioButtonPreferen } @VisibleForTesting - LocaleList getCurrentSystemLocales() { - return Resources.getSystem().getConfiguration().getLocales(); + Collection getCurrentSystemLocales() { + LocaleList localeList = Resources.getSystem().getConfiguration().getLocales(); + Collection systemLocales = new ArrayList<>(); + for (int i = 0; i < localeList.size(); i++) { + systemLocales.add(localeList.get(i)); + } + return systemLocales; } @VisibleForTesting - String[] getAssetSystemLocales() { + String[] getAssetLocales() { try { PackageManager packageManager = mContext.getPackageManager(); return packageManager.getResourcesForApplication( 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 ed4c127dcf5..0f9d54b441d 100644 --- a/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java +++ b/tests/unit/src/com/android/settings/applications/appinfo/AppLocaleDetailsTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.LocaleManager; @@ -32,7 +33,7 @@ import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.google.common.collect.Iterables; +import com.android.settingslib.widget.RadioButtonPreference; import org.junit.Before; import org.junit.Test; @@ -40,8 +41,14 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.Collection; import java.util.Locale; +/** + * Unittest for ApplocaleDetails + * TODO Need to add a unittest for the UI preference component. + */ @RunWith(AndroidJUnit4.class) public class AppLocaleDetailsTest { private static final String APP_PACKAGE_NAME = "app_package_name"; @@ -52,7 +59,7 @@ public class AppLocaleDetailsTest { private LocaleManager mLocaleManager; private Context mContext; - private LocaleList mSystemLocales; + private Collection mSystemLocales; private LocaleList mAppLocale; private String[] mAssetLocales; private LocaleList mPackageLocales; @@ -69,12 +76,48 @@ public class AppLocaleDetailsTest { when(mContext.getSystemService(LocaleManager.class)).thenReturn(mLocaleManager); setupInitialLocales( - /* appLocale= */ "en", + /* appLocale= */ "en-gb", /* simCountry= */ "tw", /* networkCountry= */ "jp", - /* systemLocales= */ "en, uk, jp, ne", - /* packageLocales= */ "pa, cn, tw, en", - /* assetLocales= */ new String[]{"en", "ne", "ms", "pa"}); + /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw", + /* packageLocales= */ "pa, cn, zh-tw, en-gb, ja-jp", + /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "zh-tw", "ja-jp"}); + } + + @Test + @UiThreadTest + public void onRadioButtonClicked_setCurrentLocaleToSystem() { + AppLocaleDetails appLocaleDetails = new AppLocaleDetails() { + @Override + void refreshUiInternal() {} + }; + DummyAppLocaleDetailsHelper helper = + spy(new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME)); + appLocaleDetails.mAppLocaleDetailsHelper = helper; + RadioButtonPreference pref = new RadioButtonPreference(mContext); + pref.setKey(AppLocaleDetails.KEY_SYSTEM_DEFAULT_LOCALE); + + appLocaleDetails.onRadioButtonClicked(pref); + + verify(helper).setAppDefaultLocale(LocaleList.forLanguageTags("")); + } + + @Test + @UiThreadTest + public void onRadioButtonClicked_setCurrentLocaleForUserSelected() { + AppLocaleDetails appLocaleDetails = new AppLocaleDetails() { + @Override + void refreshUiInternal() {} + }; + DummyAppLocaleDetailsHelper helper = + spy(new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME)); + appLocaleDetails.mAppLocaleDetailsHelper = helper; + RadioButtonPreference pref = new RadioButtonPreference(mContext); + pref.setKey("en"); + + appLocaleDetails.onRadioButtonClicked(pref); + + verify(helper).setAppDefaultLocale("en"); } @Test @@ -90,7 +133,7 @@ public class AppLocaleDetailsTest { @Test @UiThreadTest - public void handleAllLocalesData_1stLocaleOfSuggestedLocaleListIsAppLocale() { + public void handleAllLocalesData_1stLocaleIsAppLocaleAndHasSimAndNetwork() { Locale simCountryLocale = new Locale("zh", "TW"); Locale networkCountryLocale = new Locale("ja", "JP"); DummyAppLocaleDetailsHelper helper = @@ -98,36 +141,122 @@ public class AppLocaleDetailsTest { helper.handleAllLocalesData(); - Locale locale = Iterables.get(helper.getSuggestedLocales(), 0); + Collection suggestedLocales = helper.getSuggestedLocales(); + Locale locale = suggestedLocales.iterator().next(); assertTrue(locale.equals(mAppLocale.get(0))); - assertTrue(helper.getSuggestedLocales().contains(simCountryLocale)); - assertTrue(helper.getSuggestedLocales().contains(networkCountryLocale)); + assertTrue(suggestedLocales.contains(simCountryLocale)); + assertTrue(suggestedLocales.contains(networkCountryLocale)); } @Test @UiThreadTest - public void handleAllLocalesData_withoutAppLocale_1stSuggestedLocaleIsSimCountryLocale() { - Locale simCountryLocale = new Locale("zh", "TW"); + public void + handleAllLocalesData_noAppAndNoSupportedSimLocale_1stSuggestedLocaleIsAssetLocale() { + Locale firstAssetLocale = new Locale("en", "GB"); setupInitialLocales( /* appLocale= */ "", /* simCountry= */ "tw", /* networkCountry= */ "", - /* systemLocales= */ "en, uk, jp, ne", + /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw", /* packageLocales= */ "", - /* assetLocales= */ new String[]{}); + /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "ja-jp"}); DummyAppLocaleDetailsHelper helper = new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME); helper.handleAllLocalesData(); - Locale locale = Iterables.get(helper.getSuggestedLocales(), 0); - assertTrue(locale.equals(simCountryLocale)); - assertFalse(helper.getSuggestedLocales().contains(mAppLocale.get(0))); + Collection suggestedLocales = helper.getSuggestedLocales(); + Locale locale = suggestedLocales.iterator().next(); + assertTrue(locale.equals(firstAssetLocale)); } @Test @UiThreadTest - public void handleAllLocalesData_withoutAppLocale_1stSuggestedLocaleIsNetworkCountryLocale() { + public void handleAllLocalesData_noAppButHasSupportedSimLocale_1stSuggestedLocaleIsSim() { + Locale simLocale = new Locale("zh", "tw"); + setupInitialLocales( + /* appLocale= */ "", + /* simCountry= */ "tw", + /* networkCountry= */ "", + /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw", + /* packageLocales= */ "", + /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "ja-jp", "zh-tw"}); + DummyAppLocaleDetailsHelper helper = + new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME); + + helper.handleAllLocalesData(); + + Collection suggestedLocales = helper.getSuggestedLocales(); + Locale locale = suggestedLocales.iterator().next(); + assertTrue(locale.equals(simLocale)); + } + + @Test + @UiThreadTest + public void + handleAllLocalesData_noAppButHasSupportedNetworkLocale_1stSuggestedLocaleIsNetwork() { + Locale networkLocale = new Locale("ja", "JP"); + setupInitialLocales( + /* appLocale= */ "", + /* simCountry= */ "", + /* networkCountry= */ "jp", + /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw", + /* packageLocales= */ "", + /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "ja-jp"}); + DummyAppLocaleDetailsHelper helper = + new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME); + + helper.handleAllLocalesData(); + + Collection suggestedLocales = helper.getSuggestedLocales(); + Locale locale = suggestedLocales.iterator().next(); + assertTrue(locale.equals(networkLocale)); + } + + @Test + @UiThreadTest + public void handleAllLocalesData_noAppSimOrNetworkLocale_suggestedLocalesHasSystemLocale() { + setupInitialLocales( + /* appLocale= */ "", + /* simCountry= */ "", + /* networkCountry= */ "", + /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw", + /* packageLocales= */ "", + /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "zh-tw", "ja-jp"}); + DummyAppLocaleDetailsHelper helper = + new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME); + helper.handleAllLocalesData(); + + Collection suggestedLocales = helper.getSuggestedLocales(); + assertTrue(suggestedLocales.contains(Locale.forLanguageTag("ne"))); + // ru language is not present in the asset locales + assertFalse(suggestedLocales.contains(Locale.forLanguageTag("ru"))); + } + + @Test + @UiThreadTest + public void handleAllLocalesData_noAppButHasSimAndNetworkLocale_1stLocaleIsSimLocale() { + Locale simCountryLocale = new Locale("zh", "TW"); + setupInitialLocales( + /* appLocale= */ "", + /* simCountry= */ "tw", + /* networkCountry= */ "jp", + /* systemLocales= */ "en-gb, ru, ja-jp, ne, zh-tw", + /* packageLocales= */ "", + /* assetLocales= */ new String[]{"en-gb", "ne", "ms", "pa", "zh-tw", "ja-jp"}); + + DummyAppLocaleDetailsHelper helper = + new DummyAppLocaleDetailsHelper(mContext, APP_PACKAGE_NAME); + helper.handleAllLocalesData(); + + Collection suggestedLocales = helper.getSuggestedLocales(); + Locale locale = suggestedLocales.iterator().next(); + assertTrue(locale.equals(simCountryLocale)); + } + + @Test + @UiThreadTest + public void handleAllLocalesData_noSupportedLocale_noSuggestedLocales() { Locale networkCountryLocale = new Locale("en", "GB"); setupInitialLocales( /* appLocale= */ "", @@ -141,28 +270,8 @@ public class AppLocaleDetailsTest { helper.handleAllLocalesData(); - Locale locale = Iterables.get(helper.getSuggestedLocales(), 0); - assertTrue(locale.equals(networkCountryLocale)); - assertFalse(helper.getSuggestedLocales().contains(mAppLocale.get(0))); - } - - @Test - @UiThreadTest - public void handleAllLocalesData_noAppAndSimNetworkLocale_1stLocaleIsFirstOneInSystemLocales() { - 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))); + Collection suggestedLocales = helper.getSuggestedLocales(); + assertTrue(suggestedLocales.size() == 0); } @Test @@ -180,8 +289,10 @@ public class AppLocaleDetailsTest { helper.handleAllLocalesData(); - Locale locale = Iterables.get(helper.getSuggestedLocales(), 0); - assertTrue(locale.equals(mSystemLocales.get(0))); + Collection suggestedLocales = helper.getSuggestedLocales(); + Locale locale = suggestedLocales.iterator().next(); + Locale systemLocale = mSystemLocales.iterator().next(); + assertTrue(locale.equals(systemLocale)); } @Test @@ -248,15 +359,23 @@ public class AppLocaleDetailsTest { String packageLocales, String[] assetLocales) { mAppLocale = LocaleList.forLanguageTags(appLocale); - mSystemLocales = LocaleList.forLanguageTags(systemLocales); + // forLanguageTags does not filter space to the input string. If there is any space included + // in string, this will make locale fail to generate. + systemLocales = systemLocales.replaceAll("\\s+", ""); + LocaleList listOfSystemLocales = LocaleList.forLanguageTags(systemLocales); + mSystemLocales = new ArrayList<>(); + for (int i = 0; i < listOfSystemLocales.size(); i++) { + mSystemLocales.add(listOfSystemLocales.get(i)); + } mAssetLocales = assetLocales; + packageLocales = packageLocales.replaceAll("\\s+", ""); mPackageLocales = LocaleList.forLanguageTags(packageLocales); when(mTelephonyManager.getSimCountryIso()).thenReturn(simCountry); when(mTelephonyManager.getNetworkCountryIso()).thenReturn(networkCountry); when(mLocaleManager.getApplicationLocales(anyString())).thenReturn(mAppLocale); } - private class DummyAppLocaleDetailsHelper + public class DummyAppLocaleDetailsHelper extends AppLocaleDetails.AppLocaleDetailsHelper { DummyAppLocaleDetailsHelper(Context context, String packageName) { @@ -264,12 +383,12 @@ public class AppLocaleDetailsTest { } @Override - String[] getAssetSystemLocales() { + String[] getAssetLocales() { return mAssetLocales; } @Override - LocaleList getCurrentSystemLocales() { + Collection getCurrentSystemLocales() { return mSystemLocales; }