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

Commit 2728f4e6 authored by Chih-Yu Huang's avatar Chih-Yu Huang
Browse files

am: Extract UID process state into UidStateRecord

Move common UID-level process state, capability, and idle/background
tracking logic from `UidRecord` into a new abstract base class,
`UidStateRecord`. `UidRecord` now extends `UidStateRecord` and delegates
core process state management to the base class.

This refactoring abstracts logic relevant to OomAdjuster decisions and
improves modularity.

Bug: 425766486
Test: m services.core
Test: atest MockingOomAdjusterTests OomAdjusterTests
Test: FrameworksServicesTestsRavenwood_ProcessStateController
Flag: EXEMPT pure refactor

Change-Id: I9ac99857cf892be6fce9741425041f8914b14d76
parent 74963499
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ import com.android.server.ServiceThread;
import com.android.server.am.psc.PlatformCompatCache;
import com.android.server.am.psc.PlatformCompatCache.CachedCompatChangeId;
import com.android.server.am.psc.ProcessStateRecord;
import com.android.server.am.psc.UidStateRecord;
import com.android.server.wm.WindowProcessController;

import java.io.PrintWriter;
@@ -343,7 +344,7 @@ public abstract class OomAdjuster {
    private final int mNumSlots;
    protected final ArrayList<ProcessRecord> mTmpProcessList = new ArrayList<ProcessRecord>();
    protected final ArrayList<ProcessRecord> mTmpProcessList2 = new ArrayList<ProcessRecord>();
    protected final ArrayList<UidRecord> mTmpBecameIdle = new ArrayList<UidRecord>();
    protected final ArrayList<UidStateRecord> mTmpBecameIdle = new ArrayList<UidStateRecord>();
    protected final ActiveUids mTmpUidRecords;
    protected final ArrayDeque<ProcessRecord> mTmpQueue;
    protected final ArraySet<ProcessRecord> mTmpProcessSet = new ArraySet<>();
@@ -1331,7 +1332,7 @@ public abstract class OomAdjuster {

    @GuardedBy({"mService", "mProcLock"})
    private void updateAppUidRecLSP(ProcessRecord app) {
        final UidRecord uidRec = app.getUidRecord();
        final UidStateRecord uidRec = app.getUidRecord();
        if (uidRec != null) {
            final ProcessStateRecord state = app.mState;
            uidRec.setEphemeral(app.info.isInstantApp());
@@ -1339,7 +1340,7 @@ public abstract class OomAdjuster {
                uidRec.setCurProcState(state.getCurProcState());
            }
            if (app.mServices.hasForegroundServices()) {
                uidRec.setForegroundServices(true);
                uidRec.setHasForegroundServices(true);
            }
            uidRec.setCurCapability(uidRec.getCurCapability() | state.getCurCapability());
        }
@@ -1352,7 +1353,7 @@ public abstract class OomAdjuster {
        // we update the UidRecord's procstate by calling {@link UidRecord#setSetProcState}.
        mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);

        ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
        ArrayList<UidStateRecord> becameIdle = mTmpBecameIdle;
        becameIdle.clear();

        // Update from any uid changes.
@@ -1448,7 +1449,7 @@ public abstract class OomAdjuster {
                    uidRec.setSetCapability(uidRec.getCurCapability());
                    uidRec.setSetAllowListed(uidRec.isCurAllowListed());
                    uidRec.setSetIdle(uidRec.isIdle());
                    uidRec.clearProcAdjChanged();
                    uidRec.setProcAdjChanged(false);
                    if (shouldLog
                            && ((uidRec.getSetProcState() != oldProcState)
                            || (uidRec.getSetCapability() != oldCapability))) {
@@ -1477,7 +1478,7 @@ public abstract class OomAdjuster {
                    if ((uidChange & UidRecord.CHANGE_PROCSTATE) != 0) {
                        mService.noteUidProcessState(uidRec.getUid(), uidRec.getCurProcState());
                    }
                    if (uidRec.hasForegroundServices()) {
                    if (uidRec.getHasForegroundServices()) {
                        mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
                    }
                }
@@ -1948,7 +1949,7 @@ public abstract class OomAdjuster {
    protected static int getCpuCapability(ProcessRecord app, long nowUptime,
            boolean hasForegroundActivities) {
        // Note: persistent processes get all capabilities, including CPU_TIME.
        final UidRecord uidRec = app.getUidRecord();
        final UidStateRecord uidRec = app.getUidRecord();
        if (uidRec != null && uidRec.isCurAllowListed()) {
            // Process is in the power allowlist.
            return PROCESS_CAPABILITY_CPU_TIME;
@@ -2075,7 +2076,7 @@ public abstract class OomAdjuster {
            long nowElapsed, @OomAdjReason int oomAdjReson, boolean isBatchingOomAdj) {
        boolean success = true;
        final ProcessStateRecord state = app.mState;
        final UidRecord uidRec = app.getUidRecord();
        final UidStateRecord uidRec = app.getUidRecord();

        if (state.getCurRawAdj() != state.getSetRawAdj()) {
            state.setSetRawAdj(state.getCurRawAdj());
@@ -2102,7 +2103,7 @@ public abstract class OomAdjuster {
            }
            state.setSetAdj(state.getCurAdj());
            if (uidRec != null) {
                uidRec.noteProcAdjChanged();
                uidRec.setProcAdjChanged(true);
            }
            state.setVerifiedAdj(INVALID_ADJ);
        }
+3 −2
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.ServiceThread;
import com.android.server.am.psc.ProcessStateRecord;
import com.android.server.am.psc.UidStateRecord;
import com.android.server.wm.ActivityServiceConnectionsHolder;

import java.lang.annotation.Retention;
@@ -767,7 +768,7 @@ public class OomAdjusterImpl extends OomAdjuster {
            final int prevProcState = app.mState.getCurProcState();
            final int prevAdj = app.mState.getCurRawAdj();
            app.mState.resetCachedInfo();
            final UidRecord uidRec = app.getUidRecord();
            final UidStateRecord uidRec = app.getUidRecord();
            if (uidRec != null) {
                if (DEBUG_UID_OBSERVERS) {
                    Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec);
@@ -1192,7 +1193,7 @@ public class OomAdjusterImpl extends OomAdjuster {
        state.setAdjTarget(null);

        // If this UID is currently allowlisted, it should not be frozen.
        final UidRecord uidRec = app.getUidRecord();
        final UidStateRecord uidRec = app.getUidRecord();
        app.mOptRecord.setShouldNotFreeze(uidRec != null && uidRec.isCurAllowListed(),
                ProcessCachedOptimizerRecord.SHOULD_NOT_FREEZE_REASON_UID_ALLOWLISTED, mAdjSeq);

+4 −3
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ProcessChangeItem;
import com.android.server.am.psc.PlatformCompatCache;
import com.android.server.am.psc.ProcessStateRecord;
import com.android.server.am.psc.UidStateRecord;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
@@ -5306,7 +5307,7 @@ public final class ProcessList {
     */
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getUidProcStateLOSP(int uid) {
        UidRecord uidRec = mActiveUids.get(uid);
        UidStateRecord uidRec = mActiveUids.get(uid);
        return uidRec == null ? PROCESS_STATE_NONEXISTENT : uidRec.getCurProcState();
    }

@@ -5316,7 +5317,7 @@ public final class ProcessList {
     */
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    @ProcessCapability int getUidProcessCapabilityLOSP(int uid) {
        UidRecord uidRec = mActiveUids.get(uid);
        UidStateRecord uidRec = mActiveUids.get(uid);
        return uidRec == null ? PROCESS_CAPABILITY_NONE : uidRec.getCurCapability();
    }

@@ -5357,7 +5358,7 @@ public final class ProcessList {
     */
    @VisibleForTesting
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getBlockStateForUid(UidRecord uidRec) {
    int getBlockStateForUid(UidStateRecord uidRec) {
        // Denotes whether uid's process state is currently allowed network access.
        final boolean isAllowed =
                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState(),
+10 −227
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.server.am;

import android.Manifest;
import android.annotation.ElapsedRealtimeLong;
import android.app.ActivityManager;
import android.content.pm.PackageManager;
import android.os.SystemClock;
@@ -31,67 +30,14 @@ import android.util.proto.ProtoUtils;
import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
import com.android.server.am.UidObserverController.ChangeRecord;
import com.android.server.am.psc.UidStateRecord;

import java.util.function.Consumer;

/**
 * Overall information about a uid that has actively running processes.
 */
public final class UidRecord {
    private final ActivityManagerService mService;
    private final ActivityManagerGlobalLock mProcLock;
    private final int mUid;

    @CompositeRWLock({"mService", "mProcLock"})
    private int mCurProcState;

    @CompositeRWLock({"mService", "mProcLock"})
    private int mSetProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;

    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mProcAdjChanged;

    @CompositeRWLock({"mService", "mProcLock"})
    private int mCurCapability;

    @CompositeRWLock({"mService", "mProcLock"})
    private int mSetCapability;

    @CompositeRWLock({"mService", "mProcLock"})
    private long mLastBackgroundTime;

    /**
     * Last time the UID became idle. This is set to 0, once the UID becomes active.
     */
    @ElapsedRealtimeLong
    @CompositeRWLock({"mService", "mProcLock"})
    private long mLastIdleTimeIfStillIdle;

    /**
     * Last time the UID became idle. Unlike {@link #mLastIdleTimeIfStillIdle}, we never clear it.
     */
    @ElapsedRealtimeLong
    @CompositeRWLock({"mService", "mProcLock"})
    private long mRealLastIdleTime;

    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mEphemeral;

    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mForegroundServices;

    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mCurAllowList;;

    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mSetAllowList;

    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mIdle;

    @CompositeRWLock({"mService", "mProcLock"})
    private boolean mSetIdle;

public final class UidRecord extends UidStateRecord {
    @CompositeRWLock({"mService", "mProcLock"})
    private ArraySet<ProcessRecord> mProcRecords = new ArraySet<>();

@@ -172,54 +118,18 @@ public final class UidRecord {
    private boolean mUidIsFrozen;

    public UidRecord(int uid, ActivityManagerService service) {
        mUid = uid;
        mService = service;
        mProcLock = service != null ? service.mProcLock : null;
        mIdle = true;
        reset();
    }

    int getUid() {
        return mUid;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getCurProcState() {
        return mCurProcState;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setCurProcState(int curProcState) {
        mCurProcState = curProcState;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getSetProcState() {
        return mSetProcState;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setSetProcState(int setProcState) {
        mSetProcState = setProcState;
    }

    @GuardedBy({"mService", "mProcLock"})
    void noteProcAdjChanged() {
        mProcAdjChanged = true;
    }

    @GuardedBy({"mService", "mProcLock"})
    void clearProcAdjChanged() {
        mProcAdjChanged = false;
        super(uid, service, service != null ? service.mProcLock : null);
    }

    @Override
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean getProcAdjChanged() {
        return mProcAdjChanged;
    public int getNumOfProcs() {
        return mProcRecords.size();
    }

    @Override
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getMinProcAdj() {
    public int getMinProcAdj() {
        int minAdj = ProcessList.UNKNOWN_ADJ;
        for (int i = mProcRecords.size() - 1; i >= 0; i--) {
            int adj = mProcRecords.valueAt(i).getSetAdj();
@@ -230,126 +140,6 @@ public final class UidRecord {
        return minAdj;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getCurCapability() {
        return mCurCapability;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setCurCapability(int curCapability) {
        mCurCapability = curCapability;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getSetCapability() {
        return mSetCapability;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setSetCapability(int setCapability) {
        mSetCapability = setCapability;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    long getLastBackgroundTime() {
        return mLastBackgroundTime;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setLastBackgroundTime(long lastBackgroundTime) {
        mLastBackgroundTime = lastBackgroundTime;
    }

    /**
     * Last time the UID became idle. This is set to 0, once the UID becomes active.
     */
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    long getLastIdleTimeIfStillIdle() {
        return mLastIdleTimeIfStillIdle;
    }

    /**
     * Last time the UID became idle. Unlike {@link #getLastIdleTimeIfStillIdle}, we never clear it.
     */
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    long getRealLastIdleTime() {
        return mRealLastIdleTime;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setLastIdleTime(@ElapsedRealtimeLong long lastIdleTime) {
        mLastIdleTimeIfStillIdle = lastIdleTime;
        if (lastIdleTime > 0) {
            mRealLastIdleTime = lastIdleTime;
        }
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isEphemeral() {
        return mEphemeral;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setEphemeral(boolean ephemeral) {
        mEphemeral = ephemeral;
    }

    /** Returns whether the UID has any FGS of any type or not (including "short fgs") */
    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean hasForegroundServices() {
        return mForegroundServices;
    }

    /** Sets whether the UID has any FGS of any type or not (including "short fgs") */
    @GuardedBy({"mService", "mProcLock"})
    void setForegroundServices(boolean foregroundServices) {
        mForegroundServices = foregroundServices;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isCurAllowListed() {
        return mCurAllowList;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setCurAllowListed(boolean curAllowList) {
        mCurAllowList = curAllowList;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isSetAllowListed() {
        return mSetAllowList;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setSetAllowListed(boolean setAllowlist) {
        mSetAllowList = setAllowlist;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isIdle() {
        return mIdle;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setIdle(boolean idle) {
        mIdle = idle;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    boolean isSetIdle() {
        return mSetIdle;
    }

    @GuardedBy({"mService", "mProcLock"})
    void setSetIdle(boolean setIdle) {
        mSetIdle = setIdle;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    int getNumOfProcs() {
        return mProcRecords.size();
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    void forEachProcess(Consumer<ProcessRecord> callback) {
@@ -426,13 +216,6 @@ public final class UidRecord {
        mLastReportedChange = lastReportedChange;
    }

    @GuardedBy({"mService", "mProcLock"})
    void reset() {
        setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
        mForegroundServices = false;
        mCurCapability = 0;
    }

    public void updateHasInternetPermission() {
        hasInternetPermission = ActivityManager.checkUidPermission(Manifest.permission.INTERNET,
                mUid) == PackageManager.PERMISSION_GRANTED;
@@ -443,7 +226,7 @@ public final class UidRecord {
        proto.write(UidRecordProto.UID, mUid);
        proto.write(UidRecordProto.CURRENT, ProcessList.makeProcStateProtoEnum(mCurProcState));
        proto.write(UidRecordProto.EPHEMERAL, mEphemeral);
        proto.write(UidRecordProto.FG_SERVICES, mForegroundServices);
        proto.write(UidRecordProto.FG_SERVICES, mHasForegroundServices);
        proto.write(UidRecordProto.WHILELIST, mCurAllowList);
        ProtoUtils.toDuration(proto, UidRecordProto.LAST_BACKGROUND_TIME,
                mLastBackgroundTime, SystemClock.elapsedRealtime());
@@ -473,7 +256,7 @@ public final class UidRecord {
        if (mEphemeral) {
            sb.append(" ephemeral");
        }
        if (mForegroundServices) {
        if (mHasForegroundServices) {
            sb.append(" fgServices");
        }
        if (mCurAllowList) {
+331 −0

File added.

Preview size limit exceeded, changes collapsed.