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

Commit b5f28a5e authored by Jing Ji's avatar Jing Ji
Browse files

Allow limited alarms/jobs when background restricted

When app is background restricted, allow alarms/jobs but they'll be
under the quota control of restricted standby bucket.

This behavior is gated by a feature flag now.

Bug: 200326767
Test: atest CtsJobSchedulerTestCases
Test: atest CtsAlarmManagerTestCases
Test: atest FrameworksMockingServicesTests
Change-Id: I154656c19954a306e8ae05dc50ea708c4de2a739
parent 834b56e8
Loading
Loading
Loading
Loading
+49 −2
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal.AppBackgroundRestrictionListener;
import android.app.AppOpsManager;
import android.app.AppOpsManager;
import android.app.AppOpsManager.PackageOps;
import android.app.AppOpsManager.PackageOps;
import android.app.IActivityManager;
import android.app.IActivityManager;
@@ -280,6 +281,14 @@ public class AppStateTrackerImpl implements AppStateTracker {
        }
        }
    }
    }


    private final AppBackgroundRestrictionListener mAppBackgroundRestrictionListener =
            new AppBackgroundRestrictionListener() {
        @Override
        public void onAutoRestrictedBucketFeatureFlagChanged(boolean autoRestrictedBucket) {
            mHandler.notifyAutoRestrictedBucketFeatureFlagChanged(autoRestrictedBucket);
        }
    };

    /**
    /**
     * Listener for any state changes that affect any app's eligibility to run.
     * Listener for any state changes that affect any app's eligibility to run.
     */
     */
