Fix issue #11005453: [SUW] G+ profile creation for new user broken

The main problem here was a mistake when turning a single process
structure to a multi-package-process structure with a common
process.  When we cloned the original process state, if there were
any services already created for the process for that package, they
would be left with their process pointer still referencing the
original now common process instead of the package-specific process,
allowing the active counts to get bad.  Now we switch any of those
processes over to the new package-specific process.

There was also another smaller issue with how ServiceRecord is
associated with a ServiceState -- we could be waiting for an
old ServiceRecord to be destroyed while at the same time creating
a new ServiceRecord for that same service class.  These would share
the same ServiceState, so when the old record finally finished
destroying itself it would trample over whatever the new service
is doing.

This is fixed by changing the model to instead of using an "active"
reference count, we have an object identifying the current owner
of the ServiceState.  Then when the old ServiceRecord is cleaning
up, we know if it is still the owner at that point.

Also some other small things along the way -- new Log.wtfStack()
method that is convenient, new suite of Slog.wtf methods, fixed
some services to use Slog.wtf when catching exceptions being
returned to the caller so that we actually know about them.

Change-Id: I75674ce38050b6423fd3c6f43d1be172b470741f
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 6a6f027..8c1cf5f 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -84,14 +84,14 @@
     public static final int ASSERT = 7;
 
     /**
-     * Exception class used to capture a stack trace in {@link #wtf()}.
+     * Exception class used to capture a stack trace in {@link #wtf}.
      */
     private static class TerribleFailure extends Exception {
         TerribleFailure(String msg, Throwable cause) { super(msg, cause); }
     }
 
     /**
-     * Interface to handle terrible failures from {@link #wtf()}.
+     * Interface to handle terrible failures from {@link #wtf}.
      *
      * @hide
      */
@@ -257,6 +257,15 @@
     }
 
     /**
+     * Like {@link #wtf(String, String)}, but also writes to the log the full
+     * call stack.
+     * @hide
+     */
+    public static int wtfStack(String tag, String msg) {
+        return wtfStack(LOG_ID_MAIN, tag, msg);
+    }
+
+    /**
      * What a Terrible Failure: Report an exception that should never happen.
      * Similar to {@link #wtf(String, String)}, with an exception to log.
      * @param tag Used to identify the source of a log message.
@@ -274,8 +283,18 @@
      * @param tr An exception to log.  May be null.
      */
     public static int wtf(String tag, String msg, Throwable tr) {
+        return wtf(LOG_ID_MAIN, tag, msg, tr);
+    }
+
+    static int wtfStack(int logId, String tag, String msg) {
+        TerribleFailure here = new TerribleFailure("here", null);
+        here.fillInStackTrace();
+        return wtf(logId, tag, msg, here);
+    }
+
+    static int wtf(int logId, String tag, String msg, Throwable tr) {
         TerribleFailure what = new TerribleFailure(msg, tr);
-        int bytes = println_native(LOG_ID_MAIN, ASSERT, tag, msg + '\n' + getStackTraceString(tr));
+        int bytes = println_native(logId, ASSERT, tag, msg + '\n' + getStackTraceString(tr));
         sWtfHandler.onTerribleFailure(tag, what);
         return bytes;
     }
diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java
index ecf5ea1..a5c22ff 100644
--- a/core/java/android/util/Slog.java
+++ b/core/java/android/util/Slog.java
@@ -78,6 +78,22 @@
                 msg + '\n' + Log.getStackTraceString(tr));
     }
 
