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

Commit 19166cb1 authored by Kevin Han's avatar Kevin Han
Browse files

Add API to get hibernation eligibility

Add an API to get a package's eligibility for hibernation for a given
user. A package is either eligible, exempt by the system, or exempt by
the user.

This information can be used to show more accurate UI for hibernation
controls (e.g. disabling the user-controlled exemption toggle if the app
is already exempt by the system)

Bug: 200087723
Test: CTS test in topic
Change-Id: Iea844477184fadb55ea14485dff172ed7be2b715
parent b5956636
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -9699,12 +9699,17 @@ package android.permission {
  public final class PermissionControllerManager {
    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void applyStagedRuntimePermissionBackup(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
    method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public void getHibernationEligibility(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer);
    method @RequiresPermission(android.Manifest.permission.GET_RUNTIME_PERMISSIONS) public void getRuntimePermissionBackup(@NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<byte[]>);
    method public void getUnusedAppCount(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer);
    method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull java.util.concurrent.Executor, @NonNull android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback);
    method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS}) public void stageAndApplyRuntimePermissionsBackup(@NonNull byte[], @NonNull android.os.UserHandle);
    field public static final int COUNT_ONLY_WHEN_GRANTED = 1; // 0x1
    field public static final int COUNT_WHEN_SYSTEM = 2; // 0x2
    field public static final int HIBERNATION_ELIGIBILITY_ELIGIBLE = 0; // 0x0
    field public static final int HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM = 1; // 0x1
    field public static final int HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER = 2; // 0x2
    field public static final int HIBERNATION_ELIGIBILITY_UNKNOWN = -1; // 0xffffffff
    field public static final int REASON_INSTALLER_POLICY_VIOLATION = 2; // 0x2
    field public static final int REASON_MALWARE = 1; // 0x1
  }
@@ -9722,6 +9727,7 @@ package android.permission {
    method @BinderThread public abstract void onCountPermissionApps(@NonNull java.util.List<java.lang.String>, int, @NonNull java.util.function.IntConsumer);
    method @BinderThread public abstract void onGetAppPermissions(@NonNull String, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionPresentationInfo>>);
    method @BinderThread public void onGetGroupOfPlatformPermission(@NonNull String, @NonNull java.util.function.Consumer<java.lang.String>);
    method @RequiresPermission(android.Manifest.permission.MANAGE_APP_HIBERNATION) public void onGetHibernationEligibility(@NonNull String, @NonNull java.util.function.IntConsumer);
    method @BinderThread public abstract void onGetPermissionUsages(boolean, long, @NonNull java.util.function.Consumer<java.util.List<android.permission.RuntimePermissionUsageInfo>>);
    method @BinderThread public void onGetPlatformPermissionsForGroup(@NonNull String, @NonNull java.util.function.Consumer<java.util.List<java.lang.String>>);
    method @BinderThread public abstract void onGetRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.OutputStream, @NonNull Runnable);
