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

Commit adb50d8c authored by Makoto Onuki's avatar Makoto Onuki
Browse files

While-idle alarm timeout & EBS

Use the long whileidle timeout for apps in the background.

Test: Manual test with a test app (I9d0c0ed4b6a0)
Test: atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
Test: atest $ANDROID_BUILD_TOP/cts/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverAlarmTest.java
Bug: 72124522
Change-Id: Ibd0a46e573604f7f2d1ec51a60ea87c163233003
parent 64dd7468
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ package com.android.server;

option java_multiple_files = true;

// next ID: 43
message AlarmManagerServiceProto {
  option (.android.msg_privacy).dest = DEST_AUTOMATIC;

@@ -114,7 +115,14 @@ message AlarmManagerServiceProto {
    optional int32 uid = 1;
    // In the 'elapsed' timebase.
    optional int64 time_ms = 2;

    // Time when the next while-idle is allowed, in the 'elapsed' timebase.
    optional int64 next_allowed_ms = 3;
  }

  // Whether the short or long while-idle timeout should be used for each UID.
  repeated int32 use_allow_while_idle_short_time = 42;

  // For each uid, this is the last time we dispatched an "allow while idle"
  // alarm, used to determine the earliest we can dispatch the next such alarm.
  repeated LastAllowWhileIdleDispatch last_allow_while_idle_dispatch_times = 36;
+6 −1
Original line number Diff line number Diff line
@@ -24,14 +24,19 @@ package com.android.server;
option java_multiple_files = true;

// Dump from com.android.server.ForceAppStandbyTracker.
//
// Next ID: 12
message ForceAppStandbyTrackerProto {
  option (.android.msg_privacy).dest = DEST_AUTOMATIC;

  // Whether all apps are forced standby or not.
  optional bool force_all_apps_standby = 1;

  // UIDs currently active.
  repeated int32 active_uids = 2;

  // UIDs currently in the foreground.
  repeated int32 foreground_uids = 2;
  repeated int32 foreground_uids = 11;

  // App ids that are in power-save whitelist.
  repeated int32 power_save_whitelist_app_ids = 3;
+68 −35
Original line number Diff line number Diff line
@@ -1840,14 +1840,6 @@ class AlarmManagerService extends SystemService {
            if (!blocked) {
                pw.println("    none");
            }
            pw.print("  mUseAllowWhileIdleShortTime: [");
            for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
                if (mUseAllowWhileIdleShortTime.valueAt(i)) {
                    UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
                    pw.print(" ");
                }
            }
            pw.println("]");

            pw.println("  mLastAlarmDeliveredForPackage:");
            for (int i = 0; i < mLastAlarmDeliveredForPackage.size(); i++) {
@@ -1914,13 +1906,31 @@ class AlarmManagerService extends SystemService {
                pw.println("  Last allow while idle dispatch times:");
                for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
                    pw.print("    UID ");
                    UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
                    final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
                    UserHandle.formatUid(pw, uid);
                    pw.print(": ");
                    TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
                            nowELAPSED, pw);
                    final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
                    TimeUtils.formatDuration(lastTime, nowELAPSED, pw);

                    final long minInterval = getWhileIdleMinIntervalLocked(uid);
                    pw.print("  Next allowed:");
                    TimeUtils.formatDuration(lastTime + minInterval, nowELAPSED, pw);
                    pw.print(" (");
                    TimeUtils.formatDuration(minInterval, 0, pw);
                    pw.print(")");

                    pw.println();
                }
            }

            pw.print("  mUseAllowWhileIdleShortTime: [");
            for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
                if (mUseAllowWhileIdleShortTime.valueAt(i)) {
                    UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
                    pw.print(" ");
                }
            }
            pw.println("]");
            pw.println();

            if (mLog.dump(pw, "  Recent problems", "    ")) {
@@ -2181,13 +2191,23 @@ class AlarmManagerService extends SystemService {
            for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) {
                final long token = proto.start(
                        AlarmManagerServiceProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES);
                proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.UID,
                        mLastAllowWhileIdleDispatch.keyAt(i));
                proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.TIME_MS,
                        mLastAllowWhileIdleDispatch.valueAt(i));
                final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
                final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);

                proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.UID, uid);
                proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime);
                proto.write(AlarmManagerServiceProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS,
                        lastTime + getWhileIdleMinIntervalLocked(uid));
                proto.end(token);
            }

            for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
                if (mUseAllowWhileIdleShortTime.valueAt(i)) {
                    proto.write(AlarmManagerServiceProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME,
                            mUseAllowWhileIdleShortTime.keyAt(i));
                }
            }

            mLog.writeToProto(proto, AlarmManagerServiceProto.RECENT_PROBLEMS);

            final FilterStats[] topFilters = new FilterStats[10];
@@ -2866,6 +2886,23 @@ class AlarmManagerService extends SystemService {
    private native int setKernelTime(long nativeData, long millis);
    private native int setKernelTimezone(long nativeData, int minuteswest);

    private long getWhileIdleMinIntervalLocked(int uid) {
        final boolean dozing = mPendingIdleUntil != null;
        final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
        if (!dozing && !ebs) {
            return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
        }
        if (dozing) {
            return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
        }
        if (mUseAllowWhileIdleShortTime.get(uid)) {
            // if the last allow-while-idle went off while uid was fg, or the uid
            // recently came into fg, don't block the alarm for long.
            return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
        }
        return mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
    }

    boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
            final long nowRTC) {
        boolean hasWakeup = false;
@@ -2891,20 +2928,7 @@ class AlarmManagerService extends SystemService {
                    // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
                    // schedule such alarms.
                    final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0);
                    final boolean dozing = mPendingIdleUntil != null;
                    final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled();
                    final long minTime;
                    if (!dozing && !ebs) {
                        minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
                    } else if (dozing) {
                        minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
                    } else if (mUseAllowWhileIdleShortTime.get(alarm.creatorUid)) {
                        // if the last allow-while-idle went off while uid was fg, or the uid
                        // recently came into fg, don't block the alarm for long.
                        minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME;
                    } else {
                        minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
                    }
                    final long minTime = lastTime + getWhileIdleMinIntervalLocked(alarm.creatorUid);
                    if (nowELAPSED < minTime) {
                        // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
                        // alarm went off for this app.  Reschedule the alarm to be in the
@@ -3641,6 +3665,7 @@ class AlarmManagerService extends SystemService {
                } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
                    if (uid >= 0) {
                        mLastAllowWhileIdleDispatch.delete(uid);
                        mUseAllowWhileIdleShortTime.delete(uid);
                    }
                } else {
                    if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
@@ -3693,7 +3718,6 @@ class AlarmManagerService extends SystemService {

        @Override public void onUidGone(int uid, boolean disabled) {
            synchronized (mLock) {
                mUseAllowWhileIdleShortTime.delete(uid);
                if (disabled) {
                    removeForStoppedLocked(uid);
                }
@@ -3701,9 +3725,6 @@ class AlarmManagerService extends SystemService {
        }

        @Override public void onUidActive(int uid) {
            synchronized (mLock) {
                mUseAllowWhileIdleShortTime.put(uid, true);
            }
        }

        @Override public void onUidIdle(int uid, boolean disabled) {
@@ -3766,6 +3787,18 @@ class AlarmManagerService extends SystemService {
                sendPendingBackgroundAlarmsLocked(uid, packageName);
            }
        }

        @Override
        public void onUidForeground(int uid, boolean foreground) {
            synchronized (mLock) {
                if (foreground) {
                    mUseAllowWhileIdleShortTime.put(uid, true);

                    // Note we don't have to drain the pending while-idle alarms here, because
                    // this event should coincide with unblockAlarmsForUid().
                }
            }
        }
    };

    private final BroadcastStats getStatsLocked(PendingIntent pi) {
@@ -4026,7 +4059,7 @@ 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.isInForeground(alarm.creatorUid)) {
                if (mForceAppStandbyTracker.isUidInForeground(alarm.creatorUid)) {
                    mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
                } else {
                    mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
+175 −86

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ public final class BackgroundJobsController extends StateController {
            jobStatus.printUniqueId(pw);
            pw.print(" from ");
            UserHandle.formatUid(pw, uid);
            pw.print(mForceAppStandbyTracker.isInForeground(uid) ? " foreground" : " background");
            pw.print(mForceAppStandbyTracker.isUidActive(uid) ? " active" : " idle");
            if (mForceAppStandbyTracker.isUidPowerSaveWhitelisted(uid) ||
                    mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(uid)) {
                pw.print(", whitelisted");
@@ -136,7 +136,7 @@ public final class BackgroundJobsController extends StateController {
            proto.write(TrackedJob.SOURCE_PACKAGE_NAME, sourcePkg);

            proto.write(TrackedJob.IS_IN_FOREGROUND,
                    mForceAppStandbyTracker.isInForeground(sourceUid));
                    mForceAppStandbyTracker.isUidActive(sourceUid));
            proto.write(TrackedJob.IS_WHITELISTED,
                    mForceAppStandbyTracker.isUidPowerSaveWhitelisted(sourceUid) ||
                    mForceAppStandbyTracker.isUidTempPowerSaveWhitelisted(sourceUid));
Loading