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

Commit 97e0e6d0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add shell commands to grant and revoke access" into main

parents d02d4157 ab93aff6
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -26,26 +26,26 @@ import java.util.List;
 */
public interface AppFunctionAccessServiceInterface {

    /** check access */
    /** @see AppFunctionManager#checkAppFunctionAccess(String, String)  */
    boolean checkAppFunctionAccess(@NonNull String agentPackageName, int agentUserId,
            @NonNull String targetPackageName, int targetUserId);

    /** check access, but also informs if access is invalid */
    /** @see AppFunctionManager#getAppFunctionAccessRequestState(String, String)  */
    @AppFunctionManager.AppFunctionAccessState
    int getAppFunctionAccessRequestState(@NonNull String agentPackageName, int agentUserId,
            @NonNull String targetPackageName, int targetUserId);

    /** get flags for a given target and agent */
    /** @see AppFunctionManager#getAppFunctionAccessFlags(String, String)  */
    @AppFunctionManager.AppFunctionAccessFlags
    int getAppFunctionAccessFlags(@NonNull String agentPackageName, int agentUserId,
            @NonNull String targetPackageName, int targetUserId);

    /** update flags for a given target and agent */
    /** @see AppFunctionManager#updateAppFunctionAccessFlags(String, String, int, int)  */
    boolean updateAppFunctionAccessFlags(@NonNull String agentPackageName, int agentUserId,
            @NonNull String targetPackageName, int targetUserId,
            @AppFunctionManager.AppFunctionAccessFlags int flagMask,
            @AppFunctionManager.AppFunctionAccessFlags int flags) throws IllegalArgumentException;

    /** update the agent allowlist */
    /** Set the agent allowlist */
    void setAgentAllowlist(@NonNull List<SignedPackage> agentAllowlist);
}
+34 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.app.appfunctions.IExecuteAppFunctionCallback;
import android.os.ICancellationSignal;

import android.os.UserHandle;