@@ -369,6 +378,18 @@ public class AppStateTrackerImpl implements AppStateTracker {
            updateAllAlarms();
            updateAllAlarms();
        }
        }


        /**
         * Called when toggling the feature flag of moving to restricted standby bucket
         * automatically on background-restricted.
         */
        private void onAutoRestrictedBucketFeatureFlagChanged(AppStateTrackerImpl sender,
                boolean autoRestrictedBucket) {
            updateAllJobs();
            if (autoRestrictedBucket) {
                unblockAllUnrestrictedAlarms();
            }
        }

        /**
        /**
         * Called when the job restrictions for multiple UIDs might have changed, so the job
         * Called when the job restrictions for multiple UIDs might have changed, so the job
         * scheduler should re-evaluate all restrictions for all jobs.
         * scheduler should re-evaluate all restrictions for all jobs.
@@ -499,6 +520,8 @@ public class AppStateTrackerImpl implements AppStateTracker {
                    mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
                    mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
            mStandbyTracker = new StandbyTracker();
            mStandbyTracker = new StandbyTracker();
            mAppStandbyInternal.addListener(mStandbyTracker);
            mAppStandbyInternal.addListener(mStandbyTracker);
            mActivityManagerInternal.addAppBackgroundRestrictionListener(
                    mAppBackgroundRestrictionListener);


            try {
            try {
                mIActivityManager.registerUidObserver(new UidObserver(),
                mIActivityManager.registerUidObserver(new UidObserver(),
@@ -802,6 +825,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
        private static final int MSG_USER_REMOVED = 8;
        private static final int MSG_USER_REMOVED = 8;
        private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
        private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
        private static final int MSG_EXEMPTED_BUCKET_CHANGED = 10;
        private static final int MSG_EXEMPTED_BUCKET_CHANGED = 10;
        private static final int MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED = 11;


        private static final int MSG_ON_UID_ACTIVE = 12;
        private static final int MSG_ON_UID_ACTIVE = 12;
        private static final int MSG_ON_UID_GONE = 13;
        private static final int MSG_ON_UID_GONE = 13;
@@ -849,6 +873,12 @@ public class AppStateTrackerImpl implements AppStateTracker {
            obtainMessage(MSG_EXEMPTED_BUCKET_CHANGED).sendToTarget();
            obtainMessage(MSG_EXEMPTED_BUCKET_CHANGED).sendToTarget();
        }
        }


        public void notifyAutoRestrictedBucketFeatureFlagChanged(boolean autoRestrictedBucket) {
            removeMessages(MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED);
            obtainMessage(MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED,
                    autoRestrictedBucket ? 1 : 0, 0).sendToTarget();
        }

        public void doUserRemoved(int userId) {
        public void doUserRemoved(int userId) {
            obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
            obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
        }
        }
@@ -952,6 +982,13 @@ public class AppStateTrackerImpl implements AppStateTracker {
                    handleUserRemoved(msg.arg1);
                    handleUserRemoved(msg.arg1);
                    return;
                    return;


                case MSG_AUTO_RESTRICTED_BUCKET_FEATURE_FLAG_CHANGED:
                    final boolean autoRestrictedBucket = msg.arg1 == 1;
                    for (Listener l : cloneListeners()) {
                        l.onAutoRestrictedBucketFeatureFlagChanged(sender, autoRestrictedBucket);
                    }
                    return;

                case MSG_ON_UID_ACTIVE:
                case MSG_ON_UID_ACTIVE:
                    handleUidActive(msg.arg1);
                    handleUidActive(msg.arg1);
                    return;
                    return;
@@ -1120,7 +1157,12 @@ public class AppStateTrackerImpl implements AppStateTracker {
            if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) {
            if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) {
                return false;
                return false;
            }
            }
            return (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName));
            // If apps will be put into restricted standby bucket automatically on user-forced
            // app standby, instead of blocking alarms completely, let the restricted standby bucket
            // policy take care of it.
            return (mForcedAppStandbyEnabled
                    && !mActivityManagerInternal.isBgAutoRestrictedBucketFeatureFlagEnabled()
                    && isRunAnyRestrictedLocked(uid, packageName));
        }
        }
    }
    }


@@ -1161,7 +1203,12 @@ public class AppStateTrackerImpl implements AppStateTracker {
                    || ArrayUtils.contains(mTempExemptAppIds, appId)) {
                    || ArrayUtils.contains(mTempExemptAppIds, appId)) {
                return false;
                return false;
            }
            }
            if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
            // If apps will be put into restricted standby bucket automatically on user-forced
            // app standby, instead of blocking jobs completely, let the restricted standby bucket
            // policy take care of it.
            if (mForcedAppStandbyEnabled
                    && !mActivityManagerInternal.isBgAutoRestrictedBucketFeatureFlagEnabled()
                    && isRunAnyRestrictedLocked(uid, packageName)) {
                return true;
                return true;
            }
            }
            if (hasForegroundExemption) {
            if (hasForegroundExemption) {
+6 −1
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;


import android.app.ActivityManagerInternal;
import android.os.SystemClock;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.ArraySet;
@@ -59,6 +60,7 @@ public final class BackgroundJobsController extends StateController {
    static final int KNOWN_ACTIVE = 1;
    static final int KNOWN_ACTIVE = 1;
    static final int KNOWN_INACTIVE = 2;
    static final int KNOWN_INACTIVE = 2;


    private final ActivityManagerInternal mActivityManagerInternal;
    private final AppStateTrackerImpl mAppStateTracker;
    private final AppStateTrackerImpl mAppStateTracker;


    private final UpdateJobFunctor mUpdateJobFunctor = new UpdateJobFunctor();
    private final UpdateJobFunctor mUpdateJobFunctor = new UpdateJobFunctor();
@@ -66,6 +68,8 @@ public final class BackgroundJobsController extends StateController {
    public BackgroundJobsController(JobSchedulerService service) {
    public BackgroundJobsController(JobSchedulerService service) {
        super(service);
        super(service);


        mActivityManagerInternal = (ActivityManagerInternal) Objects.requireNonNull(
                LocalServices.getService(ActivityManagerInternal.class));
        mAppStateTracker = (AppStateTrackerImpl) Objects.requireNonNull(
        mAppStateTracker = (AppStateTrackerImpl) Objects.requireNonNull(
                LocalServices.getService(AppStateTracker.class));
                LocalServices.getService(AppStateTracker.class));
        mAppStateTracker.addListener(mForceAppStandbyListener);
        mAppStateTracker.addListener(mForceAppStandbyListener);
@@ -216,7 +220,8 @@ public final class BackgroundJobsController extends StateController {
        }
        }
        boolean didChange =
        boolean didChange =
                jobStatus.setBackgroundNotRestrictedConstraintSatisfied(nowElapsed, canRun,
                jobStatus.setBackgroundNotRestrictedConstraintSatisfied(nowElapsed, canRun,
                        !mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, packageName));
                        !mActivityManagerInternal.isBgAutoRestrictedBucketFeatureFlagEnabled()
                        && !mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(uid, packageName));
        didChange |= jobStatus.setUidActive(isActive);
        didChange |= jobStatus.setUidActive(isActive);
        return didChange;
        return didChange;
    }
    }
+31 −0
Original line number Original line Diff line number Diff line
@@ -724,4 +724,35 @@ public abstract class ActivityManagerInternal {
     * Get the restriction level of the given package for given user id.
     * Get the restriction level of the given package for given user id.
     */
     */
    public abstract @RestrictionLevel int getRestrictionLevel(String pkg, @UserIdInt int userId);
    public abstract @RestrictionLevel int getRestrictionLevel(String pkg, @UserIdInt int userId);

    /**
     * Get whether or not apps would be put into restricted standby bucket automatically
     * when it's background-restricted.
     */
    public abstract boolean isBgAutoRestrictedBucketFeatureFlagEnabled();

    /**
     * A listener interface, which will be notified on background restriction changes.
     */
    public interface AppBackgroundRestrictionListener {
        /**
         * Called when the background restriction level of given uid/package is changed.
         */
        default void onRestrictionLevelChanged(int uid, String packageName,
                @RestrictionLevel int newLevel) {
        }

        /**
         * Called when toggling the feature flag of moving to restricted standby bucket
         * automatically on background-restricted.
         */
        default void onAutoRestrictedBucketFeatureFlagChanged(boolean autoRestrictedBucket) {
        }
    }

    /**
     * Register the background restriction listener callback.
     */
    public abstract void addAppBackgroundRestrictionListener(
            @NonNull AppBackgroundRestrictionListener listener);
}
}
+11 −0
Original line number Original line Diff line number Diff line
@@ -16838,6 +16838,17 @@ public class ActivityManagerService extends IActivityManager.Stub
        public @RestrictionLevel int getRestrictionLevel(String pkg, @UserIdInt int userId) {
        public @RestrictionLevel int getRestrictionLevel(String pkg, @UserIdInt int userId) {
            return mAppRestrictionController.getRestrictionLevel(pkg, userId);
            return mAppRestrictionController.getRestrictionLevel(pkg, userId);
        }
        }
        @Override
        public boolean isBgAutoRestrictedBucketFeatureFlagEnabled() {
            return mAppRestrictionController.isBgAutoRestrictedBucketFeatureFlagEnabled();
        }
        @Override
        public void addAppBackgroundRestrictionListener(
                @NonNull ActivityManagerInternal.AppBackgroundRestrictionListener listener) {
            mAppRestrictionController.addAppBackgroundRestrictionListener(listener);
        }
    }
    }
    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
