Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42bb47de authored by Calvin Pan's avatar Calvin Pan
Browse files

Filter the locale not in resources

Some 1p apps may not provide all the resources in the apk, need to
reply air update to download other language resources

Bug: 213980690
Test: Test apps that the locale in <locale-config> more than
resources.

Change-Id: I1c050ffc8bba76df42832a3641ddcba1111afd33
parent 8d8d93bf
Loading
Loading
Loading
Loading
+77 −19
Original line number Diff line number Diff line
@@ -20,12 +20,15 @@ import static com.android.internal.app.AppLocaleStore.AppLocaleResult.LocaleStat

import android.app.LocaleConfig;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageManager;
import android.os.LocaleList;
import android.util.Log;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Locale;
import java.util.stream.Collectors;

class AppLocaleStore {
    private static final String TAG = AppLocaleStore.class.getSimpleName();
@@ -34,7 +37,8 @@ class AppLocaleStore {
            Context context, String packageName) {
        LocaleConfig localeConfig = null;
        AppLocaleResult.LocaleStatus localeStatus = LocaleStatus.UNKNOWN_FAILURE;
        ArrayList<Locale> appSupportedLocales = new ArrayList<>();
        HashSet<Locale> appSupportedLocales = new HashSet<>();
        HashSet<Locale> assetLocale = getAssetLocales(context, packageName);

        try {
            localeConfig = new LocaleConfig(context.createPackageContext(packageName, 0));
@@ -45,32 +49,43 @@ class AppLocaleStore {
        if (localeConfig != null) {
            if (localeConfig.getStatus() == LocaleConfig.STATUS_SUCCESS) {
                LocaleList packageLocaleList = localeConfig.getSupportedLocales();
                if (packageLocaleList.size() > 0) {
                    localeStatus = LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG;
                boolean shouldFilterNotMatchingLocale = !hasInstallerInfo(context, packageName) &&
                        isSystemApp(context, packageName);

                Log.d(TAG, "filterNonMatchingLocale. " +
                        ", shouldFilterNotMatchingLocale: " + shouldFilterNotMatchingLocale +
                        ", assetLocale size: " + assetLocale.size() +
                        ", packageLocaleList size: " + packageLocaleList.size());

                for (int i = 0; i < packageLocaleList.size(); i++) {
                    appSupportedLocales.add(packageLocaleList.get(i));
                }
                if (shouldFilterNotMatchingLocale) {
                    appSupportedLocales = filterNotMatchingLocale(appSupportedLocales, assetLocale);
                }

                if (appSupportedLocales.size() > 0) {
                    localeStatus = LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_LOCAL_CONFIG;
                } else {
                    localeStatus = LocaleStatus.NO_SUPPORTED_LANGUAGE_IN_APP;
                }
            } else if (localeConfig.getStatus() == LocaleConfig.STATUS_NOT_SPECIFIED) {
                String[] languages = getAssetLocales(context, packageName);
                if (languages.length > 0) {
                if (assetLocale.size() > 0) {
                    localeStatus = LocaleStatus.GET_SUPPORTED_LANGUAGE_FROM_ASSET;
                    for (String language : languages) {
                        appSupportedLocales.add(Locale.forLanguageTag(language));
                    }
                    appSupportedLocales = assetLocale;
                } else {
                    localeStatus = LocaleStatus.ASSET_LOCALE_IS_EMPTY;
                }
            }
        }
        Log.d(TAG, "getAppSupportedLocales(). status: " + localeStatus
        Log.d(TAG, "getAppSupportedLocales(). package: " + packageName
                + ", status: " + localeStatus
                + ", appSupportedLocales:" + appSupportedLocales.size());
        return new AppLocaleResult(localeStatus, appSupportedLocales);
    }

    private static String[] getAssetLocales(Context context, String packageName) {
    private static HashSet<Locale> getAssetLocales(Context context, String packageName) {
        HashSet<Locale> result = new HashSet<>();
        try {
            PackageManager packageManager = context.getPackageManager();
            String[] locales = packageManager.getResourcesForApplication(
@@ -78,16 +93,59 @@ class AppLocaleStore {
                            .applicationInfo).getAssets().getNonSystemLocales();
            if (locales == null) {
                Log.i(TAG, "[" + packageName + "] locales are null.");
                return new String[0];
            } else if (locales.length <= 0) {
                Log.i(TAG, "[" + packageName + "] locales length is 0.");
                return new String[0];
            } else {
                for (String language : locales) {
                    result.add(Locale.forLanguageTag(language));
                }
            }
            return locales;
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "Can not found the package name : " + packageName + " / " + e);
        }
        return new String[0];
        return result;
    }

    private static HashSet<Locale> filterNotMatchingLocale(
            HashSet<Locale> appSupportedLocales, HashSet<Locale> assetLocale) {
        return appSupportedLocales.stream()
                .filter(locale -> matchLanguageInSet(locale, assetLocale))
                .collect(Collectors.toCollection(HashSet::new));
    }

    private static boolean matchLanguageInSet(Locale locale, HashSet<Locale> localesSet) {
        if (localesSet.contains(locale)) {
            return true;
        }
        for (Locale l: localesSet) {
            if(LocaleList.matchesLanguageAndScript(l, locale)) {
                return true;
            }
        }
        return false;
    }

    private static boolean hasInstallerInfo(Context context, String packageName) {
        InstallSourceInfo installSourceInfo;
        try {
            installSourceInfo = context.getPackageManager().getInstallSourceInfo(packageName);
            return installSourceInfo != null;
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "Installer info not found for: " + packageName);
        }
        return false;
    }

    private static boolean isSystemApp(Context context, String packageName) {
        ApplicationInfo applicationInfo;
        try {
            applicationInfo = context.getPackageManager()
                    .getApplicationInfoAsUser(packageName, /* flags= */ 0, context.getUserId());
            return applicationInfo.isSystemApp();
        } catch (PackageManager.NameNotFoundException e) {
            Log.w(TAG, "Application info not found for: " + packageName);
        }
        return false;
    }

    static class AppLocaleResult {
@@ -100,9 +158,9 @@ class AppLocaleStore {
        }

        LocaleStatus mLocaleStatus;
        ArrayList<Locale> mAppSupportedLocales;
        HashSet<Locale> mAppSupportedLocales;

        public AppLocaleResult(LocaleStatus localeStatus, ArrayList<Locale> appSupportedLocales) {
        public AppLocaleResult(LocaleStatus localeStatus, HashSet<Locale> appSupportedLocales) {
            this.mLocaleStatus = localeStatus;
            this.mAppSupportedLocales = appSupportedLocales;
        }
+10 −4
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.widget.SearchView;

import com.android.internal.R;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
@@ -198,13 +197,20 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O
    }

    private Set<LocaleStore.LocaleInfo> filterTheLanguagesNotSupportedInApp(
            boolean shouldShowList, ArrayList<Locale> supportedLocales) {
            boolean shouldShowList, HashSet<Locale> supportedLocales) {
        Set<LocaleStore.LocaleInfo> filteredList = new HashSet<>();
        if (shouldShowList) {
        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;
                    }
                }
            }