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

Commit 98757b49 authored by MingWei's avatar MingWei Committed by MingWei Liao
Browse files

Add AppFunctionAccessHistoryProvider

Expose a provider for caller with MANAGE_APP_FUNCTION_ACCESS
permission to query the access history data.

API-Coverage-Bug: 442800144
Flag: android.permission.flags.app_function_access_api_enabled
Bug: 427996654
Test: atest CtsAppFunctionTestCases
Change-Id: I3c27a5290403e86e23de5ce149bf874e063319da
parent c4655419
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1787,6 +1787,7 @@ 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 getAccessFlags(@NonNull String, @NonNull String);
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @NonNull public android.net.Uri getAccessHistoryContentUri();
    method @FlaggedApi("android.permission.flags.app_function_access_api_enabled") @RequiresPermission(value=android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS, conditional=true) public int getAccessRequestState(@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();
+1 −0
Original line number Diff line number Diff line
@@ -789,6 +789,7 @@ 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") @RequiresPermission(android.Manifest.permission.MANAGE_APP_FUNCTION_ACCESS) public void clearAccessHistory();
    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();
+62 −5
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.SignedPackage;
import android.content.pm.SignedPackageParcel;
import android.net.Uri;
import android.os.CancellationSignal;
import android.os.ICancellationSignal;
import android.os.OutcomeReceiver;
@@ -123,6 +124,10 @@ public final class AppFunctionManager {
    public static final class AccessHistory implements BaseColumns {
        private AccessHistory() {}

        @NonNull
        private static final Uri TARGET_USER_URI =
                Uri.parse("content://com.android.appfunction.accesshistory/user");

        /**
         * The package name of the agent app.
         *
@@ -491,7 +496,8 @@ public final class AppFunctionManager {
                        request,
                        mContext.getUser(),
                        mContext.getPackageName(),
                        /* requestTime= */ SystemClock.elapsedRealtime());
                        /* requestTime= */ SystemClock.elapsedRealtime(),
                        /* requestWallTime= */ System.currentTimeMillis());

        try {
            ICancellationSignal cancellationTransport =
@@ -863,6 +869,7 @@ public final class AppFunctionManager {

    /**
     * Gets the current agent allowlist
     *
     * @hide
     */
    @TestApi
@@ -882,9 +889,10 @@ public final class AppFunctionManager {
        }
    }

    // TODO(b/413093397): Remove once list is ready for permanent enable.
    /**
     * Gets whether or not the agent allowlist is enabled
     * TODO b/413093397: Remove once list is ready for permanent enable
     * Gets whether or not the agent allowlist is enabled.
     *
     * @hide
     */
    @TestApi
@@ -899,8 +907,9 @@ public final class AppFunctionManager {
    }

    /**
     * Gets whether or not the agent allowlist is enabled
     * TODO b/413093397: Remove once list is ready for permanent enable
     * Gets whether or not the agent allowlist is enabled TODO b/413093397: Remove once list is
     * ready for permanent enable
     *
     * @hide
     */
    @TestApi
@@ -914,6 +923,54 @@ public final class AppFunctionManager {
        }
    }

    /**
     * Clear the access history data.
     *
     * @hide
     */
    @TestApi
    @RequiresPermission(MANAGE_APP_FUNCTION_ACCESS)
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    @UserHandleAware
    public void clearAccessHistory() {
        try {
            mService.clearAccessHistory(mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the {@code content://} style URI for the AppFunction access history table for the
     * user from the context used to obtain the instance of this class.
     *
     * <p>To query the content provider using the returned URI, the calling application must hold
     * the {@link android.Manifest.permission#MANAGE_APP_FUNCTION_ACCESS} permission.
     *
     * <p>To query for a user other than the current one, the caller must also hold the {@link
     * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
     *
     * <p>Attempting to query the content provider with the returned URI without holding the
     * necessary permissions will result in a {@link java.lang.SecurityException}.
     *
     * @return The {@link Uri} for the AppFunction access history table.
     * @hide
     */
    @SuppressLint("RequiresPermission") // Permission enforced in AppFunctionAccessHistoryProvider
    @SystemApi
    @FlaggedApi(Flags.FLAG_APP_FUNCTION_ACCESS_API_ENABLED)
    @UserHandleAware
    @NonNull
    public Uri getAccessHistoryContentUri() {
        // The verification of whether the user has access to the target user's URI is enforced
        // in the provide.
        final int userId = mContext.getUserId();
        return AccessHistory.TARGET_USER_URI
                .buildUpon()
                .appendPath(Integer.toString(userId))
                .build();
    }

    private static class CallbackWrapper extends IAppFunctionEnabledCallback.Stub {

        private final OutcomeReceiver<Void, Exception> mCallback;
+24 −5
Original line number Diff line number Diff line
@@ -42,8 +42,13 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
                    UserHandle userHandle = UserHandle.CREATOR.createFromParcel(in);
                    String callingPackage = in.readString8();
                    long requestTime = in.readLong();
                    long requestWallTime = in.readLong();
                    return new ExecuteAppFunctionAidlRequest(
                            clientRequest, userHandle, callingPackage, requestTime);
                            clientRequest,
                            userHandle,
                            callingPackage,
                            requestTime,
                            requestWallTime);
                }

                @Override
@@ -61,15 +66,23 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
    /** The package name of the app that is requesting to execute the app function. */
    private final String mCallingPackage;

    /** The time of calling executeAppFunction(). */
    /** The elapsed time since last reboot when calling executeAppFunction(). */
    private final long mRequestTime;

    public ExecuteAppFunctionAidlRequest(ExecuteAppFunctionRequest clientRequest,
            UserHandle userHandle, String callingPackage, long requestTime) {
    /** The wall clock time when calling executeAppFunction(). */
    private final long mRequestWallTime;

    public ExecuteAppFunctionAidlRequest(
            ExecuteAppFunctionRequest clientRequest,
            UserHandle userHandle,
            String callingPackage,
            long requestTime,
            long requestWallTime) {
        this.mClientRequest = Objects.requireNonNull(clientRequest);
        this.mUserHandle = Objects.requireNonNull(userHandle);
        this.mCallingPackage = Objects.requireNonNull(callingPackage);
        this.mRequestTime = requestTime;
        this.mRequestWallTime = requestWallTime;
    }

    @Override
@@ -83,6 +96,7 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
        mUserHandle.writeToParcel(dest, flags);
        dest.writeString8(mCallingPackage);
        dest.writeLong(mRequestTime);
        dest.writeLong(mRequestWallTime);
    }

    /** Returns the client request to execute an app function. */
@@ -103,8 +117,13 @@ public final class ExecuteAppFunctionAidlRequest implements Parcelable {
        return mCallingPackage;
    }

    /** Returns the time of calling executeAppFunction(). */
    /** Returns the elapsed time since last reboot when calling executeAppFunction(). */
    public long getRequestTime() {
        return mRequestTime;
    }

    /** Returns the wall time when calling executeAppFunction(). */
    public long getRequestWallTime() {
        return mRequestWallTime;
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -94,4 +94,7 @@ interface IAppFunctionManager {

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

    @EnforcePermission("MANAGE_APP_FUNCTION_ACCESS")
    void clearAccessHistory(int userId);
}
Loading