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

Commit b6ff8364 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[3rd try] JobScheduler to use UID active state for job exemption"

parents 9f3bfa1c e491821c
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -348,4 +348,9 @@ public abstract class ActivityManagerInternal {
     * Returns is the caller has the same uid as the Recents component
     */
    public abstract boolean isCallerRecents(int callingUid);

    /**
     * Whether an UID is active or idle.
     */
    public abstract boolean isUidActive(int uid);
}
+22 −15
Original line number Diff line number Diff line
@@ -100,7 +100,8 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.LocalLog;
import com.android.server.ForceAppStandbyTracker.Listener;
import com.android.internal.util.Preconditions;
import com.android.server.AppStateTracker.Listener;

/**
 * Alarm manager implementaion.
@@ -252,7 +253,7 @@ class AlarmManagerService extends SystemService {
    private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
            new SparseArray<>();

    private final ForceAppStandbyTracker mForceAppStandbyTracker;
    private AppStateTracker mAppStateTracker;
    private boolean mAppStandbyParole;
    private ArrayMap<Pair<String, Integer>, Long> mLastAlarmDeliveredForPackage = new ArrayMap<>();

@@ -710,9 +711,6 @@ class AlarmManagerService extends SystemService {
        super(context);
        mConstants = new Constants(mHandler);

        mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
        mForceAppStandbyTracker.addListener(mForceAppStandbyListener);

        publishLocalService(AlarmManagerInternal.class, new LocalService());
    }

@@ -1332,13 +1330,15 @@ class AlarmManagerService extends SystemService {
    @Override
    public void onBootPhase(int phase) {
        if (phase == PHASE_SYSTEM_SERVICES_READY) {
            mForceAppStandbyTracker.start();
            mConstants.start(getContext().getContentResolver());
            mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
            mLocalDeviceIdleController
                    = LocalServices.getService(DeviceIdleController.LocalService.class);
            mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
            mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());

            mAppStateTracker = LocalServices.getService(AppStateTracker.class);
            mAppStateTracker.addListener(mForceAppStandbyListener);
        }
    }

@@ -1727,7 +1727,8 @@ class AlarmManagerService extends SystemService {
            // timing restrictions.
            } else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
                    || UserHandle.isSameApp(callingUid, mSystemUiUid)
                    || mForceAppStandbyTracker.isUidPowerSaveWhitelisted(callingUid))) {
                    || ((mAppStateTracker != null)
                        && mAppStateTracker.isUidPowerSaveWhitelisted(callingUid)))) {
                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
                flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
            }
@@ -1810,8 +1811,10 @@ class AlarmManagerService extends SystemService {
            mConstants.dump(pw);
            pw.println();

            mForceAppStandbyTracker.dump(pw, "  ");
            if (mAppStateTracker != null) {
                mAppStateTracker.dump(pw, "  ");
                pw.println();
            }

            pw.println("  App Standby Parole: " + mAppStandbyParole);
            pw.println();
@@ -2164,8 +2167,10 @@ class AlarmManagerService extends SystemService {

            mConstants.dumpProto(proto, AlarmManagerServiceProto.SETTINGS);

            mForceAppStandbyTracker.dumpProto(proto,
            if (mAppStateTracker != null) {
                mAppStateTracker.dumpProto(proto,
                        AlarmManagerServiceProto.FORCE_APP_STANDBY_TRACKER);
            }

            proto.write(AlarmManagerServiceProto.IS_INTERACTIVE, mInteractive);
            if (!mInteractive) {
@@ -2952,8 +2957,8 @@ class AlarmManagerService extends SystemService {
        }
        final String sourcePackage = alarm.sourcePackage;
        final int sourceUid = alarm.creatorUid;
        return mForceAppStandbyTracker.areAlarmsRestricted(sourceUid, sourcePackage,
                allowWhileIdle);
        return (mAppStateTracker != null) &&
                mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage, allowWhileIdle);
    }

    private native long init();
@@ -2965,7 +2970,8 @@ class AlarmManagerService extends SystemService {

    private long getWhileIdleMinIntervalLocked(int uid) {
        final boolean dozing = mPendingIdleUntil != null;
        final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
        final boolean ebs = (mAppStateTracker != null)
                && mAppStateTracker.isForceAllAppsStandbyEnabled();
        if (!dozing && !ebs) {
            return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
        }
@@ -4156,7 +4162,8 @@ class AlarmManagerService extends SystemService {
            if (allowWhileIdle) {
                // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
                mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
                if (mForceAppStandbyTracker.isUidInForeground(alarm.creatorUid)) {
                if ((mAppStateTracker == null)
                        || mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
                    mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
                } else {
                    mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
+47 −33
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.server.DeviceIdleController.LocalService;
import com.android.server.ForceAppStandbyTrackerProto.ExemptedPackage;
import com.android.server.ForceAppStandbyTrackerProto.RunAnyInBackgroundRestrictedPackages;

@@ -73,14 +72,14 @@ import java.util.List;
 * TODO: Make it a LocalService.
 *
 * Test:
  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
  atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java
 */
