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

Commit 07e48d4a authored by Zoey Chen's avatar Zoey Chen
Browse files

[ToA] Implement grammatical gender in GrammaticalInflectionService

Bug: 314887263
Test: manual
Change-Id: I3d57b61fdfd7869bcc36fa2a953ac8630369d394
parent 0297bd45
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ public class GrammaticalInflectionManager {
        }

        try {
            mService.setSystemWideGrammaticalGender(mContext.getUserId(), grammaticalGender);
            mService.setSystemWideGrammaticalGender(grammaticalGender, mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -131,7 +131,8 @@ public class GrammaticalInflectionManager {
    @Configuration.GrammaticalGender
    public int getSystemGrammaticalGender() {
        try {
            return mService.getSystemGrammaticalGender(mContext.getUserId());
            return mService.getSystemGrammaticalGender(mContext.getAttributionSource(),
                    mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+19 −2
Original line number Diff line number Diff line
/**
 * Copyright (C) 2024 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 android.app;

import android.content.AttributionSource;

/**
 * Internal interface used to control app-specific gender.
@@ -20,10 +37,10 @@ package android.app;
     /**
      * Sets the grammatical gender to system.
      */
     void setSystemWideGrammaticalGender(int userId, int gender);
     void setSystemWideGrammaticalGender(int gender, int userId);

     /**
      * Gets the grammatical gender from system.
      */
     int getSystemGrammaticalGender(int userId);
     int getSystemGrammaticalGender(in AttributionSource attributionSource, int userId);
 }
+10 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.grammaticalinflection;

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

/**
 * System-server internal interface to the {@link android.app.GrammaticalInflectionManager}.
@@ -37,5 +38,14 @@ public abstract class GrammaticalInflectionManagerInternal {
     * at the time this is called, to be referenced later when the app is installed.
     */
    public abstract void stageAndApplyRestoredPayload(byte[] payload, int userId);

    /**
     * Get the current system grammatical gender of privileged application.
     *
     * @return the value of grammatical gender
     *
     * @see Configuration#getGrammaticalGender
     */
    public abstract @Configuration.GrammaticalGender int getSystemGrammaticalGender(int userId);
}
+39 −9
Original line number Diff line number Diff line
@@ -19,9 +19,12 @@ 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;

import android.annotation.Nullable;
import android.app.GrammaticalInflectionManager;
import android.app.IGrammaticalInflectionManager;
import android.content.AttributionSource;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
import android.os.Binder;
@@ -30,6 +33,7 @@ import android.os.Process;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.SystemProperties;
import android.permission.PermissionManager;
import android.util.AtomicFile;
import android.util.Log;
import android.util.SparseIntArray;
@@ -75,6 +79,8 @@ public class GrammaticalInflectionService extends SystemService {

    private PackageManagerInternal mPackageManagerInternal;
    private GrammaticalInflectionService.GrammaticalInflectionBinderService mBinderService;
    private PermissionManager mPermissionManager;
    private Context mContext;

    /**
     * Initializes the system service.
@@ -88,11 +94,12 @@ public class GrammaticalInflectionService extends SystemService {
     */
    public GrammaticalInflectionService(Context context) {
        super(context);
        mContext = context;
        mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
        mBackupHelper = new GrammaticalInflectionBackupHelper(
                this, context.getPackageManager());
        mBackupHelper = new GrammaticalInflectionBackupHelper(this, context.getPackageManager());
        mBinderService = new GrammaticalInflectionBinderService();
        mPermissionManager = context.getSystemService(PermissionManager.class);
    }

    @Override
@@ -112,7 +119,7 @@ public class GrammaticalInflectionService extends SystemService {
        }

        @Override
        public void setSystemWideGrammaticalGender(int userId, int grammaticalGender) {
        public void setSystemWideGrammaticalGender(int grammaticalGender, int userId) {
            checkCallerIsSystem();
            checkSystemTermsOfAddressIsEnabled();
            GrammaticalInflectionService.this.setSystemWideGrammaticalGender(grammaticalGender,
@@ -120,16 +127,17 @@ public class GrammaticalInflectionService extends SystemService {
        }

        @Override
        public int getSystemGrammaticalGender(int userId) {
        public int getSystemGrammaticalGender(AttributionSource attributionSource, int userId) {
            checkSystemTermsOfAddressIsEnabled();
            return GrammaticalInflectionService.this.getSystemGrammaticalGender(userId);
            return GrammaticalInflectionService.this.getSystemGrammaticalGender(attributionSource,
                    userId);
        }

        @Override
        public void onShellCommand(FileDescriptor in, FileDescriptor out,
                FileDescriptor err, String[] args, ShellCallback callback,
                ResultReceiver resultReceiver) {
            (new GrammaticalInflectionShellCommand(mBinderService))
            (new GrammaticalInflectionShellCommand(mBinderService, mContext.getAttributionSource()))
                    .exec(this, in, out, err, args, callback, resultReceiver);
        }
    };
@@ -148,6 +156,13 @@ public class GrammaticalInflectionService extends SystemService {
        public void stageAndApplyRestoredPayload(byte[] payload, int userId) {
            mBackupHelper.stageAndApplyRestoredPayload(payload, userId);
        }

        @Override
        public int getSystemGrammaticalGender(int userId) {
            checkCallerIsSystem();
            return GrammaticalInflectionService.this.getSystemGrammaticalGender(
                    mContext.getAttributionSource(), userId);
        }
    }

    protected int getApplicationGrammaticalGender(String appPackageName, int userId) {
@@ -211,9 +226,24 @@ public class GrammaticalInflectionService extends SystemService {
        }
    }

    // TODO(b/298591009): Add a new AppOp value for the apps that want to access the grammatical
    //  gender.
    public int getSystemGrammaticalGender(int userId) {
    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;
        }

        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()) {
+46 −0
Original line number Diff line number Diff line
/**
 * Copyright (C) 2024 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.grammaticalinflection;

import static android.Manifest.permission.READ_SYSTEM_GRAMMATICAL_GENDER;

import android.annotation.NonNull;
import android.content.AttributionSource;
import android.permission.PermissionManager;
import android.util.Log;

/**
 * Utility methods for system grammatical gender.
 */
public class GrammaticalInflectionUtils {

    private static final String TAG = "GrammaticalInflectionUtils";

    public static boolean checkSystemGrammaticalGenderPermission(
            @NonNull PermissionManager permissionManager,
            @NonNull AttributionSource attributionSource) {
        int permissionCheckResult = permissionManager.checkPermissionForDataDelivery(
                READ_SYSTEM_GRAMMATICAL_GENDER,
                attributionSource, /* message= */ null);
        if (permissionCheckResult != PermissionManager.PERMISSION_GRANTED) {
            Log.v(TAG, "AttributionSource: " + attributionSource
                    + " does not have READ_SYSTEM_GRAMMATICAL_GENDER permission.");
            return false;
        }
        return true;
    }
}