diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index d4644c59fa529..a4a39e9618900 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1027,6 +1027,9 @@
+
+
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index ec486437734b5..dec403cf5c463 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -29,6 +29,7 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.LocaleList;
@@ -622,10 +623,19 @@ public abstract class ActivityTaskManagerInternal {
@Nullable
public final LocaleList mLocales;
+ /**
+ * Gender for the application, null if app-specific grammatical gender is not set.
+ */
+ @Nullable
+ public final @Configuration.GrammaticalGender
+ Integer mGrammaticalGender;
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public PackageConfig(Integer nightMode, LocaleList locales) {
+ public PackageConfig(Integer nightMode, LocaleList locales,
+ @Configuration.GrammaticalGender Integer grammaticalGender) {
mNightMode = nightMode;
mLocales = locales;
+ mGrammaticalGender = grammaticalGender;
}
/**
@@ -659,6 +669,13 @@ public abstract class ActivityTaskManagerInternal {
*/
PackageConfigurationUpdater setLocales(LocaleList locales);
+ /**
+ * Sets the gender for the current application. This setting is persisted and will
+ * override the system configuration for this application.
+ */
+ PackageConfigurationUpdater setGrammaticalGender(
+ @Configuration.GrammaticalGender int gender);
+
/**
* Commit changes.
* @return true if the configuration changes were persisted,
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 0c6cea82e00cd..58d4e82961f68 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -536,16 +536,19 @@ public abstract class ConfigurationContainer {
* 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) {
+ public boolean applyAppSpecificConfig(Integer nightMode, LocaleList locales,
+ @Configuration.GrammaticalGender Integer gender) {
mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
boolean newNightModeSet = (nightMode != null) && setOverrideNightMode(mRequestsTmpConfig,
nightMode);
boolean newLocalesSet = (locales != null) && setOverrideLocales(mRequestsTmpConfig,
locales);
- if (newNightModeSet || newLocalesSet) {
+ boolean newGenderSet = (gender != null) && setOverrideGender(mRequestsTmpConfig,
+ gender);
+ if (newNightModeSet || newLocalesSet || newGenderSet) {
onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
}
- return newNightModeSet || newLocalesSet;
+ return newNightModeSet || newLocalesSet || newGenderSet;
}
/**
@@ -578,6 +581,21 @@ public abstract class ConfigurationContainer {
return true;
}
+ /**
+ * Overrides the gender to this ConfigurationContainer.
+ *
+ * @return true if the grammatical gender has been changed.
+ */
+ private boolean setOverrideGender(Configuration requestsTmpConfig,
+ @Configuration.GrammaticalGender int gender) {
+ if (mRequestedOverrideConfiguration.getGrammaticalGender() == gender) {
+ return false;
+ } else {
+ requestsTmpConfig.setGrammaticalGender(gender);
+ return true;
+ }
+ }
+
public boolean isActivityTypeDream() {
return getActivityType() == ACTIVITY_TYPE_DREAM;
}
diff --git a/services/core/java/com/android/server/wm/PackageConfigPersister.java b/services/core/java/com/android/server/wm/PackageConfigPersister.java
index 18a7d2e760fc9..23127ac1ba098 100644
--- a/services/core/java/com/android/server/wm/PackageConfigPersister.java
+++ b/services/core/java/com/android/server/wm/PackageConfigPersister.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.content.res.Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
+
import android.annotation.NonNull;
import android.content.res.Configuration;
import android.os.Environment;
@@ -165,7 +167,8 @@ public class PackageConfigPersister {
if (modifiedRecord != null) {
container.applyAppSpecificConfig(modifiedRecord.mNightMode,
LocaleOverlayHelper.combineLocalesIfOverlayExists(
- modifiedRecord.mLocales, mAtm.getGlobalConfiguration().getLocales()));
+ modifiedRecord.mLocales, mAtm.getGlobalConfiguration().getLocales()),
+ modifiedRecord.mGrammaticalGender);
}
}
}
@@ -188,16 +191,19 @@ public class PackageConfigPersister {
}
boolean isNightModeChanged = updateNightMode(impl.getNightMode(), record);
boolean isLocalesChanged = updateLocales(impl.getLocales(), record);
+ boolean isGenderChanged = updateGender(impl.getGrammaticalGender(), record);
if ((record.mNightMode == null || record.isResetNightMode())
- && (record.mLocales == null || record.mLocales.isEmpty())) {
+ && (record.mLocales == null || record.mLocales.isEmpty())
+ && (record.mGrammaticalGender == null
+ || record.mGrammaticalGender == GRAMMATICAL_GENDER_NOT_SPECIFIED)) {
// if all values default to system settings, we can remove the package.
removePackage(packageName, userId);
// if there was a pre-existing record for the package that was deleted,
// we return true (since it was successfully deleted), else false (since there was
// no change to the previous state).
return isRecordPresent;
- } else if (!isNightModeChanged && !isLocalesChanged) {
+ } else if (!isNightModeChanged && !isLocalesChanged && !isGenderChanged) {
return false;
} else {
final PackageConfigRecord pendingRecord =
@@ -211,7 +217,8 @@ public class PackageConfigPersister {
}
if (!updateNightMode(record.mNightMode, writeRecord)
- && !updateLocales(record.mLocales, writeRecord)) {
+ && !updateLocales(record.mLocales, writeRecord)
+ && !updateGender(record.mGrammaticalGender, writeRecord)) {
return false;
}
@@ -240,6 +247,15 @@ public class PackageConfigPersister {
return true;
}
+ private boolean updateGender(@Configuration.GrammaticalGender Integer requestedGender,
+ PackageConfigRecord record) {
+ if (requestedGender == null || requestedGender.equals(record.mGrammaticalGender)) {
+ return false;
+ }
+ record.mGrammaticalGender = requestedGender;
+ return true;
+ }
+
@GuardedBy("mLock")
void removeUser(int userId) {
synchronized (mLock) {
@@ -305,7 +321,9 @@ public class PackageConfigPersister {
return null;
}
return new ActivityTaskManagerInternal.PackageConfig(
- packageConfigRecord.mNightMode, packageConfigRecord.mLocales);
+ packageConfigRecord.mNightMode,
+ packageConfigRecord.mLocales,
+ packageConfigRecord.mGrammaticalGender);
}
}
@@ -336,6 +354,8 @@ public class PackageConfigPersister {
final int mUserId;
Integer mNightMode;
LocaleList mLocales;
+ @Configuration.GrammaticalGender
+ Integer mGrammaticalGender;
PackageConfigRecord(String name, int userId) {
mName = name;
diff --git a/services/core/java/com/android/server/wm/PackageConfigurationUpdaterImpl.java b/services/core/java/com/android/server/wm/PackageConfigurationUpdaterImpl.java
index f3be66c5e6da3..2cf8a4a7c1464 100644
--- a/services/core/java/com/android/server/wm/PackageConfigurationUpdaterImpl.java
+++ b/services/core/java/com/android/server/wm/PackageConfigurationUpdaterImpl.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import android.content.pm.PackageManager;
+import android.content.res.Configuration;
import android.os.Binder;
import android.os.LocaleList;
import android.util.ArraySet;
@@ -33,6 +34,8 @@ final class PackageConfigurationUpdaterImpl implements
private final Optional mPid;
private Integer mNightMode;
private LocaleList mLocales;
+ private @Configuration.GrammaticalGender
+ int mGrammaticalGender;
private String mPackageName;
private int mUserId;
private ActivityTaskManagerService mAtm;
@@ -67,6 +70,15 @@ final class PackageConfigurationUpdaterImpl implements
return this;
}
+ @Override
+ public ActivityTaskManagerInternal.PackageConfigurationUpdater setGrammaticalGender(
+ @Configuration.GrammaticalGender int gender) {
+ synchronized (this) {
+ mGrammaticalGender = gender;
+ }
+ return this;
+ }
+
@Override
public boolean commit() {
synchronized (this) {
@@ -112,12 +124,12 @@ final class PackageConfigurationUpdaterImpl implements
for (int i = processes.size() - 1; i >= 0; i--) {
final WindowProcessController wpc = processes.valueAt(i);
if (wpc.mInfo.packageName.equals(packageName)) {
- wpc.applyAppSpecificConfig(mNightMode, localesOverride);
+ wpc.applyAppSpecificConfig(mNightMode, localesOverride, mGrammaticalGender);
}
// Always inform individual activities about the update, since activities from other
// packages may be sharing this process
wpc.updateAppSpecificSettingsForAllActivitiesInPackage(packageName, mNightMode,
- localesOverride);
+ localesOverride, mGrammaticalGender);
}
}
@@ -128,4 +140,9 @@ final class PackageConfigurationUpdaterImpl implements
LocaleList getLocales() {
return mLocales;
}
+
+ @Configuration.GrammaticalGender
+ Integer getGrammaticalGender() {
+ return mGrammaticalGender;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index e9b81ec030817..f9670ccbed0a0 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -867,13 +867,13 @@ public class WindowProcessController extends ConfigurationContainer= 0; --i) {
final ActivityRecord r = mActivities.get(i);
// Activities from other packages could be sharing this process. Only propagate updates
// to those activities that are part of the package whose app-specific settings changed
if (packageName.equals(r.packageName)
- && r.applyAppSpecificConfig(nightMode, localesOverride)
+ && r.applyAppSpecificConfig(nightMode, localesOverride, gender)
&& r.isVisibleRequested()) {
r.ensureActivityConfiguration(0 /* globalChanges */, true /* preserveWindow */);
}