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

Commit 123e6892 authored by Michael Wachenschwanz's avatar Michael Wachenschwanz
Browse files

[1/N] Turn OomAdjuster into an abstract base class

And create OomAdjusterLegacyImpl, which overrides the same methods that
OomAdjusterModernImpl overrides (enabling a clear set of methods in
OomAdjuster to make abstract).

The main methods the OomAdjuster implementations override are the
`performUpdateOomAdj.*` methods. These methods are the entry points into
the differing update algorithm of each impl.

This CL moves the bare minimum amount of code to the new
OomAdjusterLegacyImpl to maintain the current behaviors. The next
several CLs with migrate more functionality out of the base class until
all implementation specific behavior lives in the appropriate file.

Flag: EXEMPT pure refactor
Test: atest MockingOomAdjusterTests
Test: builds and flashes
Bug: 306731120
Change-Id: I70f4b3dacae1363171fa95b421a90d502c60e5d0
parent 3528988e
Loading
Loading
Loading
Loading
+14 −91
Original line number Original line Diff line number Diff line
@@ -179,7 +179,7 @@ import java.util.List;
/**
/**
 * All of the code required to compute proc states and oom_adj values.
 * All of the code required to compute proc states and oom_adj values.
 */
 */
public class OomAdjuster {
public abstract class OomAdjuster {
    static final String TAG = "OomAdjuster";
    static final String TAG = "OomAdjuster";


    public static final int oomAdjReasonToProto(@OomAdjReason int oomReason) {
    public static final int oomAdjReasonToProto(@OomAdjReason int oomReason) {
@@ -639,14 +639,7 @@ public class OomAdjuster {
    }
    }


    @GuardedBy({"mService", "mProcLock"})
    @GuardedBy({"mService", "mProcLock"})
    protected void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) {
    protected abstract void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason);
        final ProcessRecord topApp = mService.getTopApp();
        mProcessStateCurTop = mService.mAtmInternal.getTopProcessState();
        // Clear any pending ones because we are doing a full update now.
        mPendingProcessSet.clear();
        mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false;
        updateOomAdjInnerLSP(oomAdjReason, topApp , null, null, true, true);
    }


