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

Commit dc8a48f1 authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Track the child processes that are forked by app processes"

parents 9c9331ca 15755084
Loading
Loading
Loading
Loading
+61 −23
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import dalvik.system.VMRuntime;
import libcore.io.IoUtils;

import java.io.FileDescriptor;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeoutException;

@@ -1317,34 +1318,17 @@ public class Process {
     */
    public static void waitForProcessDeath(int pid, int timeout)
            throws InterruptedException, TimeoutException {
        FileDescriptor pidfd = null;
        if (sPidFdSupported == PIDFD_UNKNOWN) {
            int fd = -1;
            try {
                fd = nativePidFdOpen(pid, 0);
                sPidFdSupported = PIDFD_SUPPORTED;
            } catch (ErrnoException e) {
                sPidFdSupported = e.errno != OsConstants.ENOSYS
                    ? PIDFD_SUPPORTED : PIDFD_UNSUPPORTED;
            } finally {
                if (fd >= 0) {
                    pidfd = new FileDescriptor();
                    pidfd.setInt$(fd);
                }
            }
        }
        boolean fallback = sPidFdSupported == PIDFD_UNSUPPORTED;
        boolean fallback = supportsPidFd();
        if (!fallback) {
            FileDescriptor pidfd = null;
            try {
                if (pidfd == null) {
                    int fd = nativePidFdOpen(pid, 0);
                final int fd = nativePidFdOpen(pid, 0);
                if (fd >= 0) {
                    pidfd = new FileDescriptor();
                    pidfd.setInt$(fd);
                } else {
                    fallback = true;
                }
                }
                if (pidfd != null) {
                    StructPollfd[] fds = new StructPollfd[] {
                        new StructPollfd()
@@ -1392,5 +1376,59 @@ public class Process {
        throw new TimeoutException();
    }

    /**
     * Determine whether the system supports pidfd APIs
     *
     * @return Returns true if the system supports pidfd APIs
     * @hide
     */
    public static boolean supportsPidFd() {
        if (sPidFdSupported == PIDFD_UNKNOWN) {
            int fd = -1;
            try {
                fd = nativePidFdOpen(myPid(), 0);
                sPidFdSupported = PIDFD_SUPPORTED;
            } catch (ErrnoException e) {
                sPidFdSupported = e.errno != OsConstants.ENOSYS
                        ? PIDFD_SUPPORTED : PIDFD_UNSUPPORTED;
            } finally {
                if (fd >= 0) {
                    final FileDescriptor f = new FileDescriptor();
                    f.setInt$(fd);
                    IoUtils.closeQuietly(f);
                }
            }
        }
        return sPidFdSupported == PIDFD_SUPPORTED;
    }

    /**
     * Open process file descriptor for given pid.
     *
     * @param pid The process ID to open for
     * @param flags Reserved, unused now, must be 0
     * @return The process file descriptor for given pid
     * @throws IOException if it can't be opened
     *
     * @hide
     */
    public static @Nullable FileDescriptor openPidFd(int pid, int flags) throws IOException {
        if (!supportsPidFd()) {
            return null;
        }
        if (flags != 0) {
            throw new IllegalArgumentException();
        }
        try {
            FileDescriptor pidfd = new FileDescriptor();
            pidfd.setInt$(nativePidFdOpen(pid, flags));
            return pidfd;
        } catch (ErrnoException e) {
            IOException ex = new IOException();
            ex.initCause(e);
            throw ex;
        }
    }

    private static native int nativePidFdOpen(int pid, int flags) throws ErrnoException;
}
+36 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DeviceConfig.Properties;
@@ -124,6 +125,7 @@ final class ActivityManagerConstants extends ContentObserver {
    private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000;
    private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000;
    private static final int DEFAULT_MIN_CRASH_INTERVAL = 2 * 60 * 1000;
    private static final int DEFAULT_MAX_PHANTOM_PROCESSES = 32;


    // Flag stored in the DeviceConfig API.
@@ -132,6 +134,11 @@ final class ActivityManagerConstants extends ContentObserver {
     */
    private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";

    /**
     * Maximum number of cached processes.
     */
    private static final String KEY_MAX_PHANTOM_PROCESSES = "max_phantom_processes";

    /**
     * Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
     * Settings.Global. This allows it to be set experimentally unless it has been
@@ -364,6 +371,11 @@ final class ActivityManagerConstants extends ContentObserver {
     */
    public final ArraySet<ComponentName> KEEP_WARMING_SERVICES = new ArraySet<ComponentName>();

    /**
     * Maximum number of phantom processes.
     */
    public int MAX_PHANTOM_PROCESSES = DEFAULT_MAX_PHANTOM_PROCESSES;

    private List<String> mDefaultImperceptibleKillExemptPackages;
    private List<Integer> mDefaultImperceptibleKillExemptProcStates;

@@ -481,6 +493,9 @@ final class ActivityManagerConstants extends ContentObserver {
                            case KEY_BINDER_HEAVY_HITTER_AUTO_SAMPLER_THRESHOLD:
                                updateBinderHeavyHitterWatcher();
                                break;
                            case KEY_MAX_PHANTOM_PROCESSES:
                                updateMaxPhantomProcesses();
                                break;
                            default:
                                break;
                        }
@@ -599,6 +614,8 @@ final class ActivityManagerConstants extends ContentObserver {
                // with defaults.
                Slog.e("ActivityManagerConstants", "Bad activity manager config settings", e);
            }
            final long currentPowerCheckInterval = POWER_CHECK_INTERVAL;

            BACKGROUND_SETTLE_TIME = mParser.getLong(KEY_BACKGROUND_SETTLE_TIME,
                    DEFAULT_BACKGROUND_SETTLE_TIME);
            FGSERVICE_MIN_SHOWN_TIME = mParser.getLong(KEY_FGSERVICE_MIN_SHOWN_TIME,
@@ -664,6 +681,13 @@ final class ActivityManagerConstants extends ContentObserver {
            PENDINGINTENT_WARNING_THRESHOLD = mParser.getInt(KEY_PENDINGINTENT_WARNING_THRESHOLD,
                    DEFAULT_PENDINGINTENT_WARNING_THRESHOLD);

            if (POWER_CHECK_INTERVAL != currentPowerCheckInterval) {
                mService.mHandler.removeMessages(
                        ActivityManagerService.CHECK_EXCESSIVE_POWER_USE_MSG);
                final Message msg = mService.mHandler.obtainMessage(
                        ActivityManagerService.CHECK_EXCESSIVE_POWER_USE_MSG);
                mService.mHandler.sendMessageDelayed(msg, POWER_CHECK_INTERVAL);
            }
            // For new flags that are intended for server-side experiments, please use the new
            // DeviceConfig package.
        }
@@ -811,6 +835,16 @@ final class ActivityManagerConstants extends ContentObserver {
        mService.scheduleUpdateBinderHeavyHitterWatcherConfig();
    }

    private void updateMaxPhantomProcesses() {
        final int oldVal = MAX_PHANTOM_PROCESSES;
        MAX_PHANTOM_PROCESSES = DeviceConfig.getInt(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_MAX_PHANTOM_PROCESSES,
                DEFAULT_MAX_PHANTOM_PROCESSES);
        if (oldVal > MAX_PHANTOM_PROCESSES) {
            mService.mHandler.post(mService.mPhantomProcessList::trimPhantomProcessesIfNecessary);
        }
    }

    void dump(PrintWriter pw) {
        pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
                + Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":");
@@ -897,6 +931,8 @@ final class ActivityManagerConstants extends ContentObserver {
        pw.println(BINDER_HEAVY_HITTER_AUTO_SAMPLER_BATCHSIZE);
        pw.print("  "); pw.print(KEY_BINDER_HEAVY_HITTER_AUTO_SAMPLER_THRESHOLD); pw.print("=");
        pw.println(BINDER_HEAVY_HITTER_AUTO_SAMPLER_THRESHOLD);
        pw.print("  "); pw.print(KEY_MAX_PHANTOM_PROCESSES); pw.print("=");
        pw.println(MAX_PHANTOM_PROCESSES);

        pw.println();
        if (mOverrideMaxCachedProcesses >= 0) {
+87 −45
Original line number Diff line number Diff line
@@ -634,6 +634,12 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
    final ProcessList mProcessList;
    /**
     * The list of phantom processes.
     * @see PhantomProcessRecord
     */
    final PhantomProcessList mPhantomProcessList;
    /**
     * Tracking long-term execution of processes to look for abuse and other
     * bad app behavior.
@@ -1996,6 +2002,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mProcessList = injector.getProcessList(this);
        mProcessList.init(this, activeUids, mPlatformCompat);
        mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(), null);
        mPhantomProcessList = new PhantomProcessList(this);
        mOomAdjuster = hasHandlerThread
                ? new OomAdjuster(this, mProcessList, activeUids, handlerThread) : null;
@@ -2053,6 +2060,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        mProcessList.init(this, activeUids, mPlatformCompat);
        mAppProfiler = new AppProfiler(this, BackgroundThread.getHandler().getLooper(),
                new LowMemDetector(this));
        mPhantomProcessList = new PhantomProcessList(this);
        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
        // Broadcast policy parameters
@@ -9209,6 +9217,10 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        if (dumpAll) {
            mPhantomProcessList.dump(pw, "  ");
        }
        if (mImportantProcesses.size() > 0) {
            synchronized (mPidsSelfLocked) {
                boolean printed = false;
@@ -14832,29 +14844,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            int i = mProcessList.mLruProcesses.size();
            while (i > 0) {
                i--;
                ProcessRecord app = mProcessList.mLruProcesses.get(i);
                final ProcessRecord app = mProcessList.mLruProcesses.get(i);
                if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
                    if (app.lastCpuTime <= 0) {
                        continue;
                    }
                    long cputimeUsed = app.curCpuTime - app.lastCpuTime;
                    if (DEBUG_POWER) {
                        StringBuilder sb = new StringBuilder(128);
                        sb.append("CPU for ");
                        app.toShortString(sb);
                        sb.append(": over ");
                        TimeUtils.formatDuration(uptimeSince, sb);
                        sb.append(" used ");
                        TimeUtils.formatDuration(cputimeUsed, sb);
                        sb.append(" (");
                        sb.append((cputimeUsed * 100) / uptimeSince);
                        sb.append("%)");
                        Slog.i(TAG_POWER, sb.toString());
                    }
                    // If the process has used too much CPU over the last duration, the
                    // user probably doesn't want this, so kill!
                    if (doCpuKills && uptimeSince > 0) {
                        // What is the limit for this process?
                    int cpuLimit;
                    long checkDur = curUptime - app.getWhenUnimportant();
                    if (checkDur <= mConstants.POWER_CHECK_INTERVAL) {
@@ -14867,9 +14858,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                    } else {
                        cpuLimit = mConstants.POWER_CHECK_MAX_CPU_4;
                    }
                        if (((cputimeUsed * 100) / uptimeSince) >= cpuLimit) {
                            mBatteryStatsService.reportExcessiveCpu(app.info.uid, app.processName,
                                        uptimeSince, cputimeUsed);
                    if (app.lastCpuTime > 0) {
                        final long cputimeUsed = app.curCpuTime - app.lastCpuTime;
                        if (checkExcessivePowerUsageLocked(uptimeSince, doCpuKills, cputimeUsed,
                                app.processName, app.toShortString(), cpuLimit, app)) {
                            app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince
                                    + " dur=" + checkDur + " limit=" + cpuLimit,
                                    ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
@@ -14878,21 +14870,71 @@ public class ActivityManagerService extends IActivityManager.Stub
                            synchronized (mProcessStats.mLock) {
                                app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList);
                            }
                        }
                    }
                    app.lastCpuTime = app.curCpuTime;
                    // Also check the phantom processes if there is any
                    final long chkDur = checkDur;
                    final int cpuLmt = cpuLimit;
                    final boolean doKill = doCpuKills;
                    mPhantomProcessList.forEachPhantomProcessOfApp(app, r -> {
                        if (r.mLastCputime > 0) {
                            final long cputimeUsed = r.mCurrentCputime - r.mLastCputime;
                            if (checkExcessivePowerUsageLocked(uptimeSince, doKill, cputimeUsed,
                                    app.processName, r.toString(), cpuLimit, app)) {
                                mPhantomProcessList.killPhantomProcessGroupLocked(app, r,
                                        ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
                                        ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
                                        "excessive cpu " + cputimeUsed + " during "
                                        + uptimeSince + " dur=" + chkDur + " limit=" + cpuLmt);
                                return false;
                            }
                        }
                        r.mLastCputime = r.mCurrentCputime;
                        return true;
                    });
                }
            }
        }
    }
    private boolean checkExcessivePowerUsageLocked(final long uptimeSince, boolean doCpuKills,
            final long cputimeUsed, final String processName, final String description,
            final int cpuLimit, final ProcessRecord app) {
        if (DEBUG_POWER) {
            StringBuilder sb = new StringBuilder(128);
            sb.append("CPU for ");
            sb.append(description);
            sb.append(": over ");
            TimeUtils.formatDuration(uptimeSince, sb);
            sb.append(" used ");
            TimeUtils.formatDuration(cputimeUsed, sb);
            sb.append(" (");
            sb.append((cputimeUsed * 100.0) / uptimeSince);
            sb.append("%)");
            Slog.i(TAG_POWER, sb.toString());
        }
        // If the process has used too much CPU over the last duration, the
        // user probably doesn't want this, so kill!
        if (doCpuKills && uptimeSince > 0) {
            if (((cputimeUsed * 100) / uptimeSince) >= cpuLimit) {
                mBatteryStatsService.reportExcessiveCpu(app.info.uid, app.processName,
                        uptimeSince, cputimeUsed);
                for (int ipkg = app.pkgList.size() - 1; ipkg >= 0; ipkg--) {
                    ProcessStats.ProcessStateHolder holder = app.pkgList.valueAt(ipkg);
                    FrameworkStatsLog.write(
                            FrameworkStatsLog.EXCESSIVE_CPU_USAGE_REPORTED,
                            app.info.uid,
                                        holder.state.getName(),
                            processName,
                            holder.state.getPackage(),
                            holder.appVersion);
                }
                return true;
            }
        }
                    app.lastCpuTime = app.curCpuTime;
                }
            }
        }
        return false;
    }
    final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
+4 −0
Original line number Diff line number Diff line
@@ -1257,6 +1257,10 @@ public class AppProfiler {
                }
            }

            if (haveNewCpuStats) {
                mService.mPhantomProcessList.updateProcessCpuStatesLocked(mProcessCpuTracker);
            }

            final BatteryStatsImpl bstats = mService.mBatteryStatsService.getActiveStatistics();
            synchronized (bstats) {
                if (haveNewCpuStats) {
+395 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading