Improve process tracking.

We now keep track of when each process is running, batched
by the current memory status of the device.  In addition,
the stats are organized by package first, and then processes
associated with each package inside of that.  Finally, we
also keep track of the overall time spent in each memory
status.

This should start to actually get us to some information
we can reach some conclusions about.  The total time spent
in each memory status gives us some indication of how much
we are running while memory is low; the new package organization
batched by memory status lets us see what packages have
what processes running when memory is low.

Change-Id: I389d62d39d115a846126cf354e4c20070d8f1180
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 6cae67c..cc0a5a3 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -51,9 +51,10 @@
     final int uid;              // uid of process; may be different from 'info' if isolated
     final int userId;           // user of process.
     final String processName;   // name of the process
-    final ProcessTracker.ProcessState tracker; // tracking execution of process
+    final ProcessTracker.ProcessState baseProcessTracker;
     // List of packages running in the process
-    final HashSet<String> pkgList = new HashSet<String>();
+    final ArrayMap<String, ProcessTracker.ProcessState> pkgList
+            = new ArrayMap<String, ProcessTracker.ProcessState>();
     IApplicationThread thread;  // the actual proc...  may be null only if
                                 // 'persistent' is true (in which case we
                                 // are in the process of launching the app)
@@ -87,6 +88,7 @@
     boolean hasAboveClient;     // Bound using BIND_ABOVE_CLIENT, so want to be lower
     boolean bad;                // True if disabled in the bad process list
     boolean killedBackground;   // True when proc has been killed due to too many bg
+    boolean setAdjChanged;      // Keep track of whether we changed 'setAdj'.
     String waitingToKill;       // Process is waiting to be killed when in the bg; reason
     IBinder forcingToForeground;// Token that is forcing this process to be foreground
     int adjSeq;                 // Sequence id for identifying oom_adj assignment cycles
@@ -327,15 +329,15 @@
     
     ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
             ApplicationInfo _info, String _processName, int _uid,
-            ProcessTracker.ProcessState _tracker) {
+            ProcessTracker.ProcessState tracker) {
         batteryStats = _batteryStats;
         info = _info;
         isolated = _info.uid != _uid;
         uid = _uid;
         userId = UserHandle.getUserId(_uid);
         processName = _processName;
-        tracker = _tracker;
-        pkgList.add(_info.packageName);
+        baseProcessTracker = tracker;
+        pkgList.put(_info.packageName, tracker);
         thread = _thread;
         maxAdj = ProcessList.CACHED_APP_MAX_ADJ;
         cachedAdj = clientCachedAdj = emptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
@@ -437,20 +439,33 @@
     /*
      *  Return true if package has been added false if not
      */
-    public boolean addPackage(String pkg) {
-        if (!pkgList.contains(pkg)) {
-            pkgList.add(pkg);
+    public boolean addPackage(String pkg, ProcessTracker tracker) {
+        if (!pkgList.containsKey(pkg)) {
+            pkgList.put(pkg, tracker.getProcessStateLocked(pkg, info.uid, processName));
             return true;
         }
         return false;
     }
-    
+
+    public void setProcessTrackerState(ProcessRecord TOP_APP, int memFactor, long now,
+            ProcessList plist) {
+        int state = this == TOP_APP ? ProcessTracker.STATE_TOP
+                : plist.adjToTrackedState(setAdj);
+        for (int ip=pkgList.size()-1; ip>=0; ip--) {
+            pkgList.valueAt(ip).setState(state, memFactor, now);
+        }
+    }
+
     /*
      *  Delete all packages from list except the package indicated in info
      */
     public void resetPackageList() {
+        long now = SystemClock.uptimeMillis();
+        for (int i=0; i<pkgList.size(); i++) {
+            pkgList.valueAt(i).setState(ProcessTracker.STATE_NOTHING, 0, now);
+        }
         pkgList.clear();
-        pkgList.add(info.packageName);
+        pkgList.put(info.packageName, baseProcessTracker);
     }
     
     public String[] getPackageList() {
@@ -459,7 +474,9 @@
             return null;
         }
         String list[] = new String[size];
-        pkgList.toArray(list);
+        for (int i=0; i<pkgList.size(); i++) {
+            list[i] = pkgList.keyAt(i);
+        }
         return list;
     }
 }