    /**
    /**
     * Update OomAdj for specific process and its reachable processes (with direction/indirect
     * Update OomAdj for specific process and its reachable processes (with direction/indirect
@@ -686,43 +679,8 @@ public class OomAdjuster {
    }
    }


    @GuardedBy({"mService", "mProcLock"})
    @GuardedBy({"mService", "mProcLock"})
    protected boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
    protected abstract boolean performUpdateOomAdjLSP(ProcessRecord app,
        final ProcessRecord topApp = mService.getTopApp();
            @OomAdjReason int oomAdjReason);

        mLastReason = oomAdjReason;
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));

        final ProcessStateRecord state = app.mState;

        // Next to find out all its reachable processes
        ArrayList<ProcessRecord> processes = mTmpProcessList;
        ActiveUids uids = mTmpUidRecords;
        mPendingProcessSet.add(app);
        mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP();

        boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet,
                processes, uids);

        // Clear the pending set as they should've been included in 'processes'.
        mPendingProcessSet.clear();

        int size = processes.size();
        if (size > 0) {
            // Update these reachable processes
            updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);
        } else if (state.getCurRawAdj() == UNKNOWN_ADJ) {
            // In case the app goes from non-cached to cached but it doesn't have other reachable
            // processes, its adj could be still unknown as of now, assign one.
            processes.add(app);
            applyLruAdjust(processes);
            applyOomAdjLSP(app, false, mInjector.getUptimeMillis(),
                    mInjector.getElapsedRealtimeMillis(), oomAdjReason);
        }
        mTmpProcessList.clear();
        mService.clearPendingTopAppLocked();
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        return true;
    }


    @GuardedBy({"mService", "mProcLock"})
    @GuardedBy({"mService", "mProcLock"})
    protected int enqueuePendingTopAppIfNecessaryLSP() {
    protected int enqueuePendingTopAppIfNecessaryLSP() {
@@ -967,25 +925,7 @@ public class OomAdjuster {
    }
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
    protected void performUpdateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) {
    protected abstract void performUpdateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason);
        final ProcessRecord topApp = mService.getTopApp();

        mLastReason = oomAdjReason;
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
        mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP();

        final ArrayList<ProcessRecord> processes = mTmpProcessList;
        final ActiveUids uids = mTmpUidRecords;
        collectReachableProcessesLocked(mPendingProcessSet, processes, uids);
        mPendingProcessSet.clear();
        synchronized (mProcLock) {
            updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false);
        }
        processes.clear();
        mService.clearPendingTopAppLocked();

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }


    /**
    /**
     * Update OomAdj for all processes within the given list (could be partial), or the whole LRU
     * Update OomAdj for all processes within the given list (could be partial), or the whole LRU
@@ -996,7 +936,7 @@ public class OomAdjuster {
     * must have called {@link collectReachableProcessesLocked} on it.
     * must have called {@link collectReachableProcessesLocked} on it.
     */
     */
    @GuardedBy({"mService", "mProcLock"})
    @GuardedBy({"mService", "mProcLock"})
    private void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
    protected void updateOomAdjInnerLSP(@OomAdjReason int oomAdjReason, final ProcessRecord topApp,
            ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
            ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
            boolean startProfiling) {
            boolean startProfiling) {
        final boolean fullUpdate = processes == null;
        final boolean fullUpdate = processes == null;
@@ -4256,51 +4196,34 @@ public class OomAdjuster {
    }
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
    void onProcessEndLocked(@NonNull ProcessRecord app) {
    abstract void onProcessEndLocked(@NonNull ProcessRecord app);
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }


    /**
    /**
     * Called when the process state is changed outside of the OomAdjuster.
     * Called when the process state is changed outside of the OomAdjuster.
     */
     */
    @GuardedBy("mService")
    @GuardedBy("mService")
    void onProcessStateChanged(@NonNull ProcessRecord app, int prevProcState) {
    abstract void onProcessStateChanged(@NonNull ProcessRecord app, int prevProcState);
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }


    /**
    /**
     * Called when the oom adj is changed outside of the OomAdjuster.
     * Called when the oom adj is changed outside of the OomAdjuster.
     */
     */
    @GuardedBy("mService")
    @GuardedBy("mService")
    void onProcessOomAdjChanged(@NonNull ProcessRecord app, int prevAdj) {
    abstract void onProcessOomAdjChanged(@NonNull ProcessRecord app, int prevAdj);
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }


    @VisibleForTesting
    @VisibleForTesting
    void resetInternal() {
    abstract void resetInternal();
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
    protected int getInitialAdj(@NonNull ProcessRecord app) {
    protected abstract int getInitialAdj(@NonNull ProcessRecord app);
        return app.mState.getCurAdj();
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
    protected int getInitialProcState(@NonNull ProcessRecord app) {
    protected abstract int getInitialProcState(@NonNull ProcessRecord app);
        return app.mState.getCurProcState();
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
    protected int getInitialCapability(@NonNull ProcessRecord app) {
    protected abstract int getInitialCapability(@NonNull ProcessRecord app);
        return app.mState.getCurCapability();
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
    protected boolean getInitialIsCurBoundByNonBgRestrictedApp(@NonNull ProcessRecord app) {
    protected abstract boolean getInitialIsCurBoundByNonBgRestrictedApp(@NonNull ProcessRecord app);
        // The caller will set the initial value in this implementation.
        return app.mState.isCurBoundByNonBgRestrictedApp();
    }


    /**
    /**
     * Evaluate the service connection, return {@code true} if the client will change any state
     * Evaluate the service connection, return {@code true} if the client will change any state
+166 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.am;

import static com.android.server.am.ProcessList.UNKNOWN_ADJ;

import android.annotation.NonNull;
import android.app.ActivityManagerInternal.OomAdjReason;
import android.os.Trace;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.ServiceThread;

import java.util.ArrayList;

public class OomAdjusterLegacyImpl extends OomAdjuster {

    OomAdjusterLegacyImpl(ActivityManagerService service, ProcessList processList,
            ActiveUids activeUids, ServiceThread adjusterThread, GlobalState globalState,
            CachedAppOptimizer cachedAppOptimizer, Injector injector) {
        super(service, processList, activeUids, adjusterThread, globalState, cachedAppOptimizer,
                injector);
    }

    @GuardedBy("mService")
    @Override
    void onProcessEndLocked(@NonNull ProcessRecord app) {
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }

    /**
     * Called when the process state is changed outside of the OomAdjuster.
     */
    @GuardedBy("mService")
    @Override
    void onProcessStateChanged(@NonNull ProcessRecord app, int prevProcState) {
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }

    /**
     * Called when the oom adj is changed outside of the OomAdjuster.
     */
    @GuardedBy("mService")
    @Override
    void onProcessOomAdjChanged(@NonNull ProcessRecord app, int prevAdj) {
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }

    @VisibleForTesting
    @Override
    void resetInternal() {
        // Empty, the OomAdjusterModernImpl will have an implementation.
    }

    @GuardedBy("mService")
    @Override
    protected int getInitialAdj(@NonNull ProcessRecord app) {
        return app.mState.getCurAdj();
    }

    @GuardedBy("mService")
    @Override
    protected int getInitialProcState(@NonNull ProcessRecord app) {
        return app.mState.getCurProcState();
    }

    @GuardedBy("mService")
    @Override
    protected int getInitialCapability(@NonNull ProcessRecord app) {
        return app.mState.getCurCapability();
    }

    @GuardedBy("mService")
    @Override
    protected boolean getInitialIsCurBoundByNonBgRestrictedApp(@NonNull ProcessRecord app) {
        // The caller will set the initial value in this implementation.
        return app.mState.isCurBoundByNonBgRestrictedApp();
    }

    @Override
    protected void performUpdateOomAdjLSP(@OomAdjReason int oomAdjReason) {
        final ProcessRecord topApp = mService.getTopApp();
        mProcessStateCurTop = mService.mAtmInternal.getTopProcessState();
        // Clear any pending ones because we are doing a full update now.
        mPendingProcessSet.clear();
        mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false;
        updateOomAdjInnerLSP(oomAdjReason, topApp, null, null, true, true);
    }

    @GuardedBy({"mService", "mProcLock"})
    @Override
    protected boolean performUpdateOomAdjLSP(ProcessRecord app, @OomAdjReason int oomAdjReason) {
        final ProcessRecord topApp = mService.getTopApp();

        mLastReason = oomAdjReason;
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));

        final ProcessStateRecord state = app.mState;

        // Next to find out all its reachable processes
        ArrayList<ProcessRecord> processes = mTmpProcessList;
        ActiveUids uids = mTmpUidRecords;
        mPendingProcessSet.add(app);
        mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP();

        boolean containsCycle = collectReachableProcessesLocked(mPendingProcessSet,
                processes, uids);

        // Clear the pending set as they should've been included in 'processes'.
        mPendingProcessSet.clear();

        int size = processes.size();
        if (size > 0) {
            // Update these reachable processes
            updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, containsCycle, false);
        } else if (state.getCurRawAdj() == UNKNOWN_ADJ) {
            // In case the app goes from non-cached to cached but it doesn't have other reachable
            // processes, its adj could be still unknown as of now, assign one.
            processes.add(app);
            applyLruAdjust(processes);
            applyOomAdjLSP(app, false, mInjector.getUptimeMillis(),
                    mInjector.getElapsedRealtimeMillis(), oomAdjReason);
        }
        mTmpProcessList.clear();
        mService.clearPendingTopAppLocked();
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        return true;
    }

    @GuardedBy("mService")
    @Override
    protected void performUpdateOomAdjPendingTargetsLocked(@OomAdjReason int oomAdjReason) {
        final ProcessRecord topApp = mService.getTopApp();

        mLastReason = oomAdjReason;
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReasonToString(oomAdjReason));
        mProcessStateCurTop = enqueuePendingTopAppIfNecessaryLSP();

        final ArrayList<ProcessRecord> processes = mTmpProcessList;
        final ActiveUids uids = mTmpUidRecords;
        collectReachableProcessesLocked(mPendingProcessSet, processes, uids);
        mPendingProcessSet.clear();
        synchronized (mProcLock) {
            updateOomAdjInnerLSP(oomAdjReason, topApp, processes, uids, true, false);
        }
        processes.clear();
        mService.clearPendingTopAppLocked();

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}
+2 −2
Original line number Original line Diff line number Diff line
@@ -51,8 +51,8 @@ public class ProcessStateController {
        mOomAdjuster = useOomAdjusterModernImpl
        mOomAdjuster = useOomAdjusterModernImpl
                ? new OomAdjusterModernImpl(ams, processList, activeUids, handlerThread,
                ? new OomAdjusterModernImpl(ams, processList, activeUids, handlerThread,
                mGlobalState, cachedAppOptimizer, oomAdjInjector)
                mGlobalState, cachedAppOptimizer, oomAdjInjector)
                : new OomAdjuster(ams, processList, activeUids, handlerThread, mGlobalState,
                : new OomAdjusterLegacyImpl(ams, processList, activeUids, handlerThread,
                        cachedAppOptimizer, oomAdjInjector);
                        mGlobalState, cachedAppOptimizer, oomAdjInjector);
    }
    }


    /**
    /**