+135 −29
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@ import static android.app.usage.UsageStatsManager.REASON_SUB_DEFAULT_UNDEFINED;
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED;
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED;
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION;
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_USER_FLAG_INTERACTION;
import static android.app.usage.UsageStatsManager.REASON_SUB_MASK;
import static android.app.usage.UsageStatsManager.REASON_SUB_MASK;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_UPDATE;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
@@ -55,6 +56,7 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityManager.RestrictionLevel;
import android.app.ActivityManager.RestrictionLevel;
import android.app.ActivityManagerInternal.AppBackgroundRestrictionListener;
import android.app.ActivityThread;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.IActivityManager;
@@ -62,11 +64,13 @@ import android.app.IUidObserver;
import android.app.usage.AppStandbyInfo;
import android.app.usage.AppStandbyInfo;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
import android.net.Uri;
import android.net.Uri;
import android.os.Handler;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.HandlerThread;
@@ -78,6 +82,7 @@ import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DeviceConfig.Properties;
import android.provider.DeviceConfig.Properties;
import android.provider.Settings.Global;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArrayMap;
import android.util.SparseArrayMap;
import android.util.TimeUtils;
import android.util.TimeUtils;
@@ -99,6 +104,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Comparator;
import java.util.List;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Consumer;


