Merge "Only keep user switcher bitmaps if needed" into lmp-mr1-dev
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index f361695b..4b0cef6 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -20,8 +20,11 @@
 import android.util.Slog;
 
 import com.android.internal.telephony.TelephonyProperties;
+
 import dalvik.system.VMRuntime;
 
+import java.util.Objects;
+
 /**
  * Information about the current build, extracted from system properties.
  */
@@ -640,6 +643,32 @@
         }
     }
 
+    /**
+     * Check that device fingerprint is defined and that it matches across
+     * various partitions.
+     *
+     * @hide
+     */
+    public static boolean isFingerprintConsistent() {
+        final String system = SystemProperties.get("ro.build.fingerprint");
+        final String vendor = SystemProperties.get("ro.vendor.build.fingerprint");
+
+        if (TextUtils.isEmpty(system)) {
+            Slog.e(TAG, "Required ro.build.fingerprint is empty!");
+            return false;
+        }
+
+        if (!TextUtils.isEmpty(vendor)) {
+            if (!Objects.equals(system, vendor)) {
+                Slog.e(TAG, "Mismatched fingerprints; system reported " + system
+                        + " but vendor reported " + vendor);
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     // The following properties only make sense for internal engineering builds.
     public static final long TIME = getLong("ro.build.date.utc") * 1000;
     public static final String USER = getString("ro.build.user");
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 19142b8..33ce517 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -53,6 +53,9 @@
 
     private static native void nativeAllocateBuffers(long nativeObject);
 
+    private static native int nativeGetWidth(long nativeObject);
+    private static native int nativeGetHeight(long nativeObject);
+
     public static final Parcelable.Creator<Surface> CREATOR =
             new Parcelable.Creator<Surface>() {
         @Override
@@ -327,7 +330,9 @@
             if (mHwuiContext == null) {
                 mHwuiContext = new HwuiContext();
             }
-            return mHwuiContext.lockCanvas();
+            return mHwuiContext.lockCanvas(
+                    nativeGetWidth(mNativeObject),
+                    nativeGetHeight(mNativeObject));
         }
     }
 
@@ -576,11 +581,11 @@
             mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject);
         }
 
-        Canvas lockCanvas() {
+        Canvas lockCanvas(int width, int height) {
             if (mCanvas != null) {
                 throw new IllegalStateException("Surface was already locked!");
             }
-            mCanvas = mRenderNode.start(0, 0);
+            mCanvas = mRenderNode.start(width, height);
             return mCanvas;
         }
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index a0b2ca8..a39ff8e 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -357,6 +357,22 @@
     parcel->writeStrongBinder( self != 0 ? self->getIGraphicBufferProducer()->asBinder() : NULL);
 }
 
+static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
+    Surface* surface = reinterpret_cast<Surface*>(nativeObject);
+    ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
+    int value = 0;
+    anw->query(anw, NATIVE_WINDOW_WIDTH, &value);
+    return value;
+}
+
+static jint nativeGetHeight(JNIEnv* env, jclass clazz, jlong nativeObject) {
+    Surface* surface = reinterpret_cast<Surface*>(nativeObject);
+    ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
+    int value = 0;
+    anw->query(anw, NATIVE_WINDOW_HEIGHT, &value);
+    return value;
+}
+
 namespace uirenderer {
 
 using namespace android::uirenderer::renderthread;
@@ -426,6 +442,8 @@
             (void*)nativeReadFromParcel },
     {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
             (void*)nativeWriteToParcel },