+    public static int wtf(String tag, String msg) {
+        return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, null);
+    }
+
+    public static int wtfStack(String tag, String msg) {
+        return Log.wtfStack(Log.LOG_ID_SYSTEM, tag, msg);
+    }
+
+    public static int wtf(String tag, Throwable tr) {
+        return Log.wtf(Log.LOG_ID_SYSTEM, tag, tr.getMessage(), tr);
+    }
+
+    public static int wtf(String tag, String msg, Throwable tr) {
+        return Log.wtf(Log.LOG_ID_SYSTEM, tag, msg, tr);
+    }
+
     public static int println(int priority, String tag, String msg) {
         return Log.println_native(Log.LOG_ID_SYSTEM, priority, tag, msg);
     }
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index a95bac8..430e43a 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -44,6 +44,7 @@
 public final class ProcessStats implements Parcelable {
     static final String TAG = "ProcessStats";
     static final boolean DEBUG = false;
+    static final boolean DEBUG_PARCEL = false;
 
     public static final String SERVICE_NAME = "procstats";
 
@@ -1076,7 +1077,7 @@
         final int[] table = new int[size];
         for (int i=0; i<size; i++) {
             table[i] = in.readInt();
-            if (DEBUG) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
+            if (DEBUG_PARCEL) Slog.i(TAG, "Reading in " + name + " table #" + i + ": "
                     + ProcessStats.printLongOffset(table[i]));
             if (!validateLongOffset(table[i])) {
                 Slog.w(TAG, "Ignoring existing stats; bad " + what + " table entry: "
@@ -1294,10 +1295,10 @@
         byte[] data = new byte[initialAvail > 0 ? (initialAvail+1) : 16384];
         while (true) {
             int amt = stream.read(data, pos, data.length-pos);
-            if (DEBUG) Slog.i("foo", "Read " + amt + " bytes at " + pos
+            if (DEBUG_PARCEL) Slog.i("foo", "Read " + amt + " bytes at " + pos
                     + " of avail " + data.length);
             if (amt < 0) {
-                if (DEBUG) Slog.i("foo", "**** FINISHED READING: pos=" + pos
+                if (DEBUG_PARCEL) Slog.i("foo", "**** FINISHED READING: pos=" + pos
                         + " len=" + data.length);
                 outLen[0] = pos;
                 return data;
@@ -1305,7 +1306,7 @@
             pos += amt;
             if (pos >= data.length) {
                 byte[] newData = new byte[pos+16384];
-                if (DEBUG) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
+                if (DEBUG_PARCEL) Slog.i(TAG, "Copying " + pos + " bytes to new array len "
                         + newData.length);
                 System.arraycopy(data, 0, newData, 0, pos);
                 data = newData;
@@ -1422,12 +1423,13 @@
                         return;
                     }
                 }
-                if (DEBUG) Slog.d(TAG, "Adding process: " + procName + " " + uid + " " + proc);
+                if (DEBUG_PARCEL) Slog.d(TAG, "Adding process: " + procName + " " + uid
+                        + " " + proc);
                 mProcesses.put(procName, uid, proc);
             }
         }
 
-        if (DEBUG) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
+        if (DEBUG_PARCEL) Slog.d(TAG, "Read " + mProcesses.getMap().size() + " processes");
 
         int NPKG = in.readInt();
         if (NPKG < 0) {
@@ -1468,10 +1470,10 @@
                         return;
                     }
                     int hasProc = in.readInt();
-                    if (DEBUG) Slog.d(TAG, "Reading package " + pkgName + " " + uid
+                    if (DEBUG_PARCEL) Slog.d(TAG, "Reading package " + pkgName + " " + uid
                             + " process " + procName + " hasProc=" + hasProc);
                     ProcessState commonProc = mProcesses.get(procName, uid);
-                    if (DEBUG) Slog.d(TAG, "Got common proc " + procName + " " + uid
+                    if (DEBUG_PARCEL) Slog.d(TAG, "Got common proc " + procName + " " + uid
                             + ": " + commonProc);
                     if (commonProc == null) {
                         mReadError = "no common proc: " + procName;
@@ -1493,11 +1495,11 @@
                                 return;
                             }
                         }
-                        if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " process: "
+                        if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
                                 + procName + " " + uid + " " + proc);
                         pkgState.mProcesses.put(procName, proc);
                     } else {
-                        if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " process: "
+                        if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " process: "
                                 + procName + " " + uid + " " + commonProc);
                         pkgState.mProcesses.put(procName, commonProc);
                     }
@@ -1522,7 +1524,7 @@
                     if (!serv.readFromParcel(in)) {
                         return;
                     }
-                    if (DEBUG) Slog.d(TAG, "Adding package " + pkgName + " service: "
+                    if (DEBUG_PARCEL) Slog.d(TAG, "Adding package " + pkgName + " service: "
                             + serviceName + " " + uid + " " + serv);
                     pkgState.mServices.put(serviceName, serv);
                 }
@@ -1531,7 +1533,7 @@
 
         mIndexToCommonString = null;
 
-        if (DEBUG) Slog.d(TAG, "Successfully read procstats!");
+        if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
     }
 
     int addLongData(int index, int type, int num) {
@@ -1577,7 +1579,7 @@
         if (idx >= LONGS_SIZE) {
             return false;
         }
-        if (DEBUG) Slog.d(TAG, "Validated long " + printLongOffset(off)
+        if (DEBUG_PARCEL) Slog.d(TAG, "Validated long " + printLongOffset(off)
                 + ": " + getLong(off, 0));
         return true;
     }
@@ -1639,13 +1641,16 @@
         if (commonProc == null) {
             commonProc = new ProcessState(this, packageName, uid, processName);
             mProcesses.put(processName, uid, commonProc);
+            if (DEBUG) Slog.d(TAG, "GETPROC created new common " + commonProc);
         }
         if (!commonProc.mMultiPackage) {
             if (packageName.equals(commonProc.mPackage)) {
                 // This common process is not in use by multiple packages, and
                 // is for the calling package, so we can just use it directly.
                 ps = commonProc;
+                if (DEBUG) Slog.d(TAG, "GETPROC also using for pkg " + commonProc);
             } else {
+                if (DEBUG) Slog.d(TAG, "GETPROC need to split common proc!");
                 // This common process has not been in use by multiple packages,
                 // but it was created for a different package than the caller.
                 // We need to convert it to a multi-package process.
@@ -1659,22 +1664,39 @@
                 // that under the now unique state for its original package name.
                 final PackageState commonPkgState = getPackageStateLocked(commonProc.mPackage, uid);
                 if (commonPkgState != null) {
-                    commonPkgState.mProcesses.put(commonProc.mName, commonProc.clone(
-                            commonProc.mPackage, now));
+                    ProcessState cloned = commonProc.clone(commonProc.mPackage, now);
+                    if (DEBUG) Slog.d(TAG, "GETPROC setting clone to pkg " + commonProc.mPackage
+                            + ": " + cloned);
+                    commonPkgState.mProcesses.put(commonProc.mName, cloned);
+                    // If this has active services, we need to update their process pointer
+                    // to point to the new package-specific process state.
+                    for (int i=commonPkgState.mServices.size()-1; i>=0; i--) {
+                        ServiceState ss = commonPkgState.mServices.valueAt(i);
+                        if (ss.mProc == commonProc) {
+                            if (DEBUG) Slog.d(TAG, "GETPROC switching service to cloned: "
+                                    + ss);
+                            ss.mProc = cloned;
+                        } else if (DEBUG) {
+                            Slog.d(TAG, "GETPROC leaving proc of " + ss);
+                        }
+                    }
                 } else {
                     Slog.w(TAG, "Cloning proc state: no package state " + commonProc.mPackage
                             + "/" + uid + " for proc " + commonProc.mName);
                 }
                 // And now make a fresh new process state for the new package name.
                 ps = new ProcessState(commonProc, packageName, uid, processName, now);
+                if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
             }
         } else {
             // The common process is for multiple packages, we need to create a
             // separate object for the per-package data.
             ps = new ProcessState(commonProc, packageName, uid, processName,
                     SystemClock.uptimeMillis());
+            if (DEBUG) Slog.d(TAG, "GETPROC created new pkg " + ps);
         }
         pkgState.mProcesses.put(processName, ps);
+        if (DEBUG) Slog.d(TAG, "GETPROC adding new pkg " + ps);
         return ps;
     }
 
@@ -1683,12 +1705,14 @@
         final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid);
         ProcessStats.ServiceState ss = as.mServices.get(className);
         if (ss != null) {
+            if (DEBUG) Slog.d(TAG, "GETSVC: returning existing " + ss);
             return ss;
         }
         final ProcessStats.ProcessState ps = processName != null
                 ? getProcessStateLocked(packageName, uid, processName) : null;
         ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps);
         as.mServices.put(className, ss);
