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

Commit 62065602 authored by Riya Ghai's avatar Riya Ghai Committed by Android (Google) Code Review
Browse files

Merge "Enable Window Manager to store app-specific locales and apply them." into sc-v2-dev

parents a83e90e0 2277de97
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.LocaleList;
import android.os.RemoteException;
import android.service.voice.IVoiceInteractionSession;
import android.util.IntArray;
@@ -610,6 +611,14 @@ public abstract class ActivityTaskManagerInternal {
         */
        PackageConfigurationUpdater setNightMode(int nightMode);

        /**
         * Sets the app-specific locales for the application referenced by this updater.
         * This setting is persisted and will overlay on top of the system locales for
         * the said application.
         * @return the current {@link PackageConfigurationUpdater} updated with the provided locale.
         */
        PackageConfigurationUpdater setLocales(LocaleList locales);

        /**
         * Commit changes.
         */
+19 −5
Original line number Diff line number Diff line
@@ -956,7 +956,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        setRecentTasks(new RecentTasks(this, mTaskSupervisor));
        mVrController = new VrController(mGlobalLock);
        mKeyguardController = mTaskSupervisor.getKeyguardController();
        mPackageConfigPersister = new PackageConfigPersister(mTaskSupervisor.mPersisterQueue);
        mPackageConfigPersister = new PackageConfigPersister(mTaskSupervisor.mPersisterQueue, this);
    }

    public void onActivityManagerInternalAdded() {
@@ -6575,7 +6575,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    final class PackageConfigurationUpdaterImpl implements
            ActivityTaskManagerInternal.PackageConfigurationUpdater {
        private final int mPid;
        private int mNightMode;
        private Integer mNightMode;
        private LocaleList mLocales;

        PackageConfigurationUpdaterImpl(int pid) {
            mPid = pid;
@@ -6587,6 +6588,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            return this;
        }

        @Override
        public ActivityTaskManagerInternal.PackageConfigurationUpdater
                setLocales(LocaleList locales) {
            mLocales = locales;
            return this;
        }

        @Override
        public void commit() {
            synchronized (mGlobalLock) {
@@ -6597,8 +6605,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                        Slog.w(TAG, "Override application configuration: cannot find pid " + mPid);
                        return;
                    }
                    wpc.setOverrideNightMode(mNightMode);
                    wpc.updateNightModeForAllActivities(mNightMode);
                    LocaleList localesOverride = LocaleOverlayHelper.combineLocalesIfOverlayExists(
                            mLocales, getGlobalConfiguration().getLocales());
                    wpc.applyAppSpecificConfig(mNightMode, localesOverride);
                    wpc.updateAppSpecificSettingsForAllActivities(mNightMode, localesOverride);
                    mPackageConfigPersister.updateFromImpl(wpc.mName, wpc.mUserId, this);
                } finally {
                    Binder.restoreCallingIdentity(ident);
@@ -6606,8 +6616,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            }
        }

        int getNightMode() {
        Integer getNightMode() {
            return mNightMode;
        }

        LocaleList getLocales() {
            return mLocales;
        }
    }
}
+34 −5
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.LocaleList;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.VisibleForTesting;
@@ -512,7 +513,7 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
        return mFullConfiguration.windowConfiguration.getWindowingMode() == WINDOWING_MODE_FREEFORM;
    }

    /** Returns the activity type associated with the the configuration container. */
    /** Returns the activity type associated with the configuration container. */
    /*@WindowConfiguration.ActivityType*/
    public int getActivityType() {
        return mFullConfiguration.windowConfiguration.getActivityType();
@@ -545,21 +546,49 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
        return getActivityType() == ACTIVITY_TYPE_ASSISTANT;
    }

    /**
     * Applies app-specific nightMode and {@link LocaleList} on requested configuration.
     * @return true if any of the requested configuration has been updated.
     */
    public boolean applyAppSpecificConfig(Integer nightMode, LocaleList locales) {
        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
        boolean newNightModeSet = (nightMode != null) && setOverrideNightMode(mRequestsTmpConfig,
                nightMode);
        boolean newLocalesSet = (locales != null) && setOverrideLocales(mRequestsTmpConfig,
                locales);
        if (newNightModeSet || newLocalesSet) {
            onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
        }
        return newNightModeSet || newLocalesSet;
    }

    /**
     * Overrides the night mode applied to this ConfigurationContainer.
     * @return true if the nightMode has been changed.
     */
    public boolean setOverrideNightMode(int nightMode) {
    private boolean setOverrideNightMode(Configuration requestsTmpConfig, int nightMode) {
        final int currentUiMode = mRequestedOverrideConfiguration.uiMode;
        final int currentNightMode = currentUiMode & Configuration.UI_MODE_NIGHT_MASK;
        final int validNightMode = nightMode & Configuration.UI_MODE_NIGHT_MASK;
        if (currentNightMode == validNightMode) {
            return false;
        }
        mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
        mRequestsTmpConfig.uiMode = validNightMode
        requestsTmpConfig.uiMode = validNightMode
                | (currentUiMode & ~Configuration.UI_MODE_NIGHT_MASK);
        onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
        return true;
    }

    /**
     * Overrides the locales applied to this ConfigurationContainer.
     * @return true if the LocaleList has been changed.
     */
    private boolean setOverrideLocales(Configuration requestsTmpConfig,
            @NonNull LocaleList overrideLocales) {
        if (mRequestedOverrideConfiguration.getLocales().equals(overrideLocales)) {
            return false;
        }
        requestsTmpConfig.setLocales(overrideLocales);
        requestsTmpConfig.userSetLocale = true;
        return true;
    }

+62 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.server.wm;

import android.os.LocaleList;

import java.util.Locale;

/**
 * Static utilities to overlay locales on top of another localeList.
 *
 * <p>This is used to overlay application-specific locales in
 *  {@link com.android.server.wm.ActivityTaskManagerInternal.PackageConfigurationUpdater} on top of
 *  system locales.
 */
final class LocaleOverlayHelper {

    /**
     * Combines the overlay locales and base locales.
     * @return the combined {@link LocaleList} if the overlay locales is not empty/null else
     * returns the empty/null LocaleList.
     */
    static LocaleList combineLocalesIfOverlayExists(LocaleList overlayLocales,
            LocaleList baseLocales) {
        if (overlayLocales == null || overlayLocales.isEmpty()) {
            return overlayLocales;
        }
        return combineLocales(overlayLocales, baseLocales);
    }

    /**
     * Creates a combined {@link LocaleList} by placing overlay locales before base locales and
     * dropping duplicates from the base locales.
     */
    private static LocaleList combineLocales(LocaleList overlayLocales, LocaleList baseLocales) {
        Locale[] combinedLocales = new Locale[overlayLocales.size() + baseLocales.size()];
        for (int i = 0; i < overlayLocales.size(); i++) {
            combinedLocales[i] = overlayLocales.get(i);
        }
        for (int i = 0; i < baseLocales.size(); i++) {
            combinedLocales[i + overlayLocales.size()] = baseLocales.get(i);
        }
        // Constructor of {@link LocaleList} removes duplicates
        return new LocaleList(combinedLocales);
    }


}
+54 −13
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;

import android.annotation.NonNull;
import android.os.Environment;
import android.os.LocaleList;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseArray;
@@ -54,12 +55,14 @@ public class PackageConfigPersister {
    private static final String TAG_CONFIG = "config";
    private static final String ATTR_PACKAGE_NAME = "package_name";
    private static final String ATTR_NIGHT_MODE = "night_mode";
    private static final String ATTR_LOCALES = "locale_list";

    private static final String PACKAGE_DIRNAME = "package_configs";
    private static final String SUFFIX_FILE_NAME = "_config.xml";

    private final PersisterQueue mPersisterQueue;
    private final Object mLock = new Object();
    private final ActivityTaskManagerService mAtm;

    @GuardedBy("mLock")
    private final SparseArray<HashMap<String, PackageConfigRecord>> mPendingWrite =
@@ -72,8 +75,9 @@ public class PackageConfigPersister {
        return new File(Environment.getDataSystemCeDirectory(userId), PACKAGE_DIRNAME);
    }

    PackageConfigPersister(PersisterQueue queue) {
    PackageConfigPersister(PersisterQueue queue, ActivityTaskManagerService atm) {
        mPersisterQueue = queue;
        mAtm = atm;
    }

    @GuardedBy("mLock")
@@ -100,7 +104,8 @@ public class PackageConfigPersister {
                    final TypedXmlPullParser in = Xml.resolvePullParser(is);
                    int event;
                    String packageName = null;
                    int nightMode = MODE_NIGHT_AUTO;
                    Integer nightMode = null;
                    LocaleList locales = null;
                    while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
                            && event != XmlPullParser.END_TAG) {
                        final String name = in.getName();
@@ -120,6 +125,9 @@ public class PackageConfigPersister {
                                        case ATTR_NIGHT_MODE:
                                            nightMode = Integer.parseInt(attrValue);
                                            break;
                                        case ATTR_LOCALES:
                                            locales = LocaleList.forLanguageTags(attrValue);
                                            break;
                                    }
                                }
                            }
@@ -130,6 +138,7 @@ public class PackageConfigPersister {
                        final PackageConfigRecord initRecord =
                                findRecordOrCreate(mModified, packageName, userId);
                        initRecord.mNightMode = nightMode;
                        initRecord.mLocales = locales;
                        if (DEBUG) {
                            Slog.d(TAG, "loadPackages: load one package " + initRecord);
                        }
@@ -155,7 +164,9 @@ public class PackageConfigPersister {
                        "updateConfigIfNeeded record " + container + " find? " + modifiedRecord);
            }
            if (modifiedRecord != null) {
                container.setOverrideNightMode(modifiedRecord.mNightMode);
                container.applyAppSpecificConfig(modifiedRecord.mNightMode,
                        LocaleOverlayHelper.combineLocalesIfOverlayExists(
                        modifiedRecord.mLocales, mAtm.getGlobalConfiguration().getLocales()));
            }
        }
    }
