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

Commit 78a7610a authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi Committed by Android (Google) Code Review
Browse files

Merge "Fix the system gender in ActivityRecord objects" into main

parents 72c37464 7e512858
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -123,8 +123,7 @@ public class GrammaticalInflectionBackupHelper {
     * Returns the system-gender to be backed up as a data-blob.
     */
    public byte[] getSystemBackupPayload(int userId) {
        int gender = mGrammaticalGenderService.getSystemGrammaticalGender(mAttributionSource,
                userId);
        int gender = mGrammaticalGenderService.getSystemGrammaticalGender(userId);
        return intToByteArray(gender);
    }

@@ -167,7 +166,7 @@ public class GrammaticalInflectionBackupHelper {
        BackupManager.dataChanged(SYSTEM_BACKUP_PACKAGE_KEY);
    }

    private byte[] convertToByteArray(HashMap<String, Integer> pkgGenderInfo) {
    private static byte[] convertToByteArray(HashMap<String, Integer> pkgGenderInfo) {
        try (final ByteArrayOutputStream out = new ByteArrayOutputStream();
             final ObjectOutputStream objStream = new ObjectOutputStream(out)) {
            objStream.writeObject(pkgGenderInfo);
@@ -178,22 +177,22 @@ public class GrammaticalInflectionBackupHelper {
        }
    }

    private byte[] intToByteArray(final int gender) {
    private static byte[] intToByteArray(final int gender) {
        ByteBuffer bb = ByteBuffer.allocate(4);
        bb.putInt(gender);
        return bb.array();
    }

    private int convertByteArrayToInt(byte[] intBytes) {
    private static int convertByteArrayToInt(byte[] intBytes) {
        ByteBuffer byteBuffer = ByteBuffer.wrap(intBytes);
        return byteBuffer.getInt();
    }

    private HashMap<String, Integer> readFromByteArray(byte[] payload) {
    private static HashMap<String, Integer> readFromByteArray(byte[] payload) {
        HashMap<String, Integer> data = new HashMap<>();

        try (ByteArrayInputStream byteIn = new ByteArrayInputStream(payload);
             ObjectInputStream in = new ObjectInputStream(byteIn)) {
        try (var byteIn = new ByteArrayInputStream(payload);
                var in = new ObjectInputStream(byteIn)) {
            data = (HashMap<String, Integer>) in.readObject();
        } catch (IOException | ClassNotFoundException e) {
            Log.e(TAG, "cannot convert payload to HashMap.", e);
@@ -205,10 +204,10 @@ public class GrammaticalInflectionBackupHelper {
    private void cleanStagedDataForOldEntries() {
        for (int i = 0; i < mCache.size(); i++) {
            int userId = mCache.keyAt(i);
            StagedData stagedData = mCache.get(userId);
            StagedData stagedData = mCache.valueAt(userId);
            if (stagedData.mCreationTimeMillis
                    < mClock.millis() - STAGE_DATA_RETENTION_PERIOD.toMillis()) {
                mCache.remove(userId);
                mCache.removeAt(i--);
            }
        }
    }
+12 −7
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.server.grammaticalinflection;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Configuration;

@@ -41,7 +40,7 @@ public abstract class GrammaticalInflectionManagerInternal {
    public abstract void stageAndApplyRestoredPayload(byte[] payload, int userId);

    /**
     * Get the current system grammatical gender of privileged application.
     * Get the current system grammatical gender for the particular user.
     *
     * @return the value of grammatical gender
     *
@@ -50,18 +49,25 @@ public abstract class GrammaticalInflectionManagerInternal {
    public abstract @Configuration.GrammaticalGender int getSystemGrammaticalGender(int userId);

    /**
     * Retrieve the system grammatical gender.
     * Get the final merged value of the global grammatical gender, user- or devsettings-set.
     *
     * @return the value of grammatical gender
     *
     */
    public abstract @Configuration.GrammaticalGender int retrieveSystemGrammaticalGender(
            @NonNull Configuration configuration);
    public abstract @Configuration.GrammaticalGender int mergedFinalSystemGrammaticalGender();

    /**
     * Get the grammatical gender from developer settings global override.
     *
     * @return the value of grammatical gender
     */
    public abstract
            @Configuration.GrammaticalGender int getGrammaticalGenderFromDeveloperSettings();

    /**
     * Whether the package can get the system grammatical gender or not.
     */
    public abstract boolean canGetSystemGrammaticalGender(int uid, @Nullable String packageName);
    public abstract boolean canGetSystemGrammaticalGender(int uid);


    /**
@@ -74,4 +80,3 @@ public abstract class GrammaticalInflectionManagerInternal {
     */
    public abstract void applyRestoredSystemPayload(byte[] payload, int userId);
}
+100 −99
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.server.grammaticalinflection;

import static android.app.Flags.systemTermsOfAddressEnabled;
import static android.content.res.Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;

import static com.android.server.grammaticalinflection.GrammaticalInflectionUtils.checkSystemGrammaticalGenderPermission;

@@ -43,6 +42,7 @@ import android.util.Log;
import android.util.SparseIntArray;
import android.util.Xml;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.TypedXmlPullParser;
@@ -126,7 +126,7 @@ public class GrammaticalInflectionService extends SystemService {

        @Override
        public void setSystemWideGrammaticalGender(int grammaticalGender, int userId) {
            isCallerAllowed();
            enforceCallerPermissions();
            GrammaticalInflectionService.this.setSystemWideGrammaticalGender(grammaticalGender,
                    userId);
        }
@@ -138,18 +138,16 @@ public class GrammaticalInflectionService extends SystemService {
                        + " does not have READ_SYSTEM_GRAMMATICAL_GENDER permission.");
            }
            return checkSystemTermsOfAddressIsEnabled()
                    ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
                    attributionSource, userId)
                    : GRAMMATICAL_GENDER_NOT_SPECIFIED;
                    ? GrammaticalInflectionService.this.getSystemGrammaticalGender(userId)
                    : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
        }

        @Override
        public int peekSystemGrammaticalGenderByUserId(AttributionSource attributionSource,
                int userId) {
            return canGetSystemGrammaticalGender(attributionSource)
                    ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
                    attributionSource, userId)
                    : GRAMMATICAL_GENDER_NOT_SPECIFIED;
                    ? GrammaticalInflectionService.this.getSystemGrammaticalGender(userId)
                    : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
        }

        @Override
@@ -163,11 +161,10 @@ public class GrammaticalInflectionService extends SystemService {

    private final class GrammaticalInflectionManagerInternalImpl
            extends GrammaticalInflectionManagerInternal {

        @Override
        @Nullable
        public byte[] getBackupPayload(int userId) {
            isCallerAllowed();
            enforceCallerPermissions();
            return mBackupHelper.getBackupPayload(userId);
        }

@@ -179,7 +176,7 @@ public class GrammaticalInflectionService extends SystemService {
        @Override
        @Nullable
        public byte[] getSystemBackupPayload(int userId) {
            isCallerAllowed();
            enforceCallerPermissions();
            return mBackupHelper.getSystemBackupPayload(userId);
        }

@@ -191,30 +188,35 @@ public class GrammaticalInflectionService extends SystemService {
        @Override
        public int getSystemGrammaticalGender(int userId) {
            return checkSystemTermsOfAddressIsEnabled()
                    ? GrammaticalInflectionService.this.getSystemGrammaticalGender(
                    mContext.getAttributionSource(), userId)
                    : GRAMMATICAL_GENDER_NOT_SPECIFIED;
                    ? GrammaticalInflectionService.this.getSystemGrammaticalGender(userId)
                    : Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
        }

        @Override
        public int retrieveSystemGrammaticalGender(Configuration configuration) {
        public int mergedFinalSystemGrammaticalGender() {
            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);
            if (systemGrammaticalGender == Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
                systemGrammaticalGender = getGrammaticalGenderFromDeveloperSettings();
            }
            return systemGrammaticalGender;
            return systemGrammaticalGender == Configuration.GRAMMATICAL_GENDER_UNDEFINED
                    ? Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED : systemGrammaticalGender;
        }

        @Override
        public boolean canGetSystemGrammaticalGender(int uid, String packageName) {
            AttributionSource attributionSource = new AttributionSource.Builder(
                    uid).setPackageName(packageName).build();
        public int getGrammaticalGenderFromDeveloperSettings() {
            return SystemProperties.getInt(GRAMMATICAL_GENDER_PROPERTY,
                    Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);
        }

        @Override
        public boolean canGetSystemGrammaticalGender(int uid) {
            if (uid == Process.SYSTEM_UID) {
                return true;
            }
            var attributionSource = new AttributionSource.Builder(uid).build();
            return GrammaticalInflectionService.this.canGetSystemGrammaticalGender(
                    attributionSource);
        }
@@ -225,7 +227,7 @@ public class GrammaticalInflectionService extends SystemService {
                mActivityTaskManagerInternal.getApplicationConfig(appPackageName, userId);

        if (appConfig == null || appConfig.mGrammaticalGender == null) {
            return GRAMMATICAL_GENDER_NOT_SPECIFIED;
            return Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
        } else {
            return appConfig.mGrammaticalGender;
        }
@@ -239,9 +241,10 @@ public class GrammaticalInflectionService extends SystemService {
                        userId);

        if (!SystemProperties.getBoolean(GRAMMATICAL_INFLECTION_ENABLED, true)) {
            if (preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED) {
            if (preValue != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED) {
                Log.d(TAG, "Clearing the user's grammatical gender setting");
                updater.setGrammaticalGender(GRAMMATICAL_GENDER_NOT_SPECIFIED).commit();
                updater.setGrammaticalGender(
                        Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED).commit();
            }
            return;
        }
@@ -250,29 +253,26 @@ public class GrammaticalInflectionService extends SystemService {
        FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_GRAMMATICAL_INFLECTION_CHANGED,
                FrameworkStatsLog.APPLICATION_GRAMMATICAL_INFLECTION_CHANGED__SOURCE_ID__OTHERS,
                uid,
                gender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
                preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED);
                gender != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED,
                preValue != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);

        updater.setGrammaticalGender(gender).commit();
    }

    protected void setSystemWideGrammaticalGender(int grammaticalGender, int userId) {
        try {
            if (!checkSystemTermsOfAddressIsEnabled()) {
                return; // Nothing to do, and the flag can't get flipped at the runtime.
            }

            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);
            synchronized (mLock) {
                final AtomicFile atomicFile = new AtomicFile(file);
                FileOutputStream stream = null;
                try {
@@ -289,10 +289,12 @@ public class GrammaticalInflectionService extends SystemService {
                }
            }
            updateConfiguration(grammaticalGender, userId);
        } finally {
            Trace.endSection();
        }
    }

    private void updateConfiguration(int grammaticalGender, int userId) {
    private static void updateConfiguration(int grammaticalGender, int userId) {
        try {
            Configuration config = new Configuration();
            int preValue = config.getGrammaticalGender();
@@ -301,37 +303,35 @@ public class GrammaticalInflectionService extends SystemService {
            FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_GRAMMATICAL_INFLECTION_CHANGED,
                    FrameworkStatsLog.SYSTEM_GRAMMATICAL_INFLECTION_CHANGED__SOURCE_ID__SYSTEM,
                    userId,
                    grammaticalGender != GRAMMATICAL_GENDER_NOT_SPECIFIED,
                    preValue != GRAMMATICAL_GENDER_NOT_SPECIFIED);
                    grammaticalGender != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED,
                    preValue != Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);
            GrammaticalInflectionBackupHelper.notifyBackupManager();
        } catch (RemoteException e) {
            Log.w(TAG, "Can not update configuration", e);
        }
    }

    public int getSystemGrammaticalGender(AttributionSource attributionSource, int userId) {
        String packageName = attributionSource.getPackageName();
        if (packageName == null) {
            Log.d(TAG, "Package name is null.");
            return GRAMMATICAL_GENDER_NOT_SPECIFIED;
        }

    /**
     * Returns the system global grammatical gender value for the requested user.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
    public int getSystemGrammaticalGender(int userId) {
        synchronized (mLock) {
            int grammaticalGender = mGrammaticalGenderCache.get(userId);
            return grammaticalGender < 0 ? GRAMMATICAL_GENDER_NOT_SPECIFIED : grammaticalGender;
            return grammaticalGender < 0
                    ? Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED : grammaticalGender;
        }
    }

    private File getGrammaticalGenderFile(int userId) {
    private static File getGrammaticalGenderFile(int userId) {
        final File dir = new File(Environment.getDataSystemCeDirectory(userId),
                TAG_GRAMMATICAL_INFLECTION);
        return new File(dir, USER_SETTINGS_FILE_NAME);
    }

    private byte[] toXmlByteArray(int grammaticalGender, FileOutputStream fileStream) {

        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    private static byte[] toXmlByteArray(int grammaticalGender, FileOutputStream fileStream)
            throws IOException {
        var outputStream = new ByteArrayOutputStream();
        TypedXmlSerializer out = Xml.resolveSerializer(fileStream);
        out.setOutput(outputStream, StandardCharsets.UTF_8.name());
        out.startDocument(/* encoding= */ null, /* standalone= */ true);
@@ -339,16 +339,11 @@ public class GrammaticalInflectionService extends SystemService {
        out.attributeInt(null, ATTR_NAME, grammaticalGender);
        out.endTag(null, TAG_GRAMMATICAL_INFLECTION);
        out.endDocument();

        return outputStream.toByteArray();
        } catch (IOException e) {
            return null;
        }
    }

    private int getGrammaticalGenderFromXml(TypedXmlPullParser parser)
    private static int getGrammaticalGenderFromXml(TypedXmlPullParser parser)
            throws IOException, XmlPullParserException {

        XmlUtils.nextElement(parser);
        while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
            String tagName = parser.getName();
@@ -359,20 +354,20 @@ public class GrammaticalInflectionService extends SystemService {
            }
        }

        return GRAMMATICAL_GENDER_NOT_SPECIFIED;
        return Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
    }

    private void isCallerAllowed() {
    private void enforceCallerPermissions() {
        int callingUid = Binder.getCallingUid();
        if (callingUid != Process.SYSTEM_UID && callingUid != Process.SHELL_UID
                && callingUid != Process.ROOT_UID) {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.CHANGE_CONFIGURATION,
                    "Caller must be system, shell, root or has CHANGE_CONFIGURATION permission.");
                    "Caller must be system, shell, root or hold CHANGE_CONFIGURATION permission.");
        }
    }

    private boolean checkSystemTermsOfAddressIsEnabled() {
    private static boolean checkSystemTermsOfAddressIsEnabled() {
        if (!systemTermsOfAddressEnabled()) {
            Log.d(TAG, "The flag must be enabled to allow calling the API.");
            return false;
@@ -387,25 +382,31 @@ public class GrammaticalInflectionService extends SystemService {

    @Override
    public void onUserUnlocked(TargetUser user) {
        if (!checkSystemTermsOfAddressIsEnabled()) {
            return;
        }
        IoThread.getHandler().post(() -> {
            int userId = user.getUserIdentifier();
            final int userId = user.getUserIdentifier();
            final File file = getGrammaticalGenderFile(userId);
            final int grammaticalGender;
            synchronized (mLock) {
                if (!file.exists()) {
                    Log.d(TAG, "User " + userId + " doesn't have the grammatical gender file.");
                    return;
                }
                if (mGrammaticalGenderCache.indexOfKey(userId) < 0) {
                if (mGrammaticalGenderCache.indexOfKey(userId) >= 0) {
                    return;
                }
                try (FileInputStream in = new FileInputStream(file)) {
                    final TypedXmlPullParser parser = Xml.resolvePullParser(in);
                        int grammaticalGender = getGrammaticalGenderFromXml(parser);
                    grammaticalGender = getGrammaticalGenderFromXml(parser);
                    mGrammaticalGenderCache.put(userId, grammaticalGender);
                        updateConfiguration(grammaticalGender, userId);
                } catch (IOException | XmlPullParserException e) {
                    Log.e(TAG, "Failed to parse XML configuration from " + file, e);
                    return;
                }
            }
            }
            updateConfiguration(grammaticalGender, userId);
        });
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -9492,6 +9492,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return false;
    }
    @Override
    protected boolean setOverrideGender(Configuration requestsTmpConfig, int gender) {
        return WindowProcessController.applyConfigGenderOverride(
                requestsTmpConfig, gender, mAtmService.mGrammaticalManagerInternal, getUid());
    }
    @VisibleForTesting
    @Override
    Rect getAnimationBounds(int appRootTaskClipMode) {
+1 −1
Original line number Diff line number Diff line
@@ -949,7 +949,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        }

        configuration.setGrammaticalGender(
                mGrammaticalManagerInternal.retrieveSystemGrammaticalGender(configuration));
                mGrammaticalManagerInternal.mergedFinalSystemGrammaticalGender());

        synchronized (mGlobalLock) {
            mForceResizableActivities = forceResizable;
Loading