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

Commit 0434c2a8 authored by fayey's avatar fayey Committed by Winson Chiu
Browse files

Allow setting app op permissions to support

PackageInstaller.SessionParams#setPermisisonStates API.

This is the first part of the Permission & app op support of Fullscreen
Intent Protection that implements the actual grant/revocation of the FSI
permission/app op to back the new PackageInstaller#setPermissionStates
API.

Test: atest

Bug: 268092291
Change-Id: I8ff039a388796dc8cebf877f25e1f535aab6e006
parent c366288a
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -172,7 +172,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
    private static final int ADB_DEV_MODE = PackageManager.INSTALL_FROM_ADB
            | PackageManager.INSTALL_ALLOW_TEST;

    private static final Set<String> ALLOWED_PERMISSION_STATE_NAMES = Set.of(
    /**
     * Set of app op permissions that the installer of a session is allowed to change through
     * {@link PackageInstaller.SessionParams#setPermissionState(String, int)}.
     */
    public static final Set<String> INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS = Set.of(
            Manifest.permission.USE_FULL_SCREEN_INTENT
    );

@@ -809,7 +813,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
                if (!hasInstallGrantRuntimePermissions) {
                    for (int index = 0; index < permissionStates.size(); index++) {
                        var permissionName = permissionStates.keyAt(index);
                        if (!ALLOWED_PERMISSION_STATE_NAMES.contains(permissionName)) {
                        if (!INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS.contains(permissionName)) {
                            throw new SecurityException("You need the "
                                    + Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS
                                    + " permission to grant runtime permissions for a session");
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ import java.util.function.BiFunction;
 * Manages all permissions and handles permissions related tasks.
 */
public class PermissionManagerService extends IPermissionManager.Stub {

    private static final String LOG_TAG = PermissionManagerService.class.getSimpleName();

    /** Map of IBinder -> Running AttributionSource */
+35 −16
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_DEFAULT;
import static android.content.pm.PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED;
import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
import static android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED;
@@ -63,6 +67,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.compat.annotation.ChangeId;
@@ -70,7 +75,6 @@ import android.compat.annotation.EnabledAfter;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PermissionGroupInfo;
@@ -129,6 +133,7 @@ import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.pm.ApexManager;
import com.android.server.pm.KnownPackages;
import com.android.server.pm.PackageInstallerService;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
@@ -3633,8 +3638,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
        }
    }

    private void grantRequestedRuntimePermissionsInternal(@NonNull AndroidPackage pkg,
            @Nullable List<String> permissions, int userId) {
    private void grantRequestedPermissionsInternal(@NonNull AndroidPackage pkg,
            @Nullable ArrayMap<String, Integer> permissionStates, int userId) {
        final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
                | PackageManager.FLAG_PERMISSION_POLICY_FIXED;

@@ -3649,15 +3654,26 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
        final int myUid = Process.myUid();

        for (String permission : pkg.getRequestedPermissions()) {
            final boolean shouldGrantPermission;
            Integer permissionState = permissionStates.get(permission);
            if (permissionState == null || permissionState == PERMISSION_STATE_DEFAULT) {
                continue;
            }

            final boolean shouldGrantRuntimePermission;
            final boolean isAppOpPermission;
            synchronized (mLock) {
                final Permission bp = mRegistry.getPermission(permission);
                shouldGrantPermission = bp != null && (bp.isRuntime() || bp.isDevelopment())
                if (bp == null) {
                    continue;
                }
                shouldGrantRuntimePermission = (bp.isRuntime() || bp.isDevelopment())
                        && (!instantApp || bp.isInstant())
                        && (supportsRuntimePermissions || !bp.isRuntimeOnly())
                        && (permissions.contains(permission));
                        && permissionState == PERMISSION_STATE_GRANTED;
                isAppOpPermission = bp.isAppOp();
            }
            if (shouldGrantPermission) {

            if (shouldGrantRuntimePermission) {
                final int flags = getPermissionFlagsInternal(pkg.getPackageName(), permission,
                        myUid, userId);
                if (supportsRuntimePermissions) {
@@ -3674,6 +3690,17 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
                                0, myUid, userId, false, mDefaultPermissionCallback);
                    }
                }
            } else if (isAppOpPermission
                    && PackageInstallerService.INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS
                    .contains(permission)) {
                int mode =
                        permissionState == PERMISSION_STATE_GRANTED ? MODE_ALLOWED : MODE_ERRORED;
                int uid = UserHandle.getUid(userId, pkg.getUid());
                String appOp = AppOpsManager.permissionToOp(permission);
                mHandler.post(() -> {
                    AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
                    appOpsManager.setUidMode(appOp, uid, mode);
                });
            }
        }
    }
@@ -4991,15 +5018,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
            addAllowlistedRestrictedPermissionsInternal(pkg,
                    params.getAllowlistedRestrictedPermissions(),
                    FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
            var grantedPermissions = new ArrayList<String>();
            var permissionStates = params.getPermissionStates();
            for (int index = 0; index < permissionStates.size(); index++) {
                if (permissionStates.valueAt(index)
                        == PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED) {
                    grantedPermissions.add(permissionStates.keyAt(index));
                }
            }
            grantRequestedRuntimePermissionsInternal(pkg, grantedPermissions, userId);
            grantRequestedPermissionsInternal(pkg, params.getPermissionStates(), userId);
        }
    }

+7 −4
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import com.android.server.permission.access.util.hasAnyBit
import com.android.server.permission.access.util.hasBits
import com.android.server.permission.access.util.withClearedCallingIdentity
import com.android.server.pm.KnownPackages
import com.android.server.pm.PackageInstallerService
import com.android.server.pm.PackageManagerLocal
import com.android.server.pm.UserManagerInternal
import com.android.server.pm.UserManagerService
@@ -770,9 +771,11 @@ class PermissionService(
                            )
                        }
                    }
                    permission.isAppOp -> setAppOpPermissionGranted(
                        packageState, userId, permissionName,
                        permissionState == PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED
                    permission.isAppOp && permissionName in
                            PackageInstallerService.INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS ->
                        setAppOpPermissionGranted(
                            packageState, userId, permissionName, permissionState ==
                                    PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED
                        )
                    else -> {}
                }