+        if (DEBUG) Slog.d(TAG, "GETSVC: creating " + ss + " in " + ps);
         return ss;
     }
 
@@ -1719,7 +1743,7 @@
     }
 
     public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpSummary,
-            boolean dumpAll) {
+            boolean dumpAll, boolean activeOnly) {
         long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
                 mStartTime, now);
         ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
@@ -1746,6 +1770,11 @@
                 if (!dumpSummary || dumpAll) {
                     for (int iproc=0; iproc<NPROCS; iproc++) {
                         ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                        if (activeOnly && !proc.isInUse()) {
+                            pw.print("      (Not active: ");
+                                    pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")");
+                            continue;
+                        }
                         pw.print("      Process ");
                         pw.print(pkgState.mProcesses.keyAt(iproc));
                         pw.print(" (");
@@ -1761,12 +1790,22 @@
                 } else {
                     ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
                     for (int iproc=0; iproc<NPROCS; iproc++) {
-                        procs.add(pkgState.mProcesses.valueAt(iproc));
+                        ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+                        if (activeOnly && !proc.isInUse()) {
+                            continue;
+                        }
+                        procs.add(proc);
                     }
                     dumpProcessSummaryLocked(pw, "      ", procs, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
                             NON_CACHED_PROC_STATES, now, totalTime);
                 }
                 for (int isvc=0; isvc<NSRVS; isvc++) {
+                    ServiceState svc = pkgState.mServices.valueAt(isvc);
+                    if (activeOnly && !svc.isInUse()) {
+                        pw.print("      (Not active: ");
+                                pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")");
+                        continue;
+                    }
                     if (dumpAll) {
                         pw.print("      Service ");
                     } else {
@@ -1774,7 +1813,6 @@
                     }
                     pw.print(pkgState.mServices.keyAt(isvc));
                     pw.println(":");
-                    ServiceState svc = pkgState.mServices.valueAt(isvc);
                     pw.print("        Process: "); pw.println(svc.mProcessName);
                     dumpServiceStats(pw, "        ", "          ", "    ", "Running", svc,
                             svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
@@ -1789,7 +1827,9 @@
                             svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
                             svc.mExecStartTime, now, totalTime, !dumpSummary || dumpAll);
                     if (dumpAll) {
-                        pw.print("        mActive="); pw.println(svc.mActive);
+                        if (svc.mOwner != null) {
+                            pw.print("        mOwner="); pw.println(svc.mOwner);
+                        }
                     }
                 }
             }
@@ -1816,6 +1856,10 @@
                         pw.println("Per-Process Stats:");
                         printedHeader = true;
                     }
+                    if (activeOnly && !proc.isInUse()) {
+                        pw.print("      (Not active: "); pw.print(procName); pw.println(")");
+                        continue;
+                    }
                     pw.print("  * "); pw.print(procName); pw.print(" / ");
                             UserHandle.formatUid(pw, uid);
                             pw.print(" ("); pw.print(proc.mDurationsTableSize);
@@ -1838,7 +1882,7 @@
             pw.println();
             if (dumpSummary) {
                 pw.println("Summary:");
-                dumpSummaryLocked(pw, reqPackage, now);
+                dumpSummaryLocked(pw, reqPackage, now, activeOnly);
             } else {
                 dumpTotalsLocked(pw, now);
             }
@@ -1916,11 +1960,11 @@
         }
     }
 
-    public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now) {
+    public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
         long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
                 mStartTime, now);
         dumpFilteredSummaryLocked(pw, null, "  ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
-                ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage);
+                ALL_PROC_STATES, NON_CACHED_PROC_STATES, now, totalTime, reqPackage, activeOnly);
         pw.println();
         dumpTotalsLocked(pw, now);
     }
@@ -1961,9 +2005,9 @@
 
     void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
             int[] screenStates, int[] memStates, int[] procStates,
-            int[] sortProcStates, long now, long totalTime, String reqPackage) {
+            int[] sortProcStates, long now, long totalTime, String reqPackage, boolean activeOnly) {
         ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
-                procStates, sortProcStates, now, reqPackage);
+                procStates, sortProcStates, now, reqPackage, activeOnly);
         if (procs.size() > 0) {
             if (header != null) {
                 pw.println();
@@ -1975,7 +2019,8 @@
     }
 
     public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
-            int[] procStates, int sortProcStates[], long now, String reqPackage) {
+            int[] procStates, int sortProcStates[], long now, String reqPackage,
+            boolean activeOnly) {
         ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>();
         ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
         for (int ip=0; ip<pkgMap.size(); ip++) {
@@ -1987,6 +2032,9 @@
                 PackageState state = procs.valueAt(iu);
                 for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
                     ProcessState proc = state.mProcesses.valueAt(iproc);
+                    if (activeOnly && !proc.isInUse()) {
+                        continue;
+                    }
                     foundProcs.add(proc.mCommonProcess);
                 }
             }