+3 −0
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@ oneway interface IPermissionController {
            in AndroidFuture<String> callback);
    void getUnusedAppCount(
            in AndroidFuture callback);
    void getHibernationEligibility(
                in String packageName,
                in AndroidFuture callback);
    void revokeOwnPermissionsOnKill(in String packageName, in List<String> permissions,
            in AndroidFuture callback);
}
+78 −0
Original line number Diff line number Diff line
@@ -128,6 +128,51 @@ public final class PermissionControllerManager {
    /** Count and app even if it is a system app. */
    public static final int COUNT_WHEN_SYSTEM = 2;

    /** @hide */
    @IntDef(prefix = { "HIBERNATION_ELIGIBILITY_"}, value = {
            HIBERNATION_ELIGIBILITY_UNKNOWN,
            HIBERNATION_ELIGIBILITY_ELIGIBLE,
            HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM,
            HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface HibernationEligibilityFlag {}

    /**
     * Unknown whether package is eligible for hibernation.
     *
     * @hide
     */
    @SystemApi
    public static final int HIBERNATION_ELIGIBILITY_UNKNOWN = -1;

    /**
     * Package is eligible for app hibernation and may be hibernated when the job runs.
     *
     * @hide
     */
    @SystemApi
    public static final int HIBERNATION_ELIGIBILITY_ELIGIBLE = 0;

    /**
     * Package is not eligible for app hibernation because it is categorically exempt via the
     * system.
     *
     * @hide
     */
    @SystemApi
    public static final int HIBERNATION_ELIGIBILITY_EXEMPT_BY_SYSTEM = 1;

    /**
     * Package is not eligible for app hibernation because it has been exempt by the user's
     * preferences. Note that this should not be set if the package is exempt from hibernation by
     * the system as the user preference would have no effect.
     *
     * @hide
     */
    @SystemApi
    public static final int HIBERNATION_ELIGIBILITY_EXEMPT_BY_USER = 2;

    /**
     * Callback for delivering the result of {@link #revokeRuntimePermissions}.
     */
@@ -818,6 +863,39 @@ public final class PermissionControllerManager {
        });
    }

    /**
     * Get the hibernation eligibility of a package. See {@link HibernationEligibilityFlag}.
     *
     * @param packageName package name to check eligibility
     * @param executor executor to run callback on
     * @param callback callback for when result is generated
     */
    @RequiresPermission(Manifest.permission.MANAGE_APP_HIBERNATION)
    public void getHibernationEligibility(@NonNull String packageName,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull IntConsumer callback) {
        checkNotNull(executor);
        checkNotNull(callback);

        mRemoteService.postAsync(service -> {
            AndroidFuture<Integer> eligibilityResult = new AndroidFuture<>();
            service.getHibernationEligibility(packageName, eligibilityResult);
            return eligibilityResult;
        }).whenCompleteAsync((eligibility, err) -> {
            if (err != null) {
                Log.e(TAG, "Error getting hibernation eligibility", err);
                callback.accept(HIBERNATION_ELIGIBILITY_UNKNOWN);
            } else {
                final long token = Binder.clearCallingIdentity();
                try {
                    callback.accept(eligibility);
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        }, executor);
    }

    /**
     * Triggers the revocation of one or more permissions for a package, under the following
     * conditions:
+32 −0
Original line number Diff line number Diff line
@@ -375,6 +375,22 @@ public abstract class PermissionControllerService extends Service {
        throw new AbstractMethodError("Must be overridden in implementing class");
    }

    /**
     * Get the hibernation eligibility of the app. See
     * {@link android.permission.PermissionControllerManager.HibernationEligibilityFlag}.
     *
     * @param packageName package to check eligibility
     * @param callback callback after eligibility is returned
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.MANAGE_APP_HIBERNATION)
    public void onGetHibernationEligibility(@NonNull String packageName,
            @NonNull IntConsumer callback) {
        throw new AbstractMethodError("Must be overridden in implementing class");
    }

    @Override
    public final @NonNull IBinder onBind(Intent intent) {
        return new IPermissionController.Stub() {
@@ -668,6 +684,22 @@ public abstract class PermissionControllerService extends Service {
                }
            }

            @Override
            public void getHibernationEligibility(@NonNull String packageName,
                    @NonNull AndroidFuture callback) {
                try {
                    Objects.requireNonNull(callback);

                    enforceSomePermissionsGrantedToCaller(
                            Manifest.permission.MANAGE_APP_HIBERNATION);

                    PermissionControllerService.this.onGetHibernationEligibility(packageName,
                            callback::complete);
                } catch (Throwable t) {
                    callback.completeExceptionally(t);
                }
            }

            @Override
            public void revokeOwnPermissionsOnKill(@NonNull String packageName,
                    @NonNull List<String> permissions, @NonNull AndroidFuture callback) {