@@ -165,10 +176,16 @@ public class PackageConfigPersister {
            ActivityTaskManagerService.PackageConfigurationUpdaterImpl impl) {
        synchronized (mLock) {
            PackageConfigRecord record = findRecordOrCreate(mModified, packageName, userId);
            if (impl.getNightMode() != null) {
                record.mNightMode = impl.getNightMode();

            if (record.isResetNightMode()) {
                removePackage(record.mName, record.mUserId);
            }
            if (impl.getLocales() != null) {
                record.mLocales = impl.getLocales();
            }
            if ((record.mNightMode == null || record.isResetNightMode())
                    && (record.mLocales == null || record.mLocales.isEmpty())) {
                // if all values default to system settings, we can remove the package.
                removePackage(packageName, userId);
            } else {
                final PackageConfigRecord pendingRecord =
                        findRecord(mPendingWrite, record.mName, record.mUserId);
@@ -179,10 +196,11 @@ public class PackageConfigPersister {
                } else {
                    writeRecord = pendingRecord;
                }
                if (writeRecord.mNightMode == record.mNightMode) {

                if (!updateNightMode(record, writeRecord) && !updateLocales(record, writeRecord)) {
                    return;
                }
                writeRecord.mNightMode = record.mNightMode;

                if (DEBUG) {
                    Slog.d(TAG, "PackageConfigUpdater save config " + writeRecord);
                }
@@ -191,6 +209,22 @@ public class PackageConfigPersister {
        }
    }

    private boolean updateNightMode(PackageConfigRecord record, PackageConfigRecord writeRecord) {
        if (record.mNightMode == null || record.mNightMode.equals(writeRecord.mNightMode)) {
            return false;
        }
        writeRecord.mNightMode = record.mNightMode;
        return true;
    }

    private boolean updateLocales(PackageConfigRecord record, PackageConfigRecord writeRecord) {
        if (record.mLocales == null || record.mLocales.equals(writeRecord.mLocales)) {
            return false;
        }
        writeRecord.mLocales = record.mLocales;
        return true;
    }

    @GuardedBy("mLock")
    void removeUser(int userId) {
        synchronized (mLock) {
@@ -210,7 +244,7 @@ public class PackageConfigPersister {
    @GuardedBy("mLock")
    void onPackageUninstall(String packageName) {
        synchronized (mLock) {
            for (int i = mModified.size() - 1; i > 0; i--) {
            for (int i = mModified.size() - 1; i >= 0; i--) {
                final int userId = mModified.keyAt(i);
                removePackage(packageName, userId);
            }
@@ -242,7 +276,8 @@ public class PackageConfigPersister {
    static class PackageConfigRecord {
        final String mName;
        final int mUserId;
        int mNightMode;
        Integer mNightMode;
        LocaleList mLocales;

        PackageConfigRecord(String name, int userId) {
            mName = name;
@@ -256,7 +291,7 @@ public class PackageConfigPersister {
        @Override
        public String toString() {
            return "PackageConfigRecord package name: " + mName + " userId " + mUserId
                    + " nightMode " + mNightMode;
                    + " nightMode " + mNightMode + " locales " + mLocales;
        }
    }

@@ -369,7 +404,13 @@ public class PackageConfigPersister {
            }
            xmlSerializer.startTag(null, TAG_CONFIG);
            xmlSerializer.attribute(null, ATTR_PACKAGE_NAME, mRecord.mName);
            if (mRecord.mNightMode != null) {
                xmlSerializer.attributeInt(null, ATTR_NIGHT_MODE, mRecord.mNightMode);
            }
            if (mRecord.mLocales != null) {
                xmlSerializer.attribute(null, ATTR_LOCALES, mRecord.mLocales
                        .toLanguageTags());
            }
            xmlSerializer.endTag(null, TAG_CONFIG);
            xmlSerializer.endDocument();
            xmlSerializer.flush();
Loading