+    {"nativeGetWidth", "(J)I", (void*)nativeGetWidth },
+    {"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
 
     // HWUI context
     {"nHwuiCreate", "(JJ)J", (void*) hwui::create },
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 981c576..c4b9c5f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5121,4 +5121,10 @@
 
     <!-- Indication that the current volume and other effects (vibration) are being suppressed by a third party, such as a notification listener. [CHAR LIMIT=30] -->
     <string name="muted_by">Muted by <xliff:g id="third_party">%1$s</xliff:g></string>
+
+    <!-- Error message shown when there is a system error which can be solved by user performing factory reset. [CHAR LIMIT=NONE] -->
+    <string name="system_error_wipe_data">There\'s an internal problem with your device, and it may be unstable until you factory data reset.</string>
+    <!-- Error message shown when there is a system error which can be solved by the manufacturer. [CHAR LIMIT=NONE] -->
+    <string name="system_error_manufacturer">There\'s an internal problem with your device. Contact your manufacturer for details.</string>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c592f49..f6d0836 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2105,4 +2105,9 @@
 
   <!-- From SignalStrength -->
   <java-symbol type="integer" name="config_LTE_RSRP_threshold_type" />
+
+  <java-symbol type="string" name="android_system_label" />
+  <java-symbol type="string" name="system_error_wipe_data" />
+  <java-symbol type="string" name="system_error_manufacturer" />
+
 </resources>
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index 55139fb..ea2e1e1 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -31,7 +31,7 @@
     <LinearLayout
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="20dp"
+        android:layout_marginStart="12dp"
         android:layout_weight="1"
         android:orientation="vertical" >
 
diff --git a/packages/SystemUI/res/layout/remember_permission_checkbox.xml b/packages/SystemUI/res/layout/remember_permission_checkbox.xml
index a21acb3..4985ff5 100644
--- a/packages/SystemUI/res/layout/remember_permission_checkbox.xml
+++ b/packages/SystemUI/res/layout/remember_permission_checkbox.xml
@@ -20,9 +20,9 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingStart="8dp"
-    android:paddingEnd="8dp"
-    android:paddingTop="8dp">
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
+    android:paddingTop="16dp">
 
     <CheckBox
         android:id="@+id/remember"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 797e7b0..3d9f723 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -321,7 +321,7 @@
     <dimen name="heads_up_window_height">250dp</dimen>
 
     <!-- The minimum amount the user needs to swipe to go to the camera / phone. -->
-    <dimen name="keyguard_min_swipe_amount">90dp</dimen>
+    <dimen name="keyguard_min_swipe_amount">110dp</dimen>
 
     <!-- The minimum background radius when swiping to a side for the camera / phone affordances. -->
     <dimen name="keyguard_affordance_min_background_radius">30dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 4857adc..0516768 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -174,7 +174,7 @@
 
         public void trimMemory(int level) {
             if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW &&
-                    mBackground != null && mIsHwAccelerated) {
+                    mBackground != null) {
                 if (DEBUG) {
                     Log.d(TAG, "trimMemory");
                 }
@@ -212,6 +212,7 @@
                 unregisterReceiver(mReceiver);
             }
             mBackground = null;
+            mWallpaperManager.forgetLoadedWallpaper();
         }
 
         void updateSurfaceSize(SurfaceHolder surfaceHolder) {
@@ -337,111 +338,116 @@
         }
 
         void drawFrame() {
-            int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
-                    getDefaultDisplay().getRotation();
+            try {
+                int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
+                        getDefaultDisplay().getRotation();
 
-            // Sometimes a wallpaper is not large enough to cover the screen in one dimension.
-            // Call updateSurfaceSize -- it will only actually do the update if the dimensions
-            // should change
-            if (newRotation != mLastRotation) {
-                // Update surface size (if necessary)
-                updateSurfaceSize(getSurfaceHolder());
-            }
-            SurfaceHolder sh = getSurfaceHolder();
-            final Rect frame = sh.getSurfaceFrame();
-            final int dw = frame.width();
-            final int dh = frame.height();
-            boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth || dh != mLastSurfaceHeight;
-
-            boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
-            if (!redrawNeeded && !mOffsetsChanged) {
-                if (DEBUG) {
-                    Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
-                            + "and offsets have not changed.");
+                // Sometimes a wallpaper is not large enough to cover the screen in one dimension.
+                // Call updateSurfaceSize -- it will only actually do the update if the dimensions
+                // should change
+                if (newRotation != mLastRotation) {
+                    // Update surface size (if necessary)
+                    updateSurfaceSize(getSurfaceHolder());
                 }
-                return;
-            }
-            mLastRotation = newRotation;
+                SurfaceHolder sh = getSurfaceHolder();
+                final Rect frame = sh.getSurfaceFrame();
+                final int dw = frame.width();
+                final int dh = frame.height();
+                boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth
+                        || dh != mLastSurfaceHeight;
 
-            // Load bitmap if it is not yet loaded or if it was loaded at a different size
-            if (mBackground == null || surfaceDimensionsChanged) {
-                if (DEBUG) {
-                    Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
-                            mBackground + ", " +
-                            ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
-                            ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
-                            dw + ", " + dh);
-                }
-                mWallpaperManager.forgetLoadedWallpaper();
-                updateWallpaperLocked();
-                if (mBackground == null) {
+                boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
+                if (!redrawNeeded && !mOffsetsChanged) {
                     if (DEBUG) {
-                        Log.d(TAG, "Unable to load bitmap");
+                        Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
+                                + "and offsets have not changed.");
                     }
                     return;
                 }
-                if (DEBUG) {
-                    if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
-                        Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
-                                dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
-                                mBackground.getHeight());
+                mLastRotation = newRotation;
+
+                // Load bitmap if it is not yet loaded or if it was loaded at a different size
+                if (mBackground == null || surfaceDimensionsChanged) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
+                                mBackground + ", " +
+                                ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
+                                ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
+                                dw + ", " + dh);
+                    }
+                    mWallpaperManager.forgetLoadedWallpaper();
+                    updateWallpaperLocked();
+                    if (mBackground == null) {
+                        if (DEBUG) {
+                            Log.d(TAG, "Unable to load bitmap");
+                        }
+                        return;
+                    }
+                    if (DEBUG) {
+                        if (dw != mBackground.getWidth() || dh != mBackground.getHeight()) {
+                            Log.d(TAG, "Surface != bitmap dimensions: surface w/h, bitmap w/h: " +
+                                    dw + ", " + dh + ", " + mBackground.getWidth() + ", " +
+                                    mBackground.getHeight());
+                        }
                     }
                 }
