[Panlingual]Enhance App's suggested language
Bug: 258128535 Test: atest Change-Id: I3cf0ea6ba7835f812e2349e16451dcd4e2fd9694
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user