/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.am;

import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
import static android.app.ActivityManager.RESTRICTION_LEVEL_EXEMPTED;
import static android.app.ActivityManager.RESTRICTION_LEVEL_HIBERNATION;
import static android.app.ActivityManager.RESTRICTION_LEVEL_MAX;
import static android.app.ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET;
import static android.app.ActivityManager.RESTRICTION_LEVEL_UNKNOWN;
import static android.app.ActivityManager.RESTRICTION_LEVEL_UNRESTRICTED;
import static android.app.ActivityManager.UID_OBSERVER_ACTIVE;
import static android.app.ActivityManager.UID_OBSERVER_GONE;
import static android.app.ActivityManager.UID_OBSERVER_IDLE;
import static android.app.ActivityManager.UID_OBSERVER_PROCSTATE;
import static android.app.usage.UsageStatsManager.REASON_MAIN_DEFAULT;
import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_USER;
import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
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_USER_FLAG_INTERACTION;
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.STANDBY_BUCKET_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
import static android.app.usage.UsageStatsManager.reasonToString;
import static android.content.Intent.ACTION_SHOW_FOREGROUND_SERVICE_MANAGER;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
import static android.os.PowerExemptionManager.REASON_ACTIVE_DEVICE_ADMIN;
import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
import static android.os.PowerExemptionManager.REASON_CARRIER_PRIVILEGED_APP;
import static android.os.PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER;
import static android.os.PowerExemptionManager.REASON_DENIED;
import static android.os.PowerExemptionManager.REASON_DEVICE_DEMO_MODE;
import static android.os.PowerExemptionManager.REASON_DEVICE_OWNER;
import static android.os.PowerExemptionManager.REASON_DISALLOW_APPS_CONTROL;
import static android.os.PowerExemptionManager.REASON_DPO_PROTECTED_APP;
import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_PLATFORM_VPN;
import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_VPN;
import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT;
import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
import static android.os.PowerExemptionManager.REASON_PROFILE_OWNER;
import static android.os.PowerExemptionManager.REASON_ROLE_DIALER;
import static android.os.PowerExemptionManager.REASON_ROLE_EMERGENCY;
import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
import static android.os.PowerExemptionManager.REASON_SYSTEM_MODULE;
import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
import static android.os.PowerExemptionManager.getExemptionReasonForStatsd;
import static android.os.PowerExemptionManager.reasonCodeToString;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;

import static com.android.internal.notification.SystemNotificationChannels.ABUSIVE_BACKGROUND_APPS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.AppFGSTracker.foregroundServiceTypeToIndex;
import static com.android.server.am.BaseAppStateTracker.ONE_DAY;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManager.RestrictionLevel;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal.AppBackgroundRestrictionListener;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.IUidObserver;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.app.usage.AppStandbyInfo;
import android.app.usage.UsageStatsManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ServiceInfo;
import android.content.pm.ServiceInfo.ForegroundServiceType;
import android.database.ContentObserver;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.AppBackgroundRestrictionsInfo;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.PowerExemptionManager.ReasonCode;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DeviceConfig.Properties;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseArrayMap;
import android.util.TimeUtils;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.function.TriConsumer;
import com.android.server.AppStateTracker;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.am.AppBatteryTracker.ImmutableBatteryUsage;
import com.android.server.apphibernation.AppHibernationManagerInternal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.usage.AppStandbyInternal;
import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

/**
 * This class tracks various state of the apps and mutates their restriction levels accordingly.
 */
public final class AppRestrictionController {
    static final String TAG = TAG_WITH_CLASS_NAME ? "AppRestrictionController" : TAG_AM;
    static final boolean DEBUG_BG_RESTRICTION_CONTROLLER = false;

    /**
     * The prefix for the sub-namespace of our device configs under
     * the {@link android.provider.DeviceConfig#NAMESPACE_ACTIVITY_MANAGER}.
     */
    static final String DEVICE_CONFIG_SUBNAMESPACE_PREFIX = "bg_";

    static final int STOCK_PM_FLAGS = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
            | MATCH_DISABLED_UNTIL_USED_COMPONENTS;

    /**
     * Whether or not to show the foreground service manager on tapping notifications.
     */
    private static final boolean ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER = true;

    /**
     * Whether or not to show the action to the foreground service manager when
     * posting the notification for background restriction.
     */
    private static final boolean ENABLE_SHOW_FGS_MANAGER_ACTION_ON_BG_RESTRICTION = false;

    private static final String APP_RESTRICTION_SETTINGS_DIRNAME = "apprestriction";
    private static final String APP_RESTRICTION_SETTINGS_FILENAME = "settings.xml";

    private static final String TAG_SETTINGS = "settings";
    private static final String ATTR_PACKAGE = "package";
    private static final String ATTR_UID = "uid";
    private static final String ATTR_CUR_LEVEL = "curlevel";
    private static final String ATTR_LEVEL_TS = "levelts";
    private static final String ATTR_REASON = "reason";

    private static final String[] ROLES_IN_INTEREST = {
        RoleManager.ROLE_DIALER,
        RoleManager.ROLE_EMERGENCY,
    };

    private final Context mContext;
    private final HandlerThread mBgHandlerThread;
    private final BgHandler mBgHandler;
    private final HandlerExecutor mBgExecutor;

    // No lock is needed, as it's immutable after initialization in constructor.
    private final ArrayList<BaseAppStateTracker> mAppStateTrackers = new ArrayList<>();

    @VisibleForTesting
    @GuardedBy("mSettingsLock")
    final RestrictionSettings mRestrictionSettings = new RestrictionSettings();

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

    /**
     * A mapping between the UID/Pkg and its pending work which should be triggered on inactive;
     * an active UID/pkg pair should have an entry here, although its pending work could be null.
     */
    @GuardedBy("mSettingsLock")
    private final SparseArrayMap<String, Runnable> mActiveUids = new SparseArrayMap<>();

    // No lock is needed as it's accessed in bg handler thread only.
    private final ArrayList<Runnable> mTmpRunnables = new ArrayList<>();

    /**
     * Power-save allowlisted app-ids (not including except-idle-allowlisted ones).
     */
    private int[] mDeviceIdleAllowlist = new int[0]; // No lock is needed.

    /**
     * Power-save allowlisted app-ids (including except-idle-allowlisted ones).
     */
    private int[] mDeviceIdleExceptIdleAllowlist = new int[0]; // No lock is needed.

    /**
     * The pre-configured system app-ids in the power-save allow list.
     *
     * @see #mDeviceIdleAllowlist.
     */
    private final ArraySet<Integer> mSystemDeviceIdleAllowlist = new ArraySet<>();

    /**
     * The pre-configured system app-ids in the power-save allow list, except-idle.
     *
     * @see #mDeviceIdleExceptIdleAllowlist.
     */
    private final ArraySet<Integer> mSystemDeviceIdleExceptIdleAllowlist = new ArraySet<>();

    private final Object mLock = new Object();
    private final Object mSettingsLock = new Object();
    private final Injector mInjector;
    private final NotificationHelper mNotificationHelper;

    private final OnRoleHoldersChangedListener mRoleHolderChangedListener =
            this::onRoleHoldersChanged;

    /**
     * The key is the UID, the value is the list of the roles it holds.
     */
    @GuardedBy("mLock")
    private final SparseArray<ArrayList<String>> mUidRolesMapping = new SparseArray<>();

    /**
     * Cache the package name and information about if it's a system module.
     */
    @GuardedBy("mLock")
    private final HashMap<String, Boolean> mSystemModulesCache = new HashMap<>();

    /**
     * The pre-config packages that are exempted from the background restrictions.
     */
    ArraySet<String> mBgRestrictionExemptioFromSysConfig;

    /**
     * Lock specifically for bookkeeping around the carrier-privileged app set.
     * Do not acquire any other locks while holding this one. Methods that
     * require this lock to be held are named with a "CPL" suffix.
     */
    private final Object mCarrierPrivilegedLock = new Object();

    /**
     * List of carrier-privileged apps that should be excluded from standby.
     */
    @GuardedBy("mCarrierPrivilegedLock")
    private List<String> mCarrierPrivilegedApps;

    /**
     * Whether or not we've loaded the restriction settings from the persistent storage.
     */
    private final AtomicBoolean mRestrictionSettingsXmlLoaded = new AtomicBoolean();

    final ActivityManagerService mActivityManagerService;

    static final int TRACKER_TYPE_UNKNOWN = 0;
    static final int TRACKER_TYPE_BATTERY = 1;
    static final int TRACKER_TYPE_BATTERY_EXEMPTION = 2;
    static final int TRACKER_TYPE_FGS = 3;
    static final int TRACKER_TYPE_MEDIA_SESSION = 4;
    static final int TRACKER_TYPE_PERMISSION = 5;
    static final int TRACKER_TYPE_BROADCAST_EVENTS = 6;
    static final int TRACKER_TYPE_BIND_SERVICE_EVENTS = 7;
    @IntDef(prefix = { "TRACKER_TYPE_" }, value = {
            TRACKER_TYPE_UNKNOWN,
            TRACKER_TYPE_BATTERY,
            TRACKER_TYPE_BATTERY_EXEMPTION,
            TRACKER_TYPE_FGS,
            TRACKER_TYPE_MEDIA_SESSION,
            TRACKER_TYPE_PERMISSION,
            TRACKER_TYPE_BROADCAST_EVENTS,
            TRACKER_TYPE_BIND_SERVICE_EVENTS,
    })
    @interface TrackerType {}