@@ -1994,8 +2042,7 @@
         ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>(foundProcs.size());
         for (int i=0; i<foundProcs.size(); i++) {
             ProcessState proc = foundProcs.valueAt(i);
-            if (computeProcessTimeLocked(proc, screenStates, memStates,
-                    procStates, now) > 0) {
+            if (computeProcessTimeLocked(proc, screenStates, memStates, procStates, now) > 0) {
                 outProcs.add(proc);
                 if (procStates != sortProcStates) {
                     computeProcessTimeLocked(proc, screenStates, memStates, sortProcStates, now);
@@ -2229,7 +2276,7 @@
         void writeDurationsToParcel(Parcel out) {
             out.writeInt(mDurationsTableSize);
             for (int i=0; i<mDurationsTableSize; i++) {
-                if (DEBUG) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
+                if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " dur #" + i + ": "
                         + printLongOffset(mDurationsTable[i]));
                 out.writeInt(mDurationsTable[i]);
             }
@@ -2350,6 +2397,7 @@
             pnew.mAvgCachedKillPss = mAvgCachedKillPss;
             pnew.mMaxCachedKillPss = mMaxCachedKillPss;
             pnew.mActive = mActive;
+            pnew.mNumActiveServices = mNumActiveServices;
             pnew.mNumStartedServices = mNumStartedServices;
             return pnew;
         }
@@ -2396,7 +2444,7 @@
             if (!mDead) {
                 return;
             }
-            throw new IllegalStateException("ProcessState dead: name=" + mName
+            Slog.wtfStack(TAG, "ProcessState dead: name=" + mName
                     + " pkg=" + mPackage + " uid=" + mUid + " common.name=" + mCommonProcess.mName);
         }
 
@@ -2405,7 +2453,7 @@
             writeDurationsToParcel(out);
             out.writeInt(mPssTableSize);
             for (int i=0; i<mPssTableSize; i++) {
-                if (DEBUG) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
+                if (DEBUG_PARCEL) Slog.i(TAG, "Writing in " + mName + " pss #" + i + ": "
                         + printLongOffset(mPssTable[i]));
                 out.writeInt(mPssTable[i]);
             }
@@ -2424,11 +2472,11 @@
             if (fully) {
                 mMultiPackage = multiPackage;
             }
-            if (DEBUG) Slog.d(TAG, "Reading durations table...");
+            if (DEBUG_PARCEL) Slog.d(TAG, "Reading durations table...");
             if (!readDurationsFromParcel(in)) {
                 return false;
             }
-            if (DEBUG) Slog.d(TAG, "Reading pss table...");
+            if (DEBUG_PARCEL) Slog.d(TAG, "Reading pss table...");
             mPssTable = mStats.readTableFromParcel(in, mName, "pss");
             if (mPssTable == BAD_TABLE) {
                 return false;
@@ -2512,21 +2560,34 @@
             mStartTime = now;
         }
 
-        void incActiveServices() {
+        void incActiveServices(String serviceName) {
+            if (DEBUG && "".equals(mName)) {
+                RuntimeException here = new RuntimeException("here");
+                here.fillInStackTrace();
+                Slog.d(TAG, "incActiveServices: " + this + " service=" + serviceName
+                        + " to " + (mNumActiveServices+1), here);
+            }
             if (mCommonProcess != this) {
-                mCommonProcess.incActiveServices();
+                mCommonProcess.incActiveServices(serviceName);
             }
             mNumActiveServices++;
         }
 
-        void decActiveServices() {
+        void decActiveServices(String serviceName) {
+            if (DEBUG && "".equals(mName)) {
+                RuntimeException here = new RuntimeException("here");
+                here.fillInStackTrace();
+                Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName
+                        + " to " + (mNumActiveServices-1), here);
+            }
             if (mCommonProcess != this) {
-                mCommonProcess.decActiveServices();
+                mCommonProcess.decActiveServices(serviceName);
             }
             mNumActiveServices--;
             if (mNumActiveServices < 0) {
-                throw new IllegalStateException("Proc active services underrun: pkg="
-                        + mPackage + " uid=" + mUid + " name=" + mName);
+                Slog.wtfStack(TAG, "Proc active services underrun: pkg=" + mPackage
+                        + " uid=" + mUid + " proc=" + mName + " service=" + serviceName);
+                mNumActiveServices = 0;
             }
         }
 
@@ -2548,8 +2609,9 @@
             if (mNumStartedServices == 0 && mCurState == STATE_SERVICE_RESTARTING) {
                 setState(STATE_NOTHING, memFactor, now, null);
             } else if (mNumStartedServices < 0) {
-                throw new IllegalStateException("Proc started services underrun: pkg="
+                Slog.wtfStack(TAG, "Proc started services underrun: pkg="
                         + mPackage + " uid=" + mUid + " name=" + mName);
+                mNumStartedServices = 0;
             }
         }
 
@@ -2689,8 +2751,7 @@
                 // The array map is still pointing to a common process state
                 // that is now shared across packages.  Update it to point to
                 // the new per-package state.
-                ProcessState proc = mStats.mPackages.get(pkgName,
-                        mUid).mProcesses.get(mName);
+                ProcessState proc = mStats.mPackages.get(pkgName, mUid).mProcesses.get(mName);
                 if (proc == null) {
                     throw new IllegalStateException("Didn't create per-package process");
                 }
@@ -2717,11 +2778,13 @@
                 PackageState pkg = mStats.mPackages.get(pkgList.keyAt(index), proc.mUid);
                 if (pkg == null) {
                     throw new IllegalStateException("No existing package "
-                            + pkgList.keyAt(index) + " for multi-proc " + proc.mName);
+                            + pkgList.keyAt(index) + "/" + proc.mUid
+                            + " for multi-proc " + proc.mName);
                 }
                 proc = pkg.mProcesses.get(proc.mName);
                 if (proc == null) {
-                    throw new IllegalStateException("Didn't create per-package process");
+                    throw new IllegalStateException("Didn't create per-package process "
+                            + proc.mName + " in pkg " + pkg.mPackageName + "/" + pkg.mUid);
                 }
                 pkgList.setValueAt(index, proc);
             }
@@ -2770,6 +2833,17 @@
             int idx = binarySearch(mPssTable, mPssTableSize, state);
             return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
         }
+
+        public String toString() {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("ProcessState{").append(Integer.toHexString(System.identityHashCode(this)))
+                    .append(" ").append(mName).append("/").append(mUid)
+                    .append(" pkg=").append(mPackage);
+            if (mMultiPackage) sb.append(" (multi)");
+            if (mCommonProcess != this) sb.append(" (sub)");
+            sb.append("}");
+            return sb.toString();
+        }
     }
 
     public static final class ServiceState extends DurationsTable {
@@ -2777,7 +2851,7 @@
         public final String mProcessName;
         ProcessState mProc;
 
-        int mActive = 0;
+        Object mOwner;
 
         public static final int SERVICE_RUN = 0;
         public static final int SERVICE_STARTED = 1;
@@ -2809,27 +2883,69 @@
             mProc = proc;
         }
 
