Merge "Isolate calls to each remote DocumentsProvider." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index ff72c4a..2ed9c58 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29459,6 +29459,7 @@
     ctor public AccessibilityNodeProvider();
     method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo(int);
     method public java.util.List<android.view.accessibility.AccessibilityNodeInfo> findAccessibilityNodeInfosByText(java.lang.String, int);
+    method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
     method public boolean performAction(int, int, android.os.Bundle);
   }
 
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 2172a7b..e2bc80a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -923,42 +923,6 @@
     }
 
     /**
-     * Create a listening, L2CAP Bluetooth socket.
-     * <p>A remote device connecting to this socket will optionally be
-     * authenticated and communication on this socket will optionally be
-     * encrypted.
-     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
-     * connections from a listening {@link BluetoothServerSocket}.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * @param secure whether security and authentication are required
-     * @param fixedChannel whether we're looking for a PSM-based connection or a fixed channel
-     * @param channel L2CAP PSM or channel to use
-     * @return a listening L2CAP BluetoothServerSocket
-     * @throws IOException on error, for example Bluetooth not available, or
-     *                     insufficient permissions, or channel in use.
-     * @hide
-     */
-    public BluetoothServerSocket listenUsingL2CapOn(boolean secure, boolean fixedChannel,
-            int channel) throws IOException {
-        BluetoothServerSocket socket;
-
-        if (fixedChannel) {
-            channel |= BluetoothSocket.PORT_MASK_FIXED_CHAN;
-        }
-
-        socket = new BluetoothServerSocket(
-                BluetoothSocket.TYPE_L2CAP, secure, secure, channel);
-        int errno = socket.mSocket.bindListen();
-        if (errno != 0) {
-            //TODO(BT): Throw the same exception error code
-            // that the previous code was using.
-            //socket.mSocket.throwErrnoNative(errno);
-            throw new IOException("Error: " + errno);
-        }
-        return socket;
-    }
-
-    /**
      * Create a listening, secure RFCOMM Bluetooth socket.
      * <p>A remote device connecting to this socket will be authenticated and
      * communication on this socket will be encrypted.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 1efdc81..5eb642c 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1172,33 +1172,6 @@
         return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null);
     }
 
-
-    /**
-     * Construct a L2CAP socket ready to start an outgoing connection.
-     * Call #connect on the returned #BluetoothSocket to begin the connection.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     *
-     * @param secure    select whether security will be required
-     * @param fixedChannel    select if this will be a "fixed channel" L2CAP connection
-     *                        or a PSM-based connection
-     * @param channel    fixed channel or PSM to connect to
-     * @return a L2CAP BluetoothSocket
-     * @throws IOException on error, for example Bluetooth not available, or
-     *                     insufficient permissions.
-     * @hide
-     */
-    public BluetoothSocket createL2CapSocket(boolean secure, boolean fixedChannel, int channel)
-            throws IOException {
-
-        if (fixedChannel) {
-            channel |= BluetoothSocket.PORT_MASK_FIXED_CHAN;
-        }
-
-        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, secure, secure, this,
-                channel, null);
-    }
-
-
     /**
      * Check that a pin is valid and convert to byte array.
      *
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 191bf67..d10eaea 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -103,8 +103,6 @@
     /*package*/ static final int SEC_FLAG_ENCRYPT = 1;
     /*package*/ static final int SEC_FLAG_AUTH = 1 << 1;
 
-    /*package*/ static final int PORT_MASK_FIXED_CHAN = 1 << 16;
-
     private final int mType;  /* one of TYPE_RFCOMM etc */
     private BluetoothDevice mDevice;    /* remote device */
     private String mAddress;    /* remote address */
@@ -117,7 +115,7 @@
     private LocalSocket mSocket;
     private InputStream mSocketIS;
     private OutputStream mSocketOS;
-    private int mPort;  /* RFCOMM channel or L2CAP psm/channel */
+    private int mPort;  /* RFCOMM channel or L2CAP psm */
     private int mFd;
     private String mServiceName;
     private static int PROXY_CONNECTION_TIMEOUT = 5000;
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 798ad7b..f5ee367 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -369,10 +369,30 @@
             }
 
             mDeviceIdList = new ArrayList<String>();
+            CameraMetadataNative info = new CameraMetadataNative();
             for (int i = 0; i < numCameras; ++i) {
                 // Non-removable cameras use integers starting at 0 for their
                 // identifiers
-                mDeviceIdList.add(String.valueOf(i));
+                boolean isDeviceSupported = false;
+                try {
+                    mCameraService.getCameraCharacteristics(i, info);
+                    if (!info.isEmpty()) {
+                        isDeviceSupported = true;
+                    } else {
+                        throw new AssertionError("Expected to get non-empty characteristics");
+                    }
+                } catch(IllegalArgumentException  e) {
+                    // Got a BAD_VALUE from service, meaning that this
+                    // device is not supported.
+                } catch(CameraRuntimeException e) {
+                    throw e.asChecked();
+                } catch(RemoteException e) {
+                    // impossible
+                }
+
+                if (isDeviceSupported) {
+                    mDeviceIdList.add(String.valueOf(i));
+                }
             }
 
         }
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/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index e835a97..41d3700 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -423,9 +423,15 @@
                         }
                     } break;
                     case AccessibilityNodeInfo.FOCUS_INPUT: {
-                        // Input focus cannot go to virtual views.
                         View target = root.findFocus();
-                        if (target != null && isShown(target)) {
+                        if (target == null || !isShown(target)) {
+                            break;
+                        }
+                        AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
+                        if (provider != null) {
+                            focused = provider.findFocus(focusType);
+                        }
+                        if (focused == null) {
                             focused = target.createAccessibilityNodeInfo();
                         }
                     } break;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1e4b29f..4366fb7 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -478,7 +478,7 @@
                               | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                               ;
                 if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
-                    mLayout.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+                    mLayout.flags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                 }
                 mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 48f0f9e..06f00f7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5249,6 +5249,7 @@
         info.setAccessibilityFocused(isAccessibilityFocused());
         info.setSelected(isSelected());
         info.setLongClickable(isLongClickable());