-            }
 
-            // Center the scaled image
-            mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(),
-                    dh / (float) mBackground.getHeight()));
-            final int availw = dw - (int) (mBackground.getWidth() * mScale);
-            final int availh = dh - (int) (mBackground.getHeight() * mScale);
-            int xPixels = availw / 2;
-            int yPixels = availh / 2;
+                // Center the scaled image
+                mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(),
+                        dh / (float) mBackground.getHeight()));
+                final int availw = dw - (int) (mBackground.getWidth() * mScale);
+                final int availh = dh - (int) (mBackground.getHeight() * mScale);
+                int xPixels = availw / 2;
+                int yPixels = availh / 2;
 
-            // Adjust the image for xOffset/yOffset values. If window manager is handling offsets,
-            // mXOffset and mYOffset are set to 0.5f by default and therefore xPixels and yPixels
-            // will remain unchanged
-            final int availwUnscaled = dw - mBackground.getWidth();
-            final int availhUnscaled = dh - mBackground.getHeight();
-            if (availwUnscaled < 0) xPixels += (int)(availwUnscaled * (mXOffset - .5f) + .5f);
-            if (availhUnscaled < 0) yPixels += (int)(availhUnscaled * (mYOffset - .5f) + .5f);
+                // Adjust the image for xOffset/yOffset values. If window manager is handling offsets,
+                // mXOffset and mYOffset are set to 0.5f by default and therefore xPixels and yPixels
+                // will remain unchanged
+                final int availwUnscaled = dw - mBackground.getWidth();
+                final int availhUnscaled = dh - mBackground.getHeight();
+                if (availwUnscaled < 0)
+                    xPixels += (int) (availwUnscaled * (mXOffset - .5f) + .5f);
+                if (availhUnscaled < 0)
+                    yPixels += (int) (availhUnscaled * (mYOffset - .5f) + .5f);
 
-            mOffsetsChanged = false;
-            mRedrawNeeded = false;
-            if (surfaceDimensionsChanged) {
-                mLastSurfaceWidth = dw;
-                mLastSurfaceHeight = dh;
-            }
-            if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
-                if (DEBUG) {
-                    Log.d(TAG, "Suppressed drawFrame since the image has not "
-                            + "actually moved an integral number of pixels.");
+                mOffsetsChanged = false;
+                mRedrawNeeded = false;
+                if (surfaceDimensionsChanged) {
+                    mLastSurfaceWidth = dw;
+                    mLastSurfaceHeight = dh;
                 }
-                return;
-            }
-            mLastXTranslation = xPixels;
-            mLastYTranslation = yPixels;
+                if (!redrawNeeded && xPixels == mLastXTranslation && yPixels == mLastYTranslation) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Suppressed drawFrame since the image has not "
+                                + "actually moved an integral number of pixels.");
+                    }
+                    return;
+                }
+                mLastXTranslation = xPixels;
+                mLastYTranslation = yPixels;
 
-            if (DEBUG) {
-                Log.d(TAG, "Redrawing wallpaper");
-            }
+                if (DEBUG) {
+                    Log.d(TAG, "Redrawing wallpaper");
+                }
 
-            if (mIsHwAccelerated) {
-                if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
+                if (mIsHwAccelerated) {
+                    if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
+                        drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
+                    }
+                } else {
                     drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
                 }
