Enable Window Manager to store app-specific locales and apply them.
Test: atest WmTests:ActivityTaskManagerServiceTests Bug: 194095029 Bug: 194369257 Bug: 194369420 Bug: 194369426 Bug: 194370141 Change-Id: I743a9cfb84f4b054caa03413f39671d3f43a81c4
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -947,7 +947,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() {
|
||||
@@ -6519,7 +6519,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;
|
||||
@@ -6531,6 +6532,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) {
|
||||
@@ -6541,8 +6549,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);
|
||||
@@ -6550,8 +6560,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
int getNightMode() {
|
||||
Integer getNightMode() {
|
||||
return mNightMode;
|
||||
}
|
||||
|
||||
LocaleList getLocales() {
|
||||
return mLocales;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
record.mNightMode = impl.getNightMode();
|
||||
|
||||
if (record.isResetNightMode()) {
|
||||
removePackage(record.mName, record.mUserId);
|
||||
if (impl.getNightMode() != null) {
|
||||
record.mNightMode = impl.getNightMode();
|
||||
}
|
||||
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);
|
||||
xmlSerializer.attributeInt(null, ATTR_NIGHT_MODE, mRecord.mNightMode);
|
||||
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();
|
||||
|
||||
@@ -57,6 +57,7 @@ import android.content.res.Configuration;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.LocaleList;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
@@ -817,10 +818,13 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateNightModeForAllActivities(int nightMode) {
|
||||
// TODO(b/199277065): Re-assess how app-specific locales are applied based on UXR
|
||||
// TODO(b/199277729): Consider whether we need to add special casing for edge cases like
|
||||
// activity-embeddings etc.
|
||||
void updateAppSpecificSettingsForAllActivities(Integer nightMode, LocaleList localesOverride) {
|
||||
for (int i = mActivities.size() - 1; i >= 0; --i) {
|
||||
final ActivityRecord r = mActivities.get(i);
|
||||
if (r.setOverrideNightMode(nightMode) && r.mVisibleRequested) {
|
||||
if (r.applyAppSpecificConfig(nightMode, localesOverride) && r.mVisibleRequested) {
|
||||
r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,13 +43,17 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.IApplicationThread;
|
||||
import android.app.PictureInPictureParams;
|
||||
import android.app.servertransaction.ClientTransaction;
|
||||
import android.app.servertransaction.EnterPipRequestedItem;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.LocaleList;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
@@ -61,6 +65,7 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoSession;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -80,6 +85,9 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
|
||||
private final ArgumentCaptor<ClientTransaction> mClientTransactionCaptor =
|
||||
ArgumentCaptor.forClass(ClientTransaction.class);
|
||||
|
||||
private static final String DEFAULT_PACKAGE_NAME = "my.application.package";
|
||||
private static final int DEFAULT_USER_ID = 100;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
setBooted(mAtm);
|
||||
@@ -480,5 +488,269 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
|
||||
assertTrue(activity.supportsMultiWindow());
|
||||
assertTrue(task.supportsMultiWindow());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_locales_successfullyApplied() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
|
||||
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB")).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange.getConfiguration().getLocales());
|
||||
assertFalse(wpcAfterConfigChange.getConfiguration().isNightModeActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_nightMode_successfullyApplied() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertTrue(wpcAfterConfigChange.getConfiguration().isNightModeActive());
|
||||
assertEquals(LocaleList.forLanguageTags("en-XC"),
|
||||
wpcAfterConfigChange.getConfiguration().getLocales());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_multipleLocaleUpdates_successfullyApplied() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
WindowProcessController wpc = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), wpc);
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange1.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpc.getConfiguration().getLocales());
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("ja-XC,en-XC")).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
|
||||
assertEquals(LocaleList.forLanguageTags("ja-XC,en-XC"),
|
||||
wpcAfterConfigChange2.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
assertEquals(LocaleList.forLanguageTags("ja-XC,en-XC"),
|
||||
wpc.getConfiguration().getLocales());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_multipleNightModeUpdates_successfullyApplied() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange1.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
|
||||
packageConfigUpdater.setNightMode(Configuration.UI_MODE_NIGHT_NO).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange2.getConfiguration().getLocales());
|
||||
assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_onPackageUninstall_configShouldNotApply() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange1.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
|
||||
mAtm.mInternal.onPackageUninstalled(DEFAULT_PACKAGE_NAME);
|
||||
|
||||
WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XC"),
|
||||
wpcAfterConfigChange2.getConfiguration().getLocales());
|
||||
assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_LocalesEmptyAndNightModeUndefined_configShouldNotApply() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
WindowProcessController wpc = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), wpc);
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange1.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpc.getConfiguration().getLocales());
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList())
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_UNDEFINED).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XC"),
|
||||
wpcAfterConfigChange2.getConfiguration().getLocales());
|
||||
assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
|
||||
assertEquals(LocaleList.forLanguageTags("en-XC"),
|
||||
wpc.getConfiguration().getLocales());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_WhenUserRemoved_configShouldNotApply() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
|
||||
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange1.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
|
||||
mAtm.mInternal.removeUser(DEFAULT_USER_ID);
|
||||
|
||||
WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XC"),
|
||||
wpcAfterConfigChange2.getConfiguration().getLocales());
|
||||
assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_setLocaleListToEmpty_doesNotOverlayLocaleListInWpc() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
|
||||
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange1.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList()).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XC"),
|
||||
wpcAfterConfigChange2.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPackageConfigUpdate_resetNightMode_doesNotOverrideNightModeInWpc() {
|
||||
Configuration config = mAtm.getGlobalConfiguration();
|
||||
config.setLocales(LocaleList.forLanguageTags("en-XC"));
|
||||
mAtm.updateGlobalConfigurationLocked(config, true, true, DEFAULT_USER_ID);
|
||||
mAtm.mProcessMap.put(Binder.getCallingPid(), createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID));
|
||||
|
||||
ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
|
||||
mAtm.mInternal.createPackageConfigurationUpdater();
|
||||
|
||||
packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
|
||||
.setNightMode(Configuration.UI_MODE_NIGHT_YES).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange1 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange1.getConfiguration().getLocales());
|
||||
assertTrue(wpcAfterConfigChange1.getConfiguration().isNightModeActive());
|
||||
|
||||
packageConfigUpdater.setNightMode(Configuration.UI_MODE_NIGHT_UNDEFINED).commit();
|
||||
|
||||
WindowProcessController wpcAfterConfigChange2 = createWindowProcessController(
|
||||
DEFAULT_PACKAGE_NAME, DEFAULT_USER_ID);
|
||||
assertEquals(LocaleList.forLanguageTags("en-XA,ar-XB,en-XC"),
|
||||
wpcAfterConfigChange2.getConfiguration().getLocales());
|
||||
assertFalse(wpcAfterConfigChange2.getConfiguration().isNightModeActive());
|
||||
}
|
||||
|
||||
private WindowProcessController createWindowProcessController(String packageName,
|
||||
int userId) {
|
||||
WindowProcessListener mMockListener = Mockito.mock(WindowProcessListener.class);
|
||||
ApplicationInfo info = mock(ApplicationInfo.class);
|
||||
info.packageName = packageName;
|
||||
WindowProcessController wpc = new WindowProcessController(
|
||||
mAtm, info, packageName, 0, userId, null, mMockListener);
|
||||
wpc.setThread(mock(IApplicationThread.class));
|
||||
return wpc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -49,6 +50,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.os.LocaleList;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -371,8 +373,9 @@ public class WindowProcessControllerTests extends WindowTestsBase {
|
||||
public void testTopActivityUiModeChangeScheduleConfigChange() {
|
||||
final ActivityRecord activity = createActivityRecord(mWpc);
|
||||
activity.mVisibleRequested = true;
|
||||
doReturn(true).when(activity).setOverrideNightMode(anyInt());
|
||||
mWpc.updateNightModeForAllActivities(Configuration.UI_MODE_NIGHT_YES);
|
||||
doReturn(true).when(activity).applyAppSpecificConfig(anyInt(), any());
|
||||
mWpc.updateAppSpecificSettingsForAllActivities(Configuration.UI_MODE_NIGHT_YES,
|
||||
LocaleList.forLanguageTags("en-XA"));
|
||||
verify(activity).ensureActivityConfiguration(anyInt(), anyBoolean());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user