-        public void makeActive() {
-            if (mActive == 0) {
-                mProc.incActiveServices();
+        public void applyNewOwner(Object newOwner) {
+            if (mOwner != newOwner) {
+                if (mOwner == null) {
+                    mOwner = newOwner;
+                    mProc.incActiveServices(mName);
+                } else {
+                    // There was already an old owner, reset this object for its
+                    // new owner.
+                    mOwner = newOwner;
+                    if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
+                            || mExecState != STATE_NOTHING) {
+                        long now = SystemClock.uptimeMillis();
+                        if (mStartedState != STATE_NOTHING) {
+                            if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+                                    + " from " + mOwner + " while started: pkg="
+                                    + mPackage + " service=" + mName + " proc=" + mProc);
+                            setStarted(false, 0, now);
+                        }
+                        if (mBoundState != STATE_NOTHING) {
+                            if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+                                    + " from " + mOwner + " while bound: pkg="
+                                    + mPackage + " service=" + mName + " proc=" + mProc);
+                            setBound(false, 0, now);
+                        }
+                        if (mExecState != STATE_NOTHING) {
+                            if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner
+                                    + " from " + mOwner + " while executing: pkg="
+                                    + mPackage + " service=" + mName + " proc=" + mProc);
+                            setExecuting(false, 0, now);
+                        }
+                    }
+                }
             }
-            mActive++;
         }
 
