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

Commit d83d6328 authored by Nate Myren's avatar Nate Myren
Browse files

Add AppFunctionManager APIs regarding AppFunction access

Bug: 413093397
Test: atest AppFunctionAccessTest
Flag: android.permission.flags.app_function_access_api_enabled

Change-Id: I53ff9570b265ee8163e3f27c2b71c1e22f47fed8
parent f282cd7e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9093,8 +9093,10 @@ package android.app.appfunctions {
  @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager {
    method @RequiresPermission(value=android.Manifest.permission.EXECUTE_APP_FUNCTIONS, conditional=true) public void executeAppFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.concurrent.Executor, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.app.appfunctions.ExecuteAppFunctionResponse,android.app.appfunctions.AppFunctionException>);
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") public int getSelfAppFunctionAccessRequestState(@NonNull String);
    method @RequiresPermission(value=android.Manifest.permission.EXECUTE_APP_FUNCTIONS, conditional=true) public void isAppFunctionEnabled(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,java.lang.Exception>);
    method public void isAppFunctionEnabled(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,java.lang.Exception>);
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") public void revokeSelfAppFunctionAccess(@NonNull String);
    method public void setAppFunctionEnabled(@NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,java.lang.Exception>);
    field @FlaggedApi("android.permission.flags.app_function_access_api_enabled") public static final int ACCESS_REQUEST_STATE_DENIED = 1; // 0x1
    field @FlaggedApi("android.permission.flags.app_function_access_api_enabled") public static final int ACCESS_REQUEST_STATE_GRANTED = 0; // 0x0
+5 −0
Original line number Diff line number Diff line
@@ -1771,6 +1771,11 @@ package android.app.ambientcontext {
package android.app.appfunctions {
  @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager {
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public int getAppFunctionAccessFlags(@NonNull String, @NonNull String);
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @RequiresPermission(value=android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS, conditional=true) public int getAppFunctionAccessRequestState(@NonNull String, @NonNull String);
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public java.util.List<java.lang.String> getValidAgents();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public java.util.List<java.lang.String> getValidTargets();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public void updateAppFunctionAccessFlags(@NonNull String, @NonNull String, int, int);
    field @FlaggedApi("android.permission.flags.app_function_access_api_enabled") public static final int ACCESS_FLAG_OTHER_DENIED = 4; // 0x4
    field @FlaggedApi("android.permission.flags.app_function_access_api_enabled") public static final int ACCESS_FLAG_OTHER_GRANTED = 2; // 0x2
    field @FlaggedApi("android.permission.flags.app_function_access_api_enabled") public static final int ACCESS_FLAG_PREGRANTED = 1; // 0x1
+10 −0
Original line number Diff line number Diff line
@@ -769,6 +769,16 @@ package android.app.admin {

}

package android.app.appfunctions {

  @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager {
    field public static final int ACCESS_FLAG_MASK_ALL = 31; // 0x1f
    field public static final int ACCESS_FLAG_MASK_OTHER = 6; // 0x6
    field public static final int ACCESS_FLAG_MASK_USER = 24; // 0x18
  }

}

package android.app.assist {

  public final class ActivityId implements android.os.Parcelable {
+11 −4
Original line number Diff line number Diff line
@@ -26,10 +26,6 @@ import java.util.List;
 */
public interface AppFunctionAccessServiceInterface {

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

    /** @see AppFunctionManager#getAppFunctionAccessRequestState(String, String)  */
    @AppFunctionManager.AppFunctionAccessState
    int getAppFunctionAccessRequestState(@NonNull String agentPackageName, int agentUserId,
@@ -46,6 +42,17 @@ public interface AppFunctionAccessServiceInterface {
            @AppFunctionManager.AppFunctionAccessFlags int flagMask,
            @AppFunctionManager.AppFunctionAccessFlags int flags) throws IllegalArgumentException;

    /** @see AppFunctionManager#revokeSelfAppFunctionAccess(String) */
    void revokeSelfAppFunctionAccess(@NonNull String targetPackageName);

    /** Set the agent allowlist */
    void setAgentAllowlist(@NonNull List<SignedPackage> agentAllowlist);

    /** @see AppFunctionManager#getValidAgents() */
    @NonNull
    List<String> getValidAgents(int userId);

    /** @see AppFunctionManager#getValidTargets(String) () */
    @NonNull
    List<String> getValidTargets(int userId);
}
+152 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.app.appfunctions;

import static android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS;
import static android.app.appfunctions.AppFunctionException.ERROR_SYSTEM_ERROR;
import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER;
import static android.permission.flags.Flags.FLAG_APP_FUNCTION_ACCESS_UI_ENABLED;
@@ -29,6 +30,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserHandleAware;
import android.app.appfunctions.AppFunctionManagerHelper.AppFunctionNotFoundException;
import android.app.appsearch.AppSearchManager;
@@ -43,6 +45,7 @@ import android.permission.flags.Flags;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;

@@ -258,12 +261,14 @@ public final class AppFunctionManager {
     * All USER flags
     * @hide
     */
    @TestApi
    public static final int ACCESS_FLAG_MASK_USER =
            ACCESS_FLAG_USER_GRANTED | ACCESS_FLAG_USER_DENIED;
    /**
     * All OTHER flags
     * @hide
     */
    @TestApi
    public static final int ACCESS_FLAG_MASK_OTHER =
            ACCESS_FLAG_OTHER_GRANTED | ACCESS_FLAG_OTHER_DENIED;

@@ -271,6 +276,7 @@ public final class AppFunctionManager {
     * All access flags
     * @hide
     */
    @TestApi
    public static final int
            ACCESS_FLAG_MASK_ALL = ACCESS_FLAG_PREGRANTED | ACCESS_FLAG_OTHER_GRANTED
            | ACCESS_FLAG_OTHER_DENIED | ACCESS_FLAG_USER_GRANTED | ACCESS_FLAG_USER_DENIED;
@@ -528,6 +534,152 @@ public final class AppFunctionManager {

    }

    /**
     * Checks whether the given agent has access to app functions of the given target app, or if
     * the access is not {@link #getSelfAppFunctionAccessRequestState valid}. Requires the
     * {@link Manifest.permission.MANAGE_APP_FUNCTION_ACCESS} permission if the
     * {@param agentPackageName} is not the calling app.
     *
     * @param agentPackageName  The package name of the agent
     * @param targetPackageName The package name of the target
     * @return The state of the access, one of {@link #ACCESS_REQUEST_STATE_GRANTED},
     * {@link #ACCESS_REQUEST_STATE_DENIED}, or {@link #ACCESS_REQUEST_STATE_UNREQUESTABLE}
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    @RequiresPermission(value = MANAGE_APP_FUNCTION_ACCESS, conditional = true)
    @AppFunctionAccessState
    public int getAppFunctionAccessRequestState(@NonNull String agentPackageName,
            @NonNull String targetPackageName) {
        try {
            return mService.getAppFunctionAccessRequestState(agentPackageName,
                    mContext.getUserId(), targetPackageName, mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Checks whether the calling app has access to app functions of the given target app,
     * for the given users, or if the access is invalid (not able to be requested). An access is
     * valid if:
     * 1. The agent (calling app) and target apps are both installed, and the agent has visibility
     * of the target.
     * 2. The agent has the {@link Manifest.permission.EXECUTE_APP_FUNCTIONS} permission granted.
     * 3. The agent is allowlisted by the system.
     * 4. The target has an AppFunctionService.
     * @param targetPackageName The package name of the target
     * @return The state of the access, one of {@link #ACCESS_REQUEST_STATE_GRANTED},
     * {@link #ACCESS_REQUEST_STATE_DENIED}, or {@link #ACCESS_REQUEST_STATE_UNREQUESTABLE}
     */
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    @AppFunctionAccessState
    public int getSelfAppFunctionAccessRequestState(@NonNull String targetPackageName) {
        return getAppFunctionAccessRequestState(mContext.getOpPackageName(), targetPackageName);
    }

    /**
     * Get the access flags for a given agent and target. These flags include extra information
     * about the access state (whether it is pregranted, if the user has set state, etc.). Returns
     * 0 if the access is not {@link #getSelfAppFunctionAccessRequestState valid}.
     *
     * @param agentPackageName  The package name of the agent
     * @param targetPackageName The package name of the target
     * @return The flags for the given agent and target app, or 0 if the combination is not valid
     * @hide
     */
    @SystemApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    @AppFunctionAccessFlags
    public int getAppFunctionAccessFlags(@NonNull String agentPackageName,
            @NonNull String targetPackageName) {
        try {
            return mService.getAppFunctionAccessFlags(agentPackageName,
                    mContext.getUserId(), targetPackageName, mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Updates the access flags for the given agent and target. If the access is not
     * {@link #getSelfAppFunctionAccessRequestState valid}, this method is a no-op.
     *
     * @param agentPackageName  The package name of the agent
     * @param targetPackageName The package name of the target
     * @param flagMask          The mask determining which flag values will be changed
     * @param flags             The flag values to be changed
     * @throws IllegalArgumentException if an invalid flag is specified, opposing flags (e.g.
     * USER_GRANTED and USER_DENIED) are set together, or a flag with an opposite is set, without
     * its opposite being explicitly cleared (via being included in the flag mask, but not the flag
     * set).
     * @hide
     */
    @SystemApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    public void updateAppFunctionAccessFlags(@NonNull String agentPackageName,
            @NonNull String targetPackageName, @AppFunctionAccessFlags int flagMask,
            @AppFunctionAccessFlags int flags) {
        try {
            mService.updateAppFunctionAccessFlags(agentPackageName,
                    mContext.getUserId(), targetPackageName, mContext.getUserId(),
                    flagMask, flags);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Revoke the App Function access for the calling app and the given target
     * @param targetPackageName The app whose AppFunctionService the calling app should lose access
     *                          to.
     */
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    public void revokeSelfAppFunctionAccess(@NonNull String targetPackageName) {
        try {
            mService.revokeSelfAppFunctionAccess(targetPackageName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }


    /**
     * Gets all {@link #getSelfAppFunctionAccessRequestState valid} agents.
     * @return A list of all valid agent package names
     * @hide
     */
    @SystemApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    public @NonNull List<String> getValidAgents() {
        try {
            return mService.getValidAgents(mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets all {@link #getSelfAppFunctionAccessRequestState valid} target apps.
     * @return A list of all target app package names in the current user that the agent can
     * request access for
     * @hide
     */
    @SystemApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    public @NonNull List<String> getValidTargets() {
        try {
            return mService.getValidTargets(mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private static class CallbackWrapper extends IAppFunctionEnabledCallback.Stub {

        private final OutcomeReceiver<Void, Exception> mCallback;
Loading