Loading core/java/android/os/Process.java +61 −23 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() Loading Loading @@ -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; } services/core/java/com/android/server/am/ActivityManagerConstants.java +36 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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, Loading Loading @@ -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. } Loading Loading @@ -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 + ":"); Loading Loading @@ -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) { Loading services/core/java/com/android/server/am/ActivityManagerService.java +87 −45 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -9209,6 +9217,10 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (dumpAll) { mPhantomProcessList.dump(pw, " "); } if (mImportantProcesses.size() > 0) { synchronized (mPidsSelfLocked) { boolean printed = false; Loading Loading @@ -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) { Loading @@ -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, Loading @@ -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) { services/core/java/com/android/server/am/AppProfiler.java +4 −0 Original line number Diff line number Diff line Loading @@ -1257,6 +1257,10 @@ public class AppProfiler { } } if (haveNewCpuStats) { mService.mPhantomProcessList.updateProcessCpuStatesLocked(mProcessCpuTracker); } final BatteryStatsImpl bstats = mService.mBatteryStatsService.getActiveStatistics(); synchronized (bstats) { if (haveNewCpuStats) { Loading services/core/java/com/android/server/am/PhantomProcessList.java 0 → 100644 +395 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/os/Process.java +61 −23 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() Loading Loading @@ -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; }
services/core/java/com/android/server/am/ActivityManagerConstants.java +36 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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, Loading Loading @@ -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. } Loading Loading @@ -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 + ":"); Loading Loading @@ -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) { Loading
services/core/java/com/android/server/am/ActivityManagerService.java +87 −45 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -9209,6 +9217,10 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (dumpAll) { mPhantomProcessList.dump(pw, " "); } if (mImportantProcesses.size() > 0) { synchronized (mPidsSelfLocked) { boolean printed = false; Loading Loading @@ -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) { Loading @@ -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, Loading @@ -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) {
services/core/java/com/android/server/am/AppProfiler.java +4 −0 Original line number Diff line number Diff line Loading @@ -1257,6 +1257,10 @@ public class AppProfiler { } } if (haveNewCpuStats) { mService.mPhantomProcessList.updateProcessCpuStatesLocked(mProcessCpuTracker); } final BatteryStatsImpl bstats = mService.mBatteryStatsService.getActiveStatistics(); synchronized (bstats) { if (haveNewCpuStats) { Loading
services/core/java/com/android/server/am/PhantomProcessList.java 0 → 100644 +395 −0 File added.Preview size limit exceeded, changes collapsed. Show changes