Merge "[Panlingual]Enhance App's suggested language"

This commit is contained in:
Allen Su
2022-12-23 06:40:25 +00:00
committed by Android (Google) Code Review
5 changed files with 518 additions and 39 deletions

View File

@@ -19,49 +19,184 @@ package com.android.internal.app;
import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_ASSET;
import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG;
import android.app.LocaleManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.LocaleList;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.annotations.VisibleForTesting;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
/** The Locale data collector for per-app language. */
class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
public class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
private static final String TAG = AppLocaleCollector.class.getSimpleName();
private final Context mContext;
private final String mAppPackageName;
private final LocaleStore.LocaleInfo mAppCurrentLocale;
private LocaleStore.LocaleInfo mAppCurrentLocale;
private Set<LocaleStore.LocaleInfo> mAllAppActiveLocales;
private Set<LocaleStore.LocaleInfo> mImeLocales;
private static final String PROP_APP_LANGUAGE_SUGGESTION =
"android.app.language.suggestion.enhanced";
private static final boolean ENABLED = true;
AppLocaleCollector(Context context, String appPackageName) {
public AppLocaleCollector(Context context, String appPackageName) {
mContext = context;
mAppPackageName = appPackageName;
mAppCurrentLocale = LocaleStore.getAppCurrentLocaleInfo(
mContext, mAppPackageName);
}
@VisibleForTesting
public LocaleStore.LocaleInfo getAppCurrentLocale() {
return LocaleStore.getAppActivatedLocaleInfo(mContext, mAppPackageName, true);
}
/**
* Get all applications' activated locales.
* @return A set which includes all applications' activated LocaleInfo.
*/
@VisibleForTesting
public Set<LocaleStore.LocaleInfo> getAllAppActiveLocales() {
PackageManager pm = mContext.getPackageManager();
LocaleManager lm = mContext.getSystemService(LocaleManager.class);
HashSet<LocaleStore.LocaleInfo> result = new HashSet<>();
if (pm != null && lm != null) {
HashMap<String, LocaleStore.LocaleInfo> map = new HashMap<>();
for (ApplicationInfo appInfo : pm.getInstalledApplications(
PackageManager.ApplicationInfoFlags.of(0))) {
LocaleStore.LocaleInfo localeInfo = LocaleStore.getAppActivatedLocaleInfo(
mContext, appInfo.packageName, false);
// For the locale to be added into the suggestion area, its country could not be
// empty.
if (localeInfo != null && localeInfo.getLocale().getCountry().length() > 0) {
map.put(localeInfo.getId(), localeInfo);
}
}
map.forEach((language, localeInfo) -> result.add(localeInfo));
}
return result;
}
/**
* Get all locales that active IME supports.
*
* @return A set which includes all LocaleInfo that active IME supports.
*/
@VisibleForTesting
public Set<LocaleStore.LocaleInfo> getActiveImeLocales() {
Set<LocaleStore.LocaleInfo> activeImeLocales = null;
InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
if (imm != null) {
InputMethodInfo activeIme = getActiveIme(imm);
if (activeIme != null) {
activeImeLocales = LocaleStore.transformImeLanguageTagToLocaleInfo(
imm.getEnabledInputMethodSubtypeList(activeIme, true));
}
}
if (activeImeLocales == null) {
return Set.of();
} else {
return activeImeLocales.stream().filter(
// For the locale to be added into the suggestion area, its country could not be
// empty.
info -> info.getLocale().getCountry().length() > 0).collect(
Collectors.toSet());
}
}
private InputMethodInfo getActiveIme(InputMethodManager imm) {
InputMethodInfo activeIme = null;
List<InputMethodInfo> infoList = imm.getEnabledInputMethodList();
String imeId = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD, mContext.getUserId());
for (InputMethodInfo method : infoList) {
if (method.getId().equals(imeId)) {
activeIme = method;
}
}
return activeIme;
}
/**
* Get the AppLocaleResult that the application supports.
* @return The AppLocaleResult that the application supports.
*/
@VisibleForTesting
public AppLocaleStore.AppLocaleResult getAppSupportedLocales() {
return AppLocaleStore.getAppSupportedLocales(mContext, mAppPackageName);
}
/**
* Get the locales that system supports excluding langTagsToIgnore.
*
* @param langTagsToIgnore A language set to be ignored.
* @param parent The parent locale.
* @param translatedOnly specified if is is only for translation.
* @return A set which includes the LocaleInfo that system supports, excluding langTagsToIgnore.
*/
@VisibleForTesting
public Set<LocaleStore.LocaleInfo> getSystemSupportedLocale(Set<String> langTagsToIgnore,
LocaleStore.LocaleInfo parent, boolean translatedOnly) {
return LocaleStore.getLevelLocales(mContext, langTagsToIgnore, parent, translatedOnly);
}
/**
* Get the locales that system activates.
* @return A set which includes all the locales that system activates.
*/
@VisibleForTesting
public List<LocaleStore.LocaleInfo> getSystemCurrentLocale() {
return LocaleStore.getSystemCurrentLocaleInfo();
}
@Override
public HashSet<String> getIgnoredLocaleList(boolean translatedOnly) {
HashSet<String> langTagsToIgnore = new HashSet<>();
LocaleList systemLangList = LocaleList.getDefault();
for(int i = 0; i < systemLangList.size(); i++) {
langTagsToIgnore.add(systemLangList.get(i).toLanguageTag());
}
if (mAppCurrentLocale != null) {
langTagsToIgnore.add(mAppCurrentLocale.getLocale().toLanguageTag());
}
if (SystemProperties.getBoolean(PROP_APP_LANGUAGE_SUGGESTION, ENABLED)) {
// Add the locale that other App activated
mAllAppActiveLocales.forEach(
info -> langTagsToIgnore.add(info.getLocale().toLanguageTag()));
// Add the locale that active IME enabled
mImeLocales.forEach(info -> langTagsToIgnore.add(info.getLocale().toLanguageTag()));
}
// Add System locales
LocaleList systemLangList = LocaleList.getDefault();
for (int i = 0; i < systemLangList.size(); i++) {
langTagsToIgnore.add(systemLangList.get(i).toLanguageTag());
}
return langTagsToIgnore;
}
@Override
public Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent,
boolean translatedOnly, boolean isForCountryMode) {
AppLocaleStore.AppLocaleResult result =
AppLocaleStore.getAppSupportedLocales(mContext, mAppPackageName);
if (mAppCurrentLocale == null) {
mAppCurrentLocale = getAppCurrentLocale();
}
if (mAllAppActiveLocales == null) {
mAllAppActiveLocales = getAllAppActiveLocales();
}
if (mImeLocales == null) {
mImeLocales = getActiveImeLocales();
}
AppLocaleStore.AppLocaleResult result = getAppSupportedLocales();
Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly);
Set<LocaleStore.LocaleInfo> appLocaleList = new HashSet<>();
Set<LocaleStore.LocaleInfo> systemLocaleList;
@@ -71,11 +206,9 @@ class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
// Get system supported locale list
if (isForCountryMode) {
systemLocaleList = LocaleStore.getLevelLocales(mContext,
langTagsToIgnore, parent, translatedOnly);
systemLocaleList = getSystemSupportedLocale(langTagsToIgnore, parent, translatedOnly);
} else {
systemLocaleList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore,
null /* no parent */, translatedOnly);
systemLocaleList = getSystemSupportedLocale(langTagsToIgnore, null, translatedOnly);
}
// Add current app locale
@@ -84,19 +217,46 @@ class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
}
// Add current system language into suggestion list
for(LocaleStore.LocaleInfo localeInfo:
LocaleStore.getSystemCurrentLocaleInfo()) {
boolean isNotCurrentLocale = mAppCurrentLocale == null
|| !localeInfo.getLocale().equals(mAppCurrentLocale.getLocale());
if (!isForCountryMode && isNotCurrentLocale) {
appLocaleList.add(localeInfo);
if (!isForCountryMode) {
boolean isCurrentLocale, isInAppOrIme;
for (LocaleStore.LocaleInfo localeInfo : getSystemCurrentLocale()) {
isCurrentLocale = mAppCurrentLocale != null
&& localeInfo.getLocale().equals(mAppCurrentLocale.getLocale());
isInAppOrIme = existsInAppOrIme(localeInfo.getLocale());
if (!isCurrentLocale && !isInAppOrIme) {
appLocaleList.add(localeInfo);
}
}
}
// Add the languages that included in system supported locale
// Add the languages that are included in system supported locale
Set<LocaleStore.LocaleInfo> suggestedSet = null;
if (shouldShowList) {
appLocaleList.addAll(filterTheLanguagesNotIncludedInSystemLocale(
systemLocaleList, result.mAppSupportedLocales));
appLocaleList.addAll(filterSupportedLocales(systemLocaleList,
result.mAppSupportedLocales));
suggestedSet = getSuggestedLocales(appLocaleList);
}
if (!isForCountryMode && SystemProperties.getBoolean(PROP_APP_LANGUAGE_SUGGESTION,
ENABLED)) {
// Add the language that other apps activate into the suggestion list.
Set<LocaleStore.LocaleInfo> localeSet = filterSupportedLocales(mAllAppActiveLocales,
result.mAppSupportedLocales);
if (suggestedSet != null) {
// Filter out the locale with the same language and country
// like zh-TW vs zh-Hant-TW.
localeSet = filterSameLanguageAndCountry(localeSet, suggestedSet);
}
appLocaleList.addAll(localeSet);
suggestedSet.addAll(localeSet);
// Add the language that the active IME enables into the suggestion list.
localeSet = filterSupportedLocales(mImeLocales, result.mAppSupportedLocales);
if (suggestedSet != null) {
localeSet = filterSameLanguageAndCountry(localeSet, suggestedSet);
}
appLocaleList.addAll(localeSet);
suggestedSet.addAll(localeSet);
}
// Add "system language" option
@@ -117,17 +277,55 @@ class AppLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase {
return true;
}
private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotIncludedInSystemLocale(
Set<LocaleStore.LocaleInfo> systemLocaleList,
private Set<LocaleStore.LocaleInfo> getSuggestedLocales(Set<LocaleStore.LocaleInfo> localeSet) {
return localeSet.stream().filter(localeInfo -> localeInfo.isSuggested()).collect(
Collectors.toSet());
}
private Set<LocaleStore.LocaleInfo> filterSameLanguageAndCountry(
Set<LocaleStore.LocaleInfo> newLocaleList,
Set<LocaleStore.LocaleInfo> existingLocaleList) {
Set<LocaleStore.LocaleInfo> result = new HashSet<>(newLocaleList.size());
for (LocaleStore.LocaleInfo appLocaleInfo : newLocaleList) {
boolean same = false;
Locale appLocale = appLocaleInfo.getLocale();
for (LocaleStore.LocaleInfo localeInfo : existingLocaleList) {
Locale suggested = localeInfo.getLocale();
if (appLocale.getLanguage().equals(suggested.getLanguage())
&& appLocale.getCountry().equals(suggested.getCountry())) {
same = true;
break;
}
}
if (!same) {
result.add(appLocaleInfo);
}
}
return result;
}
private boolean existsInAppOrIme(Locale locale) {
boolean existInApp = mAllAppActiveLocales.stream().anyMatch(
localeInfo -> localeInfo.getLocale().equals(locale));
if (existInApp) {
return true;
} else {
return mImeLocales.stream().anyMatch(
localeInfo -> localeInfo.getLocale().equals(locale));
}
}
private Set<LocaleStore.LocaleInfo> filterSupportedLocales(
Set<LocaleStore.LocaleInfo> suggestedLocales,
HashSet<Locale> appSupportedLocales) {
Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>();
for(LocaleStore.LocaleInfo li: systemLocaleList) {
for (LocaleStore.LocaleInfo li : suggestedLocales) {
if (appSupportedLocales.contains(li.getLocale())) {
filteredList.add(li);
} else {
for(Locale l: appSupportedLocales) {
if(LocaleList.matchesLanguageAndScript(li.getLocale(), l)) {
for (Locale l : appSupportedLocales) {
if (LocaleList.matchesLanguageAndScript(li.getLocale(), l)) {
filteredList.add(li);
break;
}

View File

@@ -30,7 +30,10 @@ import java.util.HashSet;
import java.util.Locale;
import java.util.stream.Collectors;
class AppLocaleStore {
/**
* A class used to access an application's supporting locales.
*/
public class AppLocaleStore {
private static final String TAG = AppLocaleStore.class.getSimpleName();
public static AppLocaleResult getAppSupportedLocales(
@@ -148,8 +151,11 @@ class AppLocaleStore {
return false;
}
static class AppLocaleResult {
enum LocaleStatus {
/**
* A class used to store an application's supporting locales.
*/
public static class AppLocaleResult {
public enum LocaleStatus {
UNKNOWN_FAILURE,
NO_SUPPORTED_LANGUAGE_IN_APP,
ASSET_LOCALE_IS_EMPTY,
@@ -158,7 +164,7 @@ class AppLocaleStore {
}
LocaleStatus mLocaleStatus;
HashSet<Locale> mAppSupportedLocales;
public HashSet<Locale> mAppSupportedLocales;
public AppLocaleResult(LocaleStatus localeStatus, HashSet<Locale> appSupportedLocales) {
this.mLocaleStatus = localeStatus;

View File

@@ -23,6 +23,7 @@ import android.os.LocaleList;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.annotations.VisibleForTesting;
@@ -45,10 +46,11 @@ public class LocaleStore {
@VisibleForTesting static final int SUGGESTION_TYPE_SIM = 1 << 0;
@VisibleForTesting static final int SUGGESTION_TYPE_CFG = 1 << 1;
// Only for per-app language picker
private static final int SUGGESTION_TYPE_CURRENT = 1 << 2;
@VisibleForTesting static final int SUGGESTION_TYPE_CURRENT = 1 << 2;
// Only for per-app language picker
private static final int SUGGESTION_TYPE_SYSTEM_LANGUAGE = 1 << 3;
@VisibleForTesting static final int SUGGESTION_TYPE_SYSTEM_LANGUAGE = 1 << 3;
// Only for per-app language picker
@VisibleForTesting static final int SUGGESTION_TYPE_OTHER_APP_LANGUAGE = 1 << 4;
private final Locale mLocale;
private final Locale mParent;
private final String mId;
@@ -259,7 +261,16 @@ public class LocaleStore {
}
}
public static LocaleInfo getAppCurrentLocaleInfo(Context context, String appPackageName) {
/**
* Get the application's activated locale.
*
* @param context UI activity's context.
* @param appPackageName The application's package name.
* @param isAppSelected True if the application is selected in the UI; false otherwise.
* @return A LocaleInfo with the application's activated locale.
*/
public static LocaleInfo getAppActivatedLocaleInfo(Context context, String appPackageName,
boolean isAppSelected) {
if (appPackageName == null) {
return null;
}
@@ -272,7 +283,11 @@ public class LocaleStore {
if (locale != null) {
LocaleInfo localeInfo = new LocaleInfo(locale);
localeInfo.mSuggestionFlags |= LocaleInfo.SUGGESTION_TYPE_CURRENT;
if (isAppSelected) {
localeInfo.mSuggestionFlags |= LocaleInfo.SUGGESTION_TYPE_CURRENT;
} else {
localeInfo.mSuggestionFlags |= LocaleInfo.SUGGESTION_TYPE_OTHER_APP_LANGUAGE;
}
localeInfo.mIsTranslated = true;
return localeInfo;
}
@@ -282,6 +297,24 @@ public class LocaleStore {
return null;
}
/**
* Transform IME's language tag to LocaleInfo.
*
* @param list A list which includes IME's subtype.
* @return A LocaleInfo set which includes IME's language tags.
*/
public static Set<LocaleInfo> transformImeLanguageTagToLocaleInfo(
List<InputMethodSubtype> list) {
Set<LocaleInfo> imeLocales = new HashSet<>();
for (InputMethodSubtype subtype : list) {
LocaleInfo localeInfo = new LocaleInfo(subtype.getLanguageTag());
localeInfo.mSuggestionFlags |= LocaleInfo.SUGGESTION_TYPE_OTHER_APP_LANGUAGE;
localeInfo.mIsTranslated = true;
imeLocales.add(localeInfo);
}
return imeLocales;
}
/**
* Returns a list of system languages with LocaleInfo
*/
@@ -458,4 +491,13 @@ public class LocaleStore {
}
return result;
}
/**
* API for testing.
*/
@UnsupportedAppUsage
@VisibleForTesting
public static LocaleInfo fromLocale(Locale locale) {
return new LocaleInfo(locale);
}
}

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.app;
import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.app.LocaleStore.LocaleInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* Unit tests for the {@link AppLocaleCollector}.
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AppLocaleCollectorTest {
private static final String TAG = "AppLocaleCollectorTest";
private AppLocaleCollector mAppLocaleCollector;
private LocaleStore.LocaleInfo mAppCurrentLocale;
private Set<LocaleInfo> mAllAppActiveLocales;
private Set<LocaleInfo> mImeLocales;
private List<LocaleInfo> mSystemCurrentLocales;
private Set<LocaleInfo> mSystemSupportedLocales;
private AppLocaleStore.AppLocaleResult mResult;
private static final String PKG1 = "pkg1";
private static final int NONE = LocaleInfo.SUGGESTION_TYPE_NONE;
private static final int SIM = LocaleInfo.SUGGESTION_TYPE_SIM;
private static final int CFG = LocaleInfo.SUGGESTION_TYPE_CFG;
private static final int SIM_CFG = SIM | CFG;
private static final int CURRENT = LocaleInfo.SUGGESTION_TYPE_CURRENT;
private static final int SYSTEM = LocaleInfo.SUGGESTION_TYPE_SYSTEM_LANGUAGE;
private static final int OTHERAPP = LocaleInfo.SUGGESTION_TYPE_OTHER_APP_LANGUAGE;
@Before
public void setUp() throws Exception {
mAppLocaleCollector = spy(
new AppLocaleCollector(InstrumentationRegistry.getContext(), PKG1));
mAppCurrentLocale = createLocaleInfo("en-US", CURRENT);
mAllAppActiveLocales = initAllAppActivatedLocales();
mImeLocales = initImeLocales();
mSystemSupportedLocales = initSystemSupportedLocales();
mSystemCurrentLocales = initSystemCurrentLocales();
mResult = new AppLocaleStore.AppLocaleResult(GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG,
initAppSupportedLocale());
}
@Test
public void testGetSupportedLocaleList() {
doReturn(mAppCurrentLocale).when(mAppLocaleCollector).getAppCurrentLocale();
doReturn(mResult).when(mAppLocaleCollector).getAppSupportedLocales();
doReturn(mAllAppActiveLocales).when(mAppLocaleCollector).getAllAppActiveLocales();
doReturn(mImeLocales).when(mAppLocaleCollector).getActiveImeLocales();
doReturn(mSystemSupportedLocales).when(mAppLocaleCollector).getSystemSupportedLocale(
anyObject(), eq(null), eq(true));
doReturn(mSystemCurrentLocales).when(mAppLocaleCollector).getSystemCurrentLocale();
Set<LocaleInfo> result = mAppLocaleCollector.getSupportedLocaleList(null, true, false);
HashMap<String, Integer> expectedResult = getExpectedResult();
assertEquals(result.size(), expectedResult.size());
for (LocaleInfo source : result) {
int suggestionFlags = expectedResult.getOrDefault(source.getId(), -1);
assertEquals(source.mSuggestionFlags, suggestionFlags);
}
}
private HashMap<String, Integer> getExpectedResult() {
HashMap<String, Integer> map = new HashMap<>();
map.put("en-US", CURRENT); // The locale current App activates.
map.put("fr", NONE); // The locale App and system support.
map.put("zu", NONE); // The locale App and system support.
map.put("en", NONE); // Use en because System supports en while APP supports en-CA, en-GB.
map.put("ko", NONE); // The locale App and system support.
map.put("en-AU", OTHERAPP); // The locale other App activates and current App supports.
map.put("en-CA", OTHERAPP); // The locale other App activates and current App supports.
map.put("ja-JP", OTHERAPP); // The locale other App activates and current App supports.
map.put("zh-Hant-TW", SIM); // The locale system activates.
map.put(createLocaleInfo("", SYSTEM).getId(), SYSTEM); // System language title
return map;
}
private Set<LocaleInfo> initSystemSupportedLocales() {
return Set.of(
createLocaleInfo("en", NONE),
createLocaleInfo("fr", NONE),
createLocaleInfo("zu", NONE),
createLocaleInfo("ko", NONE),
// will be filtered because current App doesn't support.
createLocaleInfo("es-US", SIM_CFG)
);
}
private List<LocaleInfo> initSystemCurrentLocales() {
return List.of(createLocaleInfo("zh-Hant-TW", SIM),
// will be filtered because current App activates this locale.
createLocaleInfo("en-US", SIM));
}
private Set<LocaleInfo> initAllAppActivatedLocales() {
return Set.of(
createLocaleInfo("en-CA", OTHERAPP),
createLocaleInfo("en-AU", OTHERAPP),
createLocaleInfo("ja-JP", OTHERAPP),
// will be filtered because current App activates this locale.
createLocaleInfo("en-US", OTHERAPP));
}
private Set<LocaleInfo> initImeLocales() {
return Set.of(
// will be filtered because system activates zh-Hant-TW.
createLocaleInfo("zh-TW", OTHERAPP),
// will be filtered because current App's activats this locale.
createLocaleInfo("en-US", OTHERAPP));
}
private HashSet<Locale> initAppSupportedLocale() {
HashSet<Locale> hs = new HashSet();
hs.add(Locale.forLanguageTag("en-US"));
hs.add(Locale.forLanguageTag("en-CA"));
hs.add(Locale.forLanguageTag("en-GB"));
hs.add(Locale.forLanguageTag("zh-TW"));
hs.add(Locale.forLanguageTag("ja"));
hs.add(Locale.forLanguageTag("fr"));
hs.add(Locale.forLanguageTag("zu"));
hs.add(Locale.forLanguageTag("ko"));
// will be filtered because it's not in the system language.
hs.add(Locale.forLanguageTag("mn"));
return hs;
}
private LocaleInfo createLocaleInfo(String languageTag, int suggestionFlag) {
LocaleInfo localeInfo = LocaleStore.fromLocale(Locale.forLanguageTag(languageTag));
localeInfo.mSuggestionFlags = suggestionFlag;
localeInfo.setTranslated(true);
return localeInfo;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.app;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.app.LocaleStore.LocaleInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.List;
import java.util.Set;
/**
* Unit tests for the {@link LocaleStore}.
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
public class LocaleStoreTest {
@Before
public void setUp() {
}
@Test
public void testTransformImeLanguageTagToLocaleInfo() {
List<InputMethodSubtype> list = List.of(
new InputMethodSubtypeBuilder().setLanguageTag("en-US").build(),
new InputMethodSubtypeBuilder().setLanguageTag("zh-TW").build(),
new InputMethodSubtypeBuilder().setLanguageTag("ja-JP").build());
Set<LocaleInfo> localeSet = LocaleStore.transformImeLanguageTagToLocaleInfo(list);
Set<String> expectedLanguageTag = Set.of("en-US", "zh-TW", "ja-JP");
assertEquals(localeSet.size(), expectedLanguageTag.size());
for (LocaleInfo info : localeSet) {
assertEquals(info.mSuggestionFlags, LocaleInfo.SUGGESTION_TYPE_OTHER_APP_LANGUAGE);
assertTrue(expectedLanguageTag.contains(info.getId()));
}
}
}