-        public void makeInactive() {
-            /*
-            RuntimeException here = new RuntimeException("here");
-            here.fillInStackTrace();
-            Slog.i(TAG, "Making " + this + " inactive", here);
-            */
-            mActive--;
-            if (mActive == 0) {
-                mProc.decActiveServices();
+        public void clearCurrentOwner(Object owner) {
+            if (mOwner == owner) {
+                mOwner = null;
+                mProc.decActiveServices(mName);
+                if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
+                        || mExecState != STATE_NOTHING) {
+                    long now = SystemClock.uptimeMillis();
+                    if (mStartedState != STATE_NOTHING) {
+                        Slog.wtfStack(TAG, "Service owner " + owner + " cleared while started: pkg="
+                                + mPackage + " service=" + mName + " proc=" + mProc);
+                        setStarted(false, 0, now);
+                    }
+                    if (mBoundState != STATE_NOTHING) {
+                        Slog.wtfStack(TAG, "Service owner " + owner + " cleared while bound: pkg="
+                                + mPackage + " service=" + mName + " proc=" + mProc);
+                        setBound(false, 0, now);
+                    }
+                    if (mExecState != STATE_NOTHING) {
+                        Slog.wtfStack(TAG, "Service owner " + owner + " cleared while exec: pkg="
+                                + mPackage + " service=" + mName + " proc=" + mProc);
+                        setExecuting(false, 0, now);
+                    }
+                }
             }
         }
 
         public boolean isInUse() {
-            return mActive > 0;
+            return mOwner != null;
         }
 
         void add(ServiceState other) {
@@ -2904,8 +3020,8 @@
         }
 
         public void setStarted(boolean started, int memFactor, long now) {
-            if (mActive <= 0) {
-                throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
+            if (mOwner == null) {
+                Slog.wtf(TAG, "Starting service " + this + " without owner");
             }
             final boolean wasStarted = mStartedState != STATE_NOTHING;
             final int state = started ? memFactor : STATE_NOTHING;
@@ -2931,8 +3047,8 @@
         }
 
         public void setBound(boolean bound, int memFactor, long now) {
-            if (mActive <= 0) {
-                throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
+            if (mOwner == null) {
+                Slog.wtf(TAG, "Binding service " + this + " without owner");
             }
             final int state = bound ? memFactor : STATE_NOTHING;
             if (mBoundState != state) {
@@ -2949,8 +3065,8 @@
         }
 
         public void setExecuting(boolean executing, int memFactor, long now) {
-            if (mActive <= 0) {
-                throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
+            if (mOwner == null) {
+                Slog.wtf(TAG, "Executing service " + this + " without owner");
             }
             final int state = executing ? memFactor : STATE_NOTHING;
             if (mExecState != state) {
@@ -2974,6 +3090,12 @@
             }
             return time;
         }
+
+        public String toString() {
+            return "ServiceState{" + Integer.toHexString(System.identityHashCode(this))
+                    + " " + mName + " pkg=" + mPackage + " proc="
+                    + Integer.toHexString(System.identityHashCode(this)) + "}";
+        }
     }
 
     public static final class PackageState {
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index 0bf03b5..069ae23 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -122,7 +122,9 @@
         try {
             return super.onTransact(code, data, reply, flags);
         } catch (RuntimeException e) {
-            Slog.w("clipboard", "Exception: ", e);
+            if (!(e instanceof SecurityException)) {
+                Slog.wtf("clipboard", "Exception: ", e);
+            }
             throw e;
         }
         
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 45c614f..794d274 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -817,7 +817,7 @@
             // The input method manager only throws security exceptions, so let's
             // log all others.
             if (!(e instanceof SecurityException)) {
-                Slog.e(TAG, "Input Method Manager Crash", e);
+                Slog.wtf(TAG, "Input Method Manager Crash", e);
             }
             throw e;
         }
diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java
index 3a3dfd5..dd9ae4c 100644
--- a/services/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/java/com/android/server/accounts/AccountManagerService.java
@@ -60,6 +60,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcel;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -267,6 +268,21 @@
         }, UserHandle.ALL, userFilter, null, null);
     }
 
+    @Override
+    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+            throws RemoteException {
+        try {
+            return super.onTransact(code, data, reply, flags);
+        } catch (RuntimeException e) {
+            // The account manager only throws security exceptions, so let's
+            // log all others.
+            if (!(e instanceof SecurityException)) {
+                Slog.wtf(TAG, "Account Manager Crash", e);
+            }
+            throw e;
+        }
+    }
+
     public void systemReady() {
     }
 
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 8f4bf21..27ca7a0 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -130,9 +130,9 @@
             = new ArrayList<ServiceRecord>();
 
     /**
-     * List of services that are in the process of being stopped.
+     * List of services that are in the process of being destroyed.
      */
-    final ArrayList<ServiceRecord> mStoppingServices
+    final ArrayList<ServiceRecord> mDestroyingServices
             = new ArrayList<ServiceRecord>();
 
     static final class DelayingProcess extends ArrayList<ServiceRecord> {
@@ -788,7 +788,7 @@
                     }
                 }
 
-                serviceDoneExecutingLocked(r, mStoppingServices.contains(r));
+                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -834,9 +834,9 @@
                         + " at " + b + ": apps="
                         + (b != null ? b.apps.size() : 0));
 
-                boolean inStopping = mStoppingServices.contains(r);
+                boolean inDestroying = mDestroyingServices.contains(r);
                 if (b != null) {
-                    if (b.apps.size() > 0 && !inStopping) {
+                    if (b.apps.size() > 0 && !inDestroying) {
                         // Applications have already bound since the last
                         // unbind, so just rebind right here.
                         boolean inFg = false;
@@ -856,7 +856,7 @@
                     }
                 }
 
-                serviceDoneExecutingLocked(r, inStopping);
+                serviceDoneExecutingLocked(r, inDestroying, false);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -1419,14 +1419,10 @@
         }
     }
 
-    private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
-            boolean hasConn) {
-        //Slog.i(TAG, "Bring down service:");
-        //r.dump("  ");
-
+    private final boolean isServiceNeeded(ServiceRecord r, boolean knowConn, boolean hasConn) {
         // Are we still explicitly being asked to run?
         if (r.startRequested) {
-            return;
+            return true;
         }
 
         // Is someone still bound to us keepign us running?
@@ -1434,6 +1430,18 @@
             hasConn = r.hasAutoCreateConnections();
         }
         if (hasConn) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
+            boolean hasConn) {
+        //Slog.i(TAG, "Bring down service:");
+        //r.dump("  ");
+
+        if (isServiceNeeded(r, knowConn, hasConn)) {
             return;
         }
 
@@ -1484,7 +1492,7 @@
                     } catch (Exception e) {
                         Slog.w(TAG, "Exception when unbinding service "
                                 + r.shortName, e);
-                        serviceDoneExecutingLocked(r, true);
+                        serviceDoneExecutingLocked(r, true, true);
                     }
                 }
             }
@@ -1527,14 +1535,14 @@
             r.app.services.remove(r);
             if (r.app.thread != null) {
                 try {
-                    bumpServiceExecutingLocked(r, false, "stop");
-                    mStoppingServices.add(r);
+                    bumpServiceExecutingLocked(r, false, "destroy");
+                    mDestroyingServices.add(r);
                     mAm.updateOomAdjLocked(r.app);
                     r.app.thread.scheduleStopService(r);
                 } catch (Exception e) {
-                    Slog.w(TAG, "Exception when stopping service "
+                    Slog.w(TAG, "Exception when destroying service "
                             + r.shortName, e);
-                    serviceDoneExecutingLocked(r, true);
+                    serviceDoneExecutingLocked(r, true, true);
                 }
                 updateServiceForegroundLocked(r.app, false);
             } else {
@@ -1560,7 +1568,7 @@
             r.tracker.setStarted(false, memFactor, now);
             r.tracker.setBound(false, memFactor, now);
             if (r.executeNesting == 0) {
-                r.tracker.makeInactive();
+                r.tracker.clearCurrentOwner(r);
                 r.tracker = null;
             }
         }
@@ -1619,7 +1627,7 @@
                     s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
                 } catch (Exception e) {
                     Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
-                    serviceDoneExecutingLocked(s, true);
+                    serviceDoneExecutingLocked(s, true, true);
                 }
             }
 
