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

Commit 7e52d8d8 authored by Michael Wachenschwanz's avatar Michael Wachenschwanz Committed by Android (Google) Code Review
Browse files

Merge "Revert^2 "OomAdjuster Freeze Handling with CPU capability"" into main

parents 9242915b 26a8abbd
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1016,6 +1016,12 @@ public class ActivityManager {
     */
    public static final int PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL = 1 << 6;

    /**
     * @hide
     * Process is guaranteed cpu time (IE. it will not be frozen).
     */
    public static final int PROCESS_CAPABILITY_CPU_TIME = 1 << 7;

    /**
     * @hide all capabilities, the ORing of all flags in {@link ProcessCapability}.
     *
@@ -1028,7 +1034,8 @@ public class ActivityManager {
            | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
            | PROCESS_CAPABILITY_BFSL
            | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK
            | PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
            | PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL
            | PROCESS_CAPABILITY_CPU_TIME;

    /**
     * All implicit capabilities. This capability set is currently only used for processes under
@@ -1053,6 +1060,7 @@ public class ActivityManager {
        pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
        pw.print((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
        pw.print((caps & PROCESS_CAPABILITY_CPU_TIME) != 0 ? 'T' : '-');
    }

    /** @hide */
@@ -1065,6 +1073,7 @@ public class ActivityManager {
        sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
        sb.append((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
        sb.append((caps & PROCESS_CAPABILITY_CPU_TIME) != 0 ? 'T' : '-');
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ import java.util.Random;
import java.util.Set;
import java.util.concurrent.Executor;

public final class CachedAppOptimizer {
public class CachedAppOptimizer {

    // Flags stored in the DeviceConfig API.
    @VisibleForTesting static final String KEY_USE_COMPACTION = "use_compaction";
+163 −41
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.am;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_CPU_TIME;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
@@ -155,6 +156,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -469,7 +471,6 @@ public class OomAdjuster {
            }
            Process.setThreadPriority(tid, priority);
        }

    }

    // TODO(b/346822474): hook up global state usage.
@@ -499,7 +500,8 @@ public class OomAdjuster {
    }

    OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
            ServiceThread adjusterThread, GlobalState globalState, Injector injector) {
            ServiceThread adjusterThread, GlobalState globalState,
            CachedAppOptimizer cachedAppOptimizer, Injector injector) {
        mService = service;
        mGlobalState = globalState;
        mInjector = injector;
@@ -508,7 +510,7 @@ public class OomAdjuster {
        mActiveUids = activeUids;

        mConstants = mService.mConstants;
        mCachedAppOptimizer = new CachedAppOptimizer(mService);
        mCachedAppOptimizer = cachedAppOptimizer;
        mCacheOomRanker = new CacheOomRanker(service);

        mLogger = new OomAdjusterDebugLogger(this, mService.mConstants);
@@ -2597,6 +2599,7 @@ public class OomAdjuster {
        }

        capability |= getDefaultCapability(app, procState);
        capability |= getCpuCapability(app, now);

        // Procstates below BFGS should never have this capability.
        if (procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
@@ -2739,10 +2742,14 @@ public class OomAdjuster {
            if (app.mOptRecord.setShouldNotFreeze(true, dryRun,
                    app.mOptRecord.shouldNotFreezeReason()
                    | client.mOptRecord.shouldNotFreezeReason(), mAdjSeq)) {
                if (Flags.useCpuTimeCapability()) {
                    // Do nothing, capability updated check will handle the dryrun output.
                } else {
                    // Bail out early, as we only care about the return value for a dryrun.
                    return true;
                }
            }
        }

        boolean trackedProcState = false;

@@ -2751,6 +2758,8 @@ public class OomAdjuster {
        // we check the final procstate, and remove it if the procsate is below BFGS.
        capability |= getBfslCapabilityFromClient(client);

        capability |= getCpuCapabilityFromClient(client);

        if (cr.notHasFlag(Context.BIND_WAIVE_PRIORITY)) {
            if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
                capability |= cstate.getCurCapability();
@@ -2809,10 +2818,15 @@ public class OomAdjuster {
                            app.mOptRecord.shouldNotFreezeReason()
                            | ProcessCachedOptimizerRecord
                            .SHOULD_NOT_FREEZE_REASON_BINDER_ALLOW_OOM_MANAGEMENT, mAdjSeq)) {
                        if (Flags.useCpuTimeCapability()) {
                            // Do nothing, capability updated check will handle the dryrun output.
                        } else {
                            // Bail out early, as we only care about the return value for a dryrun.
                            return true;
                        }
                    }
                    capability |= PROCESS_CAPABILITY_CPU_TIME;
                }
                // Not doing bind OOM management, so treat
                // this guy more like a started service.
                if (state.hasShownUi() && !state.getCachedIsHomeProcess()) {
@@ -3053,10 +3067,15 @@ public class OomAdjuster {
                        app.mOptRecord.shouldNotFreezeReason()
                        | ProcessCachedOptimizerRecord
                        .SHOULD_NOT_FREEZE_REASON_BIND_WAIVE_PRIORITY, mAdjSeq)) {
                    if (Flags.useCpuTimeCapability()) {
                        // Do nothing, capability updated check will handle the dryrun output.
                    } else {
                        // Bail out early, as we only care about the return value for a dryrun.
                        return true;
                    }
                }
                capability |= PROCESS_CAPABILITY_CPU_TIME;
            }
        }
        if (cr.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) {
            if (!dryRun) {
@@ -3108,9 +3127,24 @@ public class OomAdjuster {
            capability &= ~PROCESS_CAPABILITY_BFSL;
        }
        if (!updated) {
            updated = adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup
                || (capability != prevCapability
                        && (capability & prevCapability) == prevCapability);
            if (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup) {
                updated = true;
            }

            if (Flags.useCpuTimeCapability()) {
                if ((capability != prevCapability)
                        && ((capability & prevCapability) == prevCapability)) {
                    updated = true;
                }
            } else {
                // Ignore PROCESS_CAPABILITY_CPU_TIME in capability comparison
                final int curFiltered = capability & ~PROCESS_CAPABILITY_CPU_TIME;
                final int prevFiltered = prevCapability & ~PROCESS_CAPABILITY_CPU_TIME;
                if ((curFiltered != prevFiltered)
                        && ((curFiltered & prevFiltered) == prevFiltered)) {
                    updated = true;
                }
            }
        }

        if (dryRun) {
@@ -3186,6 +3220,8 @@ public class OomAdjuster {
        // we check the final procstate, and remove it if the procsate is below BFGS.
        capability |= getBfslCapabilityFromClient(client);

        capability |= getCpuCapabilityFromClient(client);

        if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
            // If the other app is cached for any reason, for purposes here
            // we are going to consider it empty.
@@ -3196,10 +3232,14 @@ public class OomAdjuster {
            if (app.mOptRecord.setShouldNotFreeze(true, dryRun,
                    app.mOptRecord.shouldNotFreezeReason()
                    | client.mOptRecord.shouldNotFreezeReason(), mAdjSeq)) {
                if (Flags.useCpuTimeCapability()) {
                    // Do nothing, capability updated check will handle the dryrun output.
                } else {
                    // Bail out early, as we only care about the return value for a dryrun.
                    return true;
                }
            }
        }

        if (!dryRun) {
            state.setCurBoundByNonBgRestrictedApp(state.isCurBoundByNonBgRestrictedApp()
@@ -3273,12 +3313,27 @@ public class OomAdjuster {
            capability &= ~PROCESS_CAPABILITY_BFSL;
        }

        if (dryRun && (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup
                || (capability != prevCapability
                        && (capability & prevCapability) == prevCapability))) {
        if (dryRun) {
            if (adj < prevRawAdj || procState < prevProcState || schedGroup > prevSchedGroup) {
                return true;
            }

            if (Flags.useCpuTimeCapability()) {
                if ((capability != prevCapability)
                        && ((capability & prevCapability) == prevCapability)) {
                    return true;
                }
            } else {
                // Ignore PROCESS_CAPABILITY_CPU_TIME in capability comparison
                final int curFiltered = capability & ~PROCESS_CAPABILITY_CPU_TIME;
                final int prevFiltered = prevCapability & ~PROCESS_CAPABILITY_CPU_TIME;
                if ((curFiltered != prevFiltered)
                        && ((curFiltered & prevFiltered) == prevFiltered)) {
                    return true;
                }
            }
        }

        if (adj < prevRawAdj) {
            schedGroup = setIntermediateAdjLSP(app, adj, prevRawAdj, schedGroup);
        }
@@ -3328,6 +3383,29 @@ public class OomAdjuster {
        return baseCapabilities | networkCapabilities;
    }

    private static int getCpuCapability(ProcessRecord app, long nowUptime) {
        final UidRecord uidRec = app.getUidRecord();
        if (uidRec != null && uidRec.isCurAllowListed()) {
            // Process has user visible activities.
            return PROCESS_CAPABILITY_CPU_TIME;
        }
        if (UserHandle.isCore(app.uid)) {
            // Make sure all system components are not frozen.
            return PROCESS_CAPABILITY_CPU_TIME;
        }
        if (app.mState.getCachedHasVisibleActivities()) {
            // Process has user visible activities.
            return PROCESS_CAPABILITY_CPU_TIME;
        }
        if (app.mServices.hasUndemotedShortForegroundService(nowUptime)) {
            // It running a short fgs, just give it cpu time.
            return PROCESS_CAPABILITY_CPU_TIME;
        }
        // TODO(b/370817323): Populate this method with all of the reasons to keep a process
        //  unfrozen.
        return 0;
    }

    /**
     * @return the BFSL capability from a client (of a service binding or provider).
     */
@@ -3375,6 +3453,15 @@ public class OomAdjuster {
        return client.mState.getCurCapability() & PROCESS_CAPABILITY_BFSL;
    }

    /**
     * @return the CPU capability from a client (of a service binding or provider).
     */
    private static int getCpuCapabilityFromClient(ProcessRecord client) {
        // Just grant CPU capability every time
        // TODO(b/370817323): Populate with reasons to not propagate cpu capability across bindings.
        return client.mState.getCurCapability() & PROCESS_CAPABILITY_CPU_TIME;
    }

    /**
     * Checks if for the given app and client, there's a cycle that should skip over the client
     * for now or use partial values to evaluate the effect of the client binding.
@@ -3955,6 +4042,39 @@ public class OomAdjuster {
        mCacheOomRanker.dump(pw);
    }

    /**
     * Return whether or not a process should be frozen.
     */
    boolean getFreezePolicy(ProcessRecord proc) {
        // Reasons to not freeze:
        if (Flags.useCpuTimeCapability()) {
            if ((proc.mState.getCurCapability() & PROCESS_CAPABILITY_CPU_TIME) != 0) {
                /// App is important enough (see {@link #getCpuCapability}) or bound by something
                /// important enough to not be frozen.
                return false;
            }
        } else {
            // The CPU capability handling covers all setShouldNotFreeze paths. Must check
            // shouldNotFreeze, if the CPU capability is not being used.
            if (proc.mOptRecord.shouldNotFreeze()) {
                return false;
            }
        }

        if (proc.mOptRecord.isFreezeExempt()) {
            return false;
        }

        // Reasons to freeze:
        if (proc.mState.getCurAdj() >= FREEZER_CUTOFF_ADJ) {
            // Oomscore is in a high enough state, it is safe to freeze.
            return true;
        }

        // Default, do not freeze a process.
        return false;
    }

    @GuardedBy({"mService", "mProcLock"})
    void updateAppFreezeStateLSP(ProcessRecord app, @OomAdjReason int oomAdjReason,
            boolean immediate, int oldOomAdj) {
@@ -3969,45 +4089,46 @@ public class OomAdjuster {
                    (state.getCurAdj() >= FREEZER_CUTOFF_ADJ ^ oldOomAdj >= FREEZER_CUTOFF_ADJ)
                    || oldOomAdj == UNKNOWN_ADJ;
            final boolean shouldNotFreezeChanged = opt.shouldNotFreezeAdjSeq() == mAdjSeq;
            if ((oomAdjChanged || shouldNotFreezeChanged)
            final boolean hasCpuCapability =
                    (PROCESS_CAPABILITY_CPU_TIME & app.mState.getCurCapability())
                            == PROCESS_CAPABILITY_CPU_TIME;
            final boolean usedToHaveCpuCapability =
                    (PROCESS_CAPABILITY_CPU_TIME & app.mState.getSetCapability())
                            == PROCESS_CAPABILITY_CPU_TIME;
            final boolean cpuCapabilityChanged = hasCpuCapability != usedToHaveCpuCapability;
            if ((oomAdjChanged || shouldNotFreezeChanged || cpuCapabilityChanged)
                    && Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        CachedAppOptimizer.ATRACE_FREEZER_TRACK,
                        "updateAppFreezeStateLSP " + app.processName
                        + " pid: " + app.getPid()
                        + " isFreezeExempt: " + opt.isFreezeExempt()
                        + " isFrozen: " + opt.isFrozen()
                        + " shouldNotFreeze: " + opt.shouldNotFreeze()
                        + " shouldNotFreezeReason: " + opt.shouldNotFreezeReason()
                        + " curAdj: " + state.getCurAdj()
                        + " oldOomAdj: " + oldOomAdj
                        + " immediate: " + immediate);
                        + " immediate: " + immediate
                        + " cpuCapability: " + hasCpuCapability);
            }
        }

        if (app.mOptRecord.isFreezeExempt()) {
            return;
        }

        // if an app is already frozen and shouldNotFreeze becomes true, immediately unfreeze
        if (opt.isFrozen() && opt.shouldNotFreeze()) {
            mCachedAppOptimizer.unfreezeAppLSP(app,
                    CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(oomAdjReason));
            return;
        }

        // Use current adjustment when freezing, set adjustment when unfreezing.
        if (state.getCurAdj() >= FREEZER_CUTOFF_ADJ && !opt.isFrozen()
                && !opt.shouldNotFreeze()) {
            if (!immediate) {
                mCachedAppOptimizer.freezeAppAsyncLSP(app);
            } else {
        if (getFreezePolicy(app)) {
            // This process should be frozen.
            if (immediate && !opt.isFrozen()) {
                // And it will be frozen immediately.
                mCachedAppOptimizer.freezeAppAsyncAtEarliestLSP(app);
            } else if (!opt.isFrozen() || !opt.isPendingFreeze()) {
                mCachedAppOptimizer.freezeAppAsyncLSP(app);
            }
        } else if (state.getSetAdj() < FREEZER_CUTOFF_ADJ) {
        } else {
            // This process should not be frozen.
            if (opt.isFrozen() || opt.isPendingFreeze()) {
                mCachedAppOptimizer.unfreezeAppLSP(app,
                        CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(oomAdjReason));
            }
        }
    }

    @GuardedBy("mService")
    void unfreezeTemporarily(ProcessRecord app, @OomAdjReason int reason) {
@@ -4029,7 +4150,8 @@ public class OomAdjuster {
        final int size = processes.size();
        for (int i = 0; i < size; i++) {
            ProcessRecord proc = processes.get(i);
            mCachedAppOptimizer.unfreezeTemporarily(proc, reason);
            mCachedAppOptimizer.unfreezeTemporarily(proc,
                    CachedAppOptimizer.getUnfreezeReasonCodeFromOomAdjReason(reason));
        }
        processes.clear();
    }
+3 −2
Original line number Diff line number Diff line
@@ -758,8 +758,9 @@ public class OomAdjusterModernImpl extends OomAdjuster {

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

    private final ProcessRecordNodes mProcessRecordProcStateNodes = new ProcessRecordNodes(
+8 −2
Original line number Diff line number Diff line
@@ -256,18 +256,24 @@ final class ProcessServiceRecord {
        }
        // Now we need to look at all short-FGS within the process and see if all of them are
        // procstate-timed-out or not.
        return !hasUndemotedShortForegroundService(nowUptime);
    }

    boolean hasUndemotedShortForegroundService(long nowUptime) {
        for (int i = mServices.size() - 1; i >= 0; i--) {
            final ServiceRecord sr = mServices.valueAt(i);
            if (!sr.isShortFgs() || !sr.hasShortFgsInfo()) {
                continue;
            }
            if (sr.getShortFgsInfo().getProcStateDemoteTime() >= nowUptime) {
                return false;
                // This short fgs has not timed out yet.
                return true;
            }
        }
        return true;
        return false;
    }


    int getReportedForegroundServiceTypes() {
        return mRepFgServiceTypes;
    }
Loading