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

Commit 1507931e authored by Jing Ji's avatar Jing Ji
Browse files

Add background restriction levels definition and its controller

This CL adds the definition of background app restriction levels.

The existing various system background app restriction features will
be mapped into the levels here, including app standby buckets,
background restrictions (forced-app-standby) etc. Future CLs may
apply restrictions to background apps accordingly.

BYPASS_INCLUSIVE_LANGUAGE_REASON=Legacy API name

Bug: 200326767
Test: atest FrameworksMockingServicesTests:BackgroundRestrictionTest
Change-Id: Icf82031c572e7b8e82e6528402e9df4de5b7a675
parent b60f95be
Loading
Loading
Loading
Loading
+25 −3
Original line number Original line Diff line number Diff line
@@ -4,8 +4,8 @@ import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.usage.AppStandbyInfo;
import android.app.usage.AppStandbyInfo;
import android.app.usage.UsageStatsManager.ForcedReasons;
import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.app.usage.UsageStatsManager.SystemForcedReasons;
import android.content.Context;
import android.content.Context;
import android.util.IndentingPrintWriter;
import android.util.IndentingPrintWriter;


@@ -152,7 +152,7 @@ public interface AppStandbyInternal {
     *                       UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons.
     *                       UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons.
     */
     */
    void restrictApp(@NonNull String packageName, int userId,
    void restrictApp(@NonNull String packageName, int userId,
            @SystemForcedReasons int restrictReason);
            @ForcedReasons int restrictReason);


    /**
    /**
     * Put the specified app in the
     * Put the specified app in the
@@ -169,7 +169,29 @@ public interface AppStandbyInternal {
     *                       UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons.
     *                       UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_* reasons.
     */
     */
    void restrictApp(@NonNull String packageName, int userId, int mainReason,
    void restrictApp(@NonNull String packageName, int userId, int mainReason,
            @SystemForcedReasons int restrictReason);
            @ForcedReasons int restrictReason);

    /**
     * Unrestrict an app if there is no other reason to restrict it.
     *
     * <p>
     * The {@code prevMainReasonRestrict} and {@code prevSubReasonRestrict} are the previous
     * reasons of why it was restricted, but the caller knows that these conditions are not true
     * anymore; therefore if there is no other reasons to restrict it (as there could bemultiple
     * reasons to restrict it), lift the restriction.
     * </p>
     *
     * @param packageName            The package name of the app.
     * @param userId                 The user id that this app runs in.
     * @param prevMainReasonRestrict The main reason that why it was restricted, must be either
     *                               {@link android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_SYSTEM}
     *                               or {@link android.app.usage.UsageStatsManager#REASON_MAIN_FORCED_BY_USER}.
     * @param prevSubReasonRestrict  The subreason that why it was restricted before.
     * @param mainReasonUnrestrict   The main reason that why it could be unrestricted now.
     * @param subReasonUnrestrict    The subreason that why it could be unrestricted now.
     */
    void maybeUnrestrictApp(@NonNull String packageName, int userId, int prevMainReasonRestrict,
            int prevSubReasonRestrict, int mainReasonUnrestrict, int subReasonUnrestrict);


    void addActiveDeviceAdmin(String adminPkg, int userId);
    void addActiveDeviceAdmin(String adminPkg, int userId);


+19 −10
Original line number Original line Diff line number Diff line
@@ -63,8 +63,8 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.usage.AppStandbyInfo;
import android.app.usage.AppStandbyInfo;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager.ForcedReasons;
import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.app.usage.UsageStatsManager.SystemForcedReasons;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
@@ -1406,13 +1406,13 @@ public class AppStandbyController


    @Override
    @Override
    public void restrictApp(@NonNull String packageName, int userId,
    public void restrictApp(@NonNull String packageName, int userId,
            @SystemForcedReasons int restrictReason) {
            @ForcedReasons int restrictReason) {
        restrictApp(packageName, userId, REASON_MAIN_FORCED_BY_SYSTEM, restrictReason);
        restrictApp(packageName, userId, REASON_MAIN_FORCED_BY_SYSTEM, restrictReason);
    }
    }


    @Override
    @Override
    public void restrictApp(@NonNull String packageName, int userId, int mainReason,
    public void restrictApp(@NonNull String packageName, int userId, int mainReason,
            @SystemForcedReasons int restrictReason) {
            @ForcedReasons int restrictReason) {
        if (mainReason != REASON_MAIN_FORCED_BY_SYSTEM
        if (mainReason != REASON_MAIN_FORCED_BY_SYSTEM
                && mainReason != REASON_MAIN_FORCED_BY_USER) {
                && mainReason != REASON_MAIN_FORCED_BY_USER) {
            Slog.e(TAG, "Tried to restrict app " + packageName + " for an unsupported reason");
            Slog.e(TAG, "Tried to restrict app " + packageName + " for an unsupported reason");
@@ -1799,27 +1799,36 @@ public class AppStandbyController
     * bucket if it was forced into the bucket by the system because it was buggy.
     * bucket if it was forced into the bucket by the system because it was buggy.
     */
     */
    @VisibleForTesting
    @VisibleForTesting
    void maybeUnrestrictBuggyApp(String packageName, int userId) {
    void maybeUnrestrictBuggyApp(@NonNull String packageName, int userId) {
        maybeUnrestrictApp(packageName, userId,
                REASON_MAIN_FORCED_BY_SYSTEM, REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY,
                REASON_MAIN_DEFAULT, REASON_SUB_DEFAULT_APP_UPDATE);
    }

    @Override
    public void maybeUnrestrictApp(@NonNull String packageName, int userId,
            int prevMainReasonRestrict, int prevSubReasonRestrict,
            int mainReasonUnrestrict, int subReasonUnrestrict) {
        synchronized (mAppIdleLock) {
        synchronized (mAppIdleLock) {
            final long elapsedRealtime = mInjector.elapsedRealtime();
            final long elapsedRealtime = mInjector.elapsedRealtime();
            final AppIdleHistory.AppUsageHistory app =
            final AppIdleHistory.AppUsageHistory app =
                    mAppIdleHistory.getAppUsageHistory(packageName, userId, elapsedRealtime);
                    mAppIdleHistory.getAppUsageHistory(packageName, userId, elapsedRealtime);
            if (app.currentBucket != STANDBY_BUCKET_RESTRICTED
            if (app.currentBucket != STANDBY_BUCKET_RESTRICTED
                    || (app.bucketingReason & REASON_MAIN_MASK) != REASON_MAIN_FORCED_BY_SYSTEM) {
                    || (app.bucketingReason & REASON_MAIN_MASK) != prevMainReasonRestrict) {
                return;
                return;
            }
            }


            final int newBucket;
            final int newBucket;
            final int newReason;
            final int newReason;
            if ((app.bucketingReason & REASON_SUB_MASK) == REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY) {
            if ((app.bucketingReason & REASON_SUB_MASK) == prevSubReasonRestrict) {
                // If bugginess was the only reason the app should be restricted, then lift it out.
                // If it was the only reason the app should be restricted, then lift it out.
                newBucket = STANDBY_BUCKET_RARE;
                newBucket = STANDBY_BUCKET_RARE;
                newReason = REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_APP_UPDATE;
                newReason = mainReasonUnrestrict | subReasonUnrestrict;
            } else {
            } else {
                // There's another reason the app was restricted. Remove the buggy bit and call
                // There's another reason the app was restricted. Remove the subreason bit and call
                // it a day.
                // it a day.
                newBucket = STANDBY_BUCKET_RESTRICTED;
                newBucket = STANDBY_BUCKET_RESTRICTED;
                newReason = app.bucketingReason & ~REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY;
                newReason = app.bucketingReason & ~prevSubReasonRestrict;
            }
            }
            mAppIdleHistory.setAppStandbyBucket(
            mAppIdleHistory.setAppStandbyBucket(
                    packageName, userId, elapsedRealtime, newBucket, newReason);
                    packageName, userId, elapsedRealtime, newBucket, newReason);
+115 −0
Original line number Original line Diff line number Diff line
@@ -937,6 +937,121 @@ public class ActivityManager {
    @EnabledSince(targetSdkVersion = VERSION_CODES.S)
    @EnabledSince(targetSdkVersion = VERSION_CODES.S)
    public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L;
    public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L;


    // The background process restriction levels. The definitions here are meant for internal
    // bookkeeping only.

    /**
     * Not a valid restriction level.
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_UNKNOWN = 0;

    /**
     * No background restrictions at all, this should NEVER be used
     * for any process other than selected system processes, currently it's reserved.
     *
     * <p>In the future, apps in {@link #RESTRICTION_LEVEL_EXEMPTED} would receive permissive
     * background restrictions to protect the system from buggy behaviors; in other words,
     * the {@link #RESTRICTION_LEVEL_EXEMPTED} would not be the truly "unrestricted" state, while
     * the {@link #RESTRICTION_LEVEL_UNRESTRICTED} here would be the last resort if there is
     * a strong reason to grant such a capability to a system app. </p>
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_UNRESTRICTED = 10;

    /**
     * The default background restriction level for the "unrestricted" apps set by the user,
     * where it'll have the {@link android.app.AppOpsManager#OP_RUN_ANY_IN_BACKGROUND} set to
     * ALLOWED, being added into the device idle allow list; however there will be still certain
     * restrictions to apps in this level.
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_EXEMPTED = 20;

    /**
     * The default background restriction level for all other apps, they'll be moved between
     * various standby buckets, including
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_ACTIVE},
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_WORKING_SET},
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_FREQUENT},
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RARE}.
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_ADAPTIVE_BUCKET = 30;

    /**
     * The background restriction level where the apps will be placed in the restricted bucket
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}.
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_RESTRICTED_BUCKET = 40;

    /**
     * The background restricted level, where apps would get more restrictions,
     * such as not allowed to launch foreground services besides on TOP.
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_BACKGROUND_RESTRICTED = 50;

    /**
     * The most restricted level where the apps are considered "in-hibernation",
     * its package visibility to the rest of the system is limited.
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_HIBERNATION = 60;

    /**
     * Not a valid restriction level, it defines the maximum numerical value of restriction level.
     *
     * @hide
     */
    public static final int RESTRICTION_LEVEL_MAX = 100;

    /** @hide */
    @IntDef(prefix = { "RESTRICTION_LEVEL_" }, value = {
            RESTRICTION_LEVEL_UNKNOWN,
            RESTRICTION_LEVEL_UNRESTRICTED,
            RESTRICTION_LEVEL_EXEMPTED,
            RESTRICTION_LEVEL_ADAPTIVE_BUCKET,
            RESTRICTION_LEVEL_RESTRICTED_BUCKET,
            RESTRICTION_LEVEL_BACKGROUND_RESTRICTED,
            RESTRICTION_LEVEL_HIBERNATION,
            RESTRICTION_LEVEL_MAX,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface RestrictionLevel{}

    /** @hide */
    public static String restrictionLevelToName(@RestrictionLevel int level) {
        switch (level) {
            case RESTRICTION_LEVEL_UNKNOWN:
                return "unknown";
            case RESTRICTION_LEVEL_UNRESTRICTED:
                return "unrestricted";
            case RESTRICTION_LEVEL_EXEMPTED:
                return "exempted";
            case RESTRICTION_LEVEL_ADAPTIVE_BUCKET:
                return "adaptive_bucket";
            case RESTRICTION_LEVEL_RESTRICTED_BUCKET:
                return "restricted_bucket";
            case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
                return "background_restricted";
            case RESTRICTION_LEVEL_HIBERNATION:
                return "hibernation";
            case RESTRICTION_LEVEL_MAX:
                return "max";
            default:
                return "";
        }
    }

    /** @hide */
    /** @hide */
    public int getFrontActivityScreenCompatMode() {
    public int getFrontActivityScreenCompatMode() {
        try {
        try {
+12 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityManager.RestrictionLevel;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.IIntentSender;
@@ -712,4 +713,15 @@ public abstract class ActivityManagerInternal {
         */
         */
        void notifyActivityEventChanged();
        void notifyActivityEventChanged();
    }
    }

    /**
     * Get the restriction level of the given UID, if it hosts multiple packages,
     * return least restricted level.
     */
    public abstract @RestrictionLevel int getRestrictionLevel(int uid);

    /**
     * Get the restriction level of the given package for given user id.
     */
    public abstract @RestrictionLevel int getRestrictionLevel(String pkg, @UserIdInt int userId);
}
}
+14 −7
Original line number Original line Diff line number Diff line
@@ -320,6 +320,17 @@ public final class UsageStatsManager {
     * @hide
     * @hide
     */
     */
    public static final int REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY = 1 << 2;
    public static final int REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY = 1 << 2;
    /**
     * The app was moved to restricted bucket due to user interaction, i.e., toggling FAS.
     *
     * <p>
     * Note: This should be coming from the more end-user facing UX, not from developer
     * options nor adb command.
     </p>
     *
     * @hide
     */
    public static final int REASON_SUB_FORCED_USER_FLAG_INTERACTION = 1 << 1;




    /** @hide */
    /** @hide */
@@ -336,14 +347,15 @@ public final class UsageStatsManager {
    public @interface StandbyBuckets {}
    public @interface StandbyBuckets {}


    /** @hide */
    /** @hide */
    @IntDef(flag = true, prefix = {"REASON_SUB_FORCED_SYSTEM_FLAG_FLAG_"}, value = {
    @IntDef(flag = true, prefix = {"REASON_SUB_FORCED_"}, value = {
            REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED,
            REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED,
            REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE,
            REASON_SUB_FORCED_SYSTEM_FLAG_BACKGROUND_RESOURCE_USAGE,
            REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE,
            REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE,
            REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY,
            REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY,
            REASON_SUB_FORCED_USER_FLAG_INTERACTION,
    })
    })
    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    public @interface SystemForcedReasons {
    public @interface ForcedReasons {
    }
    }


    /**
    /**
@@ -1188,11 +1200,6 @@ public final class UsageStatsManager {
            case REASON_MAIN_FORCED_BY_USER:
            case REASON_MAIN_FORCED_BY_USER:
                sb.append("f");
                sb.append("f");
                if (subReason > 0) {
                if (subReason > 0) {
                    // Although not expected and shouldn't happen, this could potentially have a
                    // sub-reason if the system tries to give a reason when applying the
                    // FORCED_BY_USER reason. The sub-reason is undefined (though most likely a
                    // REASON_SUB_FORCED_SYSTEM_FLAG_ sub-reason), but it's better to note it in the
                    // log than to exclude it altogether.
                    sb.append("-").append(Integer.toBinaryString(subReason));
                    sb.append("-").append(Integer.toBinaryString(subReason));
                }
                }
                break;
                break;
Loading