-            } else {
-                drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
-                if (FIXED_SIZED_SURFACE) {
+            } finally {
+                if (FIXED_SIZED_SURFACE && !mIsHwAccelerated) {
                     // If the surface is fixed-size, we should only need to
                     // draw it once and then we'll let the window manager
                     // position it appropriately.  As such, we no longer needed
                     // the loaded bitmap.  Yay!
-                    // hw-accelerated path retains bitmap for faster rotation
+                    // hw-accelerated renderer retains bitmap for faster rotation
                     mBackground = null;
                     mWallpaperManager.forgetLoadedWallpaper();
                 }
             }
-
         }
 
         private void updateWallpaperLocked() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 4667d56..58a2d41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -46,7 +46,6 @@
 
     private FlingAnimationUtils mFlingAnimationUtils;
     private Callback mCallback;
-    private int mTrackingPointer;
     private VelocityTracker mVelocityTracker;
     private boolean mSwipingInProgress;
     private float mInitialTouchX;
@@ -65,6 +64,7 @@
     private Animator mSwipeAnimator;
     private int mMinBackgroundRadius;
     private boolean mMotionPerformedByUser;
+    private boolean mMotionCancelled;
     private AnimatorListenerAdapter mFlingEndListener = new AnimatorListenerAdapter() {
         @Override
         public void onAnimationEnd(Animator animation) {
@@ -117,13 +117,11 @@
     }
 
     public boolean onTouchEvent(MotionEvent event) {
-        int pointerIndex = event.findPointerIndex(mTrackingPointer);
-        if (pointerIndex < 0) {
-            pointerIndex = 0;
-            mTrackingPointer = event.getPointerId(pointerIndex);
+        if (mMotionCancelled && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
+            return false;
         }
-        final float y = event.getY(pointerIndex);
-        final float x = event.getX(pointerIndex);
+        final float y = event.getY();
+        final float x = event.getX();
 
         boolean isUp = false;
         switch (event.getActionMasked()) {
@@ -137,22 +135,12 @@
                 initVelocityTracker();
                 trackMovement(event);
                 mMotionPerformedByUser = false;
+                mMotionCancelled = false;
                 break;
-
-            case MotionEvent.ACTION_POINTER_UP:
-                final int upPointer = event.getPointerId(event.getActionIndex());
-                if (mTrackingPointer == upPointer) {
-                    // gesture is ongoing, find a new pointer to track
-                    final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
-                    final float newY = event.getY(newIndex);
-                    final float newX = event.getX(newIndex);
-                    mTrackingPointer = event.getPointerId(newIndex);
-                    mInitialTouchY = newY;
-                    mInitialTouchX = newX;
-                    mTranslationOnDown = mTranslation;
-                }
+            case MotionEvent.ACTION_POINTER_DOWN:
+                mMotionCancelled = true;
+                endMotion(event, true /* forceSnapBack */);
                 break;
-
             case MotionEvent.ACTION_MOVE:
                 final float w = x - mInitialTouchX;
                 trackMovement(event);
@@ -174,20 +162,23 @@
             case MotionEvent.ACTION_UP:
                 isUp = true;
             case MotionEvent.ACTION_CANCEL:
-                mTrackingPointer = -1;
                 trackMovement(event);
-                if (mSwipingInProgress) {
-                    flingWithCurrentVelocity(!isUp);
-                }
-                if (mVelocityTracker != null) {
-                    mVelocityTracker.recycle();
-                    mVelocityTracker = null;
-                }
+                endMotion(event, !isUp);
                 break;
         }
         return true;
     }
 
+    private void endMotion(MotionEvent event, boolean forceSnapBack) {
+        if (mSwipingInProgress) {
+            flingWithCurrentVelocity(forceSnapBack);
+        }
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+    }
+
     private void setSwipingInProgress(boolean inProgress) {
         mSwipingInProgress = inProgress;
         if (inProgress) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d311ad9..6d9f0c5 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1183,7 +1183,7 @@
     static final int SERVICE_TIMEOUT_MSG = 12;
     static final int UPDATE_TIME_ZONE = 13;
     static final int SHOW_UID_ERROR_MSG = 14;
-    static final int IM_FEELING_LUCKY_MSG = 15;
+    static final int SHOW_FINGERPRINT_ERROR_MSG = 15;
     static final int PROC_START_TIMEOUT_MSG = 20;
     static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
     static final int KILL_APPLICATION_MSG = 22;
@@ -1212,13 +1212,13 @@
     static final int FINISH_BOOTING_MSG = 45;
     static final int START_USER_SWITCH_MSG = 46;
     static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47;
+    static final int DISMISS_DIALOG_MSG = 48;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
     static final int FIRST_COMPAT_MODE_MSG = 300;
     static final int FIRST_SUPERVISOR_STACK_MSG = 100;
 
-    AlertDialog mUidAlert;
     CompatModeDialog mCompatModeDialog;
     long mLastMemUsageReportTime = 0;
 
@@ -1447,27 +1447,27 @@
                 }
             } break;
             case SHOW_UID_ERROR_MSG: {
-                String title = "System UIDs Inconsistent";
-                String text = "UIDs on the system are inconsistent, you need to wipe your"
-                        + " data partition or your device will be unstable.";
-                Log.e(TAG, title + ": " + text);
                 if (mShowDialogs) {
-                    // XXX This is a temporary dialog, no need to localize.
                     AlertDialog d = new BaseErrorDialog(mContext);
                     d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
                     d.setCancelable(false);
-                    d.setTitle(title);
-                    d.setMessage(text);
-                    d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
-                            mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
-                    mUidAlert = d;
+                    d.setTitle(mContext.getText(R.string.android_system_label));
+                    d.setMessage(mContext.getText(R.string.system_error_wipe_data));
+                    d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+                            mHandler.obtainMessage(DISMISS_DIALOG_MSG, d));
                     d.show();
                 }
             } break;
