Loading core/java/com/android/internal/app/AppLocaleCollector.java 0 → 100644 +139 −0 Original line number Original line Diff line number Diff line /* * 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_ASSET; import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG; import android.content.Context; import android.os.Build; import android.os.LocaleList; import android.util.Log; import java.util.HashSet; import java.util.Locale; import java.util.Set; /** The Locale data collector for per-app language. */ 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; AppLocaleCollector(Context context, String appPackageName) { mContext = context; mAppPackageName = appPackageName; mAppCurrentLocale = LocaleStore.getAppCurrentLocaleInfo( mContext, mAppPackageName); } @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()); } return langTagsToIgnore; } @Override public Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, boolean translatedOnly, boolean isForCountryMode) { AppLocaleStore.AppLocaleResult result = AppLocaleStore.getAppSupportedLocales(mContext, mAppPackageName); Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly); Set<LocaleStore.LocaleInfo> appLocaleList = new HashSet<>(); Set<LocaleStore.LocaleInfo> systemLocaleList; boolean shouldShowList = result.mLocaleStatus == GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG || result.mLocaleStatus == GET_SUPPORTED_LANGUAGE_FROM_ASSET; // Get system supported locale list if (isForCountryMode) { systemLocaleList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, parent, translatedOnly); } else { systemLocaleList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, null /* no parent */, translatedOnly); } // Add current app locale if (mAppCurrentLocale != null && !isForCountryMode) { appLocaleList.add(mAppCurrentLocale); } // 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); } } // Add the languages that included in system supported locale if (shouldShowList) { appLocaleList.addAll(filterTheLanguagesNotIncludedInSystemLocale( systemLocaleList, result.mAppSupportedLocales)); } // Add "system language" option if (!isForCountryMode && shouldShowList) { appLocaleList.add(LocaleStore.getSystemDefaultLocaleInfo( mAppCurrentLocale == null)); } if (Build.isDebuggable()) { Log.d(TAG, "App locale list: " + appLocaleList); } return appLocaleList; } @Override public boolean hasSpecificPackageName() { return true; } private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotIncludedInSystemLocale( Set<LocaleStore.LocaleInfo> systemLocaleList, HashSet<Locale> appSupportedLocales) { Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>(); for(LocaleStore.LocaleInfo li: systemLocaleList) { if (appSupportedLocales.contains(li.getLocale())) { filteredList.add(li); } else { for(Locale l: appSupportedLocales) { if(LocaleList.matchesLanguageAndScript(li.getLocale(), l)) { filteredList.add(li); break; } } } } return filteredList; } } core/java/com/android/internal/app/LocalePickerWithRegion.java +46 −115 Original line number Original line Diff line number Diff line Loading @@ -16,16 +16,12 @@ package com.android.internal.app; package com.android.internal.app; import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus; import android.app.FragmentManager; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.FragmentTransaction; import android.app.ListFragment; import android.app.ListFragment; import android.content.Context; import android.content.Context; import android.os.Bundle; import android.os.Bundle; import android.os.LocaleList; import android.text.TextUtils; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MenuItem; Loading @@ -36,7 +32,6 @@ import android.widget.SearchView; import com.android.internal.R; import com.android.internal.R; import java.util.Collections; import java.util.HashSet; import java.util.HashSet; import java.util.Locale; import java.util.Locale; import java.util.Set; import java.util.Set; Loading @@ -54,6 +49,7 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O private SuggestedLocaleAdapter mAdapter; private SuggestedLocaleAdapter mAdapter; private LocaleSelectedListener mListener; private LocaleSelectedListener mListener; private LocaleCollectorBase mLocalePickerCollector; private Set<LocaleStore.LocaleInfo> mLocaleList; private Set<LocaleStore.LocaleInfo> mLocaleList; private LocaleStore.LocaleInfo mParentLocale; private LocaleStore.LocaleInfo mParentLocale; private boolean mTranslatedOnly = false; private boolean mTranslatedOnly = false; Loading @@ -62,7 +58,6 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O private boolean mPreviousSearchHadFocus = false; private boolean mPreviousSearchHadFocus = false; private int mFirstVisiblePosition = 0; private int mFirstVisiblePosition = 0; private int mTopDistance = 0; private int mTopDistance = 0; private String mAppPackageName; private CharSequence mTitle = null; private CharSequence mTitle = null; private OnActionExpandListener mOnActionExpandListener; private OnActionExpandListener mOnActionExpandListener; Loading @@ -79,31 +74,50 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O void onLocaleSelected(LocaleStore.LocaleInfo locale); void onLocaleSelected(LocaleStore.LocaleInfo locale); } } private static LocalePickerWithRegion createCountryPicker(Context context, /** * The interface which provides the locale list. */ interface LocaleCollectorBase { /** Gets the ignored locale list. */ HashSet<String> getIgnoredLocaleList(boolean translatedOnly); /** Gets the supported locale list. */ Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, boolean translatedOnly, boolean isForCountryMode); /** Indicates if the class work for specific package. */ boolean hasSpecificPackageName(); } private static LocalePickerWithRegion createCountryPicker( LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, boolean translatedOnly, String appPackageName, boolean translatedOnly, OnActionExpandListener onActionExpandListener, OnActionExpandListener onActionExpandListener) { LocaleCollectorBase localePickerCollector) { LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); localePicker.setOnActionExpandListener(onActionExpandListener); localePicker.setOnActionExpandListener(onActionExpandListener); boolean shouldShowTheList = localePicker.setListener(context, listener, parent, boolean shouldShowTheList = localePicker.setListener(listener, parent, translatedOnly, appPackageName); translatedOnly, localePickerCollector); return shouldShowTheList ? localePicker : null; return shouldShowTheList ? localePicker : null; } } public static LocalePickerWithRegion createLanguagePicker(Context context, public static LocalePickerWithRegion createLanguagePicker(Context context, LocaleSelectedListener listener, boolean translatedOnly) { LocaleSelectedListener listener, boolean translatedOnly) { LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); return createLanguagePicker(context, listener, translatedOnly, null, null); localePicker.setListener(context, listener, /* parent */ null, translatedOnly, null); return localePicker; } } public static LocalePickerWithRegion createLanguagePicker(Context context, public static LocalePickerWithRegion createLanguagePicker(Context context, LocaleSelectedListener listener, boolean translatedOnly, String appPackageName, LocaleSelectedListener listener, boolean translatedOnly, String appPackageName, OnActionExpandListener onActionExpandListener) { OnActionExpandListener onActionExpandListener) { LocaleCollectorBase localePickerController; if (TextUtils.isEmpty(appPackageName)) { localePickerController = new SystemLocaleCollector(context); } else { localePickerController = new AppLocaleCollector(context, appPackageName); } LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); localePicker.setOnActionExpandListener(onActionExpandListener); localePicker.setOnActionExpandListener(onActionExpandListener); localePicker.setListener( localePicker.setListener(listener, /* parent */ null, translatedOnly, context, listener, /* parent */ null, translatedOnly, appPackageName); localePickerController); return localePicker; return localePicker; } } Loading @@ -120,109 +134,23 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O * In this case we don't even show the list, we call the listener with that locale, * In this case we don't even show the list, we call the listener with that locale, * "pretending" it was selected, and return false.</p> * "pretending" it was selected, and return false.</p> */ */ private boolean setListener(Context context, LocaleSelectedListener listener, private boolean setListener(LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, LocaleStore.LocaleInfo parent, boolean translatedOnly, String appPackageName) { boolean translatedOnly, LocaleCollectorBase localePickerController) { this.mParentLocale = parent; this.mParentLocale = parent; this.mListener = listener; this.mListener = listener; this.mTranslatedOnly = translatedOnly; this.mTranslatedOnly = translatedOnly; this.mAppPackageName = appPackageName; this.mLocalePickerCollector = localePickerController; setRetainInstance(true); setRetainInstance(true); final HashSet<String> langTagsToIgnore = new HashSet<>(); mLocaleList = localePickerController.getSupportedLocaleList( LocaleStore.LocaleInfo appCurrentLocale = parent, translatedOnly, parent != null); LocaleStore.getAppCurrentLocaleInfo(context, appPackageName); boolean isForCountryMode = parent != null; if (!TextUtils.isEmpty(appPackageName) && !isForCountryMode) { // Filter current system locale to add them into suggestion LocaleList systemLangList = LocaleList.getDefault(); for(int i = 0; i < systemLangList.size(); i++) { langTagsToIgnore.add(systemLangList.get(i).toLanguageTag()); } if (appCurrentLocale != null) { Log.d(TAG, "appCurrentLocale: " + appCurrentLocale.getLocale().toLanguageTag()); langTagsToIgnore.add(appCurrentLocale.getLocale().toLanguageTag()); } else { Log.d(TAG, "appCurrentLocale is null"); } } else if (!translatedOnly) { final LocaleList userLocales = LocalePicker.getLocales(); final String[] langTags = userLocales.toLanguageTags().split(","); Collections.addAll(langTagsToIgnore, langTags); } if (isForCountryMode) { if (parent != null && listener != null && mLocaleList.size() == 1) { mLocaleList = LocaleStore.getLevelLocales(context, langTagsToIgnore, parent, translatedOnly); if (mLocaleList.size() <= 1) { if (listener != null && (mLocaleList.size() == 1)) { listener.onLocaleSelected(mLocaleList.iterator().next()); listener.onLocaleSelected(mLocaleList.iterator().next()); } return false; return false; } } else { } else { mLocaleList = LocaleStore.getLevelLocales(context, langTagsToIgnore, null /* no parent */, translatedOnly); } Log.d(TAG, "mLocaleList size: " + mLocaleList.size()); // Adding current locale and system default option into suggestion list if(!TextUtils.isEmpty(appPackageName)) { if (appCurrentLocale != null && !isForCountryMode) { mLocaleList.add(appCurrentLocale); } AppLocaleStore.AppLocaleResult result = AppLocaleStore.getAppSupportedLocales(context, appPackageName); boolean shouldShowList = result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG || result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_ASSET; // Add current system language into suggestion list for(LocaleStore.LocaleInfo localeInfo: LocaleStore.getSystemCurrentLocaleInfo()) { boolean isNotCurrentLocale = appCurrentLocale == null || !localeInfo.getLocale().equals(appCurrentLocale.getLocale()); if (!isForCountryMode && isNotCurrentLocale) { mLocaleList.add(localeInfo); } } // Filter the language not support in app mLocaleList = filterTheLanguagesNotSupportedInApp( shouldShowList, result.mAppSupportedLocales); Log.d(TAG, "mLocaleList after app-supported filter: " + mLocaleList.size()); // Add "system language" if (!isForCountryMode && shouldShowList) { mLocaleList.add(LocaleStore.getSystemDefaultLocaleInfo(appCurrentLocale == null)); } } return true; return true; } } private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotSupportedInApp( boolean shouldShowList, HashSet<Locale> supportedLocales) { Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>(); if (!shouldShowList) { return filteredList; } for(LocaleStore.LocaleInfo li: mLocaleList) { if (supportedLocales.contains(li.getLocale())) { filteredList.add(li); } else { for(Locale l: supportedLocales) { if(LocaleList.matchesLanguageAndScript(li.getLocale(), l)) { filteredList.add(li); break; } } } } return filteredList; } } private void returnToParentFrame() { private void returnToParentFrame() { Loading @@ -246,7 +174,9 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O mTitle = getActivity().getTitle(); mTitle = getActivity().getTitle(); final boolean countryMode = mParentLocale != null; final boolean countryMode = mParentLocale != null; final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault(); final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault(); mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode, mAppPackageName); final boolean hasSpecificPackageName = mLocalePickerCollector != null && mLocalePickerCollector.hasSpecificPackageName(); mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode, hasSpecificPackageName); final LocaleHelper.LocaleInfoComparator comp = final LocaleHelper.LocaleInfoComparator comp = new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode); new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode); mAdapter.sort(comp); mAdapter.sort(comp); Loading Loading @@ -321,8 +251,8 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O returnToParentFrame(); returnToParentFrame(); } else { } else { LocalePickerWithRegion selector = LocalePickerWithRegion.createCountryPicker( LocalePickerWithRegion selector = LocalePickerWithRegion.createCountryPicker( getContext(), mListener, locale, mTranslatedOnly /* translate only */, mListener, locale, mTranslatedOnly /* translate only */, mAppPackageName, mOnActionExpandListener); mOnActionExpandListener, this.mLocalePickerCollector); if (selector != null) { if (selector != null) { getFragmentManager().beginTransaction() getFragmentManager().beginTransaction() .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) Loading @@ -340,7 +270,8 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O inflater.inflate(R.menu.language_selection_list, menu); inflater.inflate(R.menu.language_selection_list, menu); final MenuItem searchMenuItem = menu.findItem(R.id.locale_search_menu); final MenuItem searchMenuItem = menu.findItem(R.id.locale_search_menu); if (!TextUtils.isEmpty(mAppPackageName) && mOnActionExpandListener != null) { if (mLocalePickerCollector.hasSpecificPackageName() && mOnActionExpandListener != null) { searchMenuItem.setOnActionExpandListener(mOnActionExpandListener); searchMenuItem.setOnActionExpandListener(mOnActionExpandListener); } } Loading core/java/com/android/internal/app/SuggestedLocaleAdapter.java +5 −5 Original line number Original line Diff line number Diff line Loading @@ -69,17 +69,17 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { protected Locale mDisplayLocale = null; protected Locale mDisplayLocale = null; // used to potentially cache a modified Context that uses mDisplayLocale // used to potentially cache a modified Context that uses mDisplayLocale protected Context mContextOverride = null; protected Context mContextOverride = null; private String mAppPackageName; private boolean mHasSpecificAppPackageName; public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) { public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) { this(localeOptions, countryMode, null); this(localeOptions, countryMode, false); } } public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode, public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode, String appPackageName) { boolean hasSpecificAppPackageName) { mCountryMode = countryMode; mCountryMode = countryMode; mLocaleOptions = new ArrayList<>(localeOptions.size()); mLocaleOptions = new ArrayList<>(localeOptions.size()); mAppPackageName = appPackageName; mHasSpecificAppPackageName = hasSpecificAppPackageName; for (LocaleStore.LocaleInfo li : localeOptions) { for (LocaleStore.LocaleInfo li : localeOptions) { if (li.isSuggested()) { if (li.isSuggested()) { Loading Loading @@ -136,7 +136,7 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { @Override @Override public int getViewTypeCount() { public int getViewTypeCount() { if (!TextUtils.isEmpty(mAppPackageName) && showHeaders()) { if (mHasSpecificAppPackageName && showHeaders()) { // Two headers, 1 "System language", 1 current locale // Two headers, 1 "System language", 1 current locale return APP_LANGUAGE_PICKER_TYPE_COUNT; return APP_LANGUAGE_PICKER_TYPE_COUNT; } else if (showHeaders()) { } else if (showHeaders()) { Loading core/java/com/android/internal/app/SystemLocaleCollector.java 0 → 100644 +66 −0 Original line number Original line Diff line number Diff line /* * 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 android.content.Context; import android.os.LocaleList; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** The Locale data collector for System language. */ class SystemLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase { private final Context mContext; SystemLocaleCollector(Context context) { mContext = context; } @Override public HashSet<String> getIgnoredLocaleList(boolean translatedOnly) { HashSet<String> ignoreList = new HashSet<>(); if (!translatedOnly) { final LocaleList userLocales = LocalePicker.getLocales(); final String[] langTags = userLocales.toLanguageTags().split(","); Collections.addAll(ignoreList, langTags); } return ignoreList; } @Override public Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, boolean translatedOnly, boolean isForCountryMode) { Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly); Set<LocaleStore.LocaleInfo> localeList; if (isForCountryMode) { localeList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, parent, translatedOnly); } else { localeList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, null /* no parent */, translatedOnly); } return localeList; } @Override public boolean hasSpecificPackageName() { return false; } } No newline at end of file Loading
core/java/com/android/internal/app/AppLocaleCollector.java 0 → 100644 +139 −0 Original line number Original line Diff line number Diff line /* * 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_ASSET; import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG; import android.content.Context; import android.os.Build; import android.os.LocaleList; import android.util.Log; import java.util.HashSet; import java.util.Locale; import java.util.Set; /** The Locale data collector for per-app language. */ 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; AppLocaleCollector(Context context, String appPackageName) { mContext = context; mAppPackageName = appPackageName; mAppCurrentLocale = LocaleStore.getAppCurrentLocaleInfo( mContext, mAppPackageName); } @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()); } return langTagsToIgnore; } @Override public Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, boolean translatedOnly, boolean isForCountryMode) { AppLocaleStore.AppLocaleResult result = AppLocaleStore.getAppSupportedLocales(mContext, mAppPackageName); Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly); Set<LocaleStore.LocaleInfo> appLocaleList = new HashSet<>(); Set<LocaleStore.LocaleInfo> systemLocaleList; boolean shouldShowList = result.mLocaleStatus == GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG || result.mLocaleStatus == GET_SUPPORTED_LANGUAGE_FROM_ASSET; // Get system supported locale list if (isForCountryMode) { systemLocaleList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, parent, translatedOnly); } else { systemLocaleList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, null /* no parent */, translatedOnly); } // Add current app locale if (mAppCurrentLocale != null && !isForCountryMode) { appLocaleList.add(mAppCurrentLocale); } // 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); } } // Add the languages that included in system supported locale if (shouldShowList) { appLocaleList.addAll(filterTheLanguagesNotIncludedInSystemLocale( systemLocaleList, result.mAppSupportedLocales)); } // Add "system language" option if (!isForCountryMode && shouldShowList) { appLocaleList.add(LocaleStore.getSystemDefaultLocaleInfo( mAppCurrentLocale == null)); } if (Build.isDebuggable()) { Log.d(TAG, "App locale list: " + appLocaleList); } return appLocaleList; } @Override public boolean hasSpecificPackageName() { return true; } private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotIncludedInSystemLocale( Set<LocaleStore.LocaleInfo> systemLocaleList, HashSet<Locale> appSupportedLocales) { Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>(); for(LocaleStore.LocaleInfo li: systemLocaleList) { if (appSupportedLocales.contains(li.getLocale())) { filteredList.add(li); } else { for(Locale l: appSupportedLocales) { if(LocaleList.matchesLanguageAndScript(li.getLocale(), l)) { filteredList.add(li); break; } } } } return filteredList; } }
core/java/com/android/internal/app/LocalePickerWithRegion.java +46 −115 Original line number Original line Diff line number Diff line Loading @@ -16,16 +16,12 @@ package com.android.internal.app; package com.android.internal.app; import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStatus; import android.app.FragmentManager; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.app.FragmentTransaction; import android.app.ListFragment; import android.app.ListFragment; import android.content.Context; import android.content.Context; import android.os.Bundle; import android.os.Bundle; import android.os.LocaleList; import android.text.TextUtils; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MenuItem; Loading @@ -36,7 +32,6 @@ import android.widget.SearchView; import com.android.internal.R; import com.android.internal.R; import java.util.Collections; import java.util.HashSet; import java.util.HashSet; import java.util.Locale; import java.util.Locale; import java.util.Set; import java.util.Set; Loading @@ -54,6 +49,7 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O private SuggestedLocaleAdapter mAdapter; private SuggestedLocaleAdapter mAdapter; private LocaleSelectedListener mListener; private LocaleSelectedListener mListener; private LocaleCollectorBase mLocalePickerCollector; private Set<LocaleStore.LocaleInfo> mLocaleList; private Set<LocaleStore.LocaleInfo> mLocaleList; private LocaleStore.LocaleInfo mParentLocale; private LocaleStore.LocaleInfo mParentLocale; private boolean mTranslatedOnly = false; private boolean mTranslatedOnly = false; Loading @@ -62,7 +58,6 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O private boolean mPreviousSearchHadFocus = false; private boolean mPreviousSearchHadFocus = false; private int mFirstVisiblePosition = 0; private int mFirstVisiblePosition = 0; private int mTopDistance = 0; private int mTopDistance = 0; private String mAppPackageName; private CharSequence mTitle = null; private CharSequence mTitle = null; private OnActionExpandListener mOnActionExpandListener; private OnActionExpandListener mOnActionExpandListener; Loading @@ -79,31 +74,50 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O void onLocaleSelected(LocaleStore.LocaleInfo locale); void onLocaleSelected(LocaleStore.LocaleInfo locale); } } private static LocalePickerWithRegion createCountryPicker(Context context, /** * The interface which provides the locale list. */ interface LocaleCollectorBase { /** Gets the ignored locale list. */ HashSet<String> getIgnoredLocaleList(boolean translatedOnly); /** Gets the supported locale list. */ Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, boolean translatedOnly, boolean isForCountryMode); /** Indicates if the class work for specific package. */ boolean hasSpecificPackageName(); } private static LocalePickerWithRegion createCountryPicker( LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, boolean translatedOnly, String appPackageName, boolean translatedOnly, OnActionExpandListener onActionExpandListener, OnActionExpandListener onActionExpandListener) { LocaleCollectorBase localePickerCollector) { LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); localePicker.setOnActionExpandListener(onActionExpandListener); localePicker.setOnActionExpandListener(onActionExpandListener); boolean shouldShowTheList = localePicker.setListener(context, listener, parent, boolean shouldShowTheList = localePicker.setListener(listener, parent, translatedOnly, appPackageName); translatedOnly, localePickerCollector); return shouldShowTheList ? localePicker : null; return shouldShowTheList ? localePicker : null; } } public static LocalePickerWithRegion createLanguagePicker(Context context, public static LocalePickerWithRegion createLanguagePicker(Context context, LocaleSelectedListener listener, boolean translatedOnly) { LocaleSelectedListener listener, boolean translatedOnly) { LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); return createLanguagePicker(context, listener, translatedOnly, null, null); localePicker.setListener(context, listener, /* parent */ null, translatedOnly, null); return localePicker; } } public static LocalePickerWithRegion createLanguagePicker(Context context, public static LocalePickerWithRegion createLanguagePicker(Context context, LocaleSelectedListener listener, boolean translatedOnly, String appPackageName, LocaleSelectedListener listener, boolean translatedOnly, String appPackageName, OnActionExpandListener onActionExpandListener) { OnActionExpandListener onActionExpandListener) { LocaleCollectorBase localePickerController; if (TextUtils.isEmpty(appPackageName)) { localePickerController = new SystemLocaleCollector(context); } else { localePickerController = new AppLocaleCollector(context, appPackageName); } LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); LocalePickerWithRegion localePicker = new LocalePickerWithRegion(); localePicker.setOnActionExpandListener(onActionExpandListener); localePicker.setOnActionExpandListener(onActionExpandListener); localePicker.setListener( localePicker.setListener(listener, /* parent */ null, translatedOnly, context, listener, /* parent */ null, translatedOnly, appPackageName); localePickerController); return localePicker; return localePicker; } } Loading @@ -120,109 +134,23 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O * In this case we don't even show the list, we call the listener with that locale, * In this case we don't even show the list, we call the listener with that locale, * "pretending" it was selected, and return false.</p> * "pretending" it was selected, and return false.</p> */ */ private boolean setListener(Context context, LocaleSelectedListener listener, private boolean setListener(LocaleSelectedListener listener, LocaleStore.LocaleInfo parent, LocaleStore.LocaleInfo parent, boolean translatedOnly, String appPackageName) { boolean translatedOnly, LocaleCollectorBase localePickerController) { this.mParentLocale = parent; this.mParentLocale = parent; this.mListener = listener; this.mListener = listener; this.mTranslatedOnly = translatedOnly; this.mTranslatedOnly = translatedOnly; this.mAppPackageName = appPackageName; this.mLocalePickerCollector = localePickerController; setRetainInstance(true); setRetainInstance(true); final HashSet<String> langTagsToIgnore = new HashSet<>(); mLocaleList = localePickerController.getSupportedLocaleList( LocaleStore.LocaleInfo appCurrentLocale = parent, translatedOnly, parent != null); LocaleStore.getAppCurrentLocaleInfo(context, appPackageName); boolean isForCountryMode = parent != null; if (!TextUtils.isEmpty(appPackageName) && !isForCountryMode) { // Filter current system locale to add them into suggestion LocaleList systemLangList = LocaleList.getDefault(); for(int i = 0; i < systemLangList.size(); i++) { langTagsToIgnore.add(systemLangList.get(i).toLanguageTag()); } if (appCurrentLocale != null) { Log.d(TAG, "appCurrentLocale: " + appCurrentLocale.getLocale().toLanguageTag()); langTagsToIgnore.add(appCurrentLocale.getLocale().toLanguageTag()); } else { Log.d(TAG, "appCurrentLocale is null"); } } else if (!translatedOnly) { final LocaleList userLocales = LocalePicker.getLocales(); final String[] langTags = userLocales.toLanguageTags().split(","); Collections.addAll(langTagsToIgnore, langTags); } if (isForCountryMode) { if (parent != null && listener != null && mLocaleList.size() == 1) { mLocaleList = LocaleStore.getLevelLocales(context, langTagsToIgnore, parent, translatedOnly); if (mLocaleList.size() <= 1) { if (listener != null && (mLocaleList.size() == 1)) { listener.onLocaleSelected(mLocaleList.iterator().next()); listener.onLocaleSelected(mLocaleList.iterator().next()); } return false; return false; } } else { } else { mLocaleList = LocaleStore.getLevelLocales(context, langTagsToIgnore, null /* no parent */, translatedOnly); } Log.d(TAG, "mLocaleList size: " + mLocaleList.size()); // Adding current locale and system default option into suggestion list if(!TextUtils.isEmpty(appPackageName)) { if (appCurrentLocale != null && !isForCountryMode) { mLocaleList.add(appCurrentLocale); } AppLocaleStore.AppLocaleResult result = AppLocaleStore.getAppSupportedLocales(context, appPackageName); boolean shouldShowList = result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG || result.mLocaleStatus == LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_ASSET; // Add current system language into suggestion list for(LocaleStore.LocaleInfo localeInfo: LocaleStore.getSystemCurrentLocaleInfo()) { boolean isNotCurrentLocale = appCurrentLocale == null || !localeInfo.getLocale().equals(appCurrentLocale.getLocale()); if (!isForCountryMode && isNotCurrentLocale) { mLocaleList.add(localeInfo); } } // Filter the language not support in app mLocaleList = filterTheLanguagesNotSupportedInApp( shouldShowList, result.mAppSupportedLocales); Log.d(TAG, "mLocaleList after app-supported filter: " + mLocaleList.size()); // Add "system language" if (!isForCountryMode && shouldShowList) { mLocaleList.add(LocaleStore.getSystemDefaultLocaleInfo(appCurrentLocale == null)); } } return true; return true; } } private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotSupportedInApp( boolean shouldShowList, HashSet<Locale> supportedLocales) { Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>(); if (!shouldShowList) { return filteredList; } for(LocaleStore.LocaleInfo li: mLocaleList) { if (supportedLocales.contains(li.getLocale())) { filteredList.add(li); } else { for(Locale l: supportedLocales) { if(LocaleList.matchesLanguageAndScript(li.getLocale(), l)) { filteredList.add(li); break; } } } } return filteredList; } } private void returnToParentFrame() { private void returnToParentFrame() { Loading @@ -246,7 +174,9 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O mTitle = getActivity().getTitle(); mTitle = getActivity().getTitle(); final boolean countryMode = mParentLocale != null; final boolean countryMode = mParentLocale != null; final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault(); final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault(); mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode, mAppPackageName); final boolean hasSpecificPackageName = mLocalePickerCollector != null && mLocalePickerCollector.hasSpecificPackageName(); mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode, hasSpecificPackageName); final LocaleHelper.LocaleInfoComparator comp = final LocaleHelper.LocaleInfoComparator comp = new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode); new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode); mAdapter.sort(comp); mAdapter.sort(comp); Loading Loading @@ -321,8 +251,8 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O returnToParentFrame(); returnToParentFrame(); } else { } else { LocalePickerWithRegion selector = LocalePickerWithRegion.createCountryPicker( LocalePickerWithRegion selector = LocalePickerWithRegion.createCountryPicker( getContext(), mListener, locale, mTranslatedOnly /* translate only */, mListener, locale, mTranslatedOnly /* translate only */, mAppPackageName, mOnActionExpandListener); mOnActionExpandListener, this.mLocalePickerCollector); if (selector != null) { if (selector != null) { getFragmentManager().beginTransaction() getFragmentManager().beginTransaction() .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) Loading @@ -340,7 +270,8 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O inflater.inflate(R.menu.language_selection_list, menu); inflater.inflate(R.menu.language_selection_list, menu); final MenuItem searchMenuItem = menu.findItem(R.id.locale_search_menu); final MenuItem searchMenuItem = menu.findItem(R.id.locale_search_menu); if (!TextUtils.isEmpty(mAppPackageName) && mOnActionExpandListener != null) { if (mLocalePickerCollector.hasSpecificPackageName() && mOnActionExpandListener != null) { searchMenuItem.setOnActionExpandListener(mOnActionExpandListener); searchMenuItem.setOnActionExpandListener(mOnActionExpandListener); } } Loading
core/java/com/android/internal/app/SuggestedLocaleAdapter.java +5 −5 Original line number Original line Diff line number Diff line Loading @@ -69,17 +69,17 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { protected Locale mDisplayLocale = null; protected Locale mDisplayLocale = null; // used to potentially cache a modified Context that uses mDisplayLocale // used to potentially cache a modified Context that uses mDisplayLocale protected Context mContextOverride = null; protected Context mContextOverride = null; private String mAppPackageName; private boolean mHasSpecificAppPackageName; public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) { public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode) { this(localeOptions, countryMode, null); this(localeOptions, countryMode, false); } } public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode, public SuggestedLocaleAdapter(Set<LocaleStore.LocaleInfo> localeOptions, boolean countryMode, String appPackageName) { boolean hasSpecificAppPackageName) { mCountryMode = countryMode; mCountryMode = countryMode; mLocaleOptions = new ArrayList<>(localeOptions.size()); mLocaleOptions = new ArrayList<>(localeOptions.size()); mAppPackageName = appPackageName; mHasSpecificAppPackageName = hasSpecificAppPackageName; for (LocaleStore.LocaleInfo li : localeOptions) { for (LocaleStore.LocaleInfo li : localeOptions) { if (li.isSuggested()) { if (li.isSuggested()) { Loading Loading @@ -136,7 +136,7 @@ public class SuggestedLocaleAdapter extends BaseAdapter implements Filterable { @Override @Override public int getViewTypeCount() { public int getViewTypeCount() { if (!TextUtils.isEmpty(mAppPackageName) && showHeaders()) { if (mHasSpecificAppPackageName && showHeaders()) { // Two headers, 1 "System language", 1 current locale // Two headers, 1 "System language", 1 current locale return APP_LANGUAGE_PICKER_TYPE_COUNT; return APP_LANGUAGE_PICKER_TYPE_COUNT; } else if (showHeaders()) { } else if (showHeaders()) { Loading
core/java/com/android/internal/app/SystemLocaleCollector.java 0 → 100644 +66 −0 Original line number Original line Diff line number Diff line /* * 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 android.content.Context; import android.os.LocaleList; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** The Locale data collector for System language. */ class SystemLocaleCollector implements LocalePickerWithRegion.LocaleCollectorBase { private final Context mContext; SystemLocaleCollector(Context context) { mContext = context; } @Override public HashSet<String> getIgnoredLocaleList(boolean translatedOnly) { HashSet<String> ignoreList = new HashSet<>(); if (!translatedOnly) { final LocaleList userLocales = LocalePicker.getLocales(); final String[] langTags = userLocales.toLanguageTags().split(","); Collections.addAll(ignoreList, langTags); } return ignoreList; } @Override public Set<LocaleStore.LocaleInfo> getSupportedLocaleList(LocaleStore.LocaleInfo parent, boolean translatedOnly, boolean isForCountryMode) { Set<String> langTagsToIgnore = getIgnoredLocaleList(translatedOnly); Set<LocaleStore.LocaleInfo> localeList; if (isForCountryMode) { localeList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, parent, translatedOnly); } else { localeList = LocaleStore.getLevelLocales(mContext, langTagsToIgnore, null /* no parent */, translatedOnly); } return localeList; } @Override public boolean hasSpecificPackageName() { return false; } } No newline at end of file