/**
/**
 * This class tracks various state of the apps and mutates their restriction levels accordingly.
 * This class tracks various state of the apps and mutates their restriction levels accordingly.
@@ -126,7 +132,7 @@ public final class AppRestrictionController {
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final RestrictionSettings mRestrictionSettings = new RestrictionSettings();
    private final RestrictionSettings mRestrictionSettings = new RestrictionSettings();


    private final CopyOnWriteArraySet<AppRestrictionLevelListener> mRestrictionLevelListeners =
    private final CopyOnWriteArraySet<AppBackgroundRestrictionListener> mRestrictionListeners =
            new CopyOnWriteArraySet<>();
            new CopyOnWriteArraySet<>();


    /**
    /**
@@ -312,6 +318,13 @@ public final class AppRestrictionController {
            }
            }
        }
        }


        @GuardedBy("mLock")
        void forEachUidLocked(@NonNull Consumer<Integer> consumer) {
            for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
                consumer.accept(mRestrictionLevels.keyAt(i));
            }
        }

        void removeUser(@UserIdInt int userId) {
        void removeUser(@UserIdInt int userId) {
            synchronized (mLock) {
            synchronized (mLock) {
                for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
                for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
@@ -353,18 +366,80 @@ public final class AppRestrictionController {
        }
        }
    }
    }


    private final OnPropertiesChangedListener mOnDeviceConfigChangedListener =
    final class ConstantsObserver extends ContentObserver implements
            new OnPropertiesChangedListener() {
            OnPropertiesChangedListener {
        /**
         * Whether or not to set the app to restricted standby bucket automatically
         * when it's background-restricted.
         */
        static final String KEY_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION =
                    DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "auto_restricted_bucket_on_bg_restricted";

        static final boolean DEFAULT_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION = true;

        volatile boolean mBgAutoRestrictedBucket;

        volatile boolean mRestrictedBucketEnabled;

        ConstantsObserver(Handler handler) {
            super(handler);
        }

        @Override
        @Override
        public void onPropertiesChanged(Properties properties) {
        public void onPropertiesChanged(Properties properties) {
            for (String name : properties.getKeyset()) {
            for (String name : properties.getKeyset()) {
                if (name == null || !name.startsWith(DEVICE_CONFIG_SUBNAMESPACE_PREFIX)) {
                if (name == null || !name.startsWith(DEVICE_CONFIG_SUBNAMESPACE_PREFIX)) {
                    return;
                    return;
                }
                }
                switch (name) {
                    case KEY_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION:
                        updateBgAutoRestrictedBucketChanged();
                        break;
                }
                AppRestrictionController.this.onPropertiesChanged(name);
                AppRestrictionController.this.onPropertiesChanged(name);
            }
            }
        }
        }
            };

        @Override
        public void onChange(boolean selfChange) {
            updateSettings();
        }

        public void start() {
            final ContentResolver cr = mContext.getContentResolver();
            cr.registerContentObserver(Global.getUriFor(Global.ENABLE_RESTRICTED_BUCKET),
                    false, this);
            updateSettings();
            updateDeviceConfig();
        }

        void updateSettings() {
            mRestrictedBucketEnabled = isRestrictedBucketEnabled();
        }

        private boolean isRestrictedBucketEnabled() {
            return Global.getInt(mContext.getContentResolver(),
                    Global.ENABLE_RESTRICTED_BUCKET,
                    Global.DEFAULT_ENABLE_RESTRICTED_BUCKET) == 1;
        }

        void updateDeviceConfig() {
            updateBgAutoRestrictedBucketChanged();
        }

        private void updateBgAutoRestrictedBucketChanged() {
            boolean oldValue = mBgAutoRestrictedBucket;
            mBgAutoRestrictedBucket = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION,
                    DEFAULT_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION);
            if (oldValue != mBgAutoRestrictedBucket) {
                dispatchAutoRestrictedBucketFeatureFlagChanged(mBgAutoRestrictedBucket);
            }
        }
    }

    private final ConstantsObserver mConstantsObserver;


    private final AppStateTracker.BackgroundRestrictedAppListener mBackgroundRestrictionListener =
    private final AppStateTracker.BackgroundRestrictedAppListener mBackgroundRestrictionListener =
            new AppStateTracker.BackgroundRestrictedAppListener() {
            new AppStateTracker.BackgroundRestrictedAppListener() {
@@ -422,20 +497,11 @@ public final class AppRestrictionController {
            };
            };


    /**
    /**
     * A listener interface, which will be notified on restriction level changes.
     * Register the background restriction listener callback.
     */
    public interface AppRestrictionLevelListener {
        /**
         * Called when the restriction level of given uid/package is changed.
         */
        void onRestrictionLevelChanged(int uid, String packageName, @RestrictionLevel int newLevel);
    }

    /**
     * Register the restriction level listener callback.
     */
     */
    public void addAppRestrictionLevelListener(@NonNull AppRestrictionLevelListener listener) {
    public void addAppBackgroundRestrictionListener(
        mRestrictionLevelListeners.add(listener);
            @NonNull AppBackgroundRestrictionListener listener) {
        mRestrictionListeners.add(listener);
    }
    }


    AppRestrictionController(final Context context) {
    AppRestrictionController(final Context context) {
@@ -448,13 +514,14 @@ public final class AppRestrictionController {
        mBgHandlerThread = new HandlerThread("bgres-controller");
        mBgHandlerThread = new HandlerThread("bgres-controller");
        mBgHandlerThread.start();
        mBgHandlerThread.start();
        mBgHandler = new BgHandler(mBgHandlerThread.getLooper(), injector);
        mBgHandler = new BgHandler(mBgHandlerThread.getLooper(), injector);
        mConstantsObserver = new ConstantsObserver(mBgHandler);
        injector.initAppStateTrackers(this);
        injector.initAppStateTrackers(this);
    }
    }


    void onSystemReady() {
    void onSystemReady() {
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                ActivityThread.currentApplication().getMainExecutor(),
                ActivityThread.currentApplication().getMainExecutor(), mConstantsObserver);
                mOnDeviceConfigChangedListener);
        mConstantsObserver.start();
        initRestrictionStates();
        initRestrictionStates();
        registerForUidObservers();
        registerForUidObservers();
        registerForSystemBroadcasts();
        registerForSystemBroadcasts();
@@ -559,7 +626,8 @@ public final class AppRestrictionController {
                        .isAppBackgroundRestricted(uid, packageName)) {
                        .isAppBackgroundRestricted(uid, packageName)) {
                    return RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
                    return RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
                }
                }
                level = standbyBucket == STANDBY_BUCKET_RESTRICTED
                level = mConstantsObserver.mRestrictedBucketEnabled
                        && standbyBucket == STANDBY_BUCKET_RESTRICTED
                        ? RESTRICTION_LEVEL_RESTRICTED_BUCKET
                        ? RESTRICTION_LEVEL_RESTRICTED_BUCKET
                        : RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
                        : RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
                if (calcTrackers) {
                if (calcTrackers) {
@@ -594,9 +662,13 @@ public final class AppRestrictionController {
     */
     */
    private @RestrictionLevel int calcAppRestrictionLevelFromTackers(int uid, String packageName) {
    private @RestrictionLevel int calcAppRestrictionLevelFromTackers(int uid, String packageName) {
        @RestrictionLevel int level = RESTRICTION_LEVEL_UNKNOWN;
        @RestrictionLevel int level = RESTRICTION_LEVEL_UNKNOWN;
        final boolean isRestrictedBucketEnabled = mConstantsObserver.mRestrictedBucketEnabled;
        for (int i = mAppStateTrackers.size() - 1; i >= 0; i--) {
        for (int i = mAppStateTrackers.size() - 1; i >= 0; i--) {
            @RestrictionLevel int l = mAppStateTrackers.get(i).getPolicy()
            @RestrictionLevel int l = mAppStateTrackers.get(i).getPolicy()
                    .getProposedRestrictionLevel(packageName, uid);
                    .getProposedRestrictionLevel(packageName, uid);
            if (!isRestrictedBucketEnabled && l == RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
                l = RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
            }
            level = Math.max(level, l);
            level = Math.max(level, l);
        }
        }
        return level;
        return level;
@@ -660,6 +732,10 @@ public final class AppRestrictionController {
        final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
        final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
        if (level >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
        if (level >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
                && curLevel < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
                && curLevel < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
            if (!mConstantsObserver.mRestrictedBucketEnabled
                    || !mConstantsObserver.mBgAutoRestrictedBucket) {
                return;
            }
            // Moving the app standby bucket to restricted in the meanwhile.
            // Moving the app standby bucket to restricted in the meanwhile.
            if (DEBUG_BG_RESTRICTION_CONTROLLER
            if (DEBUG_BG_RESTRICTION_CONTROLLER
                    && level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
                    && level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
@@ -736,10 +812,36 @@ public final class AppRestrictionController {


    private void dispatchAppRestrictionLevelChanges(int uid, String pkgName,
    private void dispatchAppRestrictionLevelChanges(int uid, String pkgName,
            @RestrictionLevel int newLevel) {
            @RestrictionLevel int newLevel) {
        mRestrictionLevelListeners.forEach(
        mRestrictionListeners.forEach(
                l -> l.onRestrictionLevelChanged(uid, pkgName, newLevel));
                l -> l.onRestrictionLevelChanged(uid, pkgName, newLevel));
    }
    }


    private void dispatchAutoRestrictedBucketFeatureFlagChanged(boolean newValue) {
        final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
        final ArrayList<Runnable> pendingTasks = new ArrayList<>();
        synchronized (mLock) {
            mRestrictionSettings.forEachUidLocked(uid -> {
                mRestrictionSettings.forEachPackageInUidLocked(uid, (pkgName, level, reason) -> {
                    if (level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
                        pendingTasks.add(newValue
                                ? () -> appStandbyInternal.restrictApp(pkgName,
                                UserHandle.getUserId(uid), reason & REASON_MAIN_MASK,
                                reason & REASON_SUB_MASK)
                                : () -> appStandbyInternal.maybeUnrestrictApp(pkgName,
                                UserHandle.getUserId(uid), reason & REASON_MAIN_MASK,
                                reason & REASON_SUB_MASK, REASON_MAIN_USAGE,
                                REASON_SUB_USAGE_SYSTEM_UPDATE));
                    }
                });
            });
        }
        for (int i = 0; i < pendingTasks.size(); i++) {
            pendingTasks.get(i).run();
        }
        mRestrictionListeners.forEach(
                l -> l.onAutoRestrictedBucketFeatureFlagChanged(newValue));
    }

    private void handleAppStandbyBucketChanged(int bucket, String packageName,
    private void handleAppStandbyBucketChanged(int bucket, String packageName,
            @UserIdInt int userId) {
            @UserIdInt int userId) {
        final int uid = mInjector.getPackageManagerInternal().getPackageUid(
        final int uid = mInjector.getPackageManagerInternal().getPackageUid(
@@ -1064,6 +1166,10 @@ public final class AppRestrictionController {
        mRestrictionSettings.removeUid(uid);
        mRestrictionSettings.removeUid(uid);
    }
    }


    boolean isBgAutoRestrictedBucketFeatureFlagEnabled() {
        return mConstantsObserver.mBgAutoRestrictedBucket;
    }

    private void onPropertiesChanged(String name) {
    private void onPropertiesChanged(String name) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onPropertiesChanged(name);
            mAppStateTrackers.get(i).onPropertiesChanged(name);
Loading