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

Commit d33c7cd8 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Power manager now prevents wake locks from idle uids.

The activity manager now pushes the idle/active state
down in to the power manager.  The power manager now
tracks a structure of data about each uid: how many
wake locks it holds, whether it is active, and (as before)
its current process state.

Now when apps are inactive, we always disable wake locks
they hold, regardless of the system's device idle or
other state.

Test: none

Change-Id: I2cd4077e4d8a8572525406ae9747f0a2435764da
parent fa4c3114
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -147,10 +147,18 @@ public abstract class PowerManagerInternal {

    public abstract void setDeviceIdleTempWhitelist(int[] appids);

    public abstract void startUidChanges();

    public abstract void finishUidChanges();

    public abstract void updateUidProcState(int uid, int procState);

    public abstract void uidGone(int uid);

    public abstract void uidActive(int uid);

    public abstract void uidIdle(int uid);

    /**
     * The hintId sent through this method should be in-line with the
     * PowerHint defined in android/hardware/power/<version 1.0 & up>/IPower.h
+38 −13
Original line number Diff line number Diff line
@@ -4209,18 +4209,6 @@ public final class ActivityManagerService extends ActivityManagerNative
                    "*** Delivering " + N + " uid changes");
        }
        if (mLocalPowerManager != null) {
            for (int j=0; j<N; j++) {
                UidRecord.ChangeItem item = mActiveUidChanges[j];
                if (item.change == UidRecord.CHANGE_GONE
                        || item.change == UidRecord.CHANGE_GONE_IDLE) {
                    mLocalPowerManager.uidGone(item.uid);
                } else {
                    mLocalPowerManager.updateUidProcState(item.uid, item.processState);
                }
            }
        }
        int i = mUidObservers.beginBroadcast();
        while (i > 0) {
            i--;
@@ -20819,6 +20807,27 @@ public final class ActivityManagerService extends ActivityManagerNative
        pendingChange.change = change;
        pendingChange.processState = uidRec != null
                ? uidRec.setProcState : ActivityManager.PROCESS_STATE_NONEXISTENT;
        // Directly update the power manager, since we sit on top of it and it is critical
        // it be kept in sync (so wake locks will be held as soon as appropriate).
        if (mLocalPowerManager != null) {
            switch (change) {
                case UidRecord.CHANGE_GONE:
                case UidRecord.CHANGE_GONE_IDLE:
                    mLocalPowerManager.uidGone(pendingChange.uid);
                    break;
                case UidRecord.CHANGE_IDLE:
                    mLocalPowerManager.uidIdle(pendingChange.uid);
                    break;
                case UidRecord.CHANGE_ACTIVE:
                    mLocalPowerManager.uidActive(pendingChange.uid);
                    break;
                default:
                    mLocalPowerManager.updateUidProcState(pendingChange.uid,
                            pendingChange.processState);
                    break;
            }
        }
    }
    private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName,
@@ -21367,6 +21376,9 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        // Update from any uid changes.
        if (mLocalPowerManager != null) {
            mLocalPowerManager.startUidChanges();
        }
        for (int i=mActiveUids.size()-1; i>=0; i--) {
            final UidRecord uidRec = mActiveUids.valueAt(i);
            int uidChange = UidRecord.CHANGE_PROCSTATE;
@@ -21397,6 +21409,9 @@ public final class ActivityManagerService extends ActivityManagerNative
                noteUidProcessState(uidRec.uid, uidRec.curProcState);
            }
        }
        if (mLocalPowerManager != null) {
            mLocalPowerManager.finishUidChanges();
        }
        if (mProcessStats.shouldWriteNowLocked(now)) {
            mHandler.post(new Runnable() {
@@ -21421,10 +21436,17 @@ public final class ActivityManagerService extends ActivityManagerNative
    final void idleUids() {
        synchronized (this) {
            final int N = mActiveUids.size();
            if (N <= 0) {
                return;
            }
            final long nowElapsed = SystemClock.elapsedRealtime();
            final long maxBgTime = nowElapsed - BACKGROUND_SETTLE_TIME;
            long nextTime = 0;
            for (int i=mActiveUids.size()-1; i>=0; i--) {
            if (mLocalPowerManager != null) {
                mLocalPowerManager.startUidChanges();
            }
            for (int i=N-1; i>=0; i--) {
                final UidRecord uidRec = mActiveUids.valueAt(i);
                final long bgTime = uidRec.lastBackgroundTime;
                if (bgTime > 0 && !uidRec.idle) {
@@ -21438,6 +21460,9 @@ public final class ActivityManagerService extends ActivityManagerNative
                    }
                }
            }
            if (mLocalPowerManager != null) {
                mLocalPowerManager.finishUidChanges();
            }
            if (nextTime > 0) {
                mHandler.removeMessages(IDLE_UIDS_MSG);
                mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG,
+153 −23
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ import android.service.vr.IVrStateCallbacks;
import android.util.EventLog;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.view.Display;
import android.view.WindowManagerPolicy;
@@ -483,7 +483,13 @@ public final class PowerManagerService extends SystemService
    // Set of app ids that are temporarily allowed to acquire wakelocks due to high-pri message
    int[] mDeviceIdleTempWhitelist = new int[0];

    private final SparseIntArray mUidState = new SparseIntArray();
    private final SparseArray<UidState> mUidState = new SparseArray<>();

    // We are currently in the middle of a batch change of uids.
    private boolean mUidsChanging;

    // Some uids have actually changed while mUidsChanging was true.
    private boolean mUidsChanged;

    // True if theater mode is enabled
    private boolean mTheaterModeEnabled;
@@ -878,7 +884,15 @@ public final class PowerManagerService extends SystemService
                }
                notifyAcquire = false;
            } else {
                wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
                UidState state = mUidState.get(uid);
                if (state == null) {
                    state = new UidState(uid);
                    state.mProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
                    mUidState.put(uid, state);
                }
                state.mNumWakeLocks++;
                wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid,
                        state);
                try {
                    lock.linkToDeath(wakeLock, 0);
                } catch (RemoteException ex) {
@@ -976,6 +990,12 @@ public final class PowerManagerService extends SystemService

    private void removeWakeLockLocked(WakeLock wakeLock, int index) {
        mWakeLocks.remove(index);
        UidState state = wakeLock.mUidState;
        state.mNumWakeLocks--;
        if (state.mNumWakeLocks <= 0 &&
                state.mProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
            mUidState.remove(state.mUid);
        }
        notifyWakeLockReleasedLocked(wakeLock);

        applyWakeLockFlagsOnReleaseLocked(wakeLock);
@@ -2580,20 +2600,82 @@ public final class PowerManagerService extends SystemService
        }
    }

    void updateUidProcStateInternal(int uid, int procState) {
    void startUidChangesInternal() {
        synchronized (mLock) {
            mUidState.put(uid, procState);
            if (mDeviceIdleMode) {
            mUidsChanging = true;
        }
    }

    void finishUidChangesInternal() {
        synchronized (mLock) {
            mUidsChanging = false;
            if (mUidsChanged) {
                updateWakeLockDisabledStatesLocked();
                mUidsChanged = false;
            }
        }
    }

    private void handleUidStateChangeLocked() {
        if (mUidsChanging) {
            mUidsChanged = true;
        } else {
            updateWakeLockDisabledStatesLocked();
        }
    }

    void updateUidProcStateInternal(int uid, int procState) {
        synchronized (mLock) {
            UidState state = mUidState.get(uid);
            if (state == null) {
                state = new UidState(uid);
                mUidState.put(uid, state);
            }
            state.mProcState = procState;
            if (mDeviceIdleMode && state.mNumWakeLocks > 0) {
                handleUidStateChangeLocked();
            }
        }
    }

    void uidGoneInternal(int uid) {
        synchronized (mLock) {
            mUidState.delete(uid);
            if (mDeviceIdleMode) {
                updateWakeLockDisabledStatesLocked();
            final int index = mUidState.indexOfKey(uid);
            if (index >= 0) {
                UidState state = mUidState.valueAt(index);
                state.mProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
                state.mActive = false;
                mUidState.removeAt(index);
                if (mDeviceIdleMode && state.mNumWakeLocks > 0) {
                    handleUidStateChangeLocked();
                }
            }
        }
    }

    void uidActiveInternal(int uid) {
        synchronized (mLock) {
            UidState state = mUidState.get(uid);
            if (state == null) {
                state = new UidState(uid);
                state.mProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                mUidState.put(uid, state);
            }
            state.mActive = true;
            if (state.mNumWakeLocks > 0) {
                handleUidStateChangeLocked();
            }
        }
    }

    void uidIdleInternal(int uid) {
        synchronized (mLock) {
            UidState state = mUidState.get(uid);
            if (state != null) {
                state.mActive = false;
                if (state.mNumWakeLocks > 0) {
                    handleUidStateChangeLocked();
                }
            }
        }
    }
@@ -2626,18 +2708,21 @@ public final class PowerManagerService extends SystemService
        if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
                == PowerManager.PARTIAL_WAKE_LOCK) {
            boolean disabled = false;
            if (mDeviceIdleMode) {
            final int appid = UserHandle.getAppId(wakeLock.mOwnerUid);
            if (appid >= Process.FIRST_APPLICATION_UID) {
                if (mDeviceIdleMode) {
                    // If we are in idle mode, we will ignore all partial wake locks that are
                    // for application uids that are not whitelisted.
                if (appid >= Process.FIRST_APPLICATION_UID &&
                        Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
                    final UidState state = wakeLock.mUidState;
                    if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
                            Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
                        mUidState.get(wakeLock.mOwnerUid,
                                ActivityManager.PROCESS_STATE_CACHED_EMPTY)
                                > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
                            state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
                            state.mProcState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
                        disabled = true;
                    }
                } else {
                    disabled = !wakeLock.mUidState.mActive;
                }
            }
            if (wakeLock.mDisabled != disabled) {
                wakeLock.mDisabled = disabled;
@@ -2964,10 +3049,21 @@ public final class PowerManagerService extends SystemService
            pw.println("Screen dim duration: " + screenDimDuration + " ms");

            pw.println();
            pw.println("UID states:");
            pw.print("UID states (changing=");
            pw.print(mUidsChanging);
            pw.print(" changed=");
            pw.print(mUidsChanged);
            pw.println("):");
            for (int i=0; i<mUidState.size(); i++) {
                final UidState state = mUidState.valueAt(i);
                pw.print("  UID "); UserHandle.formatUid(pw, mUidState.keyAt(i));
                pw.print(": "); pw.println(mUidState.valueAt(i));
                pw.print(": ");
                if (state.mActive) pw.print("  ACTIVE ");
                else pw.print("INACTIVE ");
                pw.print(" count=");
                pw.print(state.mNumWakeLocks);
                pw.print(" state=");
                pw.println(state.mProcState);
            }

            pw.println();
@@ -3122,13 +3218,15 @@ public final class PowerManagerService extends SystemService
        public String mHistoryTag;
        public final int mOwnerUid;
        public final int mOwnerPid;
        public final UidState mUidState;
        public long mAcquireTime;
        public boolean mNotifiedAcquired;
        public boolean mNotifiedLong;
        public boolean mDisabled;

        public WakeLock(IBinder lock, int flags, String tag, String packageName,
                WorkSource workSource, String historyTag, int ownerUid, int ownerPid) {
                WorkSource workSource, String historyTag, int ownerUid, int ownerPid,
                UidState uidState) {
            mLock = lock;
            mFlags = flags;
            mTag = tag;
@@ -3137,6 +3235,7 @@ public final class PowerManagerService extends SystemService
            mHistoryTag = historyTag;
            mOwnerUid = ownerUid;
            mOwnerPid = ownerPid;
            mUidState = uidState;
        }

        @Override
@@ -3312,6 +3411,17 @@ public final class PowerManagerService extends SystemService
        }
    }

    static final class UidState {
        final int mUid;
        int mNumWakeLocks;
        int mProcState;
        boolean mActive;

        UidState(int uid) {
            mUid = uid;
        }
    }

    private final class BinderService extends IPowerManager.Stub {
        @Override // Binder call
        public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
@@ -3879,6 +3989,16 @@ public final class PowerManagerService extends SystemService
            setDeviceIdleTempWhitelistInternal(appids);
        }

        @Override
        public void startUidChanges() {
            startUidChangesInternal();
        }

        @Override
        public void finishUidChanges() {
            finishUidChangesInternal();
        }

        @Override
        public void updateUidProcState(int uid, int procState) {
            updateUidProcStateInternal(uid, procState);
@@ -3889,6 +4009,16 @@ public final class PowerManagerService extends SystemService
            uidGoneInternal(uid);
        }

        @Override
        public void uidActive(int uid) {
            uidActiveInternal(uid);
        }

        @Override
        public void uidIdle(int uid) {
            uidIdleInternal(uid);
        }

        @Override
        public void powerHint(int hintId, int data) {
            powerHintInternal(hintId, data);