public class ForceAppStandbyTracker {
public class AppStateTracker {
    private static final String TAG = "ForceAppStandbyTracker";
    private static final boolean DEBUG = true;

    @GuardedBy("ForceAppStandbyTracker.class")
    private static ForceAppStandbyTracker sInstance;
    @GuardedBy("AppStateTracker.class")
    private static AppStateTracker sInstance;

    private final Object mLock = new Object();
    private final Context mContext;
@@ -89,6 +88,7 @@ public class ForceAppStandbyTracker {
    static final int TARGET_OP = AppOpsManager.OP_RUN_ANY_IN_BACKGROUND;

    IActivityManager mIActivityManager;
    ActivityManagerInternal mActivityManagerInternal;
    AppOpsManager mAppOpsManager;
    IAppOpsService mAppOpsService;
    PowerManagerInternal mPowerManagerInternal;
@@ -172,6 +172,9 @@ public class ForceAppStandbyTracker {
        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[] {
@@ -184,6 +187,9 @@ public class ForceAppStandbyTracker {
            "EXEMPT_CHANGED",
            "FORCE_ALL_CHANGED",
            "FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",

            "IS_UID_ACTIVE_CACHED",
            "IS_UID_ACTIVE_RAW",
    });

    @VisibleForTesting
@@ -249,7 +255,7 @@ public class ForceAppStandbyTracker {
        /**
         * This is called when the OP_RUN_ANY_IN_BACKGROUND appops changed for a package.
         */
        private void onRunAnyAppOpsChanged(ForceAppStandbyTracker sender,
        private void onRunAnyAppOpsChanged(AppStateTracker sender,
                int uid, @NonNull String packageName) {
            updateJobsForUidPackage(uid, packageName);

@@ -264,14 +270,14 @@ public class ForceAppStandbyTracker {
        /**
         * This is called when the foreground state changed for a UID.
         */
        private void onUidForegroundStateChanged(ForceAppStandbyTracker sender, int 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(ForceAppStandbyTracker sender, int uid) {
        private void onUidActiveStateChanged(AppStateTracker sender, int uid) {
            updateJobsForUid(uid);

            if (sender.isUidActive(uid)) {
@@ -282,7 +288,7 @@ public class ForceAppStandbyTracker {
        /**
         * This is called when an app-id(s) is removed from the power save whitelist.
         */
        private void onPowerSaveUnwhitelisted(ForceAppStandbyTracker sender) {
        private void onPowerSaveUnwhitelisted(AppStateTracker sender) {
            updateAllJobs();
            unblockAllUnrestrictedAlarms();
        }
@@ -291,14 +297,14 @@ public class ForceAppStandbyTracker {
         * This is called when the power save whitelist changes, excluding the
         * {@link #onPowerSaveUnwhitelisted} case.
         */
        private void onPowerSaveWhitelistedChanged(ForceAppStandbyTracker sender) {
        private void onPowerSaveWhitelistedChanged(AppStateTracker sender) {
            updateAllJobs();
        }

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

            // TODO This case happens rather frequently; consider optimizing and update jobs
            // only for affected app-ids.
@@ -311,7 +317,7 @@ public class ForceAppStandbyTracker {
        /**
         * This is called when the EXEMPT bucket is updated.
         */
        private void onExemptChanged(ForceAppStandbyTracker sender) {
        private void onExemptChanged(AppStateTracker sender) {
            // This doesn't happen very often, so just re-evaluate all jobs / alarms.
            updateAllJobs();
            unblockAllUnrestrictedAlarms();
@@ -320,7 +326,7 @@ public class ForceAppStandbyTracker {
        /**
         * This is called when the global "force all apps standby" flag changes.
         */
        private void onForceAllAppsStandbyChanged(ForceAppStandbyTracker sender) {
        private void onForceAllAppsStandbyChanged(AppStateTracker sender) {
            updateAllJobs();

            if (!sender.isForceAllAppsStandbyEnabled()) {
@@ -377,30 +383,15 @@ public class ForceAppStandbyTracker {
        }
    }

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

    private ForceAppStandbyTracker(Context context) {
        this(context, FgThread.get().getLooper());
    }

    /**
     * Get the singleton instance.
     */
    public static synchronized ForceAppStandbyTracker getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new ForceAppStandbyTracker(context);
        }
        return sInstance;
    }

    /**
     * Call it when the system is ready.
     */
    public void start() {
    public void onSystemServicesReady() {
        synchronized (mLock) {
            if (mStarted) {
                return;
@@ -408,6 +399,7 @@ public class ForceAppStandbyTracker {
            mStarted = true;

            mIActivityManager = Preconditions.checkNotNull(injectIActivityManager());
            mActivityManagerInternal = Preconditions.checkNotNull(injectActivityManagerInternal());
            mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
            mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
            mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
@@ -474,6 +466,11 @@ public class ForceAppStandbyTracker {
        return ActivityManager.getService();
    }

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

    @VisibleForTesting
    PowerManagerInternal injectPowerManagerInternal() {
        return LocalServices.getService(PowerManagerInternal.class);
@@ -804,7 +801,7 @@ public class ForceAppStandbyTracker {
                    return;
                }
            }
            final ForceAppStandbyTracker sender = ForceAppStandbyTracker.this;
            final AppStateTracker sender = AppStateTracker.this;

            long start = mStatLogger.getTime();
            switch (msg.what) {
@@ -1094,11 +1091,11 @@ public class ForceAppStandbyTracker {
    }

    /**
     * @return whether a UID is in active or not.
     * @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 ActivityManagerInternal#getUidProcessState} instead.
     * {@link #isUidActiveSynced} instead.
     */
    public boolean isUidActive(int uid) {
        if (UserHandle.isCore(uid)) {
@@ -1109,6 +1106,23 @@ public class ForceAppStandbyTracker {
        }
    }

    /**
     * @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.
     *
+7 −1
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ import com.android.internal.os.AtomicFile;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -128,6 +129,7 @@ public class DeviceIdleController extends SystemService
    private Intent mIdleIntent;
    private Intent mLightIdleIntent;
    private AnyMotionDetector mAnyMotionDetector;
    private final AppStateTracker mAppStateTracker;
    private boolean mLightEnabled;
    private boolean mDeepEnabled;
    private boolean mForceIdle;
@@ -1371,6 +1373,8 @@ public class DeviceIdleController extends SystemService
        super(context);
        mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
        mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
        mAppStateTracker = new AppStateTracker(context, FgThread.get().getLooper());
        LocalServices.addService(AppStateTracker.class, mAppStateTracker);
    }

    boolean isAppOnWhitelistInternal(int appid) {
@@ -1501,6 +1505,8 @@ public class DeviceIdleController extends SystemService
                        (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
                        mHandler, mSensorManager, this, angleThreshold);

                mAppStateTracker.onSystemServicesReady();

                mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
                mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_FOREGROUND);
@@ -2615,7 +2621,7 @@ public class DeviceIdleController extends SystemService
    }

    private void passWhiteListToForceAppStandbyTrackerLocked() {
        ForceAppStandbyTracker.getInstance(getContext()).setPowerSaveWhitelistAppIds(
        mAppStateTracker.setPowerSaveWhitelistAppIds(
                mPowerSaveWhitelistExceptIdleAppIdArray,
                mTempWhitelistAppIdArray);
    }
+9 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server;

import android.os.SystemClock;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
@@ -33,6 +34,8 @@ import java.io.PrintWriter;
 * @hide
 */
public class StatLogger {
    private static final String TAG = "StatLogger";

    private final Object mLock = new Object();

    private final int SIZE;
@@ -66,8 +69,12 @@ public class StatLogger {
     */
    public void logDurationStat(int eventId, long start) {
        synchronized (mLock) {
            if (eventId >= 0 && eventId < SIZE) {
                mCountStats[eventId]++;
                mDurationStats[eventId] += (getTime() - start);
            } else {
                Slog.wtf(TAG, "Invalid event ID: " + eventId);
            }
        }
    }

Loading