-            case IM_FEELING_LUCKY_MSG: {
-                if (mUidAlert != null) {
-                    mUidAlert.dismiss();
-                    mUidAlert = null;
+            case SHOW_FINGERPRINT_ERROR_MSG: {
+                if (mShowDialogs) {
+                    AlertDialog d = new BaseErrorDialog(mContext);
+                    d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+                    d.setCancelable(false);
+                    d.setTitle(mContext.getText(R.string.android_system_label));
+                    d.setMessage(mContext.getText(R.string.system_error_manufacturer));
+                    d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+                            mHandler.obtainMessage(DISMISS_DIALOG_MSG, d));
+                    d.show();
                 }
             } break;
             case PROC_START_TIMEOUT_MSG: {
@@ -1727,6 +1727,11 @@
                 }
                 break;
             }
+            case DISMISS_DIALOG_MSG: {
+                final Dialog d = (Dialog) msg.obj;
+                d.dismiss();
+                break;
+            }
             }
         }
     };
@@ -1776,7 +1781,8 @@
                     }
                 }
 
-                int i=0, num=0;
+                int i = 0;
+                int num = 0;
                 long[] tmp = new long[1];
                 do {
                     ProcessRecord proc;
@@ -11250,13 +11256,18 @@
 
             try {
                 if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
-                    Message msg = Message.obtain();
-                    msg.what = SHOW_UID_ERROR_MSG;
-                    mHandler.sendMessage(msg);
+                    Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
+                            + " data partition or your device will be unstable.");
+                    mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
                 }
             } catch (RemoteException e) {
             }
 
+            if (!Build.isFingerprintConsistent()) {
+                Slog.e(TAG, "Build fingerprint is not consistent, warning user");
+                mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
+            }
+
             long ident = Binder.clearCallingIdentity();
             try {
                 Intent intent = new Intent(Intent.ACTION_USER_STARTED);
@@ -13962,7 +13973,9 @@
 
         ArrayList<MemItem> procMems = new ArrayList<MemItem>();
         final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
-        long nativePss=0, dalvikPss=0, otherPss=0;
+        long nativePss = 0;
+        long dalvikPss = 0;
+        long otherPss = 0;
         long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
 
         long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0cf22493..db0f53b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1298,7 +1298,12 @@
                 if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
                     return false;
                 }
+
+                // We remember deleted user IDs to prevent them from being
+                // reused during the current boot; they can still be reused
+                // after a reboot.
                 mRemovingUserIds.put(userHandle, true);
+
                 try {
                     mAppOpsService.removeUser(userHandle);
                 } catch (RemoteException e) {
@@ -1387,18 +1392,6 @@
         // Remove this user from the list
         mUsers.remove(userHandle);
 
-        // Have user ID linger for several seconds to let external storage VFS
-        // cache entries expire. This must be greater than the 'entry_valid'
-        // timeout used by the FUSE daemon.
-        mHandler.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                synchronized (mPackagesLock) {
-                    mRemovingUserIds.delete(userHandle);
-                }
-            }
-        }, MINUTE_IN_MILLIS);
-
         mRestrictionsPinStates.remove(userHandle);
         // Remove user file
         AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));