    private final TrackerInfo mEmptyTrackerInfo = new TrackerInfo();

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            switch (intent.getAction()) {
                case Intent.ACTION_PACKAGE_ADDED: {
                    if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                        final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
                        if (uid >= 0) {
                            onUidAdded(uid);
                        }
                    }
                }
                // fall through.
                case Intent.ACTION_PACKAGE_CHANGED: {
                    final String pkgName = intent.getData().getSchemeSpecificPart();
                    final String[] cmpList = intent.getStringArrayExtra(
                            Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
                    // If this is PACKAGE_ADDED (cmpList == null), or if it's a whole-package
                    // enable/disable event (cmpList is just the package name itself), drop
                    // our carrier privileged app & system-app caches and let them refresh
                    if (cmpList == null
                            || (cmpList.length == 1 && pkgName.equals(cmpList[0]))) {
                        clearCarrierPrivilegedApps();
                    }
                } break;
                case Intent.ACTION_PACKAGE_FULLY_REMOVED: {
                    final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
                    final Uri data = intent.getData();
                    String ssp;
                    if (uid >= 0 && data != null
                            && (ssp = data.getSchemeSpecificPart()) != null) {
                        onPackageRemoved(ssp, uid);
                    }
                } break;
                case Intent.ACTION_UID_REMOVED: {
                    if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                        final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
                        if (uid >= 0) {
                            onUidRemoved(uid);
                        }
                    }
                } break;
                case Intent.ACTION_USER_ADDED: {
                    final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                    if (userId >= 0) {
                        onUserAdded(userId);
                    }
                } break;
                case Intent.ACTION_USER_STARTED: {
                    final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                    if (userId >= 0) {
                        onUserStarted(userId);
                    }
                } break;
                case Intent.ACTION_USER_STOPPED: {
                    final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                    if (userId >= 0) {
                        onUserStopped(userId);
                    }
                } break;
                case Intent.ACTION_USER_REMOVED: {
                    final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                    if (userId >= 0) {
                        onUserRemoved(userId);
                    }
                } break;
            }
        }
    };

    private final BroadcastReceiver mBootReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            switch (intent.getAction()) {
                case Intent.ACTION_LOCKED_BOOT_COMPLETED: {
                    onLockedBootCompleted();
                } break;
            }
        }
    };

    /**
     * The restriction levels that each package is on, the levels here are defined in
     * {@link android.app.ActivityManager.RESTRICTION_LEVEL_*}.
     */
    final class RestrictionSettings {
        @GuardedBy("mSettingsLock")
        final SparseArrayMap<String, PkgSettings> mRestrictionLevels = new SparseArrayMap();

        final class PkgSettings {
            private final String mPackageName;
            private final int mUid;

            private @RestrictionLevel int mCurrentRestrictionLevel;
            private @RestrictionLevel int mLastRestrictionLevel;
            private @CurrentTimeMillisLong long mLevelChangeTime;
            private int mReason;

            private @CurrentTimeMillisLong long[] mLastNotificationShownTime;
            private int[] mNotificationId;

            PkgSettings(String packageName, int uid) {
                mPackageName = packageName;
                mUid = uid;
                mCurrentRestrictionLevel = mLastRestrictionLevel = RESTRICTION_LEVEL_UNKNOWN;
            }

            @GuardedBy("mSettingsLock")
            @RestrictionLevel int update(@RestrictionLevel int level, int reason, int subReason) {
                if (level != mCurrentRestrictionLevel) {
                    mLastRestrictionLevel = mCurrentRestrictionLevel;
                    mCurrentRestrictionLevel = level;
                    mLevelChangeTime = mInjector.currentTimeMillis();
                    mReason = (REASON_MAIN_MASK & reason) | (REASON_SUB_MASK & subReason);
                    mBgHandler.obtainMessage(BgHandler.MSG_APP_RESTRICTION_LEVEL_CHANGED,
                            mUid, level, mPackageName).sendToTarget();
                }
                return mLastRestrictionLevel;
            }

            @Override
            @GuardedBy("mSettingsLock")
            public String toString() {
                final StringBuilder sb = new StringBuilder(128);
                sb.append("RestrictionLevel{");
                sb.append(Integer.toHexString(System.identityHashCode(this)));
                sb.append(':');
                sb.append(mPackageName);
                sb.append('/');
                sb.append(UserHandle.formatUid(mUid));
                sb.append('}');
                sb.append(' ');
                sb.append(ActivityManager.restrictionLevelToName(mCurrentRestrictionLevel));
                sb.append('(');
                sb.append(reasonToString(mReason));
                sb.append(')');
                return sb.toString();
            }

            void dump(PrintWriter pw, @CurrentTimeMillisLong long now) {
                synchronized (mSettingsLock) {
                    pw.print(toString());
                    if (mLastRestrictionLevel != RESTRICTION_LEVEL_UNKNOWN) {
                        pw.print('/');
                        pw.print(ActivityManager.restrictionLevelToName(mLastRestrictionLevel));
                    }
                    pw.print(" levelChange=");
                    TimeUtils.formatDuration(mLevelChangeTime - now, pw);
                    if (mLastNotificationShownTime != null) {
                        for (int i = 0; i < mLastNotificationShownTime.length; i++) {
                            if (mLastNotificationShownTime[i] > 0) {
                                pw.print(" lastNoti(");
                                pw.print(mNotificationHelper.notificationTypeToString(i));
                                pw.print(")=");
                                TimeUtils.formatDuration(mLastNotificationShownTime[i] - now, pw);
                            }
                        }
                    }
                }
                pw.print(" effectiveExemption=");
                pw.print(reasonCodeToString(getBackgroundRestrictionExemptionReason(mUid)));
            }

            String getPackageName() {
                return mPackageName;
            }

            int getUid() {
                return mUid;
            }

            @GuardedBy("mSettingsLock")
            @RestrictionLevel int getCurrentRestrictionLevel() {
                return mCurrentRestrictionLevel;
            }

            @GuardedBy("mSettingsLock")
            @RestrictionLevel int getLastRestrictionLevel() {
                return mLastRestrictionLevel;
            }

            @GuardedBy("mSettingsLock")
            int getReason() {
                return mReason;
            }

            @GuardedBy("mSettingsLock")
            @CurrentTimeMillisLong long getLastNotificationTime(
                    @NotificationHelper.NotificationType int notificationType) {
                if (mLastNotificationShownTime == null) {
                    return 0;
                }
                return mLastNotificationShownTime[notificationType];
            }

            @GuardedBy("mSettingsLock")
            void setLastNotificationTime(@NotificationHelper.NotificationType int notificationType,
                    @CurrentTimeMillisLong long timestamp) {
                setLastNotificationTime(notificationType, timestamp, true);
            }

            @VisibleForTesting
            @GuardedBy("mSettingsLock")
            void setLastNotificationTime(@NotificationHelper.NotificationType int notificationType,
                    @CurrentTimeMillisLong long timestamp, boolean persist) {
                if (mLastNotificationShownTime == null) {
                    mLastNotificationShownTime =
                            new long[NotificationHelper.NOTIFICATION_TYPE_LAST];
                }
                mLastNotificationShownTime[notificationType] = timestamp;
                if (persist && mRestrictionSettingsXmlLoaded.get()) {
                    schedulePersistToXml(UserHandle.getUserId(mUid));
                }
            }

            @GuardedBy("mSettingsLock")
            int getNotificationId(@NotificationHelper.NotificationType int notificationType) {
                if (mNotificationId == null) {
                    return 0;
                }
                return mNotificationId[notificationType];
            }

            @GuardedBy("mSettingsLock")
            void setNotificationId(@NotificationHelper.NotificationType int notificationType,
                    int notificationId) {
                if (mNotificationId == null) {
                    mNotificationId = new int[NotificationHelper.NOTIFICATION_TYPE_LAST];
                }
                mNotificationId[notificationType] = notificationId;
            }

            @VisibleForTesting
            @GuardedBy("mSettingsLock")
            void setLevelChangeTime(@CurrentTimeMillisLong long timestamp) {
                mLevelChangeTime = timestamp;
            }

            @GuardedBy("mSettingsLock")
            @Override
            public Object clone() {
                final PkgSettings newObj = new PkgSettings(mPackageName, mUid);
                newObj.mCurrentRestrictionLevel = mCurrentRestrictionLevel;
                newObj.mLastRestrictionLevel = mLastRestrictionLevel;
                newObj.mLevelChangeTime = mLevelChangeTime;
                newObj.mReason = mReason;
                if (mLastNotificationShownTime != null) {
                    newObj.mLastNotificationShownTime = Arrays.copyOf(
                            mLastNotificationShownTime, mLastNotificationShownTime.length);
                }
                if (mNotificationId != null) {
                    newObj.mNotificationId = Arrays.copyOf(mNotificationId, mNotificationId.length);
                }
                return newObj;
            }

            @GuardedBy("mSettingsLock")
            @Override
            public boolean equals(Object other) {
                if (other == this) {
                    return true;
                }
                if (other == null || !(other instanceof PkgSettings)) {
                    return false;
                }
                final PkgSettings otherSettings = (PkgSettings) other;
                return otherSettings.mUid == mUid
                        && otherSettings.mCurrentRestrictionLevel == mCurrentRestrictionLevel
                        && otherSettings.mLastRestrictionLevel == mLastRestrictionLevel
                        && otherSettings.mLevelChangeTime == mLevelChangeTime
                        && otherSettings.mReason == mReason
                        && TextUtils.equals(otherSettings.mPackageName, mPackageName)
                        && Arrays.equals(otherSettings.mLastNotificationShownTime,
                                mLastNotificationShownTime)
                        && Arrays.equals(otherSettings.mNotificationId, mNotificationId);
            }
        }

        /**
         * Update the restriction level.
         *
         * @return The previous restriction level.
         */
        @RestrictionLevel int update(String packageName, int uid, @RestrictionLevel int level,
                int reason, int subReason) {
            synchronized (mSettingsLock) {
                PkgSettings settings = getRestrictionSettingsLocked(uid, packageName);
                if (settings == null) {
                    settings = new PkgSettings(packageName, uid);
                    mRestrictionLevels.add(uid, packageName, settings);
                }
                return settings.update(level, reason, subReason);
            }
        }

        /**
         * @return The reason of why it's in this level.
         */
        int getReason(String packageName, int uid) {
            synchronized (mSettingsLock) {
                final PkgSettings settings = mRestrictionLevels.get(uid, packageName);
                return settings != null ? settings.getReason()
                        : (REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED);
            }
        }

        @RestrictionLevel int getRestrictionLevel(int uid) {
            synchronized (mSettingsLock) {
                final int uidKeyIndex = mRestrictionLevels.indexOfKey(uid);
                if (uidKeyIndex < 0) {
                    return RESTRICTION_LEVEL_UNKNOWN;
                }
                final int numPackages = mRestrictionLevels.numElementsForKeyAt(uidKeyIndex);
                if (numPackages == 0) {
                    return RESTRICTION_LEVEL_UNKNOWN;
                }
                @RestrictionLevel int level = RESTRICTION_LEVEL_UNKNOWN;
                for (int i = 0; i < numPackages; i++) {
                    final PkgSettings setting = mRestrictionLevels.valueAt(uidKeyIndex, i);
                    if (setting != null) {
                        final @RestrictionLevel int l = setting.getCurrentRestrictionLevel();
                        level = (level == RESTRICTION_LEVEL_UNKNOWN) ? l : Math.min(level, l);
                    }
                }
                return level;
            }
        }

        @RestrictionLevel int getRestrictionLevel(int uid, String packageName) {
            synchronized (mSettingsLock) {
                final PkgSettings settings = getRestrictionSettingsLocked(uid, packageName);
                return settings == null
                        ? getRestrictionLevel(uid) : settings.getCurrentRestrictionLevel();
            }
        }

        @RestrictionLevel int getRestrictionLevel(String packageName, @UserIdInt int userId) {
            final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
            final int uid = pm.getPackageUid(packageName, STOCK_PM_FLAGS, userId);
            return getRestrictionLevel(uid, packageName);
        }

        private @RestrictionLevel int getLastRestrictionLevel(int uid, String packageName) {
            synchronized (mSettingsLock) {
                final PkgSettings settings = mRestrictionLevels.get(uid, packageName);
                return settings == null
                        ? RESTRICTION_LEVEL_UNKNOWN : settings.getLastRestrictionLevel();
            }
        }

        @GuardedBy("mSettingsLock")
        void forEachPackageInUidLocked(int uid,
                @NonNull TriConsumer<String, Integer, Integer> consumer) {
            final int uidKeyIndex = mRestrictionLevels.indexOfKey(uid);
            if (uidKeyIndex < 0) {
                return;
            }
            final int numPackages = mRestrictionLevels.numElementsForKeyAt(uidKeyIndex);
            for (int i = 0; i < numPackages; i++) {
                final PkgSettings settings = mRestrictionLevels.valueAt(uidKeyIndex, i);
                consumer.accept(mRestrictionLevels.keyAt(uidKeyIndex, i),
                        settings.getCurrentRestrictionLevel(), settings.getReason());
            }
        }

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

        @GuardedBy("mSettingsLock")
        PkgSettings getRestrictionSettingsLocked(int uid, String packageName) {
            return mRestrictionLevels.get(uid, packageName);
        }

        void removeUser(@UserIdInt int userId) {
            synchronized (mSettingsLock) {
                for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
                    final int uid = mRestrictionLevels.keyAt(i);
                    if (UserHandle.getUserId(uid) != userId) {
                        continue;
                    }
                    mRestrictionLevels.deleteAt(i);
                }
            }
        }

        void removePackage(String pkgName, int uid) {
            removePackage(pkgName, uid, true);
        }

        void removePackage(String pkgName, int uid, boolean persist) {
            synchronized (mSettingsLock) {
                final int keyIndex = mRestrictionLevels.indexOfKey(uid);
                mRestrictionLevels.delete(uid, pkgName);
                if (keyIndex >= 0 && mRestrictionLevels.numElementsForKeyAt(keyIndex) == 0) {
                    mRestrictionLevels.deleteAt(keyIndex);
                }
            }
            if (persist && mRestrictionSettingsXmlLoaded.get()) {
                schedulePersistToXml(UserHandle.getUserId(uid));
            }
        }

        void removeUid(int uid) {
            removeUid(uid, true);
        }

        void removeUid(int uid, boolean persist) {
            synchronized (mSettingsLock) {
                mRestrictionLevels.delete(uid);
            }
            if (persist && mRestrictionSettingsXmlLoaded.get()) {
                schedulePersistToXml(UserHandle.getUserId(uid));
            }
        }

        @VisibleForTesting
        void reset() {
            synchronized (mSettingsLock) {
                for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
                    mRestrictionLevels.deleteAt(i);
                }
            }
        }

        @VisibleForTesting
        void resetToDefault() {
            synchronized (mSettingsLock) {
                mRestrictionLevels.forEach(settings -> {
                    settings.mCurrentRestrictionLevel = RESTRICTION_LEVEL_UNKNOWN;
                    settings.mLastRestrictionLevel = RESTRICTION_LEVEL_UNKNOWN;
                    settings.mLevelChangeTime = 0L;
                    settings.mReason = REASON_MAIN_DEFAULT | REASON_SUB_DEFAULT_UNDEFINED;
                    if (settings.mLastNotificationShownTime != null) {
                        for (int i = 0; i < settings.mLastNotificationShownTime.length; i++) {
                            settings.mLastNotificationShownTime[i] = 0L;
                        }
                    }
                });
            }
        }

        void dump(PrintWriter pw, String prefix) {
            final ArrayList<PkgSettings> settings = new ArrayList<>();
            synchronized (mSettingsLock) {
                mRestrictionLevels.forEach(setting -> settings.add(setting));
            }
            Collections.sort(settings, Comparator.comparingInt(PkgSettings::getUid));
            final long now = mInjector.currentTimeMillis();
            for (int i = 0, size = settings.size(); i < size; i++) {
                pw.print(prefix);
                pw.print('#');
                pw.print(i);
                pw.print(' ');
                settings.get(i).dump(pw, now);
                pw.println();
            }
        }

        @VisibleForTesting
        void schedulePersistToXml(@UserIdInt int userId) {
            mBgHandler.obtainMessage(BgHandler.MSG_PERSIST_RESTRICTION_SETTINGS, userId, 0)
                    .sendToTarget();
        }

        @VisibleForTesting
        void scheduleLoadFromXml() {
            mBgHandler.sendEmptyMessage(BgHandler.MSG_LOAD_RESTRICTION_SETTINGS);
        }

        @VisibleForTesting
        File getXmlFileNameForUser(@UserIdInt int userId) {
            final File dir = new File(mInjector.getDataSystemDeDirectory(
                    userId), APP_RESTRICTION_SETTINGS_DIRNAME);
            return new File(dir, APP_RESTRICTION_SETTINGS_FILENAME);
        }

        @VisibleForTesting
        void loadFromXml(boolean applyLevel) {
            final int[] allUsers = mInjector.getUserManagerInternal().getUserIds();
            for (int userId : allUsers) {
                loadFromXml(userId, applyLevel);
            }
            mRestrictionSettingsXmlLoaded.set(true);
        }

        void loadFromXml(@UserIdInt int userId, boolean applyLevel) {
            final File file = getXmlFileNameForUser(userId);
            if (!file.exists()) {
                return;
            }
            final long[] ts = new long[NotificationHelper.NOTIFICATION_TYPE_LAST];
            try (InputStream in = new FileInputStream(file)) {
                final TypedXmlPullParser parser = Xml.resolvePullParser(in);
                final long now = SystemClock.elapsedRealtime();
                int type;
                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
                    if (type != XmlPullParser.START_TAG) {
                        continue;
                    }
                    final String tagName = parser.getName();
                    if (!TAG_SETTINGS.equals(tagName)) {
                        Slog.w(TAG, "Unexpected tag name: " + tagName);
                        continue;
                    }
                    loadOneFromXml(parser, now, ts, applyLevel);
                }
                if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                    Slog.i(TAG, "Loaded from " + file);
                }
            } catch (IOException | XmlPullParserException e) {
            }
        }

        private void loadOneFromXml(TypedXmlPullParser parser, long now, long[] ts,
                boolean applyLevel) {
            // Reset the buffer.
            for (int i = 0; i < ts.length; i++) {
                ts[i] = 0L;
            }
            // Walk through the attributes.
            int uid = 0;
            String packageName = null;
            int curLevel = RESTRICTION_LEVEL_UNKNOWN;
            int reason = REASON_MAIN_DEFAULT;
            long levelTs = 0L;
            for (int i = 0; i < parser.getAttributeCount(); i++) {
                try {
                    final String attrName = parser.getAttributeName(i);
                    final String attrValue = parser.getAttributeValue(i);
                    switch (attrName) {
                        case ATTR_UID:
                            uid = Integer.parseInt(attrValue);
                            break;
                        case ATTR_PACKAGE:
                            packageName = attrValue;
                            break;
                        case ATTR_CUR_LEVEL:
                            curLevel = Integer.parseInt(attrValue);
                            break;
                        case ATTR_LEVEL_TS:
                            levelTs = Long.parseLong(attrValue);
                            break;
                        case ATTR_REASON:
                            reason = Integer.parseInt(attrValue);
                            break;
                        default:
                            @NotificationHelper.NotificationType int type =
                                    NotificationHelper.notificationTimeAttrToType(attrName);
                            ts[type] = Long.parseLong(attrValue);
                            break;
                    }
                } catch (IllegalArgumentException e) {
                }
            }
            if (uid != 0) {
                if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                    Slog.i(TAG, "Restoring " + packageName + "/" + UserHandle.formatUid(uid)
                            + " level=" + curLevel + " reason=" + Integer.toHexString(reason)
                            + " ts=" + levelTs + " noti=" + Arrays.toString(ts));
                }
                final PkgSettings pkgSettings;
                synchronized (mSettingsLock) {
                    pkgSettings = getRestrictionSettingsLocked(uid, packageName);
                    if (pkgSettings == null) {
                        return;
                    }
                    for (int i = 0; i < ts.length; i++) {
                        if (pkgSettings.getLastNotificationTime(i) == 0 && ts[i] != 0) {
                            pkgSettings.setLastNotificationTime(i, ts[i], false);
                        }
                    }
                    if (pkgSettings.mCurrentRestrictionLevel >= curLevel) {
                        // The current restriction level is the same or more restrictive,
                        // don't restore.
                        return;
                    }
                }
                final int curBucket = mInjector.getAppStandbyInternal().getAppStandbyBucket(
                        packageName, UserHandle.getUserId(uid), now, false);
                if (applyLevel) {
                    applyRestrictionLevel(packageName, uid, curLevel, mEmptyTrackerInfo,
                            curBucket, true, reason & REASON_MAIN_MASK, reason & REASON_SUB_MASK);
                } else {
                    pkgSettings.update(curLevel,
                            reason & REASON_MAIN_MASK, reason & REASON_SUB_MASK);
                }
                synchronized (mSettingsLock) {
                    // Restore the mLevelChangeTime too.
                    pkgSettings.setLevelChangeTime(levelTs);
                }
            }
        }

        @VisibleForTesting
        void persistToXml(@UserIdInt int userId) {
            final File file = getXmlFileNameForUser(userId);
            final File dir = file.getParentFile();
            if (!dir.isDirectory() && !dir.mkdirs()) {
                Slog.w(TAG, "Failed to create folder for " + userId);
                return;
            }
            final AtomicFile atomicFile = new AtomicFile(file);
            FileOutputStream stream = null;
            try {
                stream = atomicFile.startWrite();
                stream.write(toXmlByteArray(userId));
            } catch (Exception e) {
                Slog.e(TAG, "Failed to write file " + file, e);
                if (stream != null) {
                    atomicFile.failWrite(stream);
                }
                return;
            }
            atomicFile.finishWrite(stream);
            if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                Slog.i(TAG, "Successfully written to " + atomicFile);
            }
        }

        private byte[] toXmlByteArray(@UserIdInt int userId) {
            try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
                final TypedXmlSerializer serializer = Xml.resolveSerializer(os);

                serializer.startDocument(/* encoding */ null, /* standalone */ true);

                synchronized (mSettingsLock) {
                    for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
                        for (int j = mRestrictionLevels.numElementsForKeyAt(i) - 1; j >= 0; j--) {
                            final PkgSettings settings = mRestrictionLevels.valueAt(i, j);
                            final int uid = settings.getUid();
                            if (UserHandle.getUserId(uid) != userId) {
                                continue;
                            }
                            serializer.startTag(null, TAG_SETTINGS);
                            serializer.attributeInt(null, ATTR_UID, uid);
                            serializer.attribute(null, ATTR_PACKAGE, settings.getPackageName());
                            serializer.attributeInt(null, ATTR_CUR_LEVEL,
                                    settings.mCurrentRestrictionLevel);
                            serializer.attributeLong(null, ATTR_LEVEL_TS,
                                    settings.mLevelChangeTime);
                            serializer.attributeInt(null, ATTR_REASON, settings.mReason);
                            for (int k = 0; k < NotificationHelper.NOTIFICATION_TYPE_LAST; k++) {
                                serializer.attributeLong(null,
                                        NotificationHelper.notificationTypeToTimeAttr(k),
                                        settings.getLastNotificationTime(k));
                            }
                            serializer.endTag(null, TAG_SETTINGS);
                        }
                    }
                }

                serializer.endDocument();
                serializer.flush();

                return os.toByteArray();
            } catch (IOException e) {
                return null;
            }
        }

        @VisibleForTesting
        void removeXml() {
            final int[] allUsers = mInjector.getUserManagerInternal().getUserIds();
            for (int userId : allUsers) {
                getXmlFileNameForUser(userId).delete();
            }
        }

        @Override
        public Object clone() {
            final RestrictionSettings newObj = new RestrictionSettings();
            synchronized (mSettingsLock) {
                for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
                    for (int j = mRestrictionLevels.numElementsForKeyAt(i) - 1; j >= 0; j--) {
                        final PkgSettings settings = mRestrictionLevels.valueAt(i, j);
                        newObj.mRestrictionLevels.add(mRestrictionLevels.keyAt(i),
                                mRestrictionLevels.keyAt(i, j), (PkgSettings) settings.clone());
                    }
                }
            }
            return newObj;
        }

        @Override
        public boolean equals(Object other) {
            if (other == this) {
                return true;
            }
            if (other == null || !(other instanceof RestrictionSettings)) {
                return false;
            }
            final SparseArrayMap<String, PkgSettings> otherSettings = ((RestrictionSettings) other)
                    .mRestrictionLevels;
            synchronized (mSettingsLock) {
                if (otherSettings.numMaps() != mRestrictionLevels.numMaps()) {
                    return false;
                }
                for (int i = mRestrictionLevels.numMaps() - 1; i >= 0; i--) {
                    final int uid = mRestrictionLevels.keyAt(i);
                    if (otherSettings.numElementsForKey(uid)
                            != mRestrictionLevels.numElementsForKeyAt(i)) {
                        return false;
                    }
                    for (int j = mRestrictionLevels.numElementsForKeyAt(i) - 1; j >= 0; j--) {
                        final PkgSettings settings = mRestrictionLevels.valueAt(i, j);
                        if (!settings.equals(otherSettings.get(uid, settings.getPackageName()))) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
    }

    final class ConstantsObserver extends ContentObserver implements
            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";

        /**
         * Whether or not to move the app to restricted standby level automatically
         * when system detects it's abusive.
         */
        static final String KEY_BG_AUTO_RESTRICT_ABUSIVE_APPS =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "auto_restrict_abusive_apps";

        /**
         * The minimal interval in ms before posting a notification again on abusive behaviors
         * of a certain package.
         */
        static final String KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "abusive_notification_minimal_interval";

        /**
         * The minimal interval in ms before posting a notification again on long running FGS
         * from a certain package.
         */
        static final String KEY_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "long_fgs_notification_minimal_interval";

        /**
         * The behavior for an app with a FGS and its notification is still showing, when the system
         * detects it's abusive and should be put into bg restricted level. {@code true} - we'll
         * show the prompt to user, {@code false} - we'll not show it.
         */
        static final String KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_with_noti_to_bg_restricted";

        /**
         * The behavior for an app with a FGS and its notification is still showing, when the system
         * detects it's running for a very long time, should we prompt the user.
         * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it.
         */
        static final String KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_with_noti_on_long_running";

        /**
         * The behavior for an app with a FGS, when the system detects it's running for
         * a very long time, should we prompt the user.
         * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it.
         */
        static final String KEY_BG_PROMPT_FGS_ON_LONG_RUNNING =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_fgs_on_long_running";

        /**
         * The list of packages to be exempted from all these background restrictions.
         */
        static final String KEY_BG_RESTRICTION_EXEMPTED_PACKAGES =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "restriction_exempted_packages";

        /**
         * Whether or not to show the notification for abusive apps, i.e. when the system
         * detects it's draining significant amount of battery in the background.
         * {@code true} - we'll show the prompt to user, {@code false} - we'll not show it.
         */
        static final String KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "prompt_abusive_apps_to_bg_restricted";

        /**
         * Default value to {@link #mBgAutoRestrictAbusiveApps}.
         */
        static final boolean DEFAULT_BG_AUTO_RESTRICT_ABUSIVE_APPS = true;

        /**
         * Default value to {@link #mBgAutoRestrictedBucket}.
         */
        static final boolean DEFAULT_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION = false;

        /**
         * Default value to {@link #mBgAbusiveNotificationMinIntervalMs}.
         */
        static final long DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS = 30 * ONE_DAY;

        /**
         * Default value to {@link #mBgAbusiveNotificationMinIntervalMs}.
         */
        static final long DEFAULT_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL_MS = 30 * ONE_DAY;

        /**
         * Default value to {@link #mBgPromptFgsWithNotiOnLongRunning}.
         */
        static final boolean DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING = false;

        /**
         * Default value to {@link #mBgPromptFgsOnLongRunning}.
         */
        static final boolean DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING = true;

        /**
         * Default value to {@link #mBgPromptFgsWithNotiToBgRestricted}.
         */
        final boolean mDefaultBgPromptFgsWithNotiToBgRestricted;

        /**
         * Default value to {@link #mBgPromptAbusiveAppsToBgRestricted}.
         */
        final boolean mDefaultBgPromptAbusiveAppToBgRestricted;

        volatile boolean mBgAutoRestrictedBucket;

        volatile boolean mBgAutoRestrictAbusiveApps;

        volatile boolean mRestrictedBucketEnabled;

        volatile long mBgAbusiveNotificationMinIntervalMs;

        volatile long mBgLongFgsNotificationMinIntervalMs;

        /**
         * @see #KEY_BG_RESTRICTION_EXEMPTED_PACKAGES.
         *
         *<p> Mutations on them would result in copy-on-write.</p>
         */
        volatile Set<String> mBgRestrictionExemptedPackages = Collections.emptySet();

        /**
         * @see #KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED.
         */
        volatile boolean mBgPromptFgsWithNotiToBgRestricted;

        /**
         * @see #KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING.
         */
        volatile boolean mBgPromptFgsWithNotiOnLongRunning;

        /**
         * @see #KEY_BG_PROMPT_FGS_ON_LONG_RUNNING.
         */
        volatile boolean mBgPromptFgsOnLongRunning;

        /**
         * @see #KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED.
         */
        volatile boolean mBgPromptAbusiveAppsToBgRestricted;

        ConstantsObserver(Handler handler, Context context) {
            super(handler);
            mDefaultBgPromptFgsWithNotiToBgRestricted = context.getResources().getBoolean(
                    com.android.internal.R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted);
            mDefaultBgPromptAbusiveAppToBgRestricted = context.getResources().getBoolean(
                    com.android.internal.R.bool.config_bg_prompt_abusive_apps_to_bg_restricted);
        }

        @Override
        public void onPropertiesChanged(Properties properties) {
            for (String name : properties.getKeyset()) {
                if (name == null || !name.startsWith(DEVICE_CONFIG_SUBNAMESPACE_PREFIX)) {
                    return;
                }
                switch (name) {
                    case KEY_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION:
                        updateBgAutoRestrictedBucketChanged();
                        break;
                    case KEY_BG_AUTO_RESTRICT_ABUSIVE_APPS:
                        updateBgAutoRestrictAbusiveApps();
                        break;
                    case KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL:
                        updateBgAbusiveNotificationMinimalInterval();
                        break;
                    case KEY_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL:
                        updateBgLongFgsNotificationMinimalInterval();
                        break;
                    case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED:
                        updateBgPromptFgsWithNotiToBgRestricted();
                        break;
                    case KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING:
                        updateBgPromptFgsWithNotiOnLongRunning();
                        break;
                    case KEY_BG_PROMPT_FGS_ON_LONG_RUNNING:
                        updateBgPromptFgsOnLongRunning();
                        break;
                    case KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED:
                        updateBgPromptAbusiveAppToBgRestricted();
                        break;
                    case KEY_BG_RESTRICTION_EXEMPTED_PACKAGES:
                        updateBgRestrictionExemptedPackages();
                        break;
                }
                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();
            updateBgAutoRestrictAbusiveApps();
            updateBgAbusiveNotificationMinimalInterval();
            updateBgLongFgsNotificationMinimalInterval();
            updateBgPromptFgsWithNotiToBgRestricted();
            updateBgPromptFgsWithNotiOnLongRunning();
            updateBgPromptFgsOnLongRunning();
            updateBgPromptAbusiveAppToBgRestricted();
            updateBgRestrictionExemptedPackages();
        }

        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 void updateBgAutoRestrictAbusiveApps() {
            mBgAutoRestrictAbusiveApps = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_AUTO_RESTRICT_ABUSIVE_APPS,
                    DEFAULT_BG_AUTO_RESTRICT_ABUSIVE_APPS);
        }

        private void updateBgAbusiveNotificationMinimalInterval() {
            mBgAbusiveNotificationMinIntervalMs = DeviceConfig.getLong(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL,
                    DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS);
        }

        private void updateBgLongFgsNotificationMinimalInterval() {
            mBgLongFgsNotificationMinIntervalMs = DeviceConfig.getLong(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL,
                    DEFAULT_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL_MS);
        }

        private void updateBgPromptFgsWithNotiToBgRestricted() {
            mBgPromptFgsWithNotiToBgRestricted = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED,
                    mDefaultBgPromptFgsWithNotiToBgRestricted);
        }

        private void updateBgPromptFgsWithNotiOnLongRunning() {
            mBgPromptFgsWithNotiOnLongRunning = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING,
                    DEFAULT_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING);
        }

        private void updateBgPromptFgsOnLongRunning() {
            mBgPromptFgsOnLongRunning = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_PROMPT_FGS_ON_LONG_RUNNING,
                    DEFAULT_BG_PROMPT_FGS_ON_LONG_RUNNING);
        }

        private void updateBgPromptAbusiveAppToBgRestricted() {
            mBgPromptAbusiveAppsToBgRestricted = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED,
                    mDefaultBgPromptAbusiveAppToBgRestricted);
        }

        private void updateBgRestrictionExemptedPackages() {
            final String settings = DeviceConfig.getString(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_RESTRICTION_EXEMPTED_PACKAGES,
                    null);
            if (settings == null) {
                mBgRestrictionExemptedPackages = Collections.emptySet();
                return;
            }
            final String[] settingsList = settings.split(",");
            final ArraySet<String> packages = new ArraySet<>();
            for (String pkg : settingsList) {
                packages.add(pkg);
            }
            mBgRestrictionExemptedPackages = Collections.unmodifiableSet(packages);
        }

        void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.println("BACKGROUND RESTRICTION POLICY SETTINGS:");
            final String indent = "  ";
            prefix = indent + prefix;
            pw.print(prefix);
            pw.print(KEY_BG_AUTO_RESTRICTED_BUCKET_ON_BG_RESTRICTION);
            pw.print('=');
            pw.println(mBgAutoRestrictedBucket);
            pw.print(prefix);
            pw.print(KEY_BG_AUTO_RESTRICT_ABUSIVE_APPS);
            pw.print('=');
            pw.println(mBgAutoRestrictAbusiveApps);
            pw.print(prefix);
            pw.print(KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL);
            pw.print('=');
            pw.println(mBgAbusiveNotificationMinIntervalMs);
            pw.print(prefix);
            pw.print(KEY_BG_LONG_FGS_NOTIFICATION_MINIMAL_INTERVAL);
            pw.print('=');
            pw.println(mBgLongFgsNotificationMinIntervalMs);
            pw.print(prefix);
            pw.print(KEY_BG_PROMPT_FGS_ON_LONG_RUNNING);
            pw.print('=');
            pw.println(mBgPromptFgsOnLongRunning);
            pw.print(prefix);
            pw.print(KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_ON_LONG_RUNNING);
            pw.print('=');
            pw.println(mBgPromptFgsWithNotiOnLongRunning);
            pw.print(prefix);
            pw.print(KEY_BG_PROMPT_FGS_WITH_NOTIFICATION_TO_BG_RESTRICTED);
            pw.print('=');
            pw.println(mBgPromptFgsWithNotiToBgRestricted);
            pw.print(prefix);
            pw.print(KEY_BG_PROMPT_ABUSIVE_APPS_TO_BG_RESTRICTED);
            pw.print('=');
            pw.println(mBgPromptAbusiveAppsToBgRestricted);
            pw.print(prefix);
            pw.print(KEY_BG_RESTRICTION_EXEMPTED_PACKAGES);
            pw.print('=');
            pw.println(mBgRestrictionExemptedPackages.toString());
        }
    }

    /**
     * A helper object which holds an app state tracker's type and its relevant info used for
     * logging atoms to statsd.
     */
    private class TrackerInfo {
        final int mType; // tracker type
        final byte[] mInfo; // tracker info proto object for statsd

        TrackerInfo() {
            mType = TRACKER_TYPE_UNKNOWN;
            mInfo = null;
        }

        TrackerInfo(int type, byte[] info) {
            mType = type;
            mInfo = info;
        }
    }

    private final ConstantsObserver mConstantsObserver;

    private final AppStateTracker.BackgroundRestrictedAppListener mBackgroundRestrictionListener =
            new AppStateTracker.BackgroundRestrictedAppListener() {
                @Override
                public void updateBackgroundRestrictedForUidPackage(int uid, String packageName,
                        boolean restricted) {
                    mBgHandler.obtainMessage(BgHandler.MSG_BACKGROUND_RESTRICTION_CHANGED,
                            uid, restricted ? 1 : 0, packageName).sendToTarget();
                }
            };

    private final AppIdleStateChangeListener mAppIdleStateChangeListener =
            new AppIdleStateChangeListener() {
                @Override
                public void onAppIdleStateChanged(String packageName, @UserIdInt int userId,
                        boolean idle, int bucket, int reason) {
                    mBgHandler.obtainMessage(BgHandler.MSG_APP_STANDBY_BUCKET_CHANGED,
                            userId, bucket, packageName).sendToTarget();
                }

                @Override
                public void onUserInteractionStarted(String packageName, @UserIdInt int userId) {
                    mBgHandler.obtainMessage(BgHandler.MSG_USER_INTERACTION_STARTED,
                            userId, 0, packageName).sendToTarget();
                }
            };

    private final IUidObserver mUidObserver =
            new IUidObserver.Stub() {
                @Override
                public void onUidStateChanged(int uid, int procState, long procStateSeq,
                        int capability) {
                    mBgHandler.obtainMessage(BgHandler.MSG_UID_PROC_STATE_CHANGED, uid, procState)
                            .sendToTarget();
                }

                @Override
                public void onUidIdle(int uid, boolean disabled) {
                    mBgHandler.obtainMessage(BgHandler.MSG_UID_IDLE, uid, disabled ? 1 : 0)
                            .sendToTarget();
                }

                @Override
                public void onUidGone(int uid, boolean disabled) {
                    mBgHandler.obtainMessage(BgHandler.MSG_UID_GONE, uid, disabled ? 1 : 0)
                            .sendToTarget();
                }

                @Override
                public void onUidActive(int uid) {
                    mBgHandler.obtainMessage(BgHandler.MSG_UID_ACTIVE, uid, 0).sendToTarget();
                }

                @Override
                public void onUidCachedChanged(int uid, boolean cached) {
                }

                @Override
                public void onUidProcAdjChanged(int uid) {
                }
            };

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

    AppRestrictionController(final Context context, final ActivityManagerService service) {
        this(new Injector(context), service);
    }

    AppRestrictionController(final Injector injector, final ActivityManagerService service) {
        mInjector = injector;
        mContext = injector.getContext();
        mActivityManagerService = service;
        mBgHandlerThread = new HandlerThread("bgres-controller", THREAD_PRIORITY_BACKGROUND);
        mBgHandlerThread.start();
        mBgHandler = new BgHandler(mBgHandlerThread.getLooper(), injector);
        mBgExecutor = new HandlerExecutor(mBgHandler);
        mConstantsObserver = new ConstantsObserver(mBgHandler, mContext);
        mNotificationHelper = new NotificationHelper(this);
        injector.initAppStateTrackers(this);
    }

    void onSystemReady() {
        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                mBgExecutor, mConstantsObserver);
        mConstantsObserver.start();
        initBgRestrictionExemptioFromSysConfig();
        initRestrictionStates();
        initSystemModuleNames();
        initRolesInInterest();
        registerForUidObservers();
        registerForSystemBroadcasts();
        mNotificationHelper.onSystemReady();
        mInjector.getAppStateTracker().addBackgroundRestrictedAppListener(
                mBackgroundRestrictionListener);
        mInjector.getAppStandbyInternal().addListener(mAppIdleStateChangeListener);
        mInjector.getRoleManager().addOnRoleHoldersChangedListenerAsUser(mBgExecutor,
                mRoleHolderChangedListener, UserHandle.ALL);
        mInjector.scheduleInitTrackers(mBgHandler, () -> {
            for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
                mAppStateTrackers.get(i).onSystemReady();
            }
        });
    }

    @VisibleForTesting
    void resetRestrictionSettings() {
        synchronized (mSettingsLock) {
            mRestrictionSettings.reset();
        }
        initRestrictionStates();
    }

    @VisibleForTesting
    void tearDown() {
        DeviceConfig.removeOnPropertiesChangedListener(mConstantsObserver);
        unregisterForUidObservers();
        unregisterForSystemBroadcasts();
        mRestrictionSettings.removeXml();
    }

    private void initBgRestrictionExemptioFromSysConfig() {
        final SystemConfig sysConfig = SystemConfig.getInstance();
        mBgRestrictionExemptioFromSysConfig = sysConfig.getBgRestrictionExemption();
        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
            final ArraySet<String> exemptedPkgs = mBgRestrictionExemptioFromSysConfig;
            for (int i = exemptedPkgs.size() - 1; i >= 0; i--) {
                Slog.i(TAG, "bg-restriction-exemption: " + exemptedPkgs.valueAt(i));
            }
        }
        loadAppIdsFromPackageList(sysConfig.getAllowInPowerSaveExceptIdle(),
                mSystemDeviceIdleExceptIdleAllowlist);
        loadAppIdsFromPackageList(sysConfig.getAllowInPowerSave(), mSystemDeviceIdleAllowlist);
    }

    private void loadAppIdsFromPackageList(ArraySet<String> packages, ArraySet<Integer> apps) {
        final PackageManager pm = mInjector.getPackageManager();
        for (int i = packages.size() - 1; i >= 0; i--) {
            final String pkg = packages.valueAt(i);
            try {
                final ApplicationInfo ai = pm.getApplicationInfo(pkg,
                        PackageManager.MATCH_SYSTEM_ONLY);
                if (ai == null) {
                    continue;
                }
                apps.add(UserHandle.getAppId(ai.uid));
            } catch (PackageManager.NameNotFoundException e) {
            }
        }
    }

    private boolean isExemptedFromSysConfig(String packageName) {
        return mBgRestrictionExemptioFromSysConfig != null
                && mBgRestrictionExemptioFromSysConfig.contains(packageName);
    }

    private void initRestrictionStates() {
        final int[] allUsers = mInjector.getUserManagerInternal().getUserIds();
        for (int userId : allUsers) {
            refreshAppRestrictionLevelForUser(userId, REASON_MAIN_FORCED_BY_USER,
                    REASON_SUB_FORCED_USER_FLAG_INTERACTION);
        }
        if (!mInjector.isTest()) {
            // Load the previously saved levels and update the current levels if needed.
            mRestrictionSettings.scheduleLoadFromXml();
            // Also save the current levels right away.
            for (int userId : allUsers) {
                mRestrictionSettings.schedulePersistToXml(userId);
            }
        }
    }

    private void initSystemModuleNames() {
        final PackageManager pm = mInjector.getPackageManager();
        final List<ModuleInfo> moduleInfos = pm.getInstalledModules(0 /* flags */);
        if (moduleInfos == null) {
            return;
        }
        synchronized (mLock) {
            for (ModuleInfo info : moduleInfos) {
                mSystemModulesCache.put(info.getPackageName(), Boolean.TRUE);
            }
        }
    }

    private boolean isSystemModule(String packageName) {
        synchronized (mLock) {
            final Boolean val = mSystemModulesCache.get(packageName);
            if (val != null) {
                return val.booleanValue();
            }
        }

        // Slow path: check if the package is listed among the system modules.
        final PackageManager pm = mInjector.getPackageManager();
        boolean isSystemModule = false;
        try {
            isSystemModule = pm.getModuleInfo(packageName, 0 /* flags */) != null;
        } catch (PackageManager.NameNotFoundException e) {
        }

        if (!isSystemModule) {
            try {
                final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */);
                // Check if the package is contained in an APEX. There is no public API to properly
                // check whether a given APK package comes from an APEX registered as module.
                // Therefore we conservatively assume that any package scanned from an /apex path is
                // a system package.
                isSystemModule = pkg != null && pkg.applicationInfo.sourceDir.startsWith(
                        Environment.getApexDirectory().getAbsolutePath());
            } catch (PackageManager.NameNotFoundException e) {
            }
        }
        // Update the cache.
        synchronized (mLock) {
            mSystemModulesCache.put(packageName, isSystemModule);
        }
        return isSystemModule;
    }

    private void registerForUidObservers() {
        try {
            mInjector.getIActivityManager().registerUidObserver(mUidObserver,
                    UID_OBSERVER_ACTIVE | UID_OBSERVER_GONE | UID_OBSERVER_IDLE
                    | UID_OBSERVER_PROCSTATE, PROCESS_STATE_FOREGROUND_SERVICE, "android");
        } catch (RemoteException e) {
            // Intra-process call, it won't happen.
        }
    }

    private void unregisterForUidObservers() {
        try {
            mInjector.getIActivityManager().unregisterUidObserver(mUidObserver);
        } catch (RemoteException e) {
            // Intra-process call, it won't happen.
        }
    }

    /**
     * Called when initializing a user.
     */
    private void refreshAppRestrictionLevelForUser(@UserIdInt int userId, int reason,
            int subReason) {
        final List<AppStandbyInfo> appStandbyInfos = mInjector.getAppStandbyInternal()
                .getAppStandbyBuckets(userId);
        if (ArrayUtils.isEmpty(appStandbyInfos)) {
            return;
        }

        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
            Slog.i(TAG, "Refreshing restriction levels of user " + userId);
        }
        final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
        for (AppStandbyInfo info: appStandbyInfos) {
            final int uid = pm.getPackageUid(info.mPackageName, STOCK_PM_FLAGS, userId);
            if (uid < 0) {
                // Shouldn't happen.
                Slog.e(TAG, "Unable to find " + info.mPackageName + "/u" + userId);
                continue;
            }
            final Pair<Integer, TrackerInfo> levelTypePair = calcAppRestrictionLevel(
                    userId, uid, info.mPackageName, info.mStandbyBucket, false, false);
            if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                Slog.i(TAG, "Proposed restriction level of " + info.mPackageName + "/"
                        + UserHandle.formatUid(uid) + ": "
                        + ActivityManager.restrictionLevelToName(levelTypePair.first)
                        + " " + info.mStandbyBucket);
            }
            applyRestrictionLevel(info.mPackageName, uid, levelTypePair.first, levelTypePair.second,
                    info.mStandbyBucket, true, reason, subReason);
        }
    }

    void refreshAppRestrictionLevelForUid(int uid, int reason, int subReason,
            boolean allowRequestBgRestricted) {
        final String[] packages = mInjector.getPackageManager().getPackagesForUid(uid);
        if (ArrayUtils.isEmpty(packages)) {
            return;
        }
        final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
        final int userId = UserHandle.getUserId(uid);
        final long now = SystemClock.elapsedRealtime();
        for (String pkg: packages) {
            final int curBucket = appStandbyInternal.getAppStandbyBucket(pkg, userId, now, false);
            final Pair<Integer, TrackerInfo> levelTypePair = calcAppRestrictionLevel(userId, uid,
                    pkg, curBucket, allowRequestBgRestricted, true);
            if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                Slog.i(TAG, "Proposed restriction level of " + pkg + "/"
                        + UserHandle.formatUid(uid) + ": "
                        + ActivityManager.restrictionLevelToName(levelTypePair.first));
            }
            applyRestrictionLevel(pkg, uid, levelTypePair.first, levelTypePair.second,
                    curBucket, true, reason, subReason);
        }
    }

    private Pair<Integer, TrackerInfo> calcAppRestrictionLevel(@UserIdInt int userId, int uid,
            String packageName, @UsageStatsManager.StandbyBuckets int standbyBucket,
            boolean allowRequestBgRestricted, boolean calcTrackers) {
        if (mInjector.getAppHibernationInternal().isHibernatingForUser(packageName, userId)) {
            return new Pair<>(RESTRICTION_LEVEL_HIBERNATION, mEmptyTrackerInfo);
        }
        @RestrictionLevel int level;
        TrackerInfo trackerInfo = null;
        switch (standbyBucket) {
            case STANDBY_BUCKET_EXEMPTED:
                level = RESTRICTION_LEVEL_EXEMPTED;
                break;
            case STANDBY_BUCKET_NEVER:
                level = RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
                break;
            case STANDBY_BUCKET_ACTIVE:
            case STANDBY_BUCKET_WORKING_SET:
            case STANDBY_BUCKET_FREQUENT:
            case STANDBY_BUCKET_RARE:
            case STANDBY_BUCKET_RESTRICTED:
            default:
                if (mInjector.getAppStateTracker()
                        .isAppBackgroundRestricted(uid, packageName)) {
                    return new Pair<>(RESTRICTION_LEVEL_BACKGROUND_RESTRICTED, mEmptyTrackerInfo);
                }
                level = mConstantsObserver.mRestrictedBucketEnabled
                        && standbyBucket == STANDBY_BUCKET_RESTRICTED
                        ? RESTRICTION_LEVEL_RESTRICTED_BUCKET
                        : RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
                if (calcTrackers) {
                    Pair<Integer, TrackerInfo> levelTypePair = calcAppRestrictionLevelFromTackers(
                            uid, packageName, RESTRICTION_LEVEL_MAX);
                    @RestrictionLevel int l = levelTypePair.first;
                    if (l == RESTRICTION_LEVEL_EXEMPTED) {
                        return new Pair<>(RESTRICTION_LEVEL_EXEMPTED, levelTypePair.second);
                    }
                    if (l > level) {
                        level = l;
                        trackerInfo = levelTypePair.second;
                    }
                    if (level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
                        // This level can't be entered without user consent
                        if (allowRequestBgRestricted) {
                            mBgHandler.obtainMessage(BgHandler.MSG_REQUEST_BG_RESTRICTED,
                                    uid, 0, packageName).sendToTarget();
                        }
                        // Lower the level.
                        levelTypePair = calcAppRestrictionLevelFromTackers(uid, packageName,
                                RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
                        level = levelTypePair.first;
                        trackerInfo = levelTypePair.second;
                    }
                }
                break;
        }
        return new Pair<>(level, trackerInfo);
    }

    /**
     * Ask each of the trackers for their proposed restriction levels for the given uid/package,
     * and return the most restrictive level along with the type of tracker and its relevant info
     * which applied this restriction level as a {@code Pair<@RestrictionLevel, TrackerInfo>}.
     *
     * <p>Note, it's different from the {@link #getRestrictionLevel} where it returns the least
     * restrictive level. We're returning the most restrictive level here because each tracker
     * monitors certain dimensions of the app, the abusive behaviors could be detected in one or
     * more of these dimensions, but not necessarily all of them. </p>
     */
    private Pair<Integer, TrackerInfo> calcAppRestrictionLevelFromTackers(int uid,
            String packageName, @RestrictionLevel int maxLevel) {
        @RestrictionLevel int level = RESTRICTION_LEVEL_UNKNOWN;
        @RestrictionLevel int prevLevel = level;
        BaseAppStateTracker resultTracker = null;
        final boolean isRestrictedBucketEnabled = mConstantsObserver.mRestrictedBucketEnabled;
        for (int i = mAppStateTrackers.size() - 1; i >= 0; i--) {
            @RestrictionLevel int l = mAppStateTrackers.get(i).getPolicy()
                    .getProposedRestrictionLevel(packageName, uid, maxLevel);
            if (!isRestrictedBucketEnabled && l == RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
                l = RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
            }
            level = Math.max(level, l);
            if (level != prevLevel) {
                resultTracker = mAppStateTrackers.get(i);
                prevLevel = level;
            }
        }
        final TrackerInfo trackerInfo = resultTracker == null
                                            ? mEmptyTrackerInfo
                                            : new TrackerInfo(resultTracker.getType(),
                                                    resultTracker.getTrackerInfoForStatsd(uid));
        return new Pair<>(level, trackerInfo);
    }

    private static @RestrictionLevel int standbyBucketToRestrictionLevel(
            @UsageStatsManager.StandbyBuckets int standbyBucket) {
        switch (standbyBucket) {
            case STANDBY_BUCKET_EXEMPTED:
                return RESTRICTION_LEVEL_EXEMPTED;
            case STANDBY_BUCKET_NEVER:
                return RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
            case STANDBY_BUCKET_ACTIVE:
            case STANDBY_BUCKET_WORKING_SET:
            case STANDBY_BUCKET_FREQUENT:
            case STANDBY_BUCKET_RARE:
                return RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
            case STANDBY_BUCKET_RESTRICTED:
                return RESTRICTION_LEVEL_RESTRICTED_BUCKET;
            default:
                return RESTRICTION_LEVEL_UNKNOWN;
        }
    }

    /**
     * Get the restriction level of the given UID, if it hosts multiple packages,
     * return least restricted one (or if any of them is exempted).
     */
    @RestrictionLevel int getRestrictionLevel(int uid) {
        return mRestrictionSettings.getRestrictionLevel(uid);
    }

    /**
     * Get the restriction level of the given UID and package.
     */
    @RestrictionLevel int getRestrictionLevel(int uid, String packageName) {
        return mRestrictionSettings.getRestrictionLevel(uid, packageName);
    }

    /**
     * Get the restriction level of the given package in given user id.
     */
    @RestrictionLevel int getRestrictionLevel(String packageName, @UserIdInt int userId) {
        return mRestrictionSettings.getRestrictionLevel(packageName, userId);
    }

    /**
     * @return Whether or not to move the app to restricted level automatically
     * when system detects it's abusive.
     */
    boolean isAutoRestrictAbusiveAppEnabled() {
        return mConstantsObserver.mBgAutoRestrictAbusiveApps;
    }

    /**
     * @return The total foreground service durations for the given package/uid with given
     * foreground service type, or the total durations regardless the type if the given type is 0.
     */
    long getForegroundServiceTotalDurations(String packageName, int uid, long now,
            @ForegroundServiceType int serviceType) {
        return mInjector.getAppFGSTracker().getTotalDurations(packageName, uid, now,
                foregroundServiceTypeToIndex(serviceType));
    }

    /**
     * @return The total foreground service durations for the given uid with given
     * foreground service type, or the total durations regardless the type if the given type is 0.
     */
    long getForegroundServiceTotalDurations(int uid, long now,
            @ForegroundServiceType int serviceType) {
        return mInjector.getAppFGSTracker().getTotalDurations(uid, now,
                foregroundServiceTypeToIndex(serviceType));
    }

    /**
     * @return The foreground service durations since given timestamp for the given package/uid
     * with given foreground service type, or the total durations regardless the type if the given
     * type is 0.
     */
    long getForegroundServiceTotalDurationsSince(String packageName, int uid, long since, long now,
            @ForegroundServiceType int serviceType) {
        return mInjector.getAppFGSTracker().getTotalDurationsSince(packageName, uid, since, now,
                foregroundServiceTypeToIndex(serviceType));
    }

    /**
     * @return The foreground service durations since given timestamp for the given uid with given
     * foreground service type, or the total durations regardless the type if the given type is 0.
     */
    long getForegroundServiceTotalDurationsSince(int uid, long since, long now,
            @ForegroundServiceType int serviceType) {
        return mInjector.getAppFGSTracker().getTotalDurationsSince(uid, since, now,
                foregroundServiceTypeToIndex(serviceType));
    }

    /**
     * @return The total durations for the given package/uid with active media session.
     */
    long getMediaSessionTotalDurations(String packageName, int uid, long now) {
        return mInjector.getAppMediaSessionTracker().getTotalDurations(packageName, uid, now);
    }

    /**
     * @return The total durations for the given uid with active media session.
     */
    long getMediaSessionTotalDurations(int uid, long now) {
        return mInjector.getAppMediaSessionTracker().getTotalDurations(uid, now);
    }

    /**
     * @return The durations since given timestamp for the given package/uid with
     * active media session.
     */
    long getMediaSessionTotalDurationsSince(String packageName, int uid, long since, long now) {
        return mInjector.getAppMediaSessionTracker().getTotalDurationsSince(packageName, uid, since,
                now);
    }

    /**
     * @return The durations since given timestamp for the given uid with active media session.
     */
    long getMediaSessionTotalDurationsSince(int uid, long since, long now) {
        return mInjector.getAppMediaSessionTracker().getTotalDurationsSince(uid, since, now);
    }

    /**
     * @return The durations over the given window, where the given package/uid has either
     * foreground services with type "mediaPlayback" running, or active media session running.
     */
    long getCompositeMediaPlaybackDurations(String packageName, int uid, long now, long window) {
        final long since = Math.max(0, now - window);
        final long mediaPlaybackDuration = Math.max(
                getMediaSessionTotalDurationsSince(packageName, uid, since, now),
                getForegroundServiceTotalDurationsSince(packageName, uid, since, now,
                        ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK));
        return mediaPlaybackDuration;
    }

    /**
     * @return The durations over the given window, where the given uid has either foreground
     * services with type "mediaPlayback" running, or active media session running.
     */
    long getCompositeMediaPlaybackDurations(int uid, long now, long window) {
        final long since = Math.max(0, now - window);
        final long mediaPlaybackDuration = Math.max(
                getMediaSessionTotalDurationsSince(uid, since, now),
                getForegroundServiceTotalDurationsSince(uid, since, now,
                        ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK));
        return mediaPlaybackDuration;
    }

    /**
     * @return If the given package/uid has an active foreground service running.
     */
    boolean hasForegroundServices(String packageName, int uid) {
        return mInjector.getAppFGSTracker().hasForegroundServices(packageName, uid);
    }

    /**
     * @return If the given uid has an active foreground service running.
     */
    boolean hasForegroundServices(int uid) {
        return mInjector.getAppFGSTracker().hasForegroundServices(uid);
    }

    /**
     * @return If the given package/uid has a foreground service notification or not.
     */
    boolean hasForegroundServiceNotifications(String packageName, int uid) {
        return mInjector.getAppFGSTracker().hasForegroundServiceNotifications(packageName, uid);
    }

    /**
     * @return If the given uid has a foreground service notification or not.
     */
    boolean hasForegroundServiceNotifications(int uid) {
        return mInjector.getAppFGSTracker().hasForegroundServiceNotifications(uid);
    }

    /**
     * @return The to-be-exempted battery usage of the given UID in the given duration; it could
     *         be considered as "exempted" due to various use cases, i.e. media playback.
     */
    ImmutableBatteryUsage getUidBatteryExemptedUsageSince(int uid, long since, long now,
            int types) {
        return mInjector.getAppBatteryExemptionTracker()
                .getUidBatteryExemptedUsageSince(uid, since, now, types);
    }

    /**
     * @return The total battery usage of the given UID since the system boots.
     */
    @NonNull ImmutableBatteryUsage getUidBatteryUsage(int uid) {
        return mInjector.getUidBatteryUsageProvider().getUidBatteryUsage(uid);
    }

    interface UidBatteryUsageProvider {
        /**
         * @return The total battery usage of the given UID since the system boots.
         */
        @NonNull ImmutableBatteryUsage getUidBatteryUsage(int uid);
    }

    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix);
        pw.println("APP BACKGROUND RESTRICTIONS");
        prefix = "  " + prefix;
        pw.print(prefix);
        pw.println("BACKGROUND RESTRICTION LEVEL SETTINGS");
        mRestrictionSettings.dump(pw, "  " + prefix);
        mConstantsObserver.dump(pw, "  " + prefix);
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            pw.println();
            mAppStateTrackers.get(i).dump(pw, prefix);
        }
    }

    void dumpAsProto(ProtoOutputStream proto, int uid) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).dumpAsProto(proto, uid);
        }
    }

    private int getRestrictionLevelStatsd(@RestrictionLevel int level) {
        switch (level) {
            case RESTRICTION_LEVEL_UNKNOWN:
                return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN;
            case RESTRICTION_LEVEL_UNRESTRICTED:
                return AppBackgroundRestrictionsInfo.LEVEL_UNRESTRICTED;
            case RESTRICTION_LEVEL_EXEMPTED:
                return AppBackgroundRestrictionsInfo.LEVEL_EXEMPTED;
            case RESTRICTION_LEVEL_ADAPTIVE_BUCKET:
                return AppBackgroundRestrictionsInfo.LEVEL_ADAPTIVE_BUCKET;
            case RESTRICTION_LEVEL_RESTRICTED_BUCKET:
                return AppBackgroundRestrictionsInfo.LEVEL_RESTRICTED_BUCKET;
            case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
                return AppBackgroundRestrictionsInfo.LEVEL_BACKGROUND_RESTRICTED;
            case RESTRICTION_LEVEL_HIBERNATION:
                return AppBackgroundRestrictionsInfo.LEVEL_HIBERNATION;
            default:
                return AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN;
        }
    }

    private int getThresholdStatsd(int reason) {
        switch (reason) {
            case REASON_MAIN_FORCED_BY_SYSTEM:
                return AppBackgroundRestrictionsInfo.THRESHOLD_RESTRICTED;
            case REASON_MAIN_FORCED_BY_USER:
                return AppBackgroundRestrictionsInfo.THRESHOLD_USER;
            default:
                return AppBackgroundRestrictionsInfo.THRESHOLD_UNKNOWN;
        }
    }

    private int getTrackerTypeStatsd(@TrackerType int type) {
        switch (type) {
            case TRACKER_TYPE_BATTERY:
                return AppBackgroundRestrictionsInfo.BATTERY_TRACKER;
            case TRACKER_TYPE_BATTERY_EXEMPTION:
                return AppBackgroundRestrictionsInfo.BATTERY_EXEMPTION_TRACKER;
            case TRACKER_TYPE_FGS:
                return AppBackgroundRestrictionsInfo.FGS_TRACKER;
            case TRACKER_TYPE_MEDIA_SESSION:
                return AppBackgroundRestrictionsInfo.MEDIA_SESSION_TRACKER;
            case TRACKER_TYPE_PERMISSION:
                return AppBackgroundRestrictionsInfo.PERMISSION_TRACKER;
            case TRACKER_TYPE_BROADCAST_EVENTS:
                return AppBackgroundRestrictionsInfo.BROADCAST_EVENTS_TRACKER;
            case TRACKER_TYPE_BIND_SERVICE_EVENTS:
                return AppBackgroundRestrictionsInfo.BIND_SERVICE_EVENTS_TRACKER;
            default:
                return AppBackgroundRestrictionsInfo.UNKNOWN_TRACKER;
        }
    }

    private int getExemptionReasonStatsd(int uid, @RestrictionLevel int level) {
        if (level != RESTRICTION_LEVEL_EXEMPTED) {
            return AppBackgroundRestrictionsInfo.REASON_DENIED;
        }

        @ReasonCode final int reasonCode = getBackgroundRestrictionExemptionReason(uid);
        return getExemptionReasonForStatsd(reasonCode);
    }

    private int getOptimizationLevelStatsd(@RestrictionLevel int level) {
        switch (level) {
            case RESTRICTION_LEVEL_UNKNOWN:
                return AppBackgroundRestrictionsInfo.UNKNOWN;
            case RESTRICTION_LEVEL_UNRESTRICTED:
                return AppBackgroundRestrictionsInfo.NOT_OPTIMIZED;
            case RESTRICTION_LEVEL_ADAPTIVE_BUCKET:
                return AppBackgroundRestrictionsInfo.OPTIMIZED;
            case RESTRICTION_LEVEL_BACKGROUND_RESTRICTED:
                return AppBackgroundRestrictionsInfo.BACKGROUND_RESTRICTED;
            default:
                return AppBackgroundRestrictionsInfo.UNKNOWN;
        }
    }

    @SuppressWarnings("AndroidFrameworkCompatChange")
    private int getTargetSdkStatsd(String packageName) {
        final PackageManager pm = mInjector.getPackageManager();
        if (pm == null) {
            return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
        }
        try {
            final PackageInfo pkg = pm.getPackageInfo(packageName, 0 /* flags */);
            if (pkg == null || pkg.applicationInfo == null) {
                return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
            }
            final int targetSdk = pkg.applicationInfo.targetSdkVersion;
            if (targetSdk < Build.VERSION_CODES.S) {
                return AppBackgroundRestrictionsInfo.SDK_PRE_S;
            } else if (targetSdk < Build.VERSION_CODES.TIRAMISU) {
                return AppBackgroundRestrictionsInfo.SDK_S;
            } else if (targetSdk == Build.VERSION_CODES.TIRAMISU) {
                return AppBackgroundRestrictionsInfo.SDK_T;
            } else {
                return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
            }
        } catch (PackageManager.NameNotFoundException ignored) {
        }
        return AppBackgroundRestrictionsInfo.SDK_UNKNOWN;
    }

    private void applyRestrictionLevel(String pkgName, int uid,
            @RestrictionLevel int level, TrackerInfo trackerInfo,
            int curBucket, boolean allowUpdateBucket, int reason, int subReason) {
        int curLevel;
        int prevReason;
        final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
        if (trackerInfo == null) {
            trackerInfo = mEmptyTrackerInfo;
        }
        synchronized (mSettingsLock) {
            curLevel = getRestrictionLevel(uid, pkgName);
            if (curLevel == level) {
                // Nothing to do.
                return;
            }
            final int levelOfBucket = standbyBucketToRestrictionLevel(curBucket);
            if (levelOfBucket == level) {
                // If the standby bucket yield the same level, use the reason from standby bucket.
                final int bucketReason = appStandbyInternal.getAppStandbyBucketReason(
                        pkgName, UserHandle.getUserId(uid), SystemClock.elapsedRealtime());
                if (bucketReason != 0) {
                    reason = bucketReason & REASON_MAIN_MASK;
                    subReason = bucketReason & REASON_SUB_MASK;
                }
            }
            if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                Slog.i(TAG, "Updating the restriction level of " + pkgName + "/"
                        + UserHandle.formatUid(uid) + " from "
                        + ActivityManager.restrictionLevelToName(curLevel) + " to "
                        + ActivityManager.restrictionLevelToName(level)
                        + " reason=" + reason + ", subReason=" + subReason);
            }
            prevReason = mRestrictionSettings.getReason(pkgName, uid);
            mRestrictionSettings.update(pkgName, uid, level, reason, subReason);
        }

        if (!allowUpdateBucket || curBucket == STANDBY_BUCKET_EXEMPTED) {
            return;
        }
        if (level >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
                && curLevel < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
            if (!mConstantsObserver.mRestrictedBucketEnabled) {
                return;
            }
            // Moving the app standby bucket to restricted in the meanwhile.
            if (DEBUG_BG_RESTRICTION_CONTROLLER
                    && level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
                Slog.i(TAG, pkgName + "/" + UserHandle.formatUid(uid)
                        + " is bg-restricted, moving to restricted standby bucket");
            }
            if (curBucket != STANDBY_BUCKET_RESTRICTED
                    && (mConstantsObserver.mBgAutoRestrictedBucket
                    || level == RESTRICTION_LEVEL_RESTRICTED_BUCKET)) {
                // restrict the app if it hasn't done so.
                boolean doIt = true;
                synchronized (mSettingsLock) {
                    final int index = mActiveUids.indexOfKey(uid, pkgName);
                    if (index >= 0) {
                        // It's currently active, enqueue it.
                        final int localReason = reason;
                        final int localSubReason = subReason;
                        final TrackerInfo localTrackerInfo = trackerInfo;
                        mActiveUids.add(uid, pkgName, () -> {
                            appStandbyInternal.restrictApp(pkgName, UserHandle.getUserId(uid),
                                    localReason, localSubReason);
                            logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level,
                                    localTrackerInfo, localReason);
                        });
                        doIt = false;
                    }
                }
                if (doIt) {
                    appStandbyInternal.restrictApp(pkgName, UserHandle.getUserId(uid),
                            reason, subReason);
                    logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
                            reason);
                }
            }
        } else if (curLevel >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
                && level < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
            // Moved out of the background-restricted state.
            synchronized (mSettingsLock) {
                final int index = mActiveUids.indexOfKey(uid, pkgName);
                if (index >= 0) {
                    mActiveUids.add(uid, pkgName, null);
                }
            }
            appStandbyInternal.maybeUnrestrictApp(pkgName, UserHandle.getUserId(uid),
                    prevReason & REASON_MAIN_MASK, prevReason & REASON_SUB_MASK,
                    reason, subReason);
            logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
                    reason);
        }
    }

    private void logAppBackgroundRestrictionInfo(String pkgName, int uid,
            @RestrictionLevel int prevLevel, @RestrictionLevel int level,
            @NonNull TrackerInfo trackerInfo, int reason) {
        FrameworkStatsLog.write(FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO, uid,
                getRestrictionLevelStatsd(level),
                getThresholdStatsd(reason),
                getTrackerTypeStatsd(trackerInfo.mType),
                trackerInfo.mType == TRACKER_TYPE_FGS ? trackerInfo.mInfo : null,
                trackerInfo.mType == TRACKER_TYPE_BATTERY ? trackerInfo.mInfo : null,
                trackerInfo.mType == TRACKER_TYPE_BROADCAST_EVENTS ? trackerInfo.mInfo : null,
                trackerInfo.mType == TRACKER_TYPE_BIND_SERVICE_EVENTS ? trackerInfo.mInfo : null,
                getExemptionReasonStatsd(uid, level),
                getOptimizationLevelStatsd(level),
                getTargetSdkStatsd(pkgName),
                ActivityManager.isLowRamDeviceStatic(),
                getRestrictionLevelStatsd(prevLevel));
    }

    private void handleBackgroundRestrictionChanged(int uid, String pkgName, boolean restricted) {
        // Firstly, notify the trackers.
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i)
                    .onBackgroundRestrictionChanged(uid, pkgName, restricted);
        }

        final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
        final int userId = UserHandle.getUserId(uid);
        final long now = SystemClock.elapsedRealtime();
        final int curBucket = appStandbyInternal.getAppStandbyBucket(pkgName, userId, now, false);
        if (restricted) {
            // The app could fall into the background restricted with user consent only,
            // so set the reason to it.
            applyRestrictionLevel(pkgName, uid, RESTRICTION_LEVEL_BACKGROUND_RESTRICTED,
                    mEmptyTrackerInfo, curBucket, true, REASON_MAIN_FORCED_BY_USER,
                    REASON_SUB_FORCED_USER_FLAG_INTERACTION);
            mBgHandler.obtainMessage(BgHandler.MSG_CANCEL_REQUEST_BG_RESTRICTED, uid, 0, pkgName)
                    .sendToTarget();
        } else {
            // Moved out of the background-restricted state, we'd need to check if it should
            // stay in the restricted standby bucket.
            final @RestrictionLevel int lastLevel =
                    mRestrictionSettings.getLastRestrictionLevel(uid, pkgName);
            final int tentativeBucket = curBucket == STANDBY_BUCKET_EXEMPTED
                    ? STANDBY_BUCKET_EXEMPTED
                    : (lastLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET
                            ? STANDBY_BUCKET_RESTRICTED : STANDBY_BUCKET_RARE);
            final Pair<Integer, TrackerInfo> levelTypePair = calcAppRestrictionLevel(
                    UserHandle.getUserId(uid), uid, pkgName, tentativeBucket, false, true);

            applyRestrictionLevel(pkgName, uid, levelTypePair.first, levelTypePair.second,
                    curBucket, true, REASON_MAIN_USAGE, REASON_SUB_USAGE_USER_INTERACTION);
        }
    }

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

    private void dispatchAutoRestrictedBucketFeatureFlagChanged(boolean newValue) {
        final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
        final ArrayList<Runnable> pendingTasks = new ArrayList<>();
        synchronized (mSettingsLock) {
            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,
            @UserIdInt int userId) {
        final int uid = mInjector.getPackageManagerInternal().getPackageUid(
                packageName, STOCK_PM_FLAGS, userId);
        final Pair<Integer, TrackerInfo> levelTypePair = calcAppRestrictionLevel(
                userId, uid, packageName, bucket, false, false);
        applyRestrictionLevel(packageName, uid, levelTypePair.first, levelTypePair.second,
                bucket, false, REASON_MAIN_DEFAULT, REASON_SUB_DEFAULT_UNDEFINED);
    }

    void handleRequestBgRestricted(String packageName, int uid) {
        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
            Slog.i(TAG, "Requesting background restricted " + packageName + " "
                    + UserHandle.formatUid(uid));
        }
        mNotificationHelper.postRequestBgRestrictedIfNecessary(packageName, uid);
    }

    void handleCancelRequestBgRestricted(String packageName, int uid) {
        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
            Slog.i(TAG, "Cancelling requesting background restricted " + packageName + " "
                    + UserHandle.formatUid(uid));
        }
        mNotificationHelper.cancelRequestBgRestrictedIfNecessary(packageName, uid);
    }

    void handleUidProcStateChanged(int uid, int procState) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUidProcStateChanged(uid, procState);
        }
    }

    void handleUidGone(int uid) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUidGone(uid);
        }
    }

    static class NotificationHelper {
        static final String PACKAGE_SCHEME = "package";
        static final String GROUP_KEY = "com.android.app.abusive_bg_apps";

        static final int SUMMARY_NOTIFICATION_ID = SystemMessage.NOTE_ABUSIVE_BG_APPS_BASE;

        static final int NOTIFICATION_TYPE_ABUSIVE_CURRENT_DRAIN = 0;
        static final int NOTIFICATION_TYPE_LONG_RUNNING_FGS = 1;
        static final int NOTIFICATION_TYPE_LAST = 2;

        static final String ATTR_LAST_BATTERY_NOTIFICATION_TIME = "last_batt_noti_ts";
        static final String ATTR_LAST_LONG_FGS_NOTIFICATION_TIME = "last_long_fgs_noti_ts";

        @IntDef(prefix = { "NOTIFICATION_TYPE_"}, value = {
            NOTIFICATION_TYPE_ABUSIVE_CURRENT_DRAIN,
            NOTIFICATION_TYPE_LONG_RUNNING_FGS,
        })
        @Retention(RetentionPolicy.SOURCE)
        static @interface NotificationType{}

        static final String[] NOTIFICATION_TYPE_STRINGS = {
            "Abusive current drain",
            "Long-running FGS",
        };

        static final String[] NOTIFICATION_TIME_ATTRS = {
            ATTR_LAST_BATTERY_NOTIFICATION_TIME,
            ATTR_LAST_LONG_FGS_NOTIFICATION_TIME,
        };

        static @NotificationType int notificationTimeAttrToType(@NonNull String attr) {
            switch (attr) {
                case ATTR_LAST_BATTERY_NOTIFICATION_TIME:
                    return NOTIFICATION_TYPE_ABUSIVE_CURRENT_DRAIN;
                case ATTR_LAST_LONG_FGS_NOTIFICATION_TIME:
                    return NOTIFICATION_TYPE_LONG_RUNNING_FGS;
            }
            throw new IllegalArgumentException();
        }

        static @NonNull String notificationTypeToTimeAttr(@NotificationType int type) {
            return NOTIFICATION_TIME_ATTRS[type];
        }

        static final String ACTION_FGS_MANAGER_TRAMPOLINE =
                "com.android.server.am.ACTION_FGS_MANAGER_TRAMPOLINE";

        static String notificationTypeToString(@NotificationType int notificationType) {
            return NOTIFICATION_TYPE_STRINGS[notificationType];
        }

        private final AppRestrictionController mBgController;
        private final NotificationManager mNotificationManager;
        private final Injector mInjector;
        private final Object mLock;
        private final Object mSettingsLock;
        private final Context mContext;

        private final BroadcastReceiver mActionButtonReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                switch (intent.getAction()) {
                    case ACTION_FGS_MANAGER_TRAMPOLINE:
                        final String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
                        final int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
                        cancelRequestBgRestrictedIfNecessary(packageName, uid);
                        final Intent newIntent = new Intent(ACTION_SHOW_FOREGROUND_SERVICE_MANAGER);
                        newIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                        // Task manager runs in SystemUI, which is SYSTEM user only.
                        mContext.sendBroadcastAsUser(newIntent, UserHandle.SYSTEM);
                        break;
                }
            }
        };

        @GuardedBy("mSettingsLock")
        private int mNotificationIDStepper = SUMMARY_NOTIFICATION_ID + 1;

        NotificationHelper(AppRestrictionController controller) {
            mBgController = controller;
            mInjector = controller.mInjector;
            mNotificationManager = mInjector.getNotificationManager();
            mLock = controller.mLock;
            mSettingsLock = controller.mSettingsLock;
            mContext = mInjector.getContext();
        }

        void onSystemReady() {
            mContext.registerReceiverForAllUsers(mActionButtonReceiver,
                    new IntentFilter(ACTION_FGS_MANAGER_TRAMPOLINE),
                    MANAGE_ACTIVITY_TASKS, mBgController.mBgHandler, Context.RECEIVER_NOT_EXPORTED);
        }

        void postRequestBgRestrictedIfNecessary(String packageName, int uid) {
            if (!mBgController.mConstantsObserver.mBgPromptAbusiveAppsToBgRestricted) {
                if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                    Slog.i(TAG, "Not requesting bg-restriction due to config");
                }
                return;
            }

            final Intent intent = new Intent(Settings.ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL);
            intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

            final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext, 0,
                    intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE, null,
                    UserHandle.of(UserHandle.getUserId(uid)));
            Notification.Action[] actions = null;
            final boolean hasForegroundServices =
                    mBgController.hasForegroundServices(packageName, uid);
            final boolean hasForegroundServiceNotifications =
                    mBgController.hasForegroundServiceNotifications(packageName, uid);
            if (!mBgController.mConstantsObserver.mBgPromptFgsWithNotiToBgRestricted) {
                // We're not going to prompt the user if the FGS is active and its notification
                // is still showing (not dismissed/silenced/denied).
                if (hasForegroundServices && hasForegroundServiceNotifications) {
                    if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                        Slog.i(TAG, "Not requesting bg-restriction due to FGS with notification");
                    }
                    return;
                }
            }
            if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER
                    && ENABLE_SHOW_FGS_MANAGER_ACTION_ON_BG_RESTRICTION
                    && hasForegroundServices) {
                final Intent trampoline = new Intent(ACTION_FGS_MANAGER_TRAMPOLINE);
                trampoline.setPackage("android");
                trampoline.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
                trampoline.putExtra(Intent.EXTRA_UID, uid);
                final PendingIntent fgsMgrTrampoline = PendingIntent.getBroadcastAsUser(
                        mContext, 0, trampoline,
                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
                        UserHandle.CURRENT);
                actions = new Notification.Action[] {
                    new Notification.Action.Builder(null,
                            mContext.getString(
                            com.android.internal.R.string.notification_action_check_bg_apps),
                            fgsMgrTrampoline)
                            .build()
                };
            }
            postNotificationIfNecessary(NOTIFICATION_TYPE_ABUSIVE_CURRENT_DRAIN,
                    com.android.internal.R.string.notification_title_abusive_bg_apps,
                    com.android.internal.R.string.notification_content_abusive_bg_apps,
                    pendingIntent, packageName, uid, actions);
        }

        void postLongRunningFgsIfNecessary(String packageName, int uid) {
            // Log the event in statsd.
            FrameworkStatsLog.write(FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO,
                    uid,
                    mBgController.getRestrictionLevel(uid),
                    AppBackgroundRestrictionsInfo.THRESHOLD_UNKNOWN,
                    AppBackgroundRestrictionsInfo.FGS_TRACKER,
                    mInjector.getAppFGSTracker().getTrackerInfoForStatsd(uid),
                    null, // BatteryTrackerInfo
                    null, // BroadcastEventsTrackerInfo
                    null, // BindServiceEventsTrackerInfo
                    getExemptionReasonForStatsd(
                            mBgController.getBackgroundRestrictionExemptionReason(uid)),
                    AppBackgroundRestrictionsInfo.UNKNOWN, // OptimizationLevel
                    AppBackgroundRestrictionsInfo.SDK_UNKNOWN, // TargetSdk
                    ActivityManager.isLowRamDeviceStatic(),
                    mBgController.getRestrictionLevel(uid));
            PendingIntent pendingIntent;
            if (!mBgController.mConstantsObserver.mBgPromptFgsOnLongRunning) {
                if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                    Slog.i(TAG, "Long-running FGS prompt is disabled.");
                }
                return;
            }
            if (!mBgController.mConstantsObserver.mBgPromptFgsWithNotiOnLongRunning
                    && mBgController.hasForegroundServiceNotifications(packageName, uid)) {
                if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                    Slog.i(TAG, "Not prompt long-running due to FGS with notification");
                }
                return;
            }
            if (ENABLE_SHOW_FOREGROUND_SERVICE_MANAGER) {
                final Intent intent = new Intent(ACTION_SHOW_FOREGROUND_SERVICE_MANAGER);
                intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
                // Task manager runs in SystemUI, which is SYSTEM user only.
                pendingIntent = PendingIntent.getBroadcastAsUser(mContext, 0,
                        intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
                        UserHandle.SYSTEM);
            } else {
                final Intent intent = new Intent(Settings.ACTION_VIEW_ADVANCED_POWER_USAGE_DETAIL);
                intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                pendingIntent = PendingIntent.getActivityAsUser(mContext, 0,
                        intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
                        null, UserHandle.of(UserHandle.getUserId(uid)));
            }

            postNotificationIfNecessary(NOTIFICATION_TYPE_LONG_RUNNING_FGS,
                    com.android.internal.R.string.notification_title_long_running_fgs,
                    com.android.internal.R.string.notification_content_long_running_fgs,
                    pendingIntent, packageName, uid, null);
        }

        long getNotificationMinInterval(@NotificationType int notificationType) {
            switch (notificationType) {
                case NOTIFICATION_TYPE_ABUSIVE_CURRENT_DRAIN:
                    return mBgController.mConstantsObserver.mBgAbusiveNotificationMinIntervalMs;
                case NOTIFICATION_TYPE_LONG_RUNNING_FGS:
                    return mBgController.mConstantsObserver.mBgLongFgsNotificationMinIntervalMs;
                default:
                    return 0L;
            }
        }

        int getNotificationIdIfNecessary(@NotificationType int notificationType,
                String packageName, int uid) {
            synchronized (mSettingsLock) {
                final RestrictionSettings.PkgSettings settings = mBgController.mRestrictionSettings
                        .getRestrictionSettingsLocked(uid, packageName);
                if (settings == null) {
                    return 0;
                }

                final long now = mInjector.currentTimeMillis();
                final long lastNotificationShownTime =
                        settings.getLastNotificationTime(notificationType);
                if (lastNotificationShownTime != 0 && (lastNotificationShownTime
                        + getNotificationMinInterval(notificationType) > now)) {
                    if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                        Slog.i(TAG, "Not showing notification as last notification was shown "
                                + TimeUtils.formatDuration(now - lastNotificationShownTime)
                                + " ago");
                    }
                    return 0;
                }
                settings.setLastNotificationTime(notificationType, now);
                int notificationId = settings.getNotificationId(notificationType);
                if (notificationId <= 0) {
                    notificationId = mNotificationIDStepper++;
                    settings.setNotificationId(notificationType, notificationId);
                }
                if (DEBUG_BG_RESTRICTION_CONTROLLER) {
                    Slog.i(TAG, "Showing notification for " + packageName
                            + "/" + UserHandle.formatUid(uid)
                            + ", id=" + notificationId
                            + ", now=" + now
                            + ", lastShown=" + lastNotificationShownTime);
                }
                return notificationId;
            }
        }

        void postNotificationIfNecessary(@NotificationType int notificationType, int titleRes,
                int messageRes, PendingIntent pendingIntent, String packageName, int uid,
                @Nullable Notification.Action[] actions) {
            int notificationId = getNotificationIdIfNecessary(notificationType, packageName, uid);
            if (notificationId <= 0) {
                return;
            }

            final PackageManagerInternal pmi = mInjector.getPackageManagerInternal();
            final PackageManager pm = mInjector.getPackageManager();
            final ApplicationInfo ai = pmi.getApplicationInfo(packageName, STOCK_PM_FLAGS,
                    SYSTEM_UID, UserHandle.getUserId(uid));
            final String title = mContext.getString(titleRes);
            final String message = mContext.getString(messageRes,
                    ai != null ? ai.loadLabel(pm) : packageName);
            final Icon icon = ai != null ? Icon.createWithResource(packageName, ai.icon) : null;

            postNotification(notificationId, packageName, uid, title, message, icon, pendingIntent,
                    actions);
        }

        void postNotification(int notificationId, String packageName, int uid, String title,
                String message, Icon icon, PendingIntent pendingIntent,
                @Nullable Notification.Action[] actions) {
            final UserHandle targetUser = UserHandle.of(UserHandle.getUserId(uid));
            postSummaryNotification(targetUser);

            final Notification.Builder notificationBuilder = new Notification.Builder(mContext,
                    ABUSIVE_BACKGROUND_APPS)
                    .setAutoCancel(true)
                    .setGroup(GROUP_KEY)
                    .setWhen(mInjector.currentTimeMillis())
                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
                    .setColor(mContext.getColor(
                            com.android.internal.R.color.system_notification_accent_color))
                    .setContentTitle(title)
                    .setContentText(message)
                    .setContentIntent(pendingIntent);
            if (icon != null) {
                notificationBuilder.setLargeIcon(icon);
            }
            if (actions != null) {
                for (Notification.Action action : actions) {
                    notificationBuilder.addAction(action);
                }
            }

            final Notification notification = notificationBuilder.build();
            // Remember the package name for testing.
            notification.extras.putString(Intent.EXTRA_PACKAGE_NAME, packageName);

            mNotificationManager.notifyAsUser(null, notificationId, notification, targetUser);
        }

        private void postSummaryNotification(@NonNull UserHandle targetUser) {
            final Notification summary = new Notification.Builder(mContext,
                    ABUSIVE_BACKGROUND_APPS)
                    .setGroup(GROUP_KEY)
                    .setGroupSummary(true)
                    .setStyle(new Notification.BigTextStyle())
                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
                    .setColor(mContext.getColor(
                            com.android.internal.R.color.system_notification_accent_color))
                    .build();
            mNotificationManager.notifyAsUser(null, SUMMARY_NOTIFICATION_ID, summary, targetUser);
        }

        void cancelRequestBgRestrictedIfNecessary(String packageName, int uid) {
            synchronized (mSettingsLock) {
                final RestrictionSettings.PkgSettings settings = mBgController.mRestrictionSettings
                        .getRestrictionSettingsLocked(uid, packageName);
                if (settings != null) {
                    final int notificationId =
                            settings.getNotificationId(NOTIFICATION_TYPE_ABUSIVE_CURRENT_DRAIN);
                    if (notificationId > 0) {
                        mNotificationManager.cancel(notificationId);
                    }
                }
            }
        }

        void cancelLongRunningFGSNotificationIfNecessary(String packageName, int uid) {
            synchronized (mSettingsLock) {
                final RestrictionSettings.PkgSettings settings = mBgController.mRestrictionSettings
                        .getRestrictionSettingsLocked(uid, packageName);
                if (settings != null) {
                    final int notificationId =
                            settings.getNotificationId(NOTIFICATION_TYPE_LONG_RUNNING_FGS);
                    if (notificationId > 0) {
                        mNotificationManager.cancel(notificationId);
                    }
                }
            }
        }
    }

    void handleUidInactive(int uid, boolean disabled) {
        final ArrayList<Runnable> pendingTasks = mTmpRunnables;
        synchronized (mSettingsLock) {
            final int index = mActiveUids.indexOfKey(uid);
            if (index < 0) {
                return;
            }
            final int numPackages = mActiveUids.numElementsForKeyAt(index);
            for (int i = 0; i < numPackages; i++) {
                final Runnable pendingTask = mActiveUids.valueAt(index, i);
                if (pendingTask != null) {
                    pendingTasks.add(pendingTask);
                }
            }
            mActiveUids.deleteAt(index);
        }
        for (int i = 0, size = pendingTasks.size(); i < size; i++) {
            pendingTasks.get(i).run();
        }
        pendingTasks.clear();
    }

    void handleUidActive(int uid) {
        synchronized (mSettingsLock) {
            final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
            final int userId = UserHandle.getUserId(uid);
            mRestrictionSettings.forEachPackageInUidLocked(uid, (pkgName, level, reason) -> {
                if (mConstantsObserver.mBgAutoRestrictedBucket
                        && level == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
                    mActiveUids.add(uid, pkgName, () -> appStandbyInternal.restrictApp(pkgName,
                            userId, reason & REASON_MAIN_MASK, reason & REASON_SUB_MASK));
                } else {
                    mActiveUids.add(uid, pkgName, null);
                }
            });
        }
    }

    boolean isOnDeviceIdleAllowlist(int uid) {
        final int appId = UserHandle.getAppId(uid);

        return Arrays.binarySearch(mDeviceIdleAllowlist, appId) >= 0
                || Arrays.binarySearch(mDeviceIdleExceptIdleAllowlist, appId) >= 0;
    }

    boolean isOnSystemDeviceIdleAllowlist(int uid) {
        final int appId = UserHandle.getAppId(uid);

        return mSystemDeviceIdleAllowlist.contains(appId)
                || mSystemDeviceIdleExceptIdleAllowlist.contains(appId);
    }

    void setDeviceIdleAllowlist(int[] allAppids, int[] exceptIdleAppids) {
        mDeviceIdleAllowlist = allAppids;
        mDeviceIdleExceptIdleAllowlist = exceptIdleAppids;
    }

    /**
     * @return The reason code of whether or not the given UID should be exempted from background
     * restrictions here.
     *
     * <p>
     * Note: Call it with caution as it'll try to acquire locks in other services.
     * </p>
     */
    @ReasonCode
    int getBackgroundRestrictionExemptionReason(int uid) {
        if (UserHandle.isCore(uid)) {
            return REASON_SYSTEM_UID;
        }
        if (isOnSystemDeviceIdleAllowlist(uid)) {
            return REASON_SYSTEM_ALLOW_LISTED;
        }
        if (UserManager.isDeviceInDemoMode(mContext)) {
            return REASON_DEVICE_DEMO_MODE;
        }
        final int userId = UserHandle.getUserId(uid);
        if (mInjector.getUserManagerInternal()
                .hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL, userId)) {
            return REASON_DISALLOW_APPS_CONTROL;
        }
        final ActivityManagerInternal am = mInjector.getActivityManagerInternal();
        if (am.isDeviceOwner(uid)) {
            return REASON_DEVICE_OWNER;
        }
        if (am.isProfileOwner(uid)) {
            return REASON_PROFILE_OWNER;
        }
        final int uidProcState = am.getUidProcessState(uid);
        if (uidProcState <= PROCESS_STATE_PERSISTENT) {
            return REASON_PROC_STATE_PERSISTENT;
        } else if (uidProcState <= PROCESS_STATE_PERSISTENT_UI) {
            return REASON_PROC_STATE_PERSISTENT_UI;
        }
        final String[] packages = mInjector.getPackageManager().getPackagesForUid(uid);
        if (packages != null) {
            final AppOpsManager appOpsManager = mInjector.getAppOpsManager();
            final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
            final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
            // Check each packages to see if any of them is in the "fixed" exemption cases.
            for (String pkg : packages) {
                if (isSystemModule(pkg)) {
                    return REASON_SYSTEM_MODULE;
                } else if (isCarrierApp(pkg)) {
                    return REASON_CARRIER_PRIVILEGED_APP;
                } else if (isExemptedFromSysConfig(pkg)) {
                    return REASON_SYSTEM_ALLOW_LISTED;
                } else if (mConstantsObserver.mBgRestrictionExemptedPackages.contains(pkg)) {
                    return REASON_SYSTEM_ALLOW_LISTED;
                } else if (pm.isPackageStateProtected(pkg, userId)) {
                    return REASON_DPO_PROTECTED_APP;
                } else if (appStandbyInternal.isActiveDeviceAdmin(pkg, userId)) {
                    return REASON_ACTIVE_DEVICE_ADMIN;
                }
            }
            // Loop the packages again, and check the user-configurable exemptions.
            for (String pkg : packages) {
                if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN,
                        uid, pkg) == AppOpsManager.MODE_ALLOWED) {
                    return REASON_OP_ACTIVATE_VPN;
                } else if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN,
                        uid, pkg) == AppOpsManager.MODE_ALLOWED) {
                    return REASON_OP_ACTIVATE_PLATFORM_VPN;
                }
            }
        }
        if (isRoleHeldByUid(RoleManager.ROLE_DIALER, uid)) {
            return REASON_ROLE_DIALER;
        }
        if (isRoleHeldByUid(RoleManager.ROLE_EMERGENCY, uid)) {
            return REASON_ROLE_EMERGENCY;
        }
        if (isOnDeviceIdleAllowlist(uid)) {
            return REASON_ALLOWLISTED_PACKAGE;
        }
        if (am.isAssociatedCompanionApp(UserHandle.getUserId(uid), uid)) {
            return REASON_COMPANION_DEVICE_MANAGER;
        }
        return REASON_DENIED;
    }

    private boolean isCarrierApp(String packageName) {
        synchronized (mCarrierPrivilegedLock) {
            if (mCarrierPrivilegedApps == null) {
                fetchCarrierPrivilegedAppsCPL();
            }
            if (mCarrierPrivilegedApps != null) {
                return mCarrierPrivilegedApps.contains(packageName);
            }
            return false;
        }
    }

    private void clearCarrierPrivilegedApps() {
        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
            Slog.i(TAG, "Clearing carrier privileged apps list");
        }
        synchronized (mCarrierPrivilegedLock) {
            mCarrierPrivilegedApps = null; // Need to be refetched.
        }
    }

    @GuardedBy("mCarrierPrivilegedLock")
    private void fetchCarrierPrivilegedAppsCPL() {
        final TelephonyManager telephonyManager = mInjector.getTelephonyManager();
        mCarrierPrivilegedApps =
                telephonyManager.getCarrierPrivilegedPackagesForAllActiveSubscriptions();
        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
            Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
        }
    }

    private boolean isRoleHeldByUid(@NonNull String roleName, int uid) {
        synchronized (mLock) {
            final ArrayList<String> roles = mUidRolesMapping.get(uid);
            return roles != null && roles.indexOf(roleName) >= 0;
        }
    }

    private void initRolesInInterest() {
        final int[] allUsers = mInjector.getUserManagerInternal().getUserIds();
        for (String role : ROLES_IN_INTEREST) {
            if (mInjector.getRoleManager().isRoleAvailable(role)) {
                for (int userId : allUsers) {
                    final UserHandle user = UserHandle.of(userId);
                    onRoleHoldersChanged(role, user);
                }
            }
        }
    }

    private void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
        final List<String> rolePkgs = mInjector.getRoleManager().getRoleHoldersAsUser(
                roleName, user);
        final ArraySet<Integer> roleUids = new ArraySet<>();
        final int userId = user.getIdentifier();
        if (rolePkgs != null) {
            final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
            for (String pkg: rolePkgs) {
                roleUids.add(pm.getPackageUid(pkg, STOCK_PM_FLAGS, userId));
            }
        }
        synchronized (mLock) {
            for (int i = mUidRolesMapping.size() - 1; i >= 0; i--) {
                final int uid = mUidRolesMapping.keyAt(i);
                if (UserHandle.getUserId(uid) != userId) {
                    continue;
                }
                final ArrayList<String> roles = mUidRolesMapping.valueAt(i);
                final int index = roles.indexOf(roleName);
                final boolean isRole = roleUids.contains(uid);
                if (index >= 0) {
                    if (!isRole) { // Not holding this role anymore, remove it.
                        roles.remove(index);
                        if (roles.isEmpty()) {
                            mUidRolesMapping.removeAt(i);
                        }
                    }
                } else if (isRole) { // Got this new role, add it.
                    roles.add(roleName);
                    roleUids.remove(uid);
                }
            }
            for (int i = roleUids.size() - 1; i >= 0; i--) { // Take care of the leftovers.
                final ArrayList<String> roles = new ArrayList<>();
                roles.add(roleName);
                mUidRolesMapping.put(roleUids.valueAt(i), roles);
            }
        }
    }

    /**
     * @return The background handler of this controller.
     */
    Handler getBackgroundHandler() {
        return mBgHandler;
    }

    /**
     * @return The background handler thread of this controller.
     */
    @VisibleForTesting
    HandlerThread getBackgroundHandlerThread() {
        return mBgHandlerThread;
    }

    /**
     * @return The global lock of this controller.
     */
    Object getLock() {
        return mLock;
    }

    @VisibleForTesting
    void addAppStateTracker(@NonNull BaseAppStateTracker tracker) {
        mAppStateTrackers.add(tracker);
    }

    /**
     * @return The tracker instance of the given class.
     */
    <T extends BaseAppStateTracker> T getAppStateTracker(Class<T> trackerClass) {
        for (BaseAppStateTracker tracker : mAppStateTrackers) {
            if (trackerClass.isAssignableFrom(tracker.getClass())) {
                return (T) tracker;
            }
        }
        return null;
    }

    void postLongRunningFgsIfNecessary(String packageName, int uid) {
        mNotificationHelper.postLongRunningFgsIfNecessary(packageName, uid);
    }

    void cancelLongRunningFGSNotificationIfNecessary(String packageName, int uid) {
        mNotificationHelper.cancelLongRunningFGSNotificationIfNecessary(packageName, uid);
    }

    String getPackageName(int pid) {
        return mInjector.getPackageName(pid);
    }

    static class BgHandler extends Handler {
        static final int MSG_BACKGROUND_RESTRICTION_CHANGED = 0;
        static final int MSG_APP_RESTRICTION_LEVEL_CHANGED = 1;
        static final int MSG_APP_STANDBY_BUCKET_CHANGED = 2;
        static final int MSG_USER_INTERACTION_STARTED = 3;
        static final int MSG_REQUEST_BG_RESTRICTED = 4;
        static final int MSG_UID_IDLE = 5;
        static final int MSG_UID_ACTIVE = 6;
        static final int MSG_UID_GONE = 7;
        static final int MSG_UID_PROC_STATE_CHANGED = 8;
        static final int MSG_CANCEL_REQUEST_BG_RESTRICTED = 9;
        static final int MSG_LOAD_RESTRICTION_SETTINGS = 10;
        static final int MSG_PERSIST_RESTRICTION_SETTINGS = 11;

        private final Injector mInjector;

        BgHandler(Looper looper, Injector injector) {
            super(looper);
            mInjector = injector;
        }

        @Override
        public void handleMessage(Message msg) {
            final AppRestrictionController c = mInjector
                    .getAppRestrictionController();
            switch (msg.what) {
                case MSG_BACKGROUND_RESTRICTION_CHANGED: {
                    c.handleBackgroundRestrictionChanged(msg.arg1, (String) msg.obj, msg.arg2 == 1);
                } break;
                case MSG_APP_RESTRICTION_LEVEL_CHANGED: {
                    c.dispatchAppRestrictionLevelChanges(msg.arg1, (String) msg.obj, msg.arg2);
                } break;
                case MSG_APP_STANDBY_BUCKET_CHANGED: {
                    c.handleAppStandbyBucketChanged(msg.arg2, (String) msg.obj, msg.arg1);
                } break;
                case MSG_USER_INTERACTION_STARTED: {
                    c.onUserInteractionStarted((String) msg.obj, msg.arg1);
                } break;
                case MSG_REQUEST_BG_RESTRICTED: {
                    c.handleRequestBgRestricted((String) msg.obj, msg.arg1);
                } break;
                case MSG_UID_IDLE: {
                    c.handleUidInactive(msg.arg1, msg.arg2 == 1);
                } break;
                case MSG_UID_ACTIVE: {
                    c.handleUidActive(msg.arg1);
                } break;
                case MSG_CANCEL_REQUEST_BG_RESTRICTED: {
                    c.handleCancelRequestBgRestricted((String) msg.obj, msg.arg1);
                } break;
                case MSG_UID_PROC_STATE_CHANGED: {
                    c.handleUidProcStateChanged(msg.arg1, msg.arg2);
                } break;
                case MSG_UID_GONE: {
                    // It also means this UID is inactive now.
                    c.handleUidInactive(msg.arg1, msg.arg2 == 1);
                    c.handleUidGone(msg.arg1);
                } break;
                case MSG_LOAD_RESTRICTION_SETTINGS: {
                    c.mRestrictionSettings.loadFromXml(true);
                } break;
                case MSG_PERSIST_RESTRICTION_SETTINGS: {
                    c.mRestrictionSettings.persistToXml(msg.arg1);
                } break;
            }
        }
    }

    static class Injector {
        private final Context mContext;
        private ActivityManagerInternal mActivityManagerInternal;
        private AppRestrictionController mAppRestrictionController;
        private AppOpsManager mAppOpsManager;
        private AppStandbyInternal mAppStandbyInternal;
        private AppStateTracker mAppStateTracker;
        private AppHibernationManagerInternal mAppHibernationInternal;
        private IActivityManager mIActivityManager;
        private UserManagerInternal mUserManagerInternal;
        private PackageManagerInternal mPackageManagerInternal;
        private NotificationManager mNotificationManager;
        private RoleManager mRoleManager;
        private AppBatteryTracker mAppBatteryTracker;
        private AppBatteryExemptionTracker mAppBatteryExemptionTracker;
        private AppFGSTracker mAppFGSTracker;
        private AppMediaSessionTracker mAppMediaSessionTracker;
        private AppPermissionTracker mAppPermissionTracker;
        private TelephonyManager mTelephonyManager;

        Injector(Context context) {
            mContext = context;
        }

        Context getContext() {
            return mContext;
        }

        void initAppStateTrackers(AppRestrictionController controller) {
            mAppRestrictionController = controller;
            mAppBatteryTracker = new AppBatteryTracker(mContext, controller);
            mAppBatteryExemptionTracker = new AppBatteryExemptionTracker(mContext, controller);
            mAppFGSTracker = new AppFGSTracker(mContext, controller);
            mAppMediaSessionTracker = new AppMediaSessionTracker(mContext, controller);
            mAppPermissionTracker = new AppPermissionTracker(mContext, controller);
            controller.mAppStateTrackers.add(mAppBatteryTracker);
            controller.mAppStateTrackers.add(mAppBatteryExemptionTracker);
            controller.mAppStateTrackers.add(mAppFGSTracker);
            controller.mAppStateTrackers.add(mAppMediaSessionTracker);
            controller.mAppStateTrackers.add(mAppPermissionTracker);
            controller.mAppStateTrackers.add(new AppBroadcastEventsTracker(mContext, controller));
            controller.mAppStateTrackers.add(new AppBindServiceEventsTracker(mContext, controller));
        }

        ActivityManagerInternal getActivityManagerInternal() {
            if (mActivityManagerInternal == null) {
                mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
            }
            return mActivityManagerInternal;
        }

        AppRestrictionController getAppRestrictionController() {
            return mAppRestrictionController;
        }

        AppOpsManager getAppOpsManager() {
            if (mAppOpsManager == null) {
                mAppOpsManager = getContext().getSystemService(AppOpsManager.class);
            }
            return mAppOpsManager;
        }

        AppStandbyInternal getAppStandbyInternal() {
            if (mAppStandbyInternal == null) {
                mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
            }
            return mAppStandbyInternal;
        }

        AppHibernationManagerInternal getAppHibernationInternal() {
            if (mAppHibernationInternal == null) {
                mAppHibernationInternal = LocalServices.getService(
                        AppHibernationManagerInternal.class);
            }
            return mAppHibernationInternal;
        }

        AppStateTracker getAppStateTracker() {
            if (mAppStateTracker == null) {
                mAppStateTracker = LocalServices.getService(AppStateTracker.class);
            }
            return mAppStateTracker;
        }

        IActivityManager getIActivityManager() {
            return ActivityManager.getService();
        }

        UserManagerInternal getUserManagerInternal() {
            if (mUserManagerInternal == null) {
                mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
            }
            return mUserManagerInternal;
        }

        PackageManagerInternal getPackageManagerInternal() {
            if (mPackageManagerInternal == null) {
                mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
            }
            return mPackageManagerInternal;
        }

        PackageManager getPackageManager() {
            return getContext().getPackageManager();
        }

        NotificationManager getNotificationManager() {
            if (mNotificationManager == null) {
                mNotificationManager = getContext().getSystemService(NotificationManager.class);
            }
            return mNotificationManager;
        }

        RoleManager getRoleManager() {
            if (mRoleManager == null) {
                mRoleManager = getContext().getSystemService(RoleManager.class);
            }
            return mRoleManager;
        }

        TelephonyManager getTelephonyManager() {
            if (mTelephonyManager == null) {
                mTelephonyManager = getContext().getSystemService(TelephonyManager.class);
            }
            return mTelephonyManager;
        }

        AppFGSTracker getAppFGSTracker() {
            return mAppFGSTracker;
        }

        AppMediaSessionTracker getAppMediaSessionTracker() {
            return mAppMediaSessionTracker;
        }

        ActivityManagerService getActivityManagerService() {
            return mAppRestrictionController.mActivityManagerService;
        }

        UidBatteryUsageProvider getUidBatteryUsageProvider() {
            return mAppBatteryTracker;
        }

        AppBatteryExemptionTracker getAppBatteryExemptionTracker() {
            return mAppBatteryExemptionTracker;
        }

        AppPermissionTracker getAppPermissionTracker() {
            return mAppPermissionTracker;
        }

        String getPackageName(int pid) {
            final ActivityManagerService am = getActivityManagerService();
            final ProcessRecord app;
            synchronized (am.mPidsSelfLocked) {
                app = am.mPidsSelfLocked.get(pid);
                if (app != null) {
                    final ApplicationInfo ai = app.info;
                    if (ai != null) {
                        return ai.packageName;
                    }
                }
            }
            return null;
        }

        void scheduleInitTrackers(Handler handler, Runnable initializers) {
            handler.post(initializers);
        }

        File getDataSystemDeDirectory(@UserIdInt int userId) {
            return Environment.getDataSystemDeDirectory(userId);
        }

        @CurrentTimeMillisLong long currentTimeMillis() {
            return System.currentTimeMillis();
        }

        boolean isTest() {
            return false;
        }
    }

    private void registerForSystemBroadcasts() {
        final IntentFilter packageFilter = new IntentFilter();
        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        packageFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
        packageFilter.addDataScheme("package");
        mContext.registerReceiverForAllUsers(mBroadcastReceiver, packageFilter, null, mBgHandler);
        final IntentFilter userFilter = new IntentFilter();
        userFilter.addAction(Intent.ACTION_USER_ADDED);
        userFilter.addAction(Intent.ACTION_USER_REMOVED);
        userFilter.addAction(Intent.ACTION_UID_REMOVED);
        mContext.registerReceiverForAllUsers(mBroadcastReceiver, userFilter, null, mBgHandler);
        final IntentFilter bootFilter = new IntentFilter();
        bootFilter.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED);
        mContext.registerReceiverAsUser(mBootReceiver, UserHandle.SYSTEM,
                bootFilter, null, mBgHandler);
    }

    private void unregisterForSystemBroadcasts() {
        mContext.unregisterReceiver(mBroadcastReceiver);
        mContext.unregisterReceiver(mBootReceiver);
    }

    void forEachTracker(Consumer<BaseAppStateTracker> sink) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            sink.accept(mAppStateTrackers.get(i));
        }
    }

    private void onUserAdded(@UserIdInt int userId) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUserAdded(userId);
        }
    }

    private void onUserStarted(@UserIdInt int userId) {
        refreshAppRestrictionLevelForUser(userId, REASON_MAIN_FORCED_BY_USER,
                REASON_SUB_FORCED_USER_FLAG_INTERACTION);
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUserStarted(userId);
        }
    }

    private void onUserStopped(@UserIdInt int userId) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUserStopped(userId);
        }
    }

    private void onUserRemoved(@UserIdInt int userId) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUserRemoved(userId);
        }
        mRestrictionSettings.removeUser(userId);
    }

    private void onUidAdded(int uid) {
        refreshAppRestrictionLevelForUid(uid, REASON_MAIN_FORCED_BY_SYSTEM,
                REASON_SUB_FORCED_SYSTEM_FLAG_UNDEFINED, false);
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUidAdded(uid);
        }
    }

    private void onPackageRemoved(String pkgName, int uid) {
        mRestrictionSettings.removePackage(pkgName, uid);
    }

    private void onUidRemoved(int uid) {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUidRemoved(uid);
        }
        mRestrictionSettings.removeUid(uid);
    }

    private void onLockedBootCompleted() {
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onLockedBootCompleted();
        }
    }

    boolean isBgAutoRestrictedBucketFeatureFlagEnabled() {
        return mConstantsObserver.mBgAutoRestrictedBucket;
    }

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

    private void onUserInteractionStarted(String packageName, @UserIdInt int userId) {
        final int uid = mInjector.getPackageManagerInternal()
                .getPackageUid(packageName, STOCK_PM_FLAGS, userId);
        for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) {
            mAppStateTrackers.get(i).onUserInteractionStarted(packageName, uid);
        }
    }
}
