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

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

Enforce agent allowlist in AppFunctionAccessService

This CL also adds ADB commands to add agents manually, and disable the
allowlist entirely. Also modifies the signature checking logic, to
better match existing use cases.

Bug: 413093397
Test: atest AppFunctionAccessTest,AppIdAppFunctionAccessPolicyTest
Flag: android.permission.flags.app_function_access_service_enabled
Change-Id: Ie584be60e8f266778fa1b81ba7effb665c42f785
parent f7735d3e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ package android.content.pm {

  @FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled") public class SignedPackage {
    method @NonNull public byte[] getCertificateDigest();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @Nullable public byte[] getCertificateDigestOrNull();
    method @NonNull public String getPackageName();
  }

+9 −0
Original line number Diff line number Diff line
@@ -778,7 +778,10 @@ package android.app.admin {
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") @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public java.util.List<android.content.pm.SignedPackage> getAgentAllowlist();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @NonNull public java.util.Set<java.lang.String> getDeviceSettingPackages();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public boolean isAgentAllowlistEnabled();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public void setAgentAllowlistEnabled(boolean);
    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
@@ -1210,6 +1213,12 @@ package android.content.pm {
    ctor public ShortcutManager(android.content.Context);
  }

  @FlaggedApi("android.permission.flags.enhanced_confirmation_mode_apis_enabled") public class SignedPackage {
    method @NonNull public byte[] getCertificateDigest();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @Nullable public byte[] getCertificateDigestOrNull();
    method @NonNull public String getPackageName();
  }

  public class UserInfo implements android.os.Parcelable {
    ctor public UserInfo(int, String, int);
    ctor public UserInfo(int, String, String, int);
+3 −1
Original line number Diff line number Diff line
@@ -17,9 +17,11 @@
package android.app.appfunctions;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.SignedPackage;

import java.util.List;
import java.util.Set;

/**
 * @hide
@@ -46,7 +48,7 @@ public interface AppFunctionAccessServiceInterface {
    void revokeSelfAccess(@NonNull String targetPackageName);

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

    /** @see AppFunctionManager#getValidAgents() */
    @NonNull
+56 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ import android.app.appfunctions.AppFunctionManagerHelper.AppFunctionNotFoundExce
import android.app.appsearch.AppSearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.SignedPackage;
import android.content.pm.SignedPackageParcel;
import android.os.CancellationSignal;
import android.os.ICancellationSignal;
import android.os.OutcomeReceiver;
@@ -51,6 +53,7 @@ import com.android.internal.R;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -841,6 +844,59 @@ public final class AppFunctionManager {
        return new ArraySet<>(deviceSettingPackages);
    }

    /**
     * Gets the current agent allowlist
     * @hide
     */
    @TestApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    public @NonNull List<SignedPackage> getAgentAllowlist() {
        try {
            List<SignedPackageParcel> packageParcels = mService.getAgentAllowlist();
            int packageParcelsSize = packageParcels.size();
            List<SignedPackage> packages = new ArrayList<>(packageParcelsSize);
            for (int i = 0; i < packageParcelsSize; i++) {
                packages.add(new SignedPackage(packageParcels.get(i)));
            }
            return packages;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets whether or not the agent allowlist is enabled
     * TODO b/413093397: Remove once list is ready for permanent enable
     * @hide
     */
    @TestApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    public boolean isAgentAllowlistEnabled() {
        try {
            return mService.isAgentAllowlistEnabled();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets whether or not the agent allowlist is enabled
     * TODO b/413093397: Remove once list is ready for permanent enable
     * @hide
     */
    @TestApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    public void setAgentAllowlistEnabled(boolean enabled) {
        try {
            mService.setAgentAllowlistEnabled(enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private static class CallbackWrapper extends IAppFunctionEnabledCallback.Stub {

        private final OutcomeReceiver<Void, Exception> mCallback;
+10 −1
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@ import android.app.appfunctions.ExecuteAppFunctionAidlRequest;
import android.app.appfunctions.IAppFunctionEnabledCallback;
import android.app.appfunctions.IExecuteAppFunctionCallback;
import android.os.ICancellationSignal;

import android.os.UserHandle;
import android.content.pm.SignedPackageParcel;

import java.util.List;
/**
@@ -85,4 +85,13 @@ interface IAppFunctionManager {
    List<String> getValidTargets(
        int targetUserId
    );

    @EnforcePermission("MANAGE_APP_FUNCTION_ACCESS")
    List<SignedPackageParcel> getAgentAllowlist();

    @EnforcePermission("MANAGE_APP_FUNCTION_ACCESS")
    void setAgentAllowlistEnabled(boolean enabled);

    @EnforcePermission("MANAGE_APP_FUNCTION_ACCESS")
    boolean isAgentAllowlistEnabled();
}
Loading