import java.util.List;
/**
 * Defines the interface for apps to interact with the app function execution service
 * {@code AppFunctionManagerService} running in the system server process.
@@ -50,4 +52,36 @@ interface IAppFunctionManager {
        int enabledState,
        in IAppFunctionEnabledCallback callback
    );

    boolean checkAppFunctionAccess(
        in String agentPackageName,
        int agentUserId,
        in String targetPackageName,
        int targetUserId
    );

    int getAppFunctionAccessRequestState(
        in String agentPackageName,
        int agentUserId,
        in String targetPackageName,
        int targetUserId
    );

    int getAppFunctionAccessFlags(
        in String agentPackageName,
        int agentUserId,
        in String targetPackageName,
        int targetUserId
    );

    void updateAppFunctionAccessFlags(
        in String agentPackageName,
        int agentUserId,
        in String targetPackageName,
        int targetUserId,
        int flagMask,
        int flags
    );

    void revokeSelfAppFunctionAccess(in String targetPackageName);
}
+57 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.appfunctions;

import static android.app.appfunctions.AppFunctionManager.ACCESS_REQUEST_STATE_UNREQUESTABLE;
import static android.app.appfunctions.AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_METADATA_DB;
import static android.app.appfunctions.AppFunctionRuntimeMetadata.APP_FUNCTION_RUNTIME_NAMESPACE;

@@ -480,6 +481,62 @@ public class AppFunctionManagerServiceImpl extends IAppFunctionManager.Stub {
                });
    }

    @Override
    public boolean checkAppFunctionAccess(String agentPackageName, int agentUserId,
            String targetPackageName, int targetUserId) throws RemoteException {
        if (!accessCheckFlagsEnabled()) {
            return false;
        }
        return mAppFunctionAccessService.checkAppFunctionAccess(agentPackageName, agentUserId,
                targetPackageName, targetUserId);
    }

    @Override
    public int getAppFunctionAccessFlags(String agentPackageName, int agentUserId,
            String targetPackageName, int targetUserId) throws RemoteException {
        if (!accessCheckFlagsEnabled()) {
            return 0;
        }
        return mAppFunctionAccessService.getAppFunctionAccessFlags(agentPackageName, agentUserId,
                targetPackageName, targetUserId);
    }

    @Override
    public void updateAppFunctionAccessFlags(String agentPackageName, int agentUserId,
            String targetPackageName, int targetUserId, int flagMask, int flags)
            throws RemoteException {
        if (!accessCheckFlagsEnabled()) {
            return;
        }
        mAppFunctionAccessService.updateAppFunctionAccessFlags(agentPackageName, agentUserId,
                targetPackageName, targetUserId, flagMask, flags);
    }

    @Override
    public void revokeSelfAppFunctionAccess(String targetPackageName) {
        if (!accessCheckFlagsEnabled()) {
            return;
        }
        // TODO: Call mAppFunctionAccessService.revokeSelfAppFunctionAccess(targetPackageName)
        // when ag/33428645 is in.
    }

    @Override
    public int getAppFunctionAccessRequestState(String agentPackageName, int agentUserId,
            String targetPackageName, int targetUserId) throws RemoteException {
        if (!accessCheckFlagsEnabled()) {
            return ACCESS_REQUEST_STATE_UNREQUESTABLE;
        }

        return mAppFunctionAccessService.getAppFunctionAccessRequestState(agentPackageName,
                agentUserId, targetPackageName, targetUserId);
    }

    private boolean accessCheckFlagsEnabled() {
        return android.permission.flags.Flags.appFunctionAccessApiEnabled()
                && android.permission.flags.Flags.appFunctionAccessServiceEnabled();
    }

    private static void reportException(
            @NonNull IAppFunctionEnabledCallback callback, @NonNull Exception exception) {
        try {
+127 −1
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.server.appfunctions;

import static android.app.appfunctions.AppFunctionManager.ACCESS_FLAG_MASK_OTHER;
import static android.app.appfunctions.AppFunctionManager.ACCESS_FLAG_OTHER_DENIED;
import static android.app.appfunctions.AppFunctionManager.ACCESS_FLAG_OTHER_GRANTED;

import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.appfunctions.AppFunctionException;
@@ -48,7 +52,8 @@ import java.util.concurrent.TimeUnit;
/** Shell command implementation for the {@link AppFunctionManagerService}. */
public class AppFunctionManagerServiceShellCommand extends ShellCommand {

    @NonNull private final IAppFunctionManager mService;
    @NonNull
    private final IAppFunctionManager mService;