@@ -1637,7 +1645,7 @@
     }
 
     void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {
-        boolean inStopping = mStoppingServices.contains(r);
+        boolean inDestroying = mDestroyingServices.contains(r);
         if (r != null) {
             if (type == 1) {
                 // This is a call from a service start...  take care of
@@ -1690,7 +1698,7 @@
                 }
             }
             final long origId = Binder.clearCallingIdentity();
-            serviceDoneExecutingLocked(r, inStopping);
+            serviceDoneExecutingLocked(r, inDestroying, inDestroying);
             Binder.restoreCallingIdentity(origId);
         } else {
             Slog.w(TAG, "Done executing unknown service from pid "
@@ -1698,10 +1706,11 @@
         }
     }
 
-    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {
+    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
+            boolean finishing) {
         if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
                 + ": nesting=" + r.executeNesting
-                + ", inStopping=" + inStopping + ", app=" + r.app);
+                + ", inDestroying=" + inDestroying + ", app=" + r.app);
         else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
         r.executeNesting--;
         if (r.executeNesting <= 0) {
@@ -1723,10 +1732,10 @@
                         }
                     }
                 }
-                if (inStopping) {
+                if (inDestroying) {
                     if (DEBUG_SERVICE) Slog.v(TAG,
-                            "doneExecuting remove stopping " + r);
-                    mStoppingServices.remove(r);
+                            "doneExecuting remove destroying " + r);
+                    mDestroyingServices.remove(r);
                     r.bindings.clear();
                 }
                 mAm.updateOomAdjLocked(r.app);
@@ -1735,8 +1744,8 @@
             if (r.tracker != null) {
                 r.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),
                         SystemClock.uptimeMillis());
-                if (inStopping) {
-                    r.tracker.makeInactive();
+                if (finishing) {
+                    r.tracker.clearCurrentOwner(r);
                     r.tracker = null;
                 }
             }
@@ -1931,12 +1940,9 @@
             sr.app = null;
             sr.isolatedProc = null;
             sr.executeNesting = 0;
-            if (sr.tracker != null) {
-                sr.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),
-                        SystemClock.uptimeMillis());
-            }
-            if (mStoppingServices.remove(sr)) {
-                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+            sr.forceClearTracker();
+            if (mDestroyingServices.remove(sr)) {
+                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr);
             }
 
             final int numClients = sr.bindings.size();
@@ -1984,13 +1990,14 @@
         }
 
         // Make sure we have no more records on the stopping list.
-        int i = mStoppingServices.size();
+        int i = mDestroyingServices.size();
         while (i > 0) {
             i--;
-            ServiceRecord sr = mStoppingServices.get(i);
+            ServiceRecord sr = mDestroyingServices.get(i);
             if (sr.app == app) {
-                mStoppingServices.remove(i);
-                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
+                sr.forceClearTracker();
+                mDestroyingServices.remove(i);
+                if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr);
             }
         }
 
@@ -2340,10 +2347,10 @@
             needSep = true;
         }
 