+        info.setLiveRegion(getAccessibilityLiveRegion());
 
         // TODO: These make sense only if we are in an AdapterView but all
         // views can be selected. Maybe from accessibility perspective
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 76ebb6f..89c74f1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -82,7 +82,6 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.Locale;
 
 /**
  * The top of a view hierarchy, implementing the needed protocol between View
@@ -468,7 +467,7 @@
                 if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
 
                 if (!compatibilityInfo.supportsScreen()) {
-                    attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+                    attrs.flags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                     mLastInCompatMode = true;
                 }
 
@@ -750,7 +749,7 @@
             mClientWindowLayoutFlags = attrs.flags;
             // preserve compatible window flag if exists.
             int compatibleWindowFlag =
-                mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+                mWindowAttributes.flags & WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
             // transfer over system UI visibility values as they carry current state.
             attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility;
             attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
@@ -1147,10 +1146,10 @@
             mFullRedrawNeeded = true;
             mLayoutRequested = true;
             if (mLastInCompatMode) {
-                params.flags &= ~WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+                params.flags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                 mLastInCompatMode = false;
             } else {
-                params.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+                params.flags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
                 mLastInCompatMode = true;
             }
         }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c9c74e7..53f4d77 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -841,6 +841,15 @@
         // ----- HIDDEN FLAGS.
         // These start at the high bit and go down.
 
+        /**
+         * Flag for a window in local focus mode.
+         * Window in local focus mode can control focus independent of window manager using
+         * {@link Window#setLocalFocus(boolean, boolean)}.
+         * Usually window in this mode will not get touch/key events from window manager, but will
+         * get events only via local injection using {@link Window#injectInputEvent(InputEvent)}.
+         */
+        public static final int FLAG_LOCAL_FOCUS_MODE = 0x10000000;
+
         /** Window flag: Enable touches to slide out of a window into neighboring
          * windows in mid-gesture instead of being captured for the duration of
          * the gesture.
@@ -851,7 +860,7 @@
          *
          * {@hide}
          */
-        public static final int FLAG_SLIPPERY = 0x04000000;
+        public static final int FLAG_SLIPPERY = 0x20000000;
 
         /**
          * Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU}
@@ -864,29 +873,8 @@
          *
          * {@hide}
          */
-        public static final int FLAG_NEEDS_MENU_KEY = 0x08000000;
+        public static final int FLAG_NEEDS_MENU_KEY = 0x40000000;
 
-        /**
-         * Flag for a window in local focus mode.
-         * Window in local focus mode can control focus independent of window manager using
-         * {@link Window#setLocalFocus(boolean, boolean)}.
-         * Usually window in this mode will not get touch/key events from window manager, but will
-         * get events only via local injection using {@link Window#injectInputEvent(InputEvent)}.
-         */
-        public static final int FLAG_LOCAL_FOCUS_MODE = 0x10000000;
-
-        /** Window flag: special flag to limit the size of the window to be
-         * original size ([320x480] x density). Used to create window for applications
-         * running under compatibility mode.
-         *
-         * {@hide} */
-        public static final int FLAG_COMPATIBLE_WINDOW = 0x20000000;
-
-        /** Window flag: a special option intended for system dialogs.  When
-         * this flag is set, the window will demand focus unconditionally when
-         * it is created.
-         * {@hide} */
-        public static final int FLAG_SYSTEM_ERROR = 0x40000000;
 
         /**
          * Various behavioral options/flags.  Default is none.
@@ -1045,6 +1033,19 @@
          * {@hide} */
         public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 0x00000040;
 
+        /** Window flag: special flag to limit the size of the window to be
+         * original size ([320x480] x density). Used to create window for applications
+         * running under compatibility mode.
+         *
+         * {@hide} */
+        public static final int PRIVATE_FLAG_COMPATIBLE_WINDOW = 0x00000080;
+
+        /** Window flag: a special option intended for system dialogs.  When
+         * this flag is set, the window will demand focus unconditionally when
+         * it is created.
+         * {@hide} */
+        public static final int PRIVATE_FLAG_SYSTEM_ERROR = 0x00000100;
+
         /**
          * Control flags that are private to the platform.
          * @hide
@@ -1783,7 +1784,7 @@
                 sb.append(" rotAnim=");
                 sb.append(rotationAnimation);
             }
-            if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+            if ((flags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0) {
                 sb.append(" compatible=true");
             }
             if (systemUiVisibility != 0) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
index 688cbdf..718c32f 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
@@ -132,4 +132,19 @@
             int virtualViewId) {
         return null;
     }
+
+    /**
+     * Find the virtual view, i.e. a descendant of the host View, that has the
+     * specified focus type.
+     *
+     * @param focus The focus to find. One of
+     *            {@link AccessibilityNodeInfo#FOCUS_INPUT} or
+     *            {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
+     * @return The node info of the focused view or null.
+     * @see AccessibilityNodeInfo#FOCUS_INPUT
+     * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
+     */
+    public AccessibilityNodeInfo findFocus(int focus) {
+        return null;
+    }
 }
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/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 05fd613..cd853b6 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -100,8 +100,20 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        onCreate(savedInstanceState, makeMyIntent(),
-                getResources().getText(com.android.internal.R.string.whichApplication),
+        // Use a specialized prompt when we're handling the 'Home' app startActivity()
+        final int titleResource;
+        final Intent intent = makeMyIntent();
+        final Set<String> categories = intent.getCategories();
+        if (Intent.ACTION_MAIN.equals(intent.getAction())
+                && categories != null
+                && categories.size() == 1
+                && categories.contains(Intent.CATEGORY_HOME)) {
+            titleResource = com.android.internal.R.string.whichHomeApplication;
+        } else {
+            titleResource = com.android.internal.R.string.whichApplication;
+        }
+
+        onCreate(savedInstanceState, intent, getResources().getText(titleResource),
                 null, null, true);
     }
 
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
index 266ac98..7de0448 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
index 49b375f..5b916c9 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_grayedout_printer.png b/core/res/res/drawable-hdpi/ic_grayedout_printer.png
new file mode 100644
index 0000000..5e54970
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_grayedout_printer.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
index af5c463..eafc553 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
index 819c552..6583e99 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_grayedout_printer.png b/core/res/res/drawable-mdpi/ic_grayedout_printer.png
new file mode 100644
index 0000000..5e54970
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_grayedout_printer.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
index 0e1b948..028eed6 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
index 8d8aabc..61efd3a 100644
--- a/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-xhdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_grayedout_printer.png b/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
new file mode 100644
index 0000000..5e54970
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_grayedout_printer.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
index 81b0f87..668548b 100644
--- a/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-xxhdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index 053fc85..dc90bbf 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -18,7 +18,5 @@
 -->
 <resources>
     <integer name="kg_carousel_angle">75</integer>
-    <integer name="kg_security_flip_duration">100</integer>
-    <integer name="kg_security_fade_duration">100</integer>
     <integer name="kg_glowpad_rotation_offset">0</integer>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6c334e2..d57c232 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3182,6 +3182,8 @@
 
     <!-- Title of intent resolver dialog when selecting an application to run. -->
     <string name="whichApplication">Complete action using</string>