    AppFunctionManagerServiceShellCommand(@NonNull IAppFunctionManager service) {
        mService = Objects.requireNonNull(service);
@@ -85,6 +90,38 @@ public class AppFunctionManagerServiceShellCommand extends ShellCommand {
        pw.println(
                "    --user <USER_ID> (optional): The user ID under which to set the function state"
                        + ". Defaults to the current user.");

        pw.println();
        pw.println(
                "  grant-app-function-access --agent-package <AGENT_PACKAGE_NAME> "
                        + "--target-package <TARGET_PACKAGE_NAME> [--agent-user <USER_ID>] "
                        + "[--target-user <USER_ID>]");
        pw.println("    Grants an agent package access to an app's functions.");
        pw.println("    --agent-package <AGENT_PACKAGE_NAME>: The agent package to grant access.");
        pw.println("    --target-package <TARGET_PACKAGE_NAME>: The target package.");
        pw.println(
                "    --agent-user <USER_ID> (optional): The user ID for the agent package. "
                        + "Defaults to the current user.");
        pw.println(
                "    --target-user <USER_ID> (optional): The user ID for the target package. "
                        + "Defaults to the current user.");
        pw.println();
        pw.println(
                "  revoke-app-function-access --agent-package <AGENT_PACKAGE_NAME> "
                        + "--target-package <TARGET_PACKAGE_NAME> [--agent-user <USER_ID>] "
                        + "[--target-user <USER_ID>]");
        pw.println("    Revokes an agent package's access to an app's functions.");
        pw.println(
                "    --agent-package <AGENT_PACKAGE_NAME>: The agent package to revoke access "
                        + "from.");
        pw.println("    --target-package <TARGET_PACKAGE_NAME>: The target package.");
        pw.println(
                "    --agent-user <USER_ID> (optional): The user ID for the agent package. "
                        + "Defaults to the current user.");
        pw.println(
                "    --target-user <USER_ID> (optional): The user ID for the target package. "
                        + "Defaults to the current user.");

        pw.println();
    }

@@ -100,6 +137,10 @@ public class AppFunctionManagerServiceShellCommand extends ShellCommand {
                    return runExecuteAppFunction();
                case "set-enabled":
                    return runSetAppFunctionEnabled();
                case "grant-app-function-access":
                    return runGrantAppFunctionAccess();
                case "revoke-app-function-access":
                    return runRevokeAppFunctionAccess();
                default:
                    return handleDefaultCommands(cmd);
            }
@@ -371,6 +412,91 @@ public class AppFunctionManagerServiceShellCommand extends ShellCommand {
        return builder.build();
    }

    private int runGrantAppFunctionAccess() throws Exception {
        final PrintWriter pw = getOutPrintWriter();
        String agentPackage = null;
        String targetPackage = null;
        int agentUserId = ActivityManager.getCurrentUser();
        int targetUserId = ActivityManager.getCurrentUser();
        String opt;

        while ((opt = getNextOption()) != null) {
            switch (opt) {
                case "--agent-package":
                    agentPackage = getNextArgRequired();
                    break;
                case "--target-package":
                    targetPackage = getNextArgRequired();
                    break;
                case "--agent-user":
                    agentUserId = UserHandle.parseUserArg(getNextArgRequired());
                    break;
                case "--target-user":
                    targetUserId = UserHandle.parseUserArg(getNextArgRequired());
                    break;
                default:
                    pw.println("Unknown option: " + opt);
                    return -1;
            }
        }

        if (agentPackage == null) {
            pw.println("Error: --agent-package must be specified.");
            return -1;
        }
        if (targetPackage == null) {
            pw.println("Error: --target-package must be specified.");
            return -1;
        }

        mService.updateAppFunctionAccessFlags(agentPackage, agentUserId, targetPackage,
                targetUserId, ACCESS_FLAG_MASK_OTHER, ACCESS_FLAG_OTHER_GRANTED);
        pw.println("Access granted successfully.");
        return 0;
    }

    private int runRevokeAppFunctionAccess() throws Exception {
        final PrintWriter pw = getOutPrintWriter();
        String agentPackage = null;
        String targetPackage = null;
        int agentUserId = ActivityManager.getCurrentUser();
        int targetUserId = ActivityManager.getCurrentUser();
        String opt;

        while ((opt = getNextOption()) != null) {
            switch (opt) {
                case "--agent-package":
                    agentPackage = getNextArgRequired();
                    break;
                case "--target-package":
                    targetPackage = getNextArgRequired();
                    break;
                case "--agent-user":
                    agentUserId = UserHandle.parseUserArg(getNextArgRequired());
                    break;
                case "--target-user":
                    targetUserId = UserHandle.parseUserArg(getNextArgRequired());
                    break;
                default:
                    pw.println("Unknown option: " + opt);
                    return -1;
            }
        }

        if (agentPackage == null) {
            pw.println("Error: --agent-package must be specified.");
            return -1;
        }
        if (targetPackage == null) {
            pw.println("Error: --target-package must be specified.");
            return -1;
        }
        mService.updateAppFunctionAccessFlags(agentPackage, agentUserId, targetPackage,
                targetUserId, ACCESS_FLAG_MASK_OTHER, ACCESS_FLAG_OTHER_DENIED);
        pw.println("Access revoked successfully.");
        return 0;
    }

    private static String getCallingPackage() {
        return switch (Binder.getCallingUid()) {
            case Process.ROOT_UID -> "root";