-        if (mStoppingServices.size() > 0) {
+        if (mDestroyingServices.size() > 0) {
             boolean printed = false;
-            for (int i=0; i<mStoppingServices.size(); i++) {
-                ServiceRecord r = mStoppingServices.get(i);
+            for (int i=0; i< mDestroyingServices.size(); i++) {
+                ServiceRecord r = mDestroyingServices.get(i);
                 if (!matcher.match(r, r.name)) {
                     continue;
                 }
@@ -2354,10 +2361,10 @@
                 if (!printed) {
                     if (needSep) pw.println();
                     needSep = true;
-                    pw.println("  Stopping services:");
+                    pw.println("  Destroying services:");
                     printed = true;
                 }
-                pw.print("  * Stopping "); pw.println(r);
+                pw.print("  * Destroy "); pw.println(r);
                 r.dump(pw, "    ");
             }
             needSep = true;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c1ac7d5..f2ff9ca 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2051,7 +2051,7 @@
             // The activity manager only throws security exceptions, so let's
             // log all others.
             if (!(e instanceof SecurityException)) {
-                Slog.e(TAG, "Activity Manager Crash", e);
+                Slog.wtf(TAG, "Activity Manager Crash", e);
             }
             throw e;
         }
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 2c49bb9..7dc006c 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -357,7 +357,7 @@
             boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
             boolean sepProcStates, int[] procStates, long now, String reqPackage) {
         ArrayList<ProcessStats.ProcessState> procs = mProcessStats.collectProcessesLocked(
-                screenStates, memStates, procStates, procStates, now, reqPackage);
+                screenStates, memStates, procStates, procStates, now, reqPackage, false);
         if (procs.size() > 0) {
             if (header != null) {
                 pw.println(header);
@@ -519,7 +519,7 @@
     static private void dumpHelp(PrintWriter pw) {
         pw.println("Process stats (procstats) dump options:");
         pw.println("    [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
-        pw.println("    [--details] [--full-details] [--current] [--hours]");
+        pw.println("    [--details] [--full-details] [--current] [--hours] [--active]");
         pw.println("    [--commit] [--reset] [--clear] [--write] [-h] [<package.name>]");
         pw.println("  --checkin: perform a checkin: print and delete old committed states.");
         pw.println("  --c: print only state in checkin format.");
@@ -528,10 +528,11 @@
         pw.println("  --csv-mem: norm, mod, low, crit.");
         pw.println("  --csv-proc: pers, top, fore, vis, precept, backup,");
         pw.println("    service, home, prev, cached");
-        pw.println("  --details: dump all execution details, not just summary.");
-        pw.println("  --full-details: dump only detail information, for all saved state.");
+        pw.println("  --details: dump per-package details, not just summary.");
+        pw.println("  --full-details: dump all timing and active state details.");
         pw.println("  --current: only dump current state.");
         pw.println("  --hours: aggregate over about N last hours.");
+        pw.println("  --active: only show currently active processes/services.");
         pw.println("  --commit: commit current stats to disk and reset to start new stats.");
         pw.println("  --reset: reset current stats, without committing.");
         pw.println("  --clear: clear all stats; does both --reset and deletes old stats.");
@@ -562,6 +563,7 @@
         boolean dumpFullDetails = false;
         boolean dumpAll = false;
         int aggregateHours = 0;
+        boolean activeOnly = false;
         String reqPackage = null;
         boolean csvSepScreenStats = false;
         int[] csvScreenStats = new int[] { ProcessStats.ADJ_SCREEN_OFF, ProcessStats.ADJ_SCREEN_ON};
@@ -645,6 +647,9 @@
                         dumpHelp(pw);
                         return;
                     }
+                } else if ("--active".equals(arg)) {
+                    activeOnly = true;
+                    currentOnly = true;
                 } else if ("--current".equals(arg)) {
                     currentOnly = true;
                 } else if ("--commit".equals(arg)) {
@@ -779,9 +784,9 @@
                 stats.dumpCheckinLocked(pw, reqPackage);
             } else {
                 if (dumpDetails || dumpFullDetails) {
-                    stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll);
+                    stats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly);
                 } else {
-                    stats.dumpSummaryLocked(pw, reqPackage, now);
+                    stats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
                 }
             }
             return;
@@ -826,9 +831,10 @@
                                 // Always dump summary here, dumping all details is just too
                                 // much crud.
                                 if (dumpFullDetails) {
-                                    mProcessStats.dumpLocked(pw, reqPackage, now, false, false);
+                                    mProcessStats.dumpLocked(pw, reqPackage, now, false, false,
+                                            activeOnly);
                                 } else {
-                                    processStats.dumpSummaryLocked(pw, reqPackage, now);
+                                    processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
                                 }
                             }
                             if (isCheckin) {
@@ -856,12 +862,13 @@
                         pw.println("CURRENT STATS:");
                     }
                     if (dumpDetails || dumpFullDetails) {
-                        mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll);
+                        mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll,
+                                activeOnly);
                         if (dumpAll) {
                             pw.print("  mFile="); pw.println(mFile.getBaseFile());
                         }
                     } else {
-                        mProcessStats.dumpSummaryLocked(pw, reqPackage, now);
+                        mProcessStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly);
                     }
                 }
             }
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index ac14da9..c47c1ac 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -328,11 +328,23 @@
         if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
             tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
                     serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name);
-            tracker.makeActive();
+            tracker.applyNewOwner(this);
         }
         return tracker;
     }
 
+    public void forceClearTracker() {
+        if (tracker != null) {
+            int memFactor = ams.mProcessStats.getMemFactorLocked();
+            long now = SystemClock.uptimeMillis();
+            tracker.setStarted(false, memFactor, now);
+            tracker.setBound(false, memFactor, now);
+            tracker.setExecuting(false, memFactor, now);
+            tracker.clearCurrentOwner(this);
+            tracker = null;
+        }
+    }
+
     public AppBindRecord retrieveAppBindingLocked(Intent intent,
             ProcessRecord app) {
         Intent.FilterComparison filter = new Intent.FilterComparison(intent);
diff --git a/services/java/com/android/server/content/ContentService.java b/services/java/com/android/server/content/ContentService.java
index 7c82821..885ec9f 100644
--- a/services/java/com/android/server/content/ContentService.java
+++ b/services/java/com/android/server/content/ContentService.java
@@ -141,7 +141,7 @@
             // The content service only throws security exceptions, so let's
             // log all others.
             if (!(e instanceof SecurityException)) {
-                Log.e(TAG, "Content Service Crash", e);
+                Slog.wtf(TAG, "Content Service Crash", e);
             }
             throw e;
         }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 6cf3223..f093f2b 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1501,7 +1501,7 @@
             return super.onTransact(code, data, reply, flags);
         } catch (RuntimeException e) {
             if (!(e instanceof SecurityException) && !(e instanceof IllegalArgumentException)) {
-                Slog.e(TAG, "Package Manager Crash", e);
+                Slog.wtf(TAG, "Package Manager Crash", e);
             }
             throw e;
         }
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 1d95c44..87cabc9 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -126,7 +126,7 @@
         } catch (RuntimeException e) {
             // Log all 'real' exceptions thrown to the caller
             if (!(e instanceof SecurityException)) {
-                Slog.e(WindowManagerService.TAG, "Window Session Crash", e);
+                Slog.wtf(WindowManagerService.TAG, "Window Session Crash", e);
             }
             throw e;
         }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index a888731..76ba0ce 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -813,7 +813,7 @@
             // The window manager only throws security exceptions, so let's
             // log all others.
             if (!(e instanceof SecurityException)) {
-                Log.wtf(TAG, "Window Manager Crash", e);
+                Slog.wtf(TAG, "Window Manager Crash", e);
             }
             throw e;
         }