+    <!-- Title of intent resolver dialog when selecting a HOME application to run. -->
+    <string name="whichHomeApplication">Select a home app</string>
     <!-- Option to always use the selected application resolution in the future. See the "Complete action using" dialog title-->
     <string name="alwaysUse">Use by default for this action.</string>
     <!-- Text displayed when the user selects the check box for setting default application.  See the "Use by default for this action" check box. -->
@@ -4449,6 +4451,9 @@
     <!-- Print fail reason: unknown. [CHAR LIMIT=25] -->
     <string name="reason_unknown">unknown</string>
 
+    <!-- Print fail reason: the print service that has to process the print job is not available. [CHAR LIMIT=none] -->
+    <string name="reason_service_unavailable">Print service not enabled</string>
+
     <!-- Title for the notification that a print service was installed. [CHAR LIMIT=50] -->
     <string name="print_service_installed_title"><xliff:g id="name" example="Cloud Print">%s</xliff:g> service installed</string>
     <!-- Message for the notification that a print service was installed. [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c786888..d483fe0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -800,6 +800,7 @@
   <java-symbol type="string" name="web_user_agent_target_content" />
   <java-symbol type="string" name="webpage_unresponsive" />
   <java-symbol type="string" name="whichApplication" />
+  <java-symbol type="string" name="whichHomeApplication" />
   <java-symbol type="string" name="wifi_available_sign_in" />
   <java-symbol type="string" name="network_available_sign_in" />
   <java-symbol type="string" name="network_available_sign_in_detailed" />
@@ -927,6 +928,7 @@
   <java-symbol type="string" name="mediasize_japanese_kahu" />
   <java-symbol type="string" name="mediasize_japanese_kaku2" />
   <java-symbol type="string" name="mediasize_japanese_you4" />
+  <java-symbol type="string" name="reason_service_unavailable" />
   <java-symbol type="string" name="reason_unknown" />
   <java-symbol type="string" name="restr_pin_enter_admin_pin" />
   <java-symbol type="string" name="restr_pin_enter_pin" />
@@ -1040,6 +1042,7 @@
   <java-symbol type="drawable" name="ic_text_dot" />
   <java-symbol type="drawable" name="ic_print" />
   <java-symbol type="drawable" name="ic_print_error" />
+  <java-symbol type="drawable" name="ic_grayedout_printer" />
   <java-symbol type="drawable" name="indicator_code_lock_drag_direction_green_up" />
   <java-symbol type="drawable" name="indicator_code_lock_drag_direction_red_up" />
   <java-symbol type="drawable" name="indicator_code_lock_point_area_default_holo" />
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 3425c91..84ea4c90 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -2687,7 +2687,11 @@
      */
     private void queueMsgUnderWakeLock(Handler handler, int msg,
             int arg1, int arg2, Object obj, int delay) {
+        final long ident = Binder.clearCallingIdentity();
+        // Always acquire the wake lock as AudioService because it is released by the
+        // message handler.
         mAudioEventWakeLock.acquire();
+        Binder.restoreCallingIdentity(ident);
         sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
     }
 
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index def9aa7..0abd5f8 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2162,6 +2162,7 @@
     private static final int MEDIA_STARTED = 6;
     private static final int MEDIA_PAUSED = 7;
     private static final int MEDIA_STOPPED = 8;
+    private static final int MEDIA_SKIPPED = 9;
     private static final int MEDIA_TIMED_TEXT = 99;
     private static final int MEDIA_ERROR = 100;
     private static final int MEDIA_INFO = 200;
@@ -2227,6 +2228,9 @@
               if (mOnSeekCompleteListener != null) {
                   mOnSeekCompleteListener.onSeekComplete(mMediaPlayer);
               }
+              // fall through
+
+            case MEDIA_SKIPPED:
               if (mTimeProvider != null) {
                   mTimeProvider.onSeekComplete(mMediaPlayer);
               }
@@ -2812,6 +2816,7 @@
         private Handler mEventHandler;
         private boolean mRefresh = false;
         private boolean mPausing = false;
+        private boolean mSeeking = false;
         private static final int NOTIFY = 1;
         private static final int NOTIFY_TIME = 0;
         private static final int REFRESH_AND_NOTIFY_TIME = 1;
@@ -2849,7 +2854,15 @@
         }
 
         private void scheduleNotification(int type, long delayUs) {
+            // ignore time notifications until seek is handled
+            if (mSeeking &&
+                    (type == NOTIFY_TIME || type == REFRESH_AND_NOTIFY_TIME)) {
+                return;
+            }
+
             if (DEBUG) Log.v(TAG, "scheduleNotification " + type + " in " + delayUs);
+            mStopped = type == NOTIFY_STOP;
+            mSeeking = type == NOTIFY_SEEK;
             mEventHandler.removeMessages(NOTIFY);
             Message msg = mEventHandler.obtainMessage(NOTIFY, type, 0);
             mEventHandler.sendMessageDelayed(msg, (int) (delayUs / 1000));
@@ -2876,7 +2889,6 @@
             synchronized(this) {
                 if (DEBUG) Log.d(TAG, "onPaused: " + paused);
                 if (mStopped) { // handle as seek if we were stopped
-                    mStopped = false;
                     scheduleNotification(NOTIFY_SEEK, 0 /* delay */);
                 } else {
                     mPausing = paused;  // special handling if player disappeared
@@ -2890,7 +2902,6 @@
             synchronized(this) {
                 if (DEBUG) Log.d(TAG, "onStopped");
                 mPaused = true;
-                mStopped = true;
                 scheduleNotification(NOTIFY_STOP, 0 /* delay */);
             }
         }
@@ -2899,7 +2910,6 @@
         @Override
         public void onSeekComplete(MediaPlayer mp) {
             synchronized(this) {
-                mStopped = false;
                 scheduleNotification(NOTIFY_SEEK, 0 /* delay */);
             }
         }
@@ -2914,6 +2924,7 @@
         }
 
         private synchronized void notifySeek() {
+            mSeeking = false;
             try {
                 long timeUs = getCurrentTimeUs(true, false);
                 if (DEBUG) Log.d(TAG, "onSeekComplete at " + timeUs);
@@ -3025,6 +3036,11 @@
             }
             long nextTimeUs = nowUs;
 
+            if (mSeeking) {
+                // skip timed-event notifications until seek is complete
+                return;
+            }
+
             if (DEBUG) {
                 StringBuilder sb = new StringBuilder();
                 sb.append("notifyTimedEvent(").append(mLastTimeUs).append(" -> ")
@@ -3124,6 +3140,11 @@
                     if (monotonic && mLastTimeUs < mLastReportedTime) {
                         /* have to adjust time */
                         mTimeAdjustment = mLastReportedTime - mLastTimeUs;
+                        if (mTimeAdjustment > 1000000) {
+                            // schedule seeked event if time jumped significantly
+                            // TODO: do this properly by introducing an exception
+                            scheduleNotification(NOTIFY_SEEK, 0 /* delay */);
+                        }
                     } else {
                         mTimeAdjustment = 0;
                     }
diff --git a/packages/Keyguard/res/anim/keyguard_security_animate_in.xml b/packages/Keyguard/res/anim/keyguard_security_animate_in.xml
deleted file mode 100644
index 4ee30c3..0000000
--- a/packages/Keyguard/res/anim/keyguard_security_animate_in.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-
-    <scale
-        android:interpolator="@android:anim/decelerate_interpolator"
-        android:fromXScale="0.0"
-        android:toXScale="1.0"
-        android:fromYScale="1.0"
-        android:toYScale="1.0"
-        android:pivotX="50%"
-        android:pivotY="50%"
-        android:fillEnabled="true"
-        android:fillAfter="true"
-        android:duration="@integer/kg_security_flip_duration"
-        android:startOffset="@integer/kg_security_flip_duration" />
-
-</set>
-
diff --git a/packages/Keyguard/res/anim/keyguard_security_animate_out.xml b/packages/Keyguard/res/anim/keyguard_security_animate_out.xml
deleted file mode 100644
index 76d065c..0000000
--- a/packages/Keyguard/res/anim/keyguard_security_animate_out.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false">
-
-    <scale
-        android:interpolator="@android:anim/accelerate_interpolator"
-        android:fromXScale="1.0"
-        android:toXScale="0.0"
-        android:fromYScale="1.0"
-        android:toYScale="1.0"
-        android:pivotX="50%"
-        android:pivotY="50%"
-        android:fillEnabled="true"
-        android:fillAfter="true"
-        android:duration="@integer/kg_security_flip_duration" />
-
-</set>
-
diff --git a/packages/Keyguard/res/anim/keyguard_security_fade_in.xml b/packages/Keyguard/res/anim/keyguard_security_fade_in.xml
deleted file mode 100644
index c66c604..0000000
--- a/packages/Keyguard/res/anim/keyguard_security_fade_in.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@android:interpolator/decelerate_quad"
-    android:fromAlpha="0.0" android:toAlpha="1.0"
-    android:duration="@integer/kg_security_fade_duration" />
-
-
diff --git a/packages/Keyguard/res/anim/keyguard_security_fade_out.xml b/packages/Keyguard/res/anim/keyguard_security_fade_out.xml
deleted file mode 100644
index 6465b35..0000000
--- a/packages/Keyguard/res/anim/keyguard_security_fade_out.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<alpha xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@android:interpolator/accelerate_quad"
-    android:fromAlpha="1.0"
-    android:toAlpha="0.0"
-    android:duration="@integer/kg_security_fade_duration"
-/>
diff --git a/packages/Keyguard/res/values/integers.xml b/packages/Keyguard/res/values/integers.xml
index 053fc85..dc90bbf 100644
--- a/packages/Keyguard/res/values/integers.xml
+++ b/packages/Keyguard/res/values/integers.xml
@@ -18,7 +18,5 @@
 -->
 <resources>
     <integer name="kg_carousel_angle">75</integer>
-    <integer name="kg_security_flip_duration">100</integer>
-    <integer name="kg_security_fade_duration">100</integer>
     <integer name="kg_glowpad_rotation_offset">0</integer>
 </resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 4da6171..bc8c866 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -54,10 +54,10 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.animation.AnimationUtils;
 import android.widget.RemoteViews.OnClickHandler;
 
 import java.io.File;
+import java.lang.ref.WeakReference;
 import java.util.List;
 
 public class KeyguardHostView extends KeyguardViewBase {
@@ -125,6 +125,8 @@
 
     private final Rect mInsets = new Rect();
 
+    private MyOnClickHandler mOnClickHandler = new MyOnClickHandler(this);
+
     /*package*/ interface UserSwitcherCallback {
         void hideSecurityView(int duration);
         void showSecurityView();
@@ -813,24 +815,39 @@
         }
     }
 
-    private OnClickHandler mOnClickHandler = new OnClickHandler() {
+    private static class MyOnClickHandler extends OnClickHandler {
+
+        // weak reference to the hostView to avoid keeping a live reference
+        // due to Binder GC linkages to AppWidgetHost. By the same token,
+        // this click handler should not keep references to any large
+        // objects.
+        WeakReference<KeyguardHostView> mThis;
+
+        MyOnClickHandler(KeyguardHostView hostView) {
+            mThis = new WeakReference<KeyguardHostView>(hostView);
+        }
+
         @Override
         public boolean onClickHandler(final View view,
                 final android.app.PendingIntent pendingIntent,
                 final Intent fillInIntent) {
+            KeyguardHostView hostView = mThis.get();
+            if (hostView == null) {
+                return false;
+            }
             if (pendingIntent.isActivity()) {
-                setOnDismissAction(new OnDismissAction() {
+                hostView.setOnDismissAction(new OnDismissAction() {
                     public boolean onDismiss() {
                         try {
-                              // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
-                              Context context = view.getContext();
-                              ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
-                                      0, 0,
-                                      view.getMeasuredWidth(), view.getMeasuredHeight());
-                              context.startIntentSender(
-                                      pendingIntent.getIntentSender(), fillInIntent,
-                                      Intent.FLAG_ACTIVITY_NEW_TASK,
-                                      Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
+                            // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
+                            Context context = view.getContext();
+                            ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(view,
+                                    0, 0,
+                                    view.getMeasuredWidth(), view.getMeasuredHeight());
+                            context.startIntentSender(
+                                    pendingIntent.getIntentSender(), fillInIntent,
+                                    Intent.FLAG_ACTIVITY_NEW_TASK,
+                                    Intent.FLAG_ACTIVITY_NEW_TASK, 0, opts.toBundle());
                         } catch (IntentSender.SendIntentException e) {
                             android.util.Log.e(TAG, "Cannot send pending intent: ", e);
                         } catch (Exception e) {
@@ -841,10 +858,10 @@
                     }
                 });
 
-                if (mViewStateManager.isChallengeShowing()) {
-                    mViewStateManager.showBouncer(true);
+                if (hostView.mViewStateManager.isChallengeShowing()) {
+                    hostView.mViewStateManager.showBouncer(true);
                 } else {
-                    mCallback.dismiss(false);
+                    hostView.mCallback.dismiss(false);
                 }
                 return true;
             } else {
@@ -971,10 +988,6 @@
         // Find and show this child.
         final int childCount = mSecurityViewContainer.getChildCount();
 
-        mSecurityViewContainer.setInAnimation(
-                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_in));
-        mSecurityViewContainer.setOutAnimation(
-                AnimationUtils.loadAnimation(mContext, R.anim.keyguard_security_fade_out));
         final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
         for (int i = 0; i < childCount; i++) {
             if (mSecurityViewContainer.getChildAt(i).getId() == securityViewIdForMode) {
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index f4e1853..e86e9aa 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -14,10 +14,10 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
     android:layout_width="fill_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="fill_parent">
 
     <fragment
         android:name="com.android.printspooler.SelectPrinterFragment"
@@ -26,4 +26,39 @@
         android:layout_height="wrap_content">
     </fragment>
 
-</FrameLayout>
\ No newline at end of file
+    <FrameLayout
+        android:id="@+id/empty_print_state"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:visibility="gone">
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:gravity="center"
+            android:orientation="vertical">
+   
+            <ImageView
+                android:id="@+id/icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="12dip"
+                android:src="@*android:drawable/ic_grayedout_printer"
+                android:contentDescription="@string/print_no_printers_found">
+            </ImageView>
+
+            <TextView
+                android:id="@+id/message"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textColor="?android:attr/textColorSecondary"
+                android:text="@string/print_no_printers_found">
+            </TextView>
+
+        </LinearLayout>
+
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 5ee8d8c..41775a1 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -75,13 +75,16 @@
     <!-- Title for the select printer activity. [CHAR LIMIT=30] -->
     <string name="all_printers_label">All printers</string>
 
+    <!-- Title of the button to install a print service. [CHAR LIMIT=25] -->
+    <string name="add_print_service_label">Add service</string>
+
     <!-- Add printer dialog  -->
 
     <!-- Title for the alert dialog for selecting a print service. [CHAR LIMIT=50] -->
     <string name="choose_print_service">Choose print service</string>
 
-    <!-- Title for the button to search the play store for print services. [CHAR LIMIT=50] -->
-    <string name="search_play_store">Search in play store</string>
+    <!-- Title for the prompt shown as a placeholder if no printers are found while searching. [CHAR LIMIT=50] -->
+    <string name="print_no_printers_found">No printers found</string>
 
     <!-- Notifications -->
 
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
index c397c40..c888e2c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
@@ -92,6 +92,8 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         setListAdapter(new DestinationAdapter());
+        View emptyView = getActivity().findViewById(R.id.empty_print_state);
+        getListView().setEmptyView(emptyView);
     }
 
     @Override
@@ -252,7 +254,7 @@
             Uri marketUri = Uri.parse(DEFAULT_MARKET_QUERY_STRING);
             final Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
             if (getActivity().getPackageManager().resolveActivity(marketIntent, 0) != null) {
-                builder.setPositiveButton(R.string.search_play_store,
+                builder.setPositiveButton(R.string.add_print_service_label,
                     new DialogInterface.OnClickListener() {
                         public void onClick(DialogInterface dialog, int whichButton) {
                             try {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index a5fd1d7..7f93c28 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1621,7 +1621,7 @@
                 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
 
             if (!compatInfo.supportsScreen()) {
-                win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
+                win.addFlags(WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW);
             }
 
             win.setDefaultIcon(icon);
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 fa1769f..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;
                 }
             }
@@ -1839,7 +1848,7 @@
                 }
             }
         } else {
-            ServiceMap smap = mServiceMap.valueAt(userId);
+            ServiceMap smap = mServiceMap.get(userId);
             if (smap != null) {
                 ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
                 didSomething = collectForceStopServicesLocked(name, userId, evenPersistent,
@@ -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 dc915c6..f2ff9ca 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -235,7 +235,7 @@
     static final boolean DEBUG_USER_LEAVING = localLOGV || false;
     static final boolean DEBUG_VISBILITY = localLOGV || false;
     static final boolean DEBUG_PSS = localLOGV || false;
-    static final boolean DEBUG_LOCKSCREEN = localLOGV || true;
+    static final boolean DEBUG_LOCKSCREEN = localLOGV || false;
     static final boolean VALIDATE_TOKENS = true;
     static final boolean SHOW_ACTIVITY_START_TIME = true;
 
@@ -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/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4d66946..28c87d1 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -978,7 +978,7 @@
      */
     final boolean ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
             String onlyThisProcess, int configChanges, boolean forceHomeShown) {
-        if (DEBUG_VISBILITY) Slog.v(
+        if (true || DEBUG_VISBILITY) Slog.v(
                 TAG, "ensureActivitiesVisible behind " + top
                 + " configChanges=0x" + Integer.toHexString(configChanges));
 
@@ -1034,7 +1034,7 @@
                                 r.startFreezingScreenLocked(r.app, configChanges);
                             }
                             if (!r.visible) {
-                                if (DEBUG_VISBILITY) Slog.v(
+                                if (true || DEBUG_VISBILITY) Slog.v(
                                         TAG, "Starting and making visible: " + r);
                                 mWindowManager.setAppVisibility(r.appToken, true);
                             }
@@ -1056,7 +1056,7 @@
                         if (r.state != ActivityState.RESUMED && r != starting) {
                             // If this activity is paused, tell it
                             // to now show its window.
-                            if (DEBUG_VISBILITY) Slog.v(
+                            if (true || DEBUG_VISBILITY) Slog.v(
                                     TAG, "Making visible and scheduling visibility: " + r);
                             try {
                                 if (mTranslucentActivityWaiting != null) {
@@ -1110,7 +1110,7 @@
                     // Now for any activities that aren't visible to the user, make
                     // sure they no longer are keeping the screen frozen.
                     if (r.visible) {
-                        if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
+                        if (true || DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
                         r.visible = false;
                         try {
                             mWindowManager.setAppVisibility(r.appToken, false);
@@ -2367,7 +2367,7 @@
 
         if (mResumedActivity == r) {
             boolean endTask = index <= 0;
-            if (DEBUG_TRANSITION) Slog.v(TAG,
+            if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
                     "Prepare close transition: finishing " + r);
             mWindowManager.prepareAppTransition(endTask
                     ? AppTransition.TRANSIT_TASK_CLOSE
@@ -3438,23 +3438,22 @@
         // Determine if the top task is exiting and should return to home. Do this before it gets
         // removed in removeHistoryRecordsForAppsLocked.
         boolean launchHomeNext = false;
-        int top = mTaskHistory.size() - 1;
-        while (top >= 0) {
-            final TaskRecord topTask = mTaskHistory.get(top);
-            if (topTask.mActivities.isEmpty()) {
-                // Not possible, but just in case.
-                --top;
+        TaskRecord topTask = mTaskHistory.get(mTaskHistory.size() - 1);
+        ArrayList<ActivityRecord> activities = topTask.mActivities;
+        int activityNdx;
+        for (activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+            ActivityRecord r = activities.get(activityNdx);
+            if (r.finishing) {
                 continue;
             }
-            ActivityRecord r = topTask.topRunningActivityLocked(null);
-            if (r != null) {
-                // r will be launched next.
+            if (r.app != app) {
+                // This is the dying activity.
                 break;
             }
-            // There is an activity in topTask that is finishing. If topTask belongs to the app
-            // return to home depending on the task flag.
+        }
+        if (activityNdx < 0) {
+            // All activities in task belong to app. Set launchHomeNext to task's value.
             launchHomeNext = topTask.mOnTopOfHome;
-            break;
         }
 
         removeHistoryRecordsForAppLocked(app);
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index f718706..2b69a4e 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -884,6 +884,7 @@
             throws RemoteException {
 
         r.startFreezingScreenLocked(app, 0);
+        if (true) Slog.d(TAG, "realStartActivity: setting app visibility true");
         mWindowManager.setAppVisibility(r.appToken, true);
 
         // schedule launch ticks to collect information about slow apps.
@@ -1932,7 +1933,7 @@
         for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
             // Only update launchHomeTaskNext for the focused stack.
-            launchHomeTaskNext |= (stack == focusedStack && stack.handleAppDiedLocked(app));
+            launchHomeTaskNext |= (stack.handleAppDiedLocked(app) && stack == focusedStack);
         }
 
         if (!restarting) {
@@ -2299,7 +2300,7 @@
         final boolean nowVisible = allResumedActivitiesVisible();
         for (int i=0; i<N; i++) {
             ActivityRecord s = mStoppingActivities.get(i);
-            if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
+            if (true || localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
                     + nowVisible + " waitingVisible=" + s.waitingVisible
                     + " finishing=" + s.finishing);
             if (s.waitingVisible && nowVisible) {
diff --git a/services/java/com/android/server/am/AppErrorDialog.java b/services/java/com/android/server/am/AppErrorDialog.java
index bfc86b0..fffa75e 100644
--- a/services/java/com/android/server/am/AppErrorDialog.java
+++ b/services/java/com/android/server/am/AppErrorDialog.java
@@ -16,7 +16,7 @@
 
 package com.android.server.am;
 
-import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 
 import android.content.Context;
 import android.content.DialogInterface;
@@ -72,7 +72,7 @@
         }
 
         setTitle(res.getText(com.android.internal.R.string.aerr_title));
-        getWindow().addFlags(FLAG_SYSTEM_ERROR);
+        getWindow().addFlags(PRIVATE_FLAG_SYSTEM_ERROR);
         WindowManager.LayoutParams attrs = getWindow().getAttributes();
         attrs.setTitle("Application Error: " + app.info.processName);
         attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index d0a0441..4de272d 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -16,7 +16,7 @@
 
 package com.android.server.am;
 
-import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 
 import android.content.ActivityNotFoundException;
 import android.content.Context;
@@ -94,7 +94,7 @@
         if (aboveSystem) {
             getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
         }
-        getWindow().addFlags(FLAG_SYSTEM_ERROR);
+        getWindow().addFlags(PRIVATE_FLAG_SYSTEM_ERROR);
         WindowManager.LayoutParams attrs = getWindow().getAttributes();
         attrs.setTitle("Application Not Responding: " + app.info.processName);
         attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 2c49bb9..7dc006c4 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/am/StrictModeViolationDialog.java b/services/java/com/android/server/am/StrictModeViolationDialog.java
index b6d0daa..5fee0d3 100644
--- a/services/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/java/com/android/server/am/StrictModeViolationDialog.java
@@ -16,14 +16,13 @@
 
 package com.android.server.am;
 
-import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Slog;
 
 final class StrictModeViolationDialog extends BaseErrorDialog {
     private final static String TAG = "StrictModeViolationDialog";
@@ -75,7 +74,7 @@
         }
 
         setTitle(res.getText(com.android.internal.R.string.aerr_title));
-        getWindow().addFlags(FLAG_SYSTEM_ERROR);
+        getWindow().addFlags(PRIVATE_FLAG_SYSTEM_ERROR);
         getWindow().setTitle("Strict Mode Violation: " + app.info.processName);
 
         // After the timeout, pretend the user clicked the quit button
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/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index fe09a33..2ccd21c 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -453,7 +453,8 @@
                     mDisplayPowerControllerCallbacks, mHandler);
 
             mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
-                    createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"));
+                    createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
+                    mHandler);
             mSettingsObserver = new SettingsObserver(mHandler);
             mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
 
diff --git a/services/java/com/android/server/power/WirelessChargerDetector.java b/services/java/com/android/server/power/WirelessChargerDetector.java
index 35920f7..38f5d77 100644
--- a/services/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/java/com/android/server/power/WirelessChargerDetector.java
@@ -21,8 +21,11 @@
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.os.BatteryManager;
+import android.os.Handler;
+import android.os.Message;
 import android.os.SystemClock;
 import android.util.Slog;
+import android.util.TimeUtils;
 
 import java.io.PrintWriter;
 
@@ -70,12 +73,12 @@
     private static final String TAG = "WirelessChargerDetector";
     private static final boolean DEBUG = false;
 
-    // Number of nanoseconds per millisecond.
-    private static final long NANOS_PER_MS = 1000000;
-
     // The minimum amount of time to spend watching the sensor before making
     // a determination of whether movement occurred.
-    private static final long SETTLE_TIME_NANOS = 500 * NANOS_PER_MS;
+    private static final long SETTLE_TIME_MILLIS = 800;
+
+    // The sensor sampling interval.
+    private static final int SAMPLING_INTERVAL_MILLIS = 50;
 
     // The minimum number of samples that must be collected.
     private static final int MIN_SAMPLES = 3;
@@ -97,6 +100,7 @@
 
     private final SensorManager mSensorManager;
     private final SuspendBlocker mSuspendBlocker;
+    private final Handler mHandler;
 
     // The gravity sensor, or null if none.
     private Sensor mGravitySensor;
@@ -116,6 +120,9 @@
     // The suspend blocker is held while this is the case.
     private boolean mDetectionInProgress;
 
+    // The time when detection was last performed.
+    private long mDetectionStartTime;
+
     // True if the rest position should be updated if at rest.
     // Otherwise, the current rest position is simply checked and cleared if movement
     // is detected but no new rest position is stored.
@@ -127,18 +134,17 @@
     // The number of samples collected that showed evidence of not being at rest.
     private int mMovingSamples;
 
-    // The time and value of the first sample that was collected.
-    private long mFirstSampleTime;
+    // The value of the first sample that was collected.
     private float mFirstSampleX, mFirstSampleY, mFirstSampleZ;
 
-    // The time and value of the last sample that was collected (for debugging only).
-    private long mLastSampleTime;
+    // The value of the last sample that was collected.
     private float mLastSampleX, mLastSampleY, mLastSampleZ;
 
     public WirelessChargerDetector(SensorManager sensorManager,
-            SuspendBlocker suspendBlocker) {
+            SuspendBlocker suspendBlocker, Handler handler) {
         mSensorManager = sensorManager;
         mSuspendBlocker = suspendBlocker;
+        mHandler = handler;
 
         mGravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
     }
@@ -152,13 +158,13 @@
             pw.println("  mAtRest=" + mAtRest);
             pw.println("  mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ);
             pw.println("  mDetectionInProgress=" + mDetectionInProgress);
+            pw.println("  mDetectionStartTime=" + (mDetectionStartTime == 0 ? "0 (never)"
+                    : TimeUtils.formatUptime(mDetectionStartTime)));
             pw.println("  mMustUpdateRestPosition=" + mMustUpdateRestPosition);
             pw.println("  mTotalSamples=" + mTotalSamples);
             pw.println("  mMovingSamples=" + mMovingSamples);
-            pw.println("  mFirstSampleTime=" + mFirstSampleTime);
             pw.println("  mFirstSampleX=" + mFirstSampleX
                     + ", mFirstSampleY=" + mFirstSampleY + ", mFirstSampleZ=" + mFirstSampleZ);
-            pw.println("  mLastSampleTime=" + mLastSampleTime);
             pw.println("  mLastSampleX=" + mLastSampleX
                     + ", mLastSampleY=" + mLastSampleY + ", mLastSampleZ=" + mLastSampleZ);
         }
@@ -217,22 +223,56 @@
     private void startDetectionLocked() {
         if (!mDetectionInProgress && mGravitySensor != null) {
             if (mSensorManager.registerListener(mListener, mGravitySensor,
-                    SensorManager.SENSOR_DELAY_UI)) {
+                    SAMPLING_INTERVAL_MILLIS * 1000)) {
                 mSuspendBlocker.acquire();
                 mDetectionInProgress = true;
+                mDetectionStartTime = SystemClock.uptimeMillis();
                 mTotalSamples = 0;
                 mMovingSamples = 0;
+
+                Message msg = Message.obtain(mHandler, mSensorTimeout);
+                msg.setAsynchronous(true);
+                mHandler.sendMessageDelayed(msg, SETTLE_TIME_MILLIS);
             }
         }
     }
 
-    private void processSample(long timeNanos, float x, float y, float z) {
-        synchronized (mLock) {
-            if (!mDetectionInProgress) {
-                return;
+    private void finishDetectionLocked() {
+        if (mDetectionInProgress) {
+            mSensorManager.unregisterListener(mListener);
+            mHandler.removeCallbacks(mSensorTimeout);
+
+            if (mMustUpdateRestPosition) {
+                clearAtRestLocked();
+                if (mTotalSamples < MIN_SAMPLES) {
+                    Slog.w(TAG, "Wireless charger detector is broken.  Only received "
+                            + mTotalSamples + " samples from the gravity sensor but we "
+                            + "need at least " + MIN_SAMPLES + " and we expect to see "
+                            + "about " + SETTLE_TIME_MILLIS / SAMPLING_INTERVAL_MILLIS
+                            + " on average.");
+                } else if (mMovingSamples == 0) {
+                    mAtRest = true;
+                    mRestX = mLastSampleX;
+                    mRestY = mLastSampleY;
+                    mRestZ = mLastSampleZ;
+                }
+                mMustUpdateRestPosition = false;
             }
 
-            mLastSampleTime = timeNanos;
+            if (DEBUG) {
+                Slog.d(TAG, "New state: mAtRest=" + mAtRest
+                        + ", mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
+                        + ", mTotalSamples=" + mTotalSamples
+                        + ", mMovingSamples=" + mMovingSamples);
+            }
+
+            mDetectionInProgress = false;
+            mSuspendBlocker.release();
+        }
+    }
+
+    private void processSampleLocked(float x, float y, float z) {
+        if (mDetectionInProgress) {
             mLastSampleX = x;
             mLastSampleY = y;
             mLastSampleZ = z;
@@ -240,7 +280,6 @@
             mTotalSamples += 1;
             if (mTotalSamples == 1) {
                 // Save information about the first sample collected.
-                mFirstSampleTime = timeNanos;
                 mFirstSampleX = x;
                 mFirstSampleY = y;
                 mFirstSampleZ = z;
@@ -260,32 +299,6 @@
                 }
                 clearAtRestLocked();
             }
-
-            // Save the result when done.
-            if (timeNanos - mFirstSampleTime >= SETTLE_TIME_NANOS
-                    && mTotalSamples >= MIN_SAMPLES) {
-                mSensorManager.unregisterListener(mListener);
-                if (mMustUpdateRestPosition) {
-                    if (mMovingSamples == 0) {
-                        mAtRest = true;
-                        mRestX = x;
-                        mRestY = y;
-                        mRestZ = z;
-                    } else {
-                        clearAtRestLocked();
-                    }
-                    mMustUpdateRestPosition = false;
-                }
-                mDetectionInProgress = false;
-                mSuspendBlocker.release();
-
-                if (DEBUG) {
-                    Slog.d(TAG, "New state: mAtRest=" + mAtRest
-                            + ", mRestX=" + mRestX + ", mRestY=" + mRestY + ", mRestZ=" + mRestZ
-                            + ", mTotalSamples=" + mTotalSamples
-                            + ", mMovingSamples=" + mMovingSamples);
-                }
-            }
         }
     }
 
@@ -323,14 +336,22 @@
     private final SensorEventListener mListener = new SensorEventListener() {
         @Override
         public void onSensorChanged(SensorEvent event) {
-            // We use SystemClock.elapsedRealtimeNanos() instead of event.timestamp because
-            // on some devices the sensor HAL may produce timestamps that are not monotonic.
-            processSample(SystemClock.elapsedRealtimeNanos(),
-                    event.values[0], event.values[1], event.values[2]);
+            synchronized (mLock) {
+                processSampleLocked(event.values[0], event.values[1], event.values[2]);
+            }
         }
 
         @Override
         public void onAccuracyChanged(Sensor sensor, int accuracy) {
         }
     };
+
+    private final Runnable mSensorTimeout = new Runnable() {
+        @Override
+        public void run() {
+            synchronized (mLock) {
+                finishDetectionLocked();
+            }
+        }
+    };
 }
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index bc70fe3..3b0ee24 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -134,6 +134,11 @@
         }
         if (service != null) {
             service.onPrintJobQueued(printJob);
+        } else {
+            // The service for the job is no longer enabled, so just
+            // fail the job with the appropriate message.
+            mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
+                    mContext.getString(R.string.reason_service_unavailable));
         }
     }
 
@@ -779,7 +784,7 @@
             for (int i = 0; i < printJobCount; i++) {
                 PrintJobInfo printJob = printJobs.get(i);
                 mSpooler.setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
-                        mContext.getString(R.string.reason_unknown));
+                        mContext.getString(R.string.reason_service_unavailable));
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
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 80c50cc..76ba0ce 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -255,6 +255,9 @@
     /** Amount of time (in milliseconds) to delay before declaring a window freeze timeout. */
     static final int WINDOW_FREEZE_TIMEOUT_DURATION = 2000;
 
+    /** Amount of time (in milliseconds) to delay before declaring a starting window leaked. */
+    static final int STARTING_WINDOW_TIMEOUT_DURATION = 10000;
+
     /**
      * If true, the window manager will do its own custom freezing and general
      * management of the screen during rotation.
@@ -810,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;
         }
@@ -2256,6 +2259,8 @@
                 token.appWindowToken.startingWindow = win;
                 if (DEBUG_STARTING_WINDOW) Slog.v (TAG, "addWindow: " + token.appWindowToken
                         + " startingWindow=" + win);
+                Message m = mH.obtainMessage(H.REMOVE_STARTING_TIMEOUT, token.appWindowToken);
+                mH.sendMessageDelayed(m, STARTING_WINDOW_TIMEOUT_DURATION);
             }
 
             boolean imMayMove = true;
@@ -2356,6 +2361,10 @@
     }
 
     public void removeWindowLocked(Session session, WindowState win) {
+        if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
+            if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Starting window removed " + win);
+            removeStartingWindowTimeout(win.mAppToken);
+        }
 
         if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
             TAG, "Remove " + win + " client="
@@ -2498,6 +2507,7 @@
         if (atoken != null) {
             if (atoken.startingWindow == win) {
                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Nulling startingWindow " + win);
+                removeStartingWindowTimeout(atoken);
                 atoken.startingWindow = null;
             } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
                 // If this is the last window and we had requested a starting
@@ -2507,12 +2517,7 @@
             } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
                 // If this is the last window except for a starting transition
                 // window, we need to get rid of the starting transition.
-                if (DEBUG_STARTING_WINDOW) {
-                    Slog.v(TAG, "Schedule remove starting " + token
-                            + ": no more real windows");
-                }
-                Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
-                mH.sendMessage(m);
+                scheduleRemoveStartingWindow(atoken);
             }
         }
 
@@ -2788,7 +2793,7 @@
             if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
                     + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
 
-            win.mEnforceSizeCompat = (win.mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
+            win.mEnforceSizeCompat = (win.mAttrs.flags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
 
             if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
                 winAnimator.mAlpha = attrs.alpha;
@@ -3964,6 +3969,7 @@
                         if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE || DEBUG_STARTING_WINDOW) {
                             Slog.v(TAG, "Removing starting window: " + startingWindow);
                         }
+                        removeStartingWindowTimeout(ttoken);
                         startingWindow.getWindowList().remove(startingWindow);
                         mWindowsChanged = true;
                         if (DEBUG_ADD_REMOVE) Slog.v(TAG,
@@ -4527,14 +4533,29 @@
         }
         Binder.restoreCallingIdentity(origId);
 
-        if (startingToken != null) {
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
-                    + startingToken + ": app token removed");
-            Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
-            mH.sendMessage(m);
+        // Will only remove if startingToken non null.
+        scheduleRemoveStartingWindow(startingToken);
+    }
+
+    void removeStartingWindowTimeout(AppWindowToken wtoken) {
+        if (wtoken != null) {
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
+                    ": Remove starting window timeout " + wtoken + (wtoken != null ?
+                    " startingWindow=" + wtoken.startingWindow : ""));
+            mH.removeMessages(H.REMOVE_STARTING_TIMEOUT, wtoken);
         }
     }
 
+    void scheduleRemoveStartingWindow(AppWindowToken wtoken) {
+        if (wtoken != null && wtoken.startingWindow != null) {
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, Debug.getCallers(1) +
+                    ": Schedule remove starting " + wtoken + (wtoken != null ?
+                    " startingWindow=" + wtoken.startingWindow : ""));
+            removeStartingWindowTimeout(wtoken);
+            Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken);
+            mH.sendMessage(m);
+        }
+    }
     private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
         final int NW = token.windows.size();
         if (NW > 0) {
@@ -7053,6 +7074,8 @@
         public static final int TAP_OUTSIDE_STACK = 31;
         public static final int NOTIFY_ACTIVITY_DRAWN = 32;
 
+        public static final int REMOVE_STARTING_TIMEOUT = 33;
+
         @Override
         public void handleMessage(Message msg) {
             if (DEBUG_WINDOW_TRACE) {
@@ -7151,6 +7174,7 @@
                                             "Aborted starting " + wtoken
                                             + ": removed=" + wtoken.removed
                                             + " startingData=" + wtoken.startingData);
+                                    removeStartingWindowTimeout(wtoken);
                                     wtoken.startingWindow = null;
                                     wtoken.startingData = null;
                                     abort = true;
@@ -7175,6 +7199,11 @@
                     }
                 } break;
 
+                case REMOVE_STARTING_TIMEOUT: {
+                    final AppWindowToken wtoken = (AppWindowToken)msg.obj;
+                    Slog.e(TAG, "Starting window " + wtoken + " timed out");
+                    // Fall through.
+                }
                 case REMOVE_STARTING: {
                     final AppWindowToken wtoken = (AppWindowToken)msg.obj;
                     IBinder token = null;
@@ -9676,6 +9705,7 @@
                     winAnimator.mSurfaceShown = false;
                     winAnimator.mSurfaceControl = null;
                     winAnimator.mWin.mHasSurface = false;
+                    scheduleRemoveStartingWindow(winAnimator.mWin.mAppToken);
                 }
 
                 try {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 64b5a09..d56e225 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -20,7 +20,7 @@
 import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
 
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -332,7 +332,7 @@
         mContext = mService.mContext;
         DeathRecipient deathRecipient = new DeathRecipient();
         mSeq = seq;
-        mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
+        mEnforceSizeCompat = (mAttrs.flags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
         if (WindowManagerService.localLOGV) Slog.v(
             TAG, "Window " + this + " client=" + c.asBinder()
             + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);