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

Commit 586d9646 authored by Kweku Adams's avatar Kweku Adams
Browse files

Avoid infinite pending MSG_CHECK_IDLE_STATES messages.

1. Make sure we don't have periodic MSG_CHECK_IDLE_STATES messages for
   UserHandle.USER_ALL due to Doze allowlist changes.
2. Make sure we don't have duplicate and periodic MSG_CHECK_IDLE_STATES
   messages for a single user ID.

Bug: 221352666
Test: atest AppStandbyControllerTests
Change-Id: Iedfe02107f97a4c0b07ec0fc6463500faf286a06
parent 7baf6d7c
Loading
Loading
Loading
Loading
+42 −5
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ import android.util.IndentingPrintWriter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.view.Display;
import android.widget.Toast;
@@ -260,6 +261,13 @@ public class AppStandbyController

    private final CountDownLatch mAdminDataAvailableLatch = new CountDownLatch(1);

    /**
     * Set of user IDs and the next time (in the elapsed realtime timebase) when we should check the
     * apps' idle states.
     */
    @GuardedBy("mPendingIdleStateChecks")
    private final SparseLongArray mPendingIdleStateChecks = new SparseLongArray();

    // Cache the active network scorer queried from the network scorer service
    private volatile String mCachedNetworkScorer = null;
    // The last time the network scorer service was queried
@@ -722,7 +730,14 @@ public class AppStandbyController

    @Override
    public void postCheckIdleStates(int userId) {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
        if (userId == UserHandle.USER_ALL) {
            postOneTimeCheckIdleStates();
        } else {
            synchronized (mPendingIdleStateChecks) {
                mPendingIdleStateChecks.put(userId, mInjector.elapsedRealtime());
            }
            mHandler.obtainMessage(MSG_CHECK_IDLE_STATES).sendToTarget();
        }
    }

    @Override
@@ -2374,10 +2389,32 @@ public class AppStandbyController
                    break;

                case MSG_CHECK_IDLE_STATES:
                    if (checkIdleStates(msg.arg1) && mAppIdleEnabled) {
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(
                                MSG_CHECK_IDLE_STATES, msg.arg1, 0),
                                mCheckIdleIntervalMillis);
                    removeMessages(MSG_CHECK_IDLE_STATES);

                    long earliestCheck = Long.MAX_VALUE;
                    final long nowElapsed = mInjector.elapsedRealtime();
                    synchronized (mPendingIdleStateChecks) {
                        for (int i = mPendingIdleStateChecks.size() - 1; i >= 0; --i) {
                            long expirationTime = mPendingIdleStateChecks.valueAt(i);

                            if (expirationTime <= nowElapsed) {
                                final int userId = mPendingIdleStateChecks.keyAt(i);
                                if (checkIdleStates(userId) && mAppIdleEnabled) {
                                    expirationTime = nowElapsed + mCheckIdleIntervalMillis;
                                    mPendingIdleStateChecks.put(userId, expirationTime);
                                } else {
                                    mPendingIdleStateChecks.removeAt(i);
                                    continue;
                                }
                            }

                            earliestCheck = Math.min(earliestCheck, expirationTime);
                        }
                    }
                    if (earliestCheck != Long.MAX_VALUE) {
                        mHandler.sendMessageDelayed(
                                mHandler.obtainMessage(MSG_CHECK_IDLE_STATES),
                                earliestCheck - nowElapsed);
                    }
                    break;