From be4e6aaa0252dd7da28b7aa85beba982538efa46 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 7 Jun 2013 13:25:29 -0700 Subject: [PATCH] Initial super-primitive process tracker. The goal of this is to keep track of what app processes are doing, to determine who is being abusive, when the system is getting into memory constrained situations, and help the user determine how to resolve this. Right now it doesn't really do any of that, just keeps track of how long every process has been running since boot. Also update the activity manager to use "cached" as the terminology for what it used to interchangeably call hidden and background processes, and switch ProcessMap over to using ArrayMap. Change-Id: I270b0006aab1f38e17b7d9b65728679173c343f2 --- .../java/com/android/server/ProcessMap.java | 9 +- .../com/android/server/am/ActiveServices.java | 2 +- .../server/am/ActivityManagerService.java | 473 ++++++++++-------- .../com/android/server/am/ActivityResult.java | 2 +- .../server/am/ActivityStackSupervisor.java | 2 +- .../com/android/server/am/AppBindRecord.java | 2 +- .../com/android/server/am/AppErrorDialog.java | 2 +- .../com/android/server/am/AppErrorResult.java | 3 +- .../server/am/AppNotRespondingDialog.java | 2 +- .../am/AppWaitingForDebuggerDialog.java | 2 +- .../com/android/server/am/BackupRecord.java | 2 +- .../android/server/am/BroadcastFilter.java | 2 +- .../com/android/server/am/BroadcastQueue.java | 2 +- .../android/server/am/BroadcastRecord.java | 2 +- .../android/server/am/CompatModeDialog.java | 2 +- .../android/server/am/CompatModePackages.java | 2 +- .../android/server/am/ConnectionRecord.java | 2 +- .../server/am/ContentProviderConnection.java | 2 +- .../server/am/ContentProviderRecord.java | 2 +- .../server/am/CoreSettingsObserver.java | 2 +- .../com/android/server/am/DeviceMonitor.java | 234 --------- .../android/server/am/FactoryErrorDialog.java | 2 +- .../android/server/am/IntentBindRecord.java | 2 +- .../server/am/LaunchWarningWindow.java | 2 +- .../server/am/NativeCrashListener.java | 2 +- .../server/am/PendingIntentRecord.java | 2 +- .../server/am/PendingThumbnailsRecord.java | 2 +- .../com/android/server/am/ProcessList.java | 55 +- .../com/android/server/am/ProcessRecord.java | 23 +- .../com/android/server/am/ProcessTracker.java | 110 ++++ .../com/android/server/am/ProviderMap.java | 2 +- .../com/android/server/am/ReceiverList.java | 2 +- .../com/android/server/am/ServiceRecord.java | 2 +- .../server/am/StrictModeViolationDialog.java | 2 +- .../com/android/server/am/TaskRecord.java | 2 +- .../com/android/server/am/TransferPipe.java | 2 +- .../com/android/server/am/UriPermission.java | 2 +- .../android/server/am/UriPermissionOwner.java | 2 +- .../android/server/am/UserStartedState.java | 2 +- 39 files changed, 464 insertions(+), 507 deletions(-) delete mode 100644 services/java/com/android/server/am/DeviceMonitor.java create mode 100644 services/java/com/android/server/am/ProcessTracker.java diff --git a/services/java/com/android/server/ProcessMap.java b/services/java/com/android/server/ProcessMap.java index 6b264035b1460..20c97ba247894 100644 --- a/services/java/com/android/server/ProcessMap.java +++ b/services/java/com/android/server/ProcessMap.java @@ -16,13 +16,12 @@ package com.android.server; +import android.util.ArrayMap; import android.util.SparseArray; -import java.util.HashMap; - public class ProcessMap { - final HashMap> mMap - = new HashMap>(); + final ArrayMap> mMap + = new ArrayMap>(); public E get(String name, int uid) { SparseArray uids = mMap.get(name); @@ -50,7 +49,7 @@ public class ProcessMap { } } - public HashMap> getMap() { + public ArrayMap> getMap() { return mMap; } } diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index a77379e32c4a2..98c43521208eb 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -57,7 +57,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; -public class ActiveServices { +public final class ActiveServices { static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE; static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING; static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index bb201743321d2..f06b9a62fc78c 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -26,6 +26,7 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; import android.app.AppOpsManager; import android.appwidget.AppWidgetManager; +import android.util.ArrayMap; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsService; @@ -400,6 +401,12 @@ public final class ActivityManagerService extends ActivityManagerNative */ final ProcessMap mProcessNames = new ProcessMap(); + /** + * Tracking long-term execution of processes to look for abuse and other + * bad app behavior. + */ + final ProcessTracker mProcessTracker = new ProcessTracker(); + /** * The currently running isolated processes. */ @@ -614,8 +621,8 @@ public final class ActivityManagerService extends ActivityManagerNative * by the user ID the sticky is for, and can include UserHandle.USER_ALL * for stickies that are sent to all users. */ - final SparseArray>> mStickyBroadcasts = - new SparseArray>>(); + final SparseArray>> mStickyBroadcasts = + new SparseArray>>(); final ActiveServices mServices; @@ -803,16 +810,16 @@ public final class ActivityManagerService extends ActivityManagerNative int mLruSeq = 0; /** - * Keep track of the non-hidden/empty process we last found, to help - * determine how to distribute hidden/empty processes next time. + * Keep track of the non-cached/empty process we last found, to help + * determine how to distribute cached/empty processes next time. */ - int mNumNonHiddenProcs = 0; + int mNumNonCachedProcs = 0; /** - * Keep track of the number of hidden procs, to balance oom adj + * Keep track of the number of cached procs, to balance oom adj * distribution between those and empty procs. */ - int mNumHiddenProcs = 0; + int mNumCachedProcs = 0; /** * Keep track of the number of service processes we last found, to @@ -895,7 +902,7 @@ public final class ActivityManagerService extends ActivityManagerNative */ boolean mBooted = false; - int mProcessLimit = ProcessList.MAX_HIDDEN_APPS; + int mProcessLimit = ProcessList.MAX_CACHED_APPS; int mProcessLimitOverride = -1; WindowManagerService mWindowManager; @@ -1476,6 +1483,7 @@ public final class ActivityManagerService extends ActivityManagerNative ServiceManager.addService("meminfo", new MemBinder(m)); ServiceManager.addService("gfxinfo", new GraphicsBinder(m)); ServiceManager.addService("dbinfo", new DbBinder(m)); + ServiceManager.addService("procstats", new ProcBinder(m)); if (MONITOR_CPU_USAGE) { ServiceManager.addService("cpuinfo", new CpuBinder(m)); } @@ -1692,6 +1700,26 @@ public final class ActivityManagerService extends ActivityManagerNative } } + static class ProcBinder extends Binder { + ActivityManagerService mActivityManagerService; + ProcBinder(ActivityManagerService activityManagerService) { + mActivityManagerService = activityManagerService; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump procstats from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + + mActivityManagerService.dumpProcessTracker(fd, pw, args); + } + } + private ActivityManagerService() { Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); @@ -1780,7 +1808,9 @@ public final class ActivityManagerService extends ActivityManagerNative // We need to tell all apps about the system property change. ArrayList procs = new ArrayList(); synchronized(this) { - for (SparseArray apps : mProcessNames.getMap().values()) { + final int NP = mProcessNames.getMap().size(); + for (int ip=0; ip apps = mProcessNames.getMap().valueAt(ip); final int NA = apps.size(); for (int ia=0; ia