[ToA] Implement grammatical gender in ActivityTaskManagerService and WindowProcessController
Bug: 314886712
Bug: 314886661
Test: manual + Presubmit
Test: atest GrammaticalInflectionManagerTest
Test: atest WmTests:ActivityStarterTests
Test: atest WmTests:WindowProcessControllerTests
Change-Id: Iccd16c83f0d9d04db68d12355de749955c3d002b
Unresolved-Comment-Reason: will fix the comments in the next CL
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index e99fcc9..84ef6e5 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -914,6 +914,9 @@
<!-- Permission required for Cts test ScreenRecordingCallbackTests -->
<uses-permission android:name="android.permission.DETECT_SCREEN_RECORDING" />
+ <!-- Permissions required for CTS test - GrammaticalInflectionManagerTest -->
+ <uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
+
<application
android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
index c260f10..6a6e6ab 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionManagerInternal.java
@@ -47,5 +47,19 @@
* @see Configuration#getGrammaticalGender
*/
public abstract @Configuration.GrammaticalGender int getSystemGrammaticalGender(int userId);
+
+ /**
+ * Retrieve the system grammatical gender.
+ *
+ * @return the value of grammatical gender
+ *
+ */
+ public abstract @Configuration.GrammaticalGender int retrieveSystemGrammaticalGender(
+ Configuration configuration);
+
+ /**
+ * Whether the package can get the system grammatical gender or not.
+ */
+ public abstract boolean canGetSystemGrammaticalGender(int uid, String packageName);
}
diff --git a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
index 6eb7e95..d01f54f 100644
--- a/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
+++ b/services/core/java/com/android/server/grammaticalinflection/GrammaticalInflectionService.java
@@ -22,17 +22,21 @@
import static com.android.server.grammaticalinflection.GrammaticalInflectionUtils.checkSystemGrammaticalGenderPermission;
import android.annotation.Nullable;
+import android.app.ActivityTaskManager;
import android.app.GrammaticalInflectionManager;
import android.app.IGrammaticalInflectionManager;
import android.content.AttributionSource;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
+import android.content.res.Configuration;
import android.os.Binder;
import android.os.Environment;
import android.os.Process;
+import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.SystemProperties;
+import android.os.Trace;
import android.permission.PermissionManager;
import android.util.AtomicFile;
import android.util.Log;
@@ -43,6 +47,7 @@
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -71,6 +76,7 @@
private static final String TAG_GRAMMATICAL_INFLECTION = "grammatical_inflection";
private static final String GRAMMATICAL_INFLECTION_ENABLED =
"i18n.grammatical_Inflection.enabled";
+ private static final String GRAMMATICAL_GENDER_PROPERTY = "persist.sys.grammatical_gender";
private final GrammaticalInflectionBackupHelper mBackupHelper;
private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
@@ -121,16 +127,16 @@
@Override
public void setSystemWideGrammaticalGender(int grammaticalGender, int userId) {
checkCallerIsSystem();
- checkSystemTermsOfAddressIsEnabled();
GrammaticalInflectionService.this.setSystemWideGrammaticalGender(grammaticalGender,
userId);
}
@Override
public int getSystemGrammaticalGender(AttributionSource attributionSource, int userId) {
- checkSystemTermsOfAddressIsEnabled();
- return GrammaticalInflectionService.this.getSystemGrammaticalGender(attributionSource,
- userId);
+ return canGetSystemGrammaticalGender(attributionSource)
+ ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
+ attributionSource, userId)
+ : GRAMMATICAL_GENDER_NOT_SPECIFIED;
}
@Override
@@ -159,9 +165,33 @@
@Override
public int getSystemGrammaticalGender(int userId) {
- checkCallerIsSystem();
- return GrammaticalInflectionService.this.getSystemGrammaticalGender(
- mContext.getAttributionSource(), userId);
+ return checkSystemTermsOfAddressIsEnabled()
+ ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
+ mContext.getAttributionSource(), userId)
+ : GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ }
+
+ @Override
+ public int retrieveSystemGrammaticalGender(Configuration configuration) {
+ int systemGrammaticalGender = getSystemGrammaticalGender(mContext.getUserId());
+ // Retrieve the grammatical gender from system property, set it into
+ // configuration which will get updated later if the grammatical gender raw value of
+ // current configuration is {@link Configuration#GRAMMATICAL_GENDER_UNDEFINED}.
+ if (configuration.getGrammaticalGenderRaw()
+ == Configuration.GRAMMATICAL_GENDER_UNDEFINED
+ || systemGrammaticalGender <= Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+ systemGrammaticalGender = SystemProperties.getInt(GRAMMATICAL_GENDER_PROPERTY,
+ Configuration.GRAMMATICAL_GENDER_UNDEFINED);
+ }
+ return systemGrammaticalGender;
+ }
+
+ @Override
+ public boolean canGetSystemGrammaticalGender(int uid, String packageName) {
+ AttributionSource attributionSource = new AttributionSource.Builder(
+ uid).setPackageName(packageName).build();
+ return GrammaticalInflectionService.this.canGetSystemGrammaticalGender(
+ attributionSource);
}
}
@@ -202,11 +232,20 @@
}
protected void setSystemWideGrammaticalGender(int grammaticalGender, int userId) {
+ Trace.beginSection("GrammaticalInflectionService.setSystemWideGrammaticalGender");
if (!GrammaticalInflectionManager.VALID_GRAMMATICAL_GENDER_VALUES.contains(
grammaticalGender)) {
throw new IllegalArgumentException("Unknown grammatical gender");
}
+ if (!checkSystemTermsOfAddressIsEnabled()) {
+ if (grammaticalGender == GRAMMATICAL_GENDER_NOT_SPECIFIED) {
+ return;
+ }
+ Log.d(TAG, "Clearing the system grammatical gender setting");
+ grammaticalGender = GRAMMATICAL_GENDER_NOT_SPECIFIED;
+ }
+
synchronized (mLock) {
final File file = getGrammaticalGenderFile(userId);
final AtomicFile atomicFile = new AtomicFile(file);
@@ -224,6 +263,15 @@
throw new RuntimeException(e);
}
}
+
+ try {
+ Configuration config = new Configuration();
+ config.setGrammaticalGender(grammaticalGender);
+ ActivityTaskManager.getService().updateConfiguration(config);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Can not update configuration", e);
+ }
+ Trace.endSection();
}
public int getSystemGrammaticalGender(AttributionSource attributionSource, int userId) {
@@ -233,34 +281,9 @@
return GRAMMATICAL_GENDER_NOT_SPECIFIED;
}
- int callingUid = Binder.getCallingUid();
- if (mPackageManagerInternal.getPackageUid(packageName, 0, userId) != callingUid) {
- Log.d(TAG,
- "Package " + packageName + " does not belong to the calling uid " + callingUid);
- return GRAMMATICAL_GENDER_NOT_SPECIFIED;
- }
-
- if (!checkSystemGrammaticalGenderPermission(mPermissionManager, attributionSource)) {
- return GRAMMATICAL_GENDER_NOT_SPECIFIED;
- }
-
synchronized (mLock) {
- final File file = getGrammaticalGenderFile(userId);
- if (!file.exists()) {
- Log.d(TAG, "User " + userId + "doesn't have the grammatical gender file.");
- return GRAMMATICAL_GENDER_NOT_SPECIFIED;
- }
-
- if (mGrammaticalGenderCache.indexOfKey(userId) < 0) {
- try {
- InputStream in = new FileInputStream(file);
- final TypedXmlPullParser parser = Xml.resolvePullParser(in);
- mGrammaticalGenderCache.put(userId, getGrammaticalGenderFromXml(parser));
- } catch (IOException | XmlPullParserException e) {
- Log.e(TAG, "Failed to parse XML configuration from " + file, e);
- }
- }
- return mGrammaticalGenderCache.get(userId);
+ int grammaticalGender = mGrammaticalGenderCache.get(userId);
+ return grammaticalGender < 0 ? GRAMMATICAL_GENDER_NOT_SPECIFIED : grammaticalGender;
}
}
@@ -311,9 +334,39 @@
}
}
- private void checkSystemTermsOfAddressIsEnabled() {
+ private boolean checkSystemTermsOfAddressIsEnabled() {
if (!systemTermsOfAddressEnabled()) {
- throw new RuntimeException("The flag must be enabled to allow calling the API.");
+ Log.d(TAG, "The flag must be enabled to allow calling the API.");
+ return false;
}
+ return true;
+ }
+
+ private boolean canGetSystemGrammaticalGender(AttributionSource attributionSource) {
+ return checkSystemTermsOfAddressIsEnabled() && checkSystemGrammaticalGenderPermission(
+ mPermissionManager, attributionSource);
+ }
+
+ @Override
+ public void onUserUnlocked(TargetUser user) {
+ IoThread.getHandler().post(() -> {
+ int userId = user.getUserIdentifier();
+ final File file = getGrammaticalGenderFile(userId);
+ synchronized (mLock) {
+ if (!file.exists()) {
+ Log.d(TAG, "User " + userId + "doesn't have the grammatical gender file.");
+ return;
+ }
+ if (mGrammaticalGenderCache.indexOfKey(userId) < 0) {
+ try {
+ InputStream in = new FileInputStream(file);
+ final TypedXmlPullParser parser = Xml.resolvePullParser(in);
+ mGrammaticalGenderCache.put(userId, getGrammaticalGenderFromXml(parser));
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Failed to parse XML configuration from " + file, e);
+ }
+ }
+ }
+ });
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 0def5a1..8773366 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -276,6 +276,7 @@
import com.android.server.am.PendingIntentRecord;
import com.android.server.am.UserState;
import com.android.server.firewall.IntentFirewall;
+import com.android.server.grammaticalinflection.GrammaticalInflectionManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.sdksandbox.SdkSandboxManagerLocal;
@@ -317,7 +318,6 @@
* {@hide}
*/
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
- private static final String GRAMMATICAL_GENDER_PROPERTY = "persist.sys.grammatical_gender";
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_ATM;
static final String TAG_ROOT_TASK = TAG + POSTFIX_ROOT_TASK;
static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
@@ -381,6 +381,7 @@
private PowerManagerInternal mPowerManagerInternal;
private UsageStatsManagerInternal mUsageStatsInternal;
+ GrammaticalInflectionManagerInternal mGrammaticalManagerInternal;
PendingIntentController mPendingIntentController;
IntentFirewall mIntentFirewall;
@@ -881,6 +882,8 @@
mActivityClientController.onSystemReady();
// TODO(b/258792202) Cleanup once ASM is ready to launch
ActivitySecurityModelFeatureFlags.initialize(mContext.getMainExecutor(), pm);
+ mGrammaticalManagerInternal = LocalServices.getService(
+ GrammaticalInflectionManagerInternal.class);
}
}
@@ -938,13 +941,8 @@
configuration.setLayoutDirection(configuration.locale);
}
- // Retrieve the grammatical gender from system property, set it into configuration which
- // will get updated later if the grammatical gender raw value of current configuration is
- // {@link Configuration#GRAMMATICAL_GENDER_UNDEFINED}.
- if (configuration.getGrammaticalGenderRaw() == Configuration.GRAMMATICAL_GENDER_UNDEFINED) {
- configuration.setGrammaticalGender(SystemProperties.getInt(GRAMMATICAL_GENDER_PROPERTY,
- Configuration.GRAMMATICAL_GENDER_UNDEFINED));
- }
+ configuration.setGrammaticalGender(
+ mGrammaticalManagerInternal.retrieveSystemGrammaticalGender(configuration));
synchronized (mGlobalLock) {
mForceResizableActivities = forceResizable;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 6d2e8cc..6acf1f3 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -28,6 +28,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.server.am.ProcessList.INVALID_ADJ;
+import static com.android.server.grammaticalinflection.GrammaticalInflectionUtils.checkSystemGrammaticalGenderPermission;
import static com.android.server.wm.ActivityRecord.State.DESTROYED;
import static com.android.server.wm.ActivityRecord.State.DESTROYING;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
@@ -298,6 +299,8 @@
*/
private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
+ private boolean mCanUseSystemGrammaticalGender;
+
public WindowProcessController(@NonNull ActivityTaskManagerService atm,
@NonNull ApplicationInfo info, String name, int uid, int userId, Object owner,
@NonNull WindowProcessListener listener) {
@@ -319,6 +322,9 @@
mIsActivityConfigOverrideAllowed = false;
}
+ mCanUseSystemGrammaticalGender = mAtm.mGrammaticalManagerInternal != null
+ && mAtm.mGrammaticalManagerInternal.canGetSystemGrammaticalGender(mUid,
+ mInfo.packageName);
onConfigurationChanged(atm.getGlobalConfiguration());
mAtm.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, mInfo.packageName);
}
@@ -1568,6 +1574,11 @@
return;
}
+ if (mCanUseSystemGrammaticalGender) {
+ config.setGrammaticalGender(
+ mAtm.mGrammaticalManagerInternal.getSystemGrammaticalGender(mUserId));
+ }
+
if (mPauseConfigurationDispatchCount > 0) {
mHasPendingConfigurationChange = true;
return;