/*
 * Copyright (C) 2017 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;

import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AppOpsManager.PackageOps;
import android.app.IActivityManager;
import android.app.IUidObserver;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager.ServiceType;
import android.os.PowerManagerInternal;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseSetArray;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;

/**
 * Class to keep track of the information related to "force app standby", which includes:
 * - OP_RUN_ANY_IN_BACKGROUND for each package
 * - UID foreground/active state
 * - User+system power save whitelist
 * - Temporary power save whitelist
 * - Global "force all apps standby" mode enforced by battery saver.
 *
 * Test:
  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
 */
public class AppStateTracker {
    private static final String TAG = "AppStateTracker";
    private static final boolean DEBUG = false;

    private final Object mLock = new Object();
    private final Context mContext;

    @VisibleForTesting
    static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;

    IActivityManager mIActivityManager;
    ActivityManagerInternal mActivityManagerInternal;
    AppOpsManager mAppOpsManager;
    IAppOpsService mAppOpsService;
    PowerManagerInternal mPowerManagerInternal;
    StandbyTracker mStandbyTracker;
    UsageStatsManagerInternal mUsageStatsManagerInternal;

    private final MyHandler mHandler;

    @VisibleForTesting
    FeatureFlagsObserver mFlagsObserver;

    /**
     * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
     */
    @GuardedBy("mLock")
    final ArraySet<Pair<Integer, String>> mRunAnyRestrictedPackages = new ArraySet<>();

    /** UIDs that are active. */
    @GuardedBy("mLock")
    final SparseBooleanArray mActiveUids = new SparseBooleanArray();

    /** UIDs that are in the foreground. */
    @GuardedBy("mLock")
    final SparseBooleanArray mForegroundUids = new SparseBooleanArray();

    /**
     * System except-idle + user whitelist in the device idle controller.
     */
    @GuardedBy("mLock")
    private int[] mPowerWhitelistedAllAppIds = new int[0];

    /**
     * User whitelisted apps in the device idle controller.
     */
    @GuardedBy("mLock")
    private int[] mPowerWhitelistedUserAppIds = new int[0];

    @GuardedBy("mLock")
    private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;

    /**
     * Per-user packages that are in the EXEMPT bucket.
     */
    @GuardedBy("mLock")
    private final SparseSetArray<String> mExemptedPackages = new SparseSetArray<>();

    @GuardedBy("mLock")
    final ArraySet<Listener> mListeners = new ArraySet<>();

    @GuardedBy("mLock")
    boolean mStarted;

    /**
     * Only used for small battery use-case.
     */
    @GuardedBy("mLock")
    boolean mIsPluggedIn;

    @GuardedBy("mLock")
    boolean mBatterySaverEnabled;

    /**
     * True if the forced app standby is currently enabled
     */
    @GuardedBy("mLock")
    boolean mForceAllAppsStandby;

    /**
     * True if the forced app standby for small battery devices feature is enabled in settings
     */
    @GuardedBy("mLock")
    boolean mForceAllAppStandbyForSmallBattery;

    /**
     * True if the forced app standby feature is enabled in settings
     */
    @GuardedBy("mLock")
    boolean mForcedAppStandbyEnabled;

    interface Stats {
        int UID_FG_STATE_CHANGED = 0;
        int UID_ACTIVE_STATE_CHANGED = 1;
        int RUN_ANY_CHANGED = 2;
        int ALL_UNWHITELISTED = 3;
        int ALL_WHITELIST_CHANGED = 4;
        int TEMP_WHITELIST_CHANGED = 5;
        int EXEMPT_CHANGED = 6;
        int FORCE_ALL_CHANGED = 7;
        int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;

        int IS_UID_ACTIVE_CACHED = 9;
        int IS_UID_ACTIVE_RAW = 10;
    }

    private final StatLogger mStatLogger = new StatLogger(new String[] {
            "UID_FG_STATE_CHANGED",
            "UID_ACTIVE_STATE_CHANGED",
            "RUN_ANY_CHANGED",
            "ALL_UNWHITELISTED",
            "ALL_WHITELIST_CHANGED",
            "TEMP_WHITELIST_CHANGED",
            "EXEMPT_CHANGED",
            "FORCE_ALL_CHANGED",
            "FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",

            "IS_UID_ACTIVE_CACHED",
            "IS_UID_ACTIVE_RAW",
    });

    @VisibleForTesting
    class FeatureFlagsObserver extends ContentObserver {
        FeatureFlagsObserver() {
            super(null);
        }

        void register() {
            mContext.getContentResolver().registerContentObserver(
                    Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
                    false, this);

            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED), false, this);
        }

        boolean isForcedAppStandbyEnabled() {
            return injectGetGlobalSettingInt(Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
        }

        boolean isForcedAppStandbyForSmallBatteryEnabled() {
            return injectGetGlobalSettingInt(
                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED).equals(uri)) {
                final boolean enabled = isForcedAppStandbyEnabled();
                synchronized (mLock) {
                    if (mForcedAppStandbyEnabled == enabled) {
                        return;
                    }
                    mForcedAppStandbyEnabled = enabled;
                    if (DEBUG) {
                        Slog.d(TAG,"Forced app standby feature flag changed: "
                                + mForcedAppStandbyEnabled);
                    }
                }
                mHandler.notifyForcedAppStandbyFeatureFlagChanged();
            } else if (Settings.Global.getUriFor(
                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED).equals(uri)) {
                final boolean enabled = isForcedAppStandbyForSmallBatteryEnabled();
                synchronized (mLock) {
                    if (mForceAllAppStandbyForSmallBattery == enabled) {
                        return;
                    }
                    mForceAllAppStandbyForSmallBattery = enabled;
                    if (DEBUG) {
                        Slog.d(TAG, "Forced app standby for small battery feature flag changed: "
                                + mForceAllAppStandbyForSmallBattery);
                    }
                    updateForceAllAppStandbyState();
                }
            } else {
                Slog.w(TAG, "Unexpected feature flag uri encountered: " + uri);
            }
        }
    }

    public static abstract class Listener {
        /**
         * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
         */
        private void onRunAnyAppOpsChanged(AppStateTracker sender,
                int uid, @NonNull String packageName) {
            updateJobsForUidPackage(uid, packageName, sender.isUidActive(uid));

            if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ false)) {
                unblockAlarmsForUidPackage(uid, packageName);
            } else if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ true)){
                // we need to deliver the allow-while-idle alarms for this uid, package
                unblockAllUnrestrictedAlarms();
            }

            if (!sender.isRunAnyInBackgroundAppOpsAllowed(uid, packageName)) {
                Slog.v(TAG, "Package " + packageName + "/" + uid
                        + " toggled into fg service restriction");
                stopForegroundServicesForUidPackage(uid, packageName);
            }
        }

        /**
         * This is called when the foreground state changed for a UID.
         */
        private void onUidForegroundStateChanged(AppStateTracker sender, int uid) {
            onUidForeground(uid, sender.isUidInForeground(uid));
        }

        /**
         * This is called when the active/idle state changed for a UID.
         */
        private void onUidActiveStateChanged(AppStateTracker sender, int uid) {
            final boolean isActive = sender.isUidActive(uid);

            updateJobsForUid(uid, isActive);

            if (isActive) {
                unblockAlarmsForUid(uid);
            }
        }

        /**
         * This is called when an app-id(s) is removed from the power save whitelist.
         */
        private void onPowerSaveUnwhitelisted(AppStateTracker sender) {
            updateAllJobs();
            unblockAllUnrestrictedAlarms();
        }

        /**
         * This is called when the power save whitelist changes, excluding the
         * {@link #onPowerSaveUnwhitelisted} case.
         */
        private void onPowerSaveWhitelistedChanged(AppStateTracker sender) {
            updateAllJobs();
        }

        /**
         * This is called when the temp whitelist changes.
         */
        private void onTempPowerSaveWhitelistChanged(AppStateTracker sender) {

            // TODO This case happens rather frequently; consider optimizing and update jobs
            // only for affected app-ids.

            updateAllJobs();

            // Note when an app is just put in the temp whitelist, we do *not* drain pending alarms.
        }

        /**
         * This is called when the EXEMPT bucket is updated.
         */
        private void onExemptChanged(AppStateTracker sender) {
            // This doesn't happen very often, so just re-evaluate all jobs / alarms.
            updateAllJobs();
            unblockAllUnrestrictedAlarms();
        }

        /**
         * This is called when the global "force all apps standby" flag changes.
         */
        private void onForceAllAppsStandbyChanged(AppStateTracker sender) {
            updateAllJobs();

            if (!sender.isForceAllAppsStandbyEnabled()) {
                unblockAllUnrestrictedAlarms();
            }
        }

        /**
         * Called when the job restrictions for multiple UIDs might have changed, so the job
         * scheduler should re-evaluate all restrictions for all jobs.
         */
        public void updateAllJobs() {
        }

        /**
         * Called when the job restrictions for a UID might have changed, so the job
         * scheduler should re-evaluate all restrictions for all jobs.
         */
        public void updateJobsForUid(int uid, boolean isNowActive) {
        }

        /**
         * Called when the job restrictions for a UID - package might have changed, so the job
         * scheduler should re-evaluate all restrictions for all jobs.
         */
        public void updateJobsForUidPackage(int uid, String packageName, boolean isNowActive) {
        }

        /**
         * Called when an app goes into forced app standby and its foreground
         * services need to be removed from that state.
         */
        public void stopForegroundServicesForUidPackage(int uid, String packageName) {
        }

        /**
         * Called when the job restrictions for multiple UIDs might have changed, so the alarm
         * manager should re-evaluate all restrictions for all blocked jobs.
         */
        public void unblockAllUnrestrictedAlarms() {
        }

        /**
         * Called when all jobs for a specific UID are unblocked.
         */
        public void unblockAlarmsForUid(int uid) {
        }

        /**
         * Called when all alarms for a specific UID - package are unblocked.
         */
        public void unblockAlarmsForUidPackage(int uid, String packageName) {
        }

        /**
         * Called when a UID comes into the foreground or the background.
         *
         * @see #isUidInForeground(int)
         */
        public void onUidForeground(int uid, boolean foreground) {
        }
    }

    public AppStateTracker(Context context, Looper looper) {
        mContext = context;
        mHandler = new MyHandler(looper);
    }

    /**
     * Call it when the system is ready.
     */
    public void onSystemServicesReady() {
        synchronized (mLock) {
            if (mStarted) {
                return;
            }
            mStarted = true;

            mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
            mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal());
            mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
            mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
            mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
            mUsageStatsManagerInternal = Preconditions.checkNotNull(
                    injectUsageStatsManagerInternal());

            mFlagsObserver = new FeatureFlagsObserver();
            mFlagsObserver.register();
            mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
            mForceAllAppStandbyForSmallBattery =
                    mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
            mStandbyTracker = new StandbyTracker();
            mUsageStatsManagerInternal.addAppIdleStateChangeListener(mStandbyTracker);

            try {
                mIActivityManager.registerUidObserver(new UidObserver(),
                        ActivityManager.UID_OBSERVER_GONE
                                | ActivityManager.UID_OBSERVER_IDLE
                                | ActivityManager.UID_OBSERVER_ACTIVE
                                | ActivityManager.UID_OBSERVER_PROCSTATE,
                        ActivityManager.PROCESS_STATE_UNKNOWN, null);
                mAppOpsService.startWatchingMode(TARGET_OP, null,
                        new AppOpsWatcher());
            } catch (RemoteException e) {
                // shouldn't happen.
            }

            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_USER_REMOVED);
            filter.addAction(Intent.ACTION_BATTERY_CHANGED);
            mContext.registerReceiver(new MyReceiver(), filter);

            refreshForcedAppStandbyUidPackagesLocked();

            mPowerManagerInternal.registerLowPowerModeObserver(
                    ServiceType.FORCE_ALL_APPS_STANDBY,
                    (state) -> {
                        synchronized (mLock) {
                            mBatterySaverEnabled = state.batterySaverEnabled;
                            updateForceAllAppStandbyState();
                        }
                    });

            mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
                    ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;

            updateForceAllAppStandbyState();
        }
    }

    @VisibleForTesting
    AppOpsManager injectAppOpsManager() {
        return mContext.getSystemService(AppOpsManager.class);
    }

    @VisibleForTesting
    IAppOpsService injectIAppOpsService() {
        return IAppOpsService.Stub.asInterface(
                ServiceManager.getService(Context.APP_OPS_SERVICE));
    }

    @VisibleForTesting
    IActivityManager injectIActivityManager() {
        return ActivityManager.getService();
    }

    @VisibleForTesting
    ActivityManagerInternal injectActivityManagerInternal() {
        return LocalServices.getService(ActivityManagerInternal.class);
    }

    @VisibleForTesting
    PowerManagerInternal injectPowerManagerInternal() {
        return LocalServices.getService(PowerManagerInternal.class);
    }

    @VisibleForTesting
    UsageStatsManagerInternal injectUsageStatsManagerInternal() {
        return LocalServices.getService(UsageStatsManagerInternal.class);
    }

    @VisibleForTesting
    boolean isSmallBatteryDevice() {
        return ActivityManager.isSmallBatteryDevice();
    }

    @VisibleForTesting
    int injectGetGlobalSettingInt(String key, int def) {
        return Settings.Global.getInt(mContext.getContentResolver(), key, def);
    }

    /**
     * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
     */
    @GuardedBy("mLock")
    private void refreshForcedAppStandbyUidPackagesLocked() {
        mRunAnyRestrictedPackages.clear();
        final List<PackageOps> ops = mAppOpsManager.getPackagesForOps(
                new int[] {TARGET_OP});

        if (ops == null) {
            return;
        }
        final int size = ops.size();
        for (int i = 0; i < size; i++) {
            final AppOpsManager.PackageOps pkg = ops.get(i);
            final List<AppOpsManager.OpEntry> entries = ops.get(i).getOps();

            for (int j = 0; j < entries.size(); j++) {
                AppOpsManager.OpEntry ent = entries.get(j);
                if (ent.getOp() != TARGET_OP) {
                    continue;
                }
                if (ent.getMode() != AppOpsManager.MODE_ALLOWED) {
                    mRunAnyRestrictedPackages.add(Pair.create(
                            pkg.getUid(), pkg.getPackageName()));
                }
            }
        }
    }

    private void updateForceAllAppStandbyState() {
        synchronized (mLock) {
            if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {
                toggleForceAllAppsStandbyLocked(!mIsPluggedIn);
            } else {
                toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
            }
        }
    }

    /**
     * Update {@link #mForceAllAppsStandby} and notifies the listeners.
     */
    @GuardedBy("mLock")
    private void toggleForceAllAppsStandbyLocked(boolean enable) {
        if (enable == mForceAllAppsStandby) {
            return;
        }
        mForceAllAppsStandby = enable;

        mHandler.notifyForceAllAppsStandbyChanged();
    }

    @GuardedBy("mLock")
    private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
        final int size = mRunAnyRestrictedPackages.size();
        if (size > 8) {
            return mRunAnyRestrictedPackages.indexOf(Pair.create(uid, packageName));
        }
        for (int i = 0; i < size; i++) {
            final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);

            if ((pair.first == uid) && packageName.equals(pair.second)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * @return whether a uid package-name pair is in mRunAnyRestrictedPackages.
     */
    @GuardedBy("mLock")
    boolean isRunAnyRestrictedLocked(int uid, @NonNull String packageName) {
        return findForcedAppStandbyUidPackageIndexLocked(uid, packageName) >= 0;
    }

    /**
     * Add to / remove from {@link #mRunAnyRestrictedPackages}.
     */
    @GuardedBy("mLock")
    boolean updateForcedAppStandbyUidPackageLocked(int uid, @NonNull String packageName,
            boolean restricted) {
        final int index = findForcedAppStandbyUidPackageIndexLocked(uid, packageName);
        final boolean wasRestricted = index >= 0;
        if (wasRestricted == restricted) {
            return false;
        }
        if (restricted) {
            mRunAnyRestrictedPackages.add(Pair.create(uid, packageName));
        } else {
            mRunAnyRestrictedPackages.removeAt(index);
        }
        return true;
    }

    private static boolean addUidToArray(SparseBooleanArray array, int uid) {
        if (UserHandle.isCore(uid)) {
            return false;
        }
        if (array.get(uid)) {
            return false;
        }
        array.put(uid, true);
        return true;
    }

    private static boolean removeUidFromArray(SparseBooleanArray array, int uid, boolean remove) {
        if (UserHandle.isCore(uid)) {
            return false;
        }
        if (!array.get(uid)) {
            return false;
        }
        if (remove) {
            array.delete(uid);
        } else {
            array.put(uid, false);
        }
        return true;
    }

    private final class UidObserver extends IUidObserver.Stub {
        @Override
        public void onUidStateChanged(int uid, int procState, long procStateSeq) {
            mHandler.onUidStateChanged(uid, procState);
        }

        @Override
        public void onUidActive(int uid) {
            mHandler.onUidActive(uid);
        }

        @Override
        public void onUidGone(int uid, boolean disabled) {
            mHandler.onUidGone(uid, disabled);
        }

        @Override
        public void onUidIdle(int uid, boolean disabled) {
            mHandler.onUidIdle(uid, disabled);
        }

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

    private final class AppOpsWatcher extends IAppOpsCallback.Stub {
        @Override
        public void opChanged(int op, int uid, String packageName) throws RemoteException {
            boolean restricted = false;
            try {
                restricted = mAppOpsService.checkOperation(TARGET_OP,
                        uid, packageName) != AppOpsManager.MODE_ALLOWED;
            } catch (RemoteException e) {
                // Shouldn't happen
            }
            synchronized (mLock) {
                if (updateForcedAppStandbyUidPackageLocked(uid, packageName, restricted)) {
                    mHandler.notifyRunAnyAppOpsChanged(uid, packageName);
                }
            }
        }
    }

    private final class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                if (userId > 0) {
                    mHandler.doUserRemoved(userId);
                }
            } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
                synchronized (mLock) {
                    mIsPluggedIn = (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0);
                }
                updateForceAllAppStandbyState();
            }
        }
    }

    final class StandbyTracker extends AppIdleStateChangeListener {
        @Override
        public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
                int bucket, int reason) {
            if (DEBUG) {
                Slog.d(TAG,"onAppIdleStateChanged: " + packageName + " u" + userId
                        + (idle ? " idle" : " active") + " " + bucket);
            }
            final boolean changed;
            if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
                changed = mExemptedPackages.add(userId, packageName);
            } else {
                changed = mExemptedPackages.remove(userId, packageName);
            }
            if (changed) {
                mHandler.notifyExemptChanged();
            }
        }

        @Override
        public void onParoleStateChanged(boolean isParoleOn) {
        }
    }

    private Listener[] cloneListeners() {
        synchronized (mLock) {
            return mListeners.toArray(new Listener[mListeners.size()]);
        }
    }

    private class MyHandler extends Handler {
        private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0;
        private static final int MSG_UID_FG_STATE_CHANGED = 1;
        private static final int MSG_RUN_ANY_CHANGED = 3;
        private static final int MSG_ALL_UNWHITELISTED = 4;
        private static final int MSG_ALL_WHITELIST_CHANGED = 5;
        private static final int MSG_TEMP_WHITELIST_CHANGED = 6;
        private static final int MSG_FORCE_ALL_CHANGED = 7;
        private static final int MSG_USER_REMOVED = 8;
        private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
        private static final int MSG_EXEMPT_CHANGED = 10;

        private static final int MSG_ON_UID_STATE_CHANGED = 11;
        private static final int MSG_ON_UID_ACTIVE = 12;
        private static final int MSG_ON_UID_GONE = 13;
        private static final int MSG_ON_UID_IDLE = 14;

        public MyHandler(Looper looper) {
            super(looper);
        }

        public void notifyUidActiveStateChanged(int uid) {
            obtainMessage(MSG_UID_ACTIVE_STATE_CHANGED, uid, 0).sendToTarget();
        }

        public void notifyUidForegroundStateChanged(int uid) {
            obtainMessage(MSG_UID_FG_STATE_CHANGED, uid, 0).sendToTarget();
        }

        public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
            obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
        }

        public void notifyAllUnwhitelisted() {
            removeMessages(MSG_ALL_UNWHITELISTED);
            obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
        }

        public void notifyAllWhitelistChanged() {
            removeMessages(MSG_ALL_WHITELIST_CHANGED);
            obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
        }

        public void notifyTempWhitelistChanged() {
            removeMessages(MSG_TEMP_WHITELIST_CHANGED);
            obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
        }

        public void notifyForceAllAppsStandbyChanged() {
            removeMessages(MSG_FORCE_ALL_CHANGED);
            obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
        }

        public void notifyForcedAppStandbyFeatureFlagChanged() {
            removeMessages(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED);
            obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
        }

        public void notifyExemptChanged() {
            removeMessages(MSG_EXEMPT_CHANGED);
            obtainMessage(MSG_EXEMPT_CHANGED).sendToTarget();
        }

        public void doUserRemoved(int userId) {
            obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
        }

        public void onUidStateChanged(int uid, int procState) {
            obtainMessage(MSG_ON_UID_STATE_CHANGED, uid, procState).sendToTarget();
        }

        public void onUidActive(int uid) {
            obtainMessage(MSG_ON_UID_ACTIVE, uid, 0).sendToTarget();
        }

        public void onUidGone(int uid, boolean disabled) {
            obtainMessage(MSG_ON_UID_GONE, uid, disabled ? 1 : 0).sendToTarget();
        }

        public void onUidIdle(int uid, boolean disabled) {
            obtainMessage(MSG_ON_UID_IDLE, uid, disabled ? 1 : 0).sendToTarget();
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_USER_REMOVED:
                    handleUserRemoved(msg.arg1);
                    return;
            }

            // Only notify the listeners when started.
            synchronized (mLock) {
                if (!mStarted) {
                    return;
                }
            }
            final AppStateTracker sender = AppStateTracker.this;

            long start = mStatLogger.getTime();
            switch (msg.what) {
                case MSG_UID_ACTIVE_STATE_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onUidActiveStateChanged(sender, msg.arg1);
                    }
                    mStatLogger.logDurationStat(Stats.UID_ACTIVE_STATE_CHANGED, start);
                    return;

                case MSG_UID_FG_STATE_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onUidForegroundStateChanged(sender, msg.arg1);
                    }
                    mStatLogger.logDurationStat(Stats.UID_FG_STATE_CHANGED, start);
                    return;

                case MSG_RUN_ANY_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
                    }
                    mStatLogger.logDurationStat(Stats.RUN_ANY_CHANGED, start);
                    return;

                case MSG_ALL_UNWHITELISTED:
                    for (Listener l : cloneListeners()) {
                        l.onPowerSaveUnwhitelisted(sender);
                    }
                    mStatLogger.logDurationStat(Stats.ALL_UNWHITELISTED, start);
                    return;

                case MSG_ALL_WHITELIST_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onPowerSaveWhitelistedChanged(sender);
                    }
                    mStatLogger.logDurationStat(Stats.ALL_WHITELIST_CHANGED, start);
                    return;

                case MSG_TEMP_WHITELIST_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onTempPowerSaveWhitelistChanged(sender);
                    }
                    mStatLogger.logDurationStat(Stats.TEMP_WHITELIST_CHANGED, start);
                    return;

                case MSG_EXEMPT_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onExemptChanged(sender);
                    }
                    mStatLogger.logDurationStat(Stats.EXEMPT_CHANGED, start);
                    return;

                case MSG_FORCE_ALL_CHANGED:
                    for (Listener l : cloneListeners()) {
                        l.onForceAllAppsStandbyChanged(sender);
                    }
                    mStatLogger.logDurationStat(Stats.FORCE_ALL_CHANGED, start);
                    return;

                case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
                    // Feature flag for forced app standby changed.
                    final boolean unblockAlarms;
                    synchronized (mLock) {
                        unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby;
                    }
                    for (Listener l : cloneListeners()) {
                        l.updateAllJobs();
                        if (unblockAlarms) {
                            l.unblockAllUnrestrictedAlarms();
                        }
                    }
                    mStatLogger.logDurationStat(
                            Stats.FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED, start);
                    return;

                case MSG_USER_REMOVED:
                    handleUserRemoved(msg.arg1);
                    return;

                case MSG_ON_UID_STATE_CHANGED:
                    handleUidStateChanged(msg.arg1, msg.arg2);
                    return;
                case MSG_ON_UID_ACTIVE:
                    handleUidActive(msg.arg1);
                    return;
                case MSG_ON_UID_GONE:
                    handleUidGone(msg.arg1, msg.arg1 != 0);
                    return;
                case MSG_ON_UID_IDLE:
                    handleUidIdle(msg.arg1, msg.arg1 != 0);
                    return;
            }
        }

        public void handleUidStateChanged(int uid, int procState) {
            synchronized (mLock) {
                if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
                    if (removeUidFromArray(mForegroundUids, uid, false)) {
                        mHandler.notifyUidForegroundStateChanged(uid);
                    }
                } else {
                    if (addUidToArray(mForegroundUids, uid)) {
                        mHandler.notifyUidForegroundStateChanged(uid);
                    }
                }
            }
        }

        public void handleUidActive(int uid) {
            synchronized (mLock) {
                if (addUidToArray(mActiveUids, uid)) {
                    mHandler.notifyUidActiveStateChanged(uid);
                }
            }
        }

        public void handleUidGone(int uid, boolean disabled) {
            removeUid(uid, true);
        }

        public void handleUidIdle(int uid, boolean disabled) {
            // Just to avoid excessive memcpy, don't remove from the array in this case.
            removeUid(uid, false);
        }

        private void removeUid(int uid, boolean remove) {
            synchronized (mLock) {
                if (removeUidFromArray(mActiveUids, uid, remove)) {
                    mHandler.notifyUidActiveStateChanged(uid);
                }
                if (removeUidFromArray(mForegroundUids, uid, remove)) {
                    mHandler.notifyUidForegroundStateChanged(uid);
                }
            }
        }
    }

    void handleUserRemoved(int removedUserId) {
        synchronized (mLock) {
            for (int i = mRunAnyRestrictedPackages.size() - 1; i >= 0; i--) {
                final Pair<Integer, String> pair = mRunAnyRestrictedPackages.valueAt(i);
                final int uid = pair.first;
                final int userId = UserHandle.getUserId(uid);

                if (userId == removedUserId) {
                    mRunAnyRestrictedPackages.removeAt(i);
                }
            }
            cleanUpArrayForUser(mActiveUids, removedUserId);
            cleanUpArrayForUser(mForegroundUids, removedUserId);
            mExemptedPackages.remove(removedUserId);
        }
    }

    private void cleanUpArrayForUser(SparseBooleanArray array, int removedUserId) {
        for (int i = array.size() - 1; i >= 0; i--) {
            final int uid = array.keyAt(i);
            final int userId = UserHandle.getUserId(uid);

            if (userId == removedUserId) {
                array.removeAt(i);
            }
        }
    }

    /**
     * Called by device idle controller to update the power save whitelists.
     */
    public void setPowerSaveWhitelistAppIds(
            int[] powerSaveWhitelistExceptIdleAppIdArray,
            int[] powerSaveWhitelistUserAppIdArray,
            int[] tempWhitelistAppIdArray) {
        synchronized (mLock) {
            final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
            final int[] previousTempWhitelist = mTempWhitelistedAppIds;

            mPowerWhitelistedAllAppIds = powerSaveWhitelistExceptIdleAppIdArray;
            mTempWhitelistedAppIds = tempWhitelistAppIdArray;
            mPowerWhitelistedUserAppIds = powerSaveWhitelistUserAppIdArray;

            if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
                mHandler.notifyAllUnwhitelisted();
            } else if (!Arrays.equals(previousWhitelist, mPowerWhitelistedAllAppIds)) {
                mHandler.notifyAllWhitelistChanged();
            }

            if (!Arrays.equals(previousTempWhitelist, mTempWhitelistedAppIds)) {
                mHandler.notifyTempWhitelistChanged();
            }

        }
    }

    /**
     * @retunr true if a sorted app-id array {@code prevArray} has at least one element
     * that's not in a sorted app-id array {@code newArray}.
     */
    @VisibleForTesting
    static boolean isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray) {
        int i1 = 0;
        int i2 = 0;
        boolean prevFinished;
        boolean newFinished;

        for (;;) {
            prevFinished = i1 >= prevArray.length;
            newFinished = i2 >= newArray.length;
            if (prevFinished || newFinished) {
                break;
            }
            int a1 = prevArray[i1];
            int a2 = newArray[i2];

            if (a1 == a2) {
                i1++;
                i2++;
                continue;
            }
            if (a1 < a2) {
                // prevArray has an element that's not in a2.
                return true;
            }
            i2++;
        }
        if (prevFinished) {
            return false;
        }
        return newFinished;
    }

    // Public interface.

    /**
     * Register a new listener.
     */
    public void addListener(@NonNull Listener listener) {
        synchronized (mLock) {
            mListeners.add(listener);
        }
    }

    /**
     * @return whether alarms should be restricted for a UID package-name.
     */
    public boolean areAlarmsRestricted(int uid, @NonNull String packageName,
            boolean isExemptOnBatterySaver) {
        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
                isExemptOnBatterySaver);
    }

    /**
     * @return whether jobs should be restricted for a UID package-name.
     */
    public boolean areJobsRestricted(int uid, @NonNull String packageName,
            boolean hasForegroundExemption) {
        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
                hasForegroundExemption);
    }

    /**
     * @return whether foreground services should be suppressed in the background
     * due to forced app standby for the given app
     */
    public boolean areForegroundServicesRestricted(int uid, @NonNull String packageName) {
        synchronized (mLock) {
            return isRunAnyRestrictedLocked(uid, packageName);
        }
    }

    /**
     * @return whether force-app-standby is effective for a UID package-name.
     */
    private boolean isRestricted(int uid, @NonNull String packageName,
            boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
        if (isUidActive(uid)) {
            return false;
        }
        synchronized (mLock) {
            // Whitelisted?
            final int appId = UserHandle.getAppId(uid);
            if (ArrayUtils.contains(mPowerWhitelistedAllAppIds, appId)) {
                return false;
            }
            if (useTempWhitelistToo &&
                    ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
                return false;
            }
            if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
                return true;
            }
            if (exemptOnBatterySaver) {
                return false;
            }
            final int userId = UserHandle.getUserId(uid);
            if (mExemptedPackages.contains(userId, packageName)) {
                return false;
            }
            return mForceAllAppsStandby;
        }
    }

    /**
     * @return whether a UID is in active or not *based on cached information.*
     *
     * Note this information is based on the UID proc state callback, meaning it's updated
     * asynchronously and may subtly be stale. If the fresh data is needed, use
     * {@link #isUidActiveSynced} instead.
     */
    public boolean isUidActive(int uid) {
        if (UserHandle.isCore(uid)) {
            return true;
        }
        synchronized (mLock) {
            return mActiveUids.get(uid);
        }
    }

    /**
     * @return whether a UID is in active or not *right now.*
     *
     * This gives the fresh information, but may access the activity manager so is slower.
     */
    public boolean isUidActiveSynced(int uid) {
        if (isUidActive(uid)) { // Use the cached one first.
            return true;
        }
        final long start = mStatLogger.getTime();

        final boolean ret = mActivityManagerInternal.isUidActive(uid);
        mStatLogger.logDurationStat(Stats.IS_UID_ACTIVE_RAW, start);

        return ret;
    }

    /**
     * @return whether a UID is in the foreground or not.
     *
     * Note this information is based on the UID proc state callback, meaning it's updated
     * asynchronously and may subtly be stale. If the fresh data is needed, use
     * {@link ActivityManagerInternal#getUidProcessState} instead.
     */
    public boolean isUidInForeground(int uid) {
        if (UserHandle.isCore(uid)) {
            return true;
        }
        synchronized (mLock) {
            return mForegroundUids.get(uid);
        }
    }

    /**
     * @return whether force all apps standby is enabled or not.
     *
     */
    boolean isForceAllAppsStandbyEnabled() {
        synchronized (mLock) {
            return mForceAllAppsStandby;
        }
    }

    /**
     * @return whether a UID/package has {@code OP_RUN_ANY_IN_BACKGROUND} allowed or not.
     *
     * Note clients normally shouldn't need to access it. It's only for dumpsys.
     */
    public boolean isRunAnyInBackgroundAppOpsAllowed(int uid, @NonNull String packageName) {
        synchronized (mLock) {
            return !isRunAnyRestrictedLocked(uid, packageName);
        }
    }

    /**
     * @return whether a UID is in the user / system defined power-save whitelist or not.
     *
     * Note clients normally shouldn't need to access it. It's only for dumpsys.
     */
    public boolean isUidPowerSaveWhitelisted(int uid) {
        synchronized (mLock) {
            return ArrayUtils.contains(mPowerWhitelistedAllAppIds, UserHandle.getAppId(uid));
        }
    }

    /**
     * @param uid the uid to check for
     * @return whether a UID is in the user defined power-save whitelist or not.
     */
    public boolean isUidPowerSaveUserWhitelisted(int uid) {
        synchronized (mLock) {
            return ArrayUtils.contains(mPowerWhitelistedUserAppIds, UserHandle.getAppId(uid));
        }
    }

    /**
     * @return whether a UID is in the temp power-save whitelist or not.
     *
     * Note clients normally shouldn't need to access it. It's only for dumpsys.
     */
    public boolean isUidTempPowerSaveWhitelisted(int uid) {
        synchronized (mLock) {
            return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid));
        }
    }

    @Deprecated
    public void dump(PrintWriter pw, String prefix) {
        dump(new IndentingPrintWriter(pw, "  ").setIndent(prefix));
    }

    public void dump(IndentingPrintWriter pw) {
        synchronized (mLock) {
            pw.println("Forced App Standby Feature enabled: " + mForcedAppStandbyEnabled);

            pw.print("Force all apps standby: ");
            pw.println(isForceAllAppsStandbyEnabled());

            pw.print("Small Battery Device: ");
            pw.println(isSmallBatteryDevice());

            pw.print("Force all apps standby for small battery device: ");
            pw.println(mForceAllAppStandbyForSmallBattery);

            pw.print("Plugged In: ");
            pw.println(mIsPluggedIn);

            pw.print("Active uids: ");
            dumpUids(pw, mActiveUids);

            pw.print("Foreground uids: ");
            dumpUids(pw, mForegroundUids);

            pw.print("Except-idle + user whitelist appids: ");
            pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));

            pw.print("User whitelist appids: ");
            pw.println(Arrays.toString(mPowerWhitelistedUserAppIds));

            pw.print("Temp whitelist appids: ");
            pw.println(Arrays.toString(mTempWhitelistedAppIds));

            pw.println("Exempted packages:");
            pw.increaseIndent();
            for (int i = 0; i < mExemptedPackages.size(); i++) {
                pw.print("User ");
                pw.print(mExemptedPackages.keyAt(i));
                pw.println();

                pw.increaseIndent();
                for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
                    pw.print(mExemptedPackages.valueAt(i, j));
                    pw.println();
                }
                pw.decreaseIndent();
            }
            pw.decreaseIndent();
            pw.println();

            pw.println("Restricted packages:");
            pw.increaseIndent();
            for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
                pw.print(UserHandle.formatUid(uidAndPackage.first));
                pw.print(" ");
                pw.print(uidAndPackage.second);
                pw.println();
            }
            pw.decreaseIndent();

            mStatLogger.dump(pw);
        }
    }

    private void dumpUids(PrintWriter pw, SparseBooleanArray array) {
        pw.print("[");

        String sep = "";
        for (int i = 0; i < array.size(); i++) {
            if (array.valueAt(i)) {
                pw.print(sep);
                pw.print(UserHandle.formatUid(array.keyAt(i)));
                sep = " ";
            }
        }
        pw.println("]");
    }

    public void dumpProto(ProtoOutputStream proto, long fieldId) {
        synchronized (mLock) {
            final long token = proto.start(fieldId);

            proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
            proto.write(ForceAppStandbyTrackerProto.IS_SMALL_BATTERY_DEVICE,
                    isSmallBatteryDevice());
            proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
                    mForceAllAppStandbyForSmallBattery);
            proto.write(ForceAppStandbyTrackerProto.IS_PLUGGED_IN, mIsPluggedIn);

            for (int i = 0; i < mActiveUids.size(); i++) {
                if (mActiveUids.valueAt(i)) {
                    proto.write(ForceAppStandbyTrackerProto.ACTIVE_UIDS,
                            mActiveUids.keyAt(i));
                }
            }

            for (int i = 0; i < mForegroundUids.size(); i++) {
                if (mForegroundUids.valueAt(i)) {
                    proto.write(ForceAppStandbyTrackerProto.FOREGROUND_UIDS,
                            mForegroundUids.keyAt(i));
                }
            }

            for (int appId : mPowerWhitelistedAllAppIds) {
                proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
            }

            for (int appId : mPowerWhitelistedUserAppIds) {
                proto.write(ForceAppStandbyTrackerProto.POWER_SAVE_USER_WHITELIST_APP_IDS, appId);
            }

            for (int appId : mTempWhitelistedAppIds) {
                proto.write(ForceAppStandbyTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
            }

            for (int i = 0; i < mExemptedPackages.size(); i++) {
                for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
                    final long token2 = proto.start(
                            ForceAppStandbyTrackerProto.EXEMPTED_PACKAGES);

                    proto.write(ExemptedPackage.USER_ID, mExemptedPackages.keyAt(i));
                    proto.write(ExemptedPackage.PACKAGE_NAME, mExemptedPackages.valueAt(i, j));

                    proto.end(token2);
                }
            }

            for (Pair<Integer, String> uidAndPackage : mRunAnyRestrictedPackages) {
                final long token2 = proto.start(
                        ForceAppStandbyTrackerProto.RUN_ANY_IN_BACKGROUND_RESTRICTED_PACKAGES);
                proto.write(RunAnyInBackgroundRestrictedPackages.UID, uidAndPackage.first);
                proto.write(RunAnyInBackgroundRestrictedPackages.PACKAGE_NAME,
                        uidAndPackage.second);
                proto.end(token2);
            }

            mStatLogger.dumpProto(proto, ForceAppStandbyTrackerProto.STATS);

            proto.end(token);
        }
    }
}
