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

Commit 77f6bc89 authored by Alexander Mishkovets's avatar Alexander Mishkovets
Browse files

Integrate system language filtering functionality

Filter system languages based on the configuration provided via
the corresponding system property.

Bug: 154133013
Test: manual; atest LocalizationTest
Change-Id: I7e4694f4b381ab81d0e8ceab97bad68bb266aaee
parent 65530b75
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -456,6 +456,7 @@ java_library {

        "com.android.sysprop.apex",
        "com.android.sysprop.init",
        "com.android.sysprop.localization",
        "PlatformProperties",
    ],
    sdk_version: "core_platform",
+63 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.app;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.ListFragment;
@@ -28,6 +30,7 @@ import android.os.Bundle;
import android.os.LocaleList;
import android.os.RemoteException;
import android.provider.Settings;
import android.sysprop.LocalizationProperties;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,6 +46,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class LocalePicker extends ListFragment {
    private static final String TAG = "LocalePicker";
@@ -92,7 +98,38 @@ public class LocalePicker extends ListFragment {
    }

    public static String[] getSupportedLocales(Context context) {
        return context.getResources().getStringArray(R.array.supported_locales);
        String[] allLocales = context.getResources().getStringArray(R.array.supported_locales);

        Predicate<String> localeFilter = getLocaleFilter();
        if (localeFilter == null) {
            return allLocales;
        }

        List<String> result = new ArrayList<>(allLocales.length);
        for (String locale : allLocales) {
            if (localeFilter.test(locale)) {
                result.add(locale);
            }
        }

        int localeCount = result.size();
        return (localeCount == allLocales.length) ? allLocales
                : result.toArray(new String[localeCount]);
    }

    @Nullable
    private static Predicate<String> getLocaleFilter() {
        try {
            return LocalizationProperties.locale_filter()
                    .map(filter -> Pattern.compile(filter).asPredicate())
                    .orElse(null);
        } catch (SecurityException e) {
            Log.e(TAG, "Failed to read locale filter.", e);
        } catch (PatternSyntaxException e) {
            Log.e(TAG, "Bad locale filter format (\"" + e.getPattern() + "\"), skipping.");
        }

        return null;
    }

    public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) {
@@ -265,6 +302,11 @@ public class LocalePicker extends ListFragment {
     */
    @UnsupportedAppUsage
    public static void updateLocales(LocaleList locales) {
        if (locales != null) {
            locales = removeExcludedLocales(locales);
        }
        // Note: the empty list case is covered by Configuration.setLocales().

        try {
            final IActivityManager am = ActivityManager.getService();
            final Configuration config = am.getConfiguration();
@@ -280,6 +322,26 @@ public class LocalePicker extends ListFragment {
        }
    }

    @NonNull
    private static LocaleList removeExcludedLocales(@NonNull LocaleList locales) {
        Predicate<String> localeFilter = getLocaleFilter();
        if (localeFilter == null) {
            return locales;
        }

        int localeCount = locales.size();
        ArrayList<Locale> filteredLocales = new ArrayList<>(localeCount);
        for (int i = 0; i < localeCount; ++i) {
            Locale locale = locales.get(i);
            if (localeFilter.test(locale.toString())) {
                filteredLocales.add(locale);
            }
        }

        return (localeCount == filteredLocales.size()) ? locales
                : new LocaleList(filteredLocales.toArray(new Locale[0]));
    }

    /**
     * Get the locale list.
     *
+21 −0
Original line number Diff line number Diff line
// Copyright (C) 2020 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.

sysprop_library {
    name: "com.android.sysprop.localization",
    srcs: ["LocalizationProperties.sysprop"],
    property_owner: "Platform",
    api_packages: ["android.sysprop"],
    vendor_available: false,
}
+24 −0
Original line number Diff line number Diff line
# Copyright (C) 2020 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.

module: "android.sysprop.LocalizationProperties"
owner: Platform

prop {
    api_name: "locale_filter"
    type: String
    prop_name: "ro.localization.locale_filter"
    scope: Internal
    access: Readonly
}
+9 −0
Original line number Diff line number Diff line
props {
  module: "android.sysprop.LocalizationProperties"
  prop {
    api_name: "locale_filter"
    type: String
    scope: Internal
    prop_name: "ro.localization.locale_filter"
  }
}
Loading