Merge "Clearing tasks along with application data. (Bug 16952119)" into lmp-dev
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 5f0fa18..b6c650d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -738,7 +738,13 @@
      * Create and return an animation to re-display a force hidden window.
      */
     public Animation createForceHideEnterAnimation(boolean onWallpaper);
-    
+
+    /**
+     * Create and return an animation to let the wallpaper disappear after being shown on a force
+     * hiding window.
+     */
+    public Animation createForceHideWallpaperExitAnimation();
+
     /**
      * Called from the input reader thread before a key is enqueued.
      *
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 60e649b..9fa6882 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -17,17 +17,14 @@
 package com.android.internal.widget;
 
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.os.Debug;
 import android.os.Parcel;
@@ -38,6 +35,8 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
 
 import com.android.internal.R;
 
@@ -59,6 +58,11 @@
 
     private static final boolean PROFILE_DRAWING = false;
     private final CellState[][] mCellStates;
+
+    private final int mDotSize;
+    private final int mDotSizeActivated;
+    private final int mPathWidth;
+
     private boolean mDrawingProfilingStarted = false;
 
     private Paint mPaint = new Paint();
@@ -104,33 +108,22 @@
     private boolean mEnableHapticFeedback = true;
     private boolean mPatternInProgress = false;
 
-    private float mDiameterFactor = 0.10f; // TODO: move to attrs
-    private final int mStrokeAlpha = 128;
     private float mHitFactor = 0.6f;
 
     private float mSquareWidth;
     private float mSquareHeight;
 
-    private final Bitmap mBitmapBtnDefault;
-    private final Bitmap mBitmapBtnTouched;
-    private final Bitmap mBitmapCircleDefault;
-    private final Bitmap mBitmapCircleAlpha;
-    private final Bitmap mBitmapArrowAlphaUp;
-
     private final Path mCurrentPath = new Path();
     private final Rect mInvalidate = new Rect();
     private final Rect mTmpInvalidateRect = new Rect();
 
-    private int mBitmapWidth;
-    private int mBitmapHeight;
-
     private int mAspect;
-    private final Matrix mArrowMatrix = new Matrix();
-    private final Matrix mCircleMatrix = new Matrix();
-    private final PorterDuffColorFilter mRegularColorFilter;
-    private final PorterDuffColorFilter mErrorColorFilter;
-    private final PorterDuffColorFilter mSuccessColorFilter;
+    private int mRegularColor;
+    private int mErrorColor;
+    private int mSuccessColor;
 
+    private Interpolator mFastOutSlowInInterpolator;
+    private Interpolator mLinearOutSlowInInterpolator;
 
     /**
      * Represents a cell in the 3 X 3 matrix of the unlock pattern view.
@@ -194,6 +187,10 @@
         public float scale = 1.0f;
         public float translateY = 0.0f;
         public float alpha = 1.0f;
+        public float size;
+        public float lineEndX = Float.MIN_VALUE;
+        public float lineEndY = Float.MIN_VALUE;
+        public ValueAnimator lineAnimator;
      }
 
     /**
@@ -272,63 +269,48 @@
         mPathPaint.setAntiAlias(true);
         mPathPaint.setDither(true);
 
-        int regularColor = getResources().getColor(R.color.lock_pattern_view_regular_color);
-        int errorColor = getResources().getColor(R.color.lock_pattern_view_error_color);
-        int successColor = getResources().getColor(R.color.lock_pattern_view_success_color);
-        regularColor = a.getColor(R.styleable.LockPatternView_regularColor, regularColor);
-        errorColor = a.getColor(R.styleable.LockPatternView_errorColor, errorColor);
-        successColor = a.getColor(R.styleable.LockPatternView_successColor, successColor);
-        mRegularColorFilter = new PorterDuffColorFilter(regularColor, PorterDuff.Mode.SRC_ATOP);
-        mErrorColorFilter = new PorterDuffColorFilter(errorColor, PorterDuff.Mode.SRC_ATOP);
-        mSuccessColorFilter = new PorterDuffColorFilter(successColor, PorterDuff.Mode.SRC_ATOP);
+        mRegularColor = getResources().getColor(R.color.lock_pattern_view_regular_color);
+        mErrorColor = getResources().getColor(R.color.lock_pattern_view_error_color);
+        mSuccessColor = getResources().getColor(R.color.lock_pattern_view_success_color);
+        mRegularColor = a.getColor(R.styleable.LockPatternView_regularColor, mRegularColor);
+        mErrorColor = a.getColor(R.styleable.LockPatternView_errorColor, mErrorColor);
+        mSuccessColor = a.getColor(R.styleable.LockPatternView_successColor, mSuccessColor);
 
-        int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, regularColor);
+        int pathColor = a.getColor(R.styleable.LockPatternView_pathColor, mRegularColor);
         mPathPaint.setColor(pathColor);
 
-        mPathPaint.setAlpha(mStrokeAlpha);
         mPathPaint.setStyle(Paint.Style.STROKE);
         mPathPaint.setStrokeJoin(Paint.Join.ROUND);
         mPathPaint.setStrokeCap(Paint.Cap.ROUND);
 
-        // lot's of bitmaps!
-        // TODO: those bitmaps are hardcoded to the Material Theme which should not be the case!
-        mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default_mtrl_alpha);
-        mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched_mtrl_alpha);
-        mBitmapCircleDefault = getBitmapFor(
-                R.drawable.indicator_code_lock_point_area_default_mtrl_alpha);
-        mBitmapCircleAlpha = getBitmapFor(R.drawable.indicator_code_lock_point_area_mtrl_alpha);
-        mBitmapArrowAlphaUp = getBitmapFor(
-                R.drawable.indicator_code_lock_drag_direction_up_mtrl_alpha);
+        mPathWidth = getResources().getDimensionPixelSize(R.dimen.lock_pattern_dot_line_width);
+        mPathPaint.setStrokeWidth(mPathWidth);
 
-        // bitmaps have the size of the largest bitmap in this group
-        final Bitmap bitmaps[] = { mBitmapBtnDefault, mBitmapBtnTouched, mBitmapCircleDefault,
-                mBitmapCircleAlpha};
-
-        for (Bitmap bitmap : bitmaps) {
-            mBitmapWidth = Math.max(mBitmapWidth, bitmap.getWidth());
-            mBitmapHeight = Math.max(mBitmapHeight, bitmap.getHeight());
-        }
+        mDotSize = getResources().getDimensionPixelSize(R.dimen.lock_pattern_dot_size);
+        mDotSizeActivated = getResources().getDimensionPixelSize(
+                R.dimen.lock_pattern_dot_size_activated);
 
         mPaint.setAntiAlias(true);
         mPaint.setDither(true);
-        mPaint.setFilterBitmap(true);
 
         mCellStates = new CellState[3][3];
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
                 mCellStates[i][j] = new CellState();
+                mCellStates[i][j].size = mDotSize;
             }
         }
+
+        mFastOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
+        mLinearOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
     }
 
     public CellState[][] getCellStates() {
         return mCellStates;
     }
 
-    private Bitmap getBitmapFor(int resId) {
-        return BitmapFactory.decodeResource(getContext().getResources(), resId);
-    }
-
     /**
      * @return Whether the view is in stealth mode.
      */
@@ -510,18 +492,6 @@
     }
 
     @Override
-    protected int getSuggestedMinimumWidth() {
-        // View should be large enough to contain 3 side-by-side target bitmaps
-        return 3 * mBitmapWidth;
-    }
-
-    @Override
-    protected int getSuggestedMinimumHeight() {
-        // View should be large enough to contain 3 side-by-side target bitmaps
-        return 3 * mBitmapWidth;
-    }
-
-    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int minimumWidth = getSuggestedMinimumWidth();
         final int minimumHeight = getSuggestedMinimumHeight();
@@ -594,9 +564,73 @@
     private void addCellToPattern(Cell newCell) {
         mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
         mPattern.add(newCell);
+        if (!mInStealthMode) {
+            startCellActivatedAnimation(newCell);
+        }
         notifyCellAdded();
     }
 
+    private void startCellActivatedAnimation(Cell cell) {
+        final CellState cellState = mCellStates[cell.row][cell.column];
+        startSizeAnimation(mDotSize, mDotSizeActivated, 96, mLinearOutSlowInInterpolator,
+                cellState, new Runnable() {
+            @Override
+            public void run() {
+                startSizeAnimation(mDotSizeActivated, mDotSize, 192, mFastOutSlowInInterpolator,
+                        cellState, null);
+            }
+        });
+        startLineEndAnimation(cellState, mInProgressX, mInProgressY,
+                getCenterXForColumn(cell.column), getCenterYForRow(cell.row));
+    }
+
+    private void startLineEndAnimation(final CellState state,
+            final float startX, final float startY, final float targetX, final float targetY) {
+        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
+        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                float t = (float) animation.getAnimatedValue();
+                state.lineEndX = (1 - t) * startX + t * targetX;
+                state.lineEndY = (1 - t) * startY + t * targetY;
+                invalidate();
+            }
+        });
+        valueAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                state.lineAnimator = null;
+            }
+        });
+        valueAnimator.setInterpolator(mFastOutSlowInInterpolator);
+        valueAnimator.setDuration(100);
+        valueAnimator.start();
+        state.lineAnimator = valueAnimator;
+    }
+
+    private void startSizeAnimation(float start, float end, long duration, Interpolator interpolator,
+            final CellState state, final Runnable endRunnable) {
+        ValueAnimator valueAnimator = ValueAnimator.ofFloat(start, end);
+        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                state.size = (float) animation.getAnimatedValue();
+                invalidate();
+            }
+        });
+        if (endRunnable != null) {
+            valueAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    endRunnable.run();
+                }
+            });
+        }
+        valueAnimator.setInterpolator(interpolator);
+        valueAnimator.setDuration(duration);
+        valueAnimator.start();
+    }
+
     // helper method to find which cell a point maps to
     private Cell checkForNewHit(float x, float y) {
 
@@ -713,7 +747,7 @@
     private void handleActionMove(MotionEvent event) {
         // Handle all recent motion events so we don't skip any cells even when the device
         // is busy...
-        final float radius = (mSquareWidth * mDiameterFactor * 0.5f);
+        final float radius = mPathWidth;
         final int historySize = event.getHistorySize();
         mTmpInvalidateRect.setEmpty();
         boolean invalidateNow = false;
@@ -782,6 +816,7 @@
         // report pattern detected
         if (!mPattern.isEmpty()) {
             mPatternInProgress = false;
+            cancelLineAnimations();
             notifyPatternDetected();
             invalidate();
         }
@@ -793,6 +828,18 @@
         }
     }
 
+    private void cancelLineAnimations() {
+        for (int i = 0; i < 3; i++) {
+            for (int j = 0; j < 3; j++) {
+                CellState state = mCellStates[i][j];
+                if (state.lineAnimator != null) {
+                    state.lineAnimator.cancel();
+                    state.lineEndX = Float.MIN_VALUE;
+                    state.lineEndY = Float.MIN_VALUE;
+                }
+            }
+        }
+    }
     private void handleActionDown(MotionEvent event) {
         resetPattern();
         final float x = event.getX();
@@ -882,62 +929,33 @@
             invalidate();
         }
 
-        final float squareWidth = mSquareWidth;
-        final float squareHeight = mSquareHeight;
-
-        float radius = (squareWidth * mDiameterFactor * 0.5f);
-        mPathPaint.setStrokeWidth(radius);
-
         final Path currentPath = mCurrentPath;
         currentPath.rewind();
 
         // draw the circles
-        final int paddingTop = mPaddingTop;
-        final int paddingLeft = mPaddingLeft;
-
         for (int i = 0; i < 3; i++) {
-            float topY = paddingTop + i * squareHeight;
-            //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
+            float centerY = getCenterYForRow(i);
             for (int j = 0; j < 3; j++) {
-                float leftX = paddingLeft + j * squareWidth;
-                float scale = mCellStates[i][j].scale;
-                mPaint.setAlpha((int) (mCellStates[i][j].alpha * 255));
-                float translationY = mCellStates[i][j].translateY;
-                drawCircle(canvas, (int) leftX, (int) topY + translationY, scale, drawLookup[i][j]);
+                CellState cellState = mCellStates[i][j];
+                float centerX = getCenterXForColumn(j);
+                float size = cellState.size * cellState.scale;
+                float translationY = cellState.translateY;
+                drawCircle(canvas, (int) centerX, (int) centerY + translationY,
+                        size, drawLookup[i][j], cellState.alpha);
             }
         }
 
-        // Reset the alpha to draw normally
-        mPaint.setAlpha(255);
-
         // TODO: the path should be created and cached every time we hit-detect a cell
         // only the last segment of the path should be computed here
         // draw the path of the pattern (unless we are in stealth mode)
         final boolean drawPath = !mInStealthMode;
 
-        // draw the arrows associated with the path (unless we are in stealth mode)
         if (drawPath) {
-            for (int i = 0; i < count - 1; i++) {
-                Cell cell = pattern.get(i);
-                Cell next = pattern.get(i + 1);
+            mPathPaint.setColor(getCurrentColor(true /* partOfPattern */));
 
-                // only draw the part of the pattern stored in
-                // the lookup table (this is only different in the case
-                // of animation).
-                if (!drawLookup[next.row][next.column]) {
-                    break;
-                }
-
-                float leftX = paddingLeft + cell.column * squareWidth;
-                float topY = paddingTop + cell.row * squareHeight
-                        + mCellStates[cell.row][cell.column].translateY;
-
-                drawArrow(canvas, leftX, topY, cell, next);
-            }
-        }
-
-        if (drawPath) {
             boolean anyCircles = false;
+            float lastX = 0f;
+            float lastY = 0f;
             for (int i = 0; i < count; i++) {
                 Cell cell = pattern.get(i);
 
@@ -951,123 +969,66 @@
 
                 float centerX = getCenterXForColumn(cell.column);
                 float centerY = getCenterYForRow(cell.row);
-
-                // Respect translation in animation
-                centerY += mCellStates[cell.row][cell.column].translateY;
-                if (i == 0) {
-                    currentPath.moveTo(centerX, centerY);
-                } else {
-                    currentPath.lineTo(centerX, centerY);
+                if (i != 0) {
+                    CellState state = mCellStates[cell.row][cell.column];
+                    currentPath.rewind();
+                    currentPath.moveTo(lastX, lastY);
+                    if (state.lineEndX != Float.MIN_VALUE && state.lineEndY != Float.MIN_VALUE) {
+                        currentPath.lineTo(state.lineEndX, state.lineEndY);
+                    } else {
+                        currentPath.lineTo(centerX, centerY);
+                    }
+                    canvas.drawPath(currentPath, mPathPaint);
                 }
+                lastX = centerX;
+                lastY = centerY;
             }
 
-            // add last in progress section
+            // draw last in progress section
             if ((mPatternInProgress || mPatternDisplayMode == DisplayMode.Animate)
                     && anyCircles) {
+                currentPath.rewind();
+                currentPath.moveTo(lastX, lastY);
                 currentPath.lineTo(mInProgressX, mInProgressY);
+
+                mPathPaint.setAlpha((int) (calculateLastSegmentAlpha(
+                        mInProgressX, mInProgressY, lastX, lastY) * 255f));
+                canvas.drawPath(currentPath, mPathPaint);
             }
-            canvas.drawPath(currentPath, mPathPaint);
         }
     }
 
-    private void drawArrow(Canvas canvas, float leftX, float topY, Cell start, Cell end) {
-        if (mPatternInProgress) {
-            mPaint.setColorFilter(mRegularColorFilter);
-        } else {
-            boolean success = mPatternDisplayMode != DisplayMode.Wrong;
-            mPaint.setColorFilter(success ? mSuccessColorFilter : mErrorColorFilter);
-        }
-
-        final int endRow = end.row;
-        final int startRow = start.row;
-        final int endColumn = end.column;
-        final int startColumn = start.column;
-
-        // offsets for centering the bitmap in the cell
-        final int offsetX = ((int) mSquareWidth - mBitmapWidth) / 2;
-        final int offsetY = ((int) mSquareHeight - mBitmapHeight) / 2;
-
-        // compute transform to place arrow bitmaps at correct angle inside circle.
-        // This assumes that the arrow image is drawn at 12:00 with it's top edge
-        // coincident with the circle bitmap's top edge.
-        final int cellWidth = mBitmapWidth;
-        final int cellHeight = mBitmapHeight;
-
-        // the up arrow bitmap is at 12:00, so find the rotation from x axis and add 90 degrees.
-        final float theta = (float) Math.atan2(
-                (double) (endRow - startRow), (double) (endColumn - startColumn));
-        final float angle = (float) Math.toDegrees(theta) + 90.0f;
-
-        // compose matrix
-        float sx = Math.min(mSquareWidth / mBitmapWidth, 1.0f);
-        float sy = Math.min(mSquareHeight / mBitmapHeight, 1.0f);
-        mArrowMatrix.setTranslate(leftX + offsetX, topY + offsetY); // transform to cell position
-        mArrowMatrix.preTranslate(mBitmapWidth/2, mBitmapHeight/2);
-        mArrowMatrix.preScale(sx, sy);
-        mArrowMatrix.preTranslate(-mBitmapWidth/2, -mBitmapHeight/2);
-        mArrowMatrix.preRotate(angle, cellWidth / 2.0f, cellHeight / 2.0f);  // rotate about cell center
-        mArrowMatrix.preTranslate((cellWidth - mBitmapArrowAlphaUp.getWidth()) / 2.0f, 0.0f); // translate to 12:00 pos
-        canvas.drawBitmap(mBitmapArrowAlphaUp, mArrowMatrix, mPaint);
+    private float calculateLastSegmentAlpha(float x, float y, float lastX, float lastY) {
+        float diffX = x - lastX;
+        float diffY = y - lastY;
+        float dist = (float) Math.sqrt(diffX*diffX + diffY*diffY);
+        float frac = dist/mSquareWidth;
+        return Math.min(1f, Math.max(0f, (frac - 0.3f) * 4f));
     }
 
-    /**
-     * @param canvas
-     * @param leftX
-     * @param topY
-     * @param partOfPattern Whether this circle is part of the pattern.
-     */
-    private void drawCircle(Canvas canvas, float leftX, float topY, float scale,
-            boolean partOfPattern) {
-        Bitmap outerCircle;
-        Bitmap innerCircle;
-        ColorFilter outerFilter;
-        if (!partOfPattern || mInStealthMode) {
+    private int getCurrentColor(boolean partOfPattern) {
+        if (!partOfPattern || mInStealthMode || mPatternInProgress) {
             // unselected circle
-            outerCircle = mBitmapCircleDefault;
-            innerCircle = mBitmapBtnDefault;
-            outerFilter = mRegularColorFilter;
-        } else if (mPatternInProgress) {
-            // user is in middle of drawing a pattern
-            outerCircle = mBitmapCircleAlpha;
-            innerCircle = mBitmapBtnTouched;
-            outerFilter = mRegularColorFilter;
+            return mRegularColor;
         } else if (mPatternDisplayMode == DisplayMode.Wrong) {
             // the pattern is wrong
-            outerCircle = mBitmapCircleAlpha;
-            innerCircle = mBitmapBtnDefault;
-            outerFilter = mErrorColorFilter;
+            return mErrorColor;
         } else if (mPatternDisplayMode == DisplayMode.Correct ||
                 mPatternDisplayMode == DisplayMode.Animate) {
-            // the pattern is correct
-            outerCircle = mBitmapCircleAlpha;
-            innerCircle = mBitmapBtnDefault;
-            outerFilter = mSuccessColorFilter;
+            return mSuccessColor;
         } else {
             throw new IllegalStateException("unknown display mode " + mPatternDisplayMode);
         }
+    }
 
-        final int width = mBitmapWidth;
-        final int height = mBitmapHeight;
-
-        final float squareWidth = mSquareWidth;
-        final float squareHeight = mSquareHeight;
-
-        int offsetX = (int) ((squareWidth - width) / 2f);
-        int offsetY = (int) ((squareHeight - height) / 2f);
-
-        // Allow circles to shrink if the view is too small to hold them.
-        float sx = Math.min(mSquareWidth / mBitmapWidth, 1.0f);
-        float sy = Math.min(mSquareHeight / mBitmapHeight, 1.0f);
-
-        mCircleMatrix.setTranslate(leftX + offsetX, topY + offsetY);
-        mCircleMatrix.preTranslate(mBitmapWidth/2, mBitmapHeight/2);
-        mCircleMatrix.preScale(sx * scale, sy * scale);
-        mCircleMatrix.preTranslate(-mBitmapWidth/2, -mBitmapHeight/2);
-
-        mPaint.setColorFilter(outerFilter);
-        canvas.drawBitmap(outerCircle, mCircleMatrix, mPaint);
-        mPaint.setColorFilter(mRegularColorFilter);
-        canvas.drawBitmap(innerCircle, mCircleMatrix, mPaint);
+    /**
+     * @param partOfPattern Whether this circle is part of the pattern.
+     */
+    private void drawCircle(Canvas canvas, float centerX, float centerY, float size,
+            boolean partOfPattern, float alpha) {
+        mPaint.setColor(getCurrentColor(partOfPattern));
+        mPaint.setAlpha((int) (alpha * 255));
+        canvas.drawCircle(centerX, centerY, size/2, mPaint);
     }
 
     @Override
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index ace17ae..e8afada 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -1,34 +1,28 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/*
-** Copyright 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.
-*/
--->
+  ~ Copyright (C) 2014 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:detachWallpaper="true" android:shareInterpolator="false" android:startOffset="100">
-    <alpha
-        android:fromAlpha="0.0" android:toAlpha="1.0"
-        android:fillEnabled="true" android:fillBefore="true"
-        android:interpolator="@interpolator/linear_out_slow_in"
-        android:duration="@integer/config_shortAnimTime"/>
-    <scale
-        android:fromXScale="0.95" android:toXScale="1.0"
-        android:fromYScale="0.95" android:toYScale="1.0"
-        android:pivotX="50%" android:pivotY="50%"
-        android:fillEnabled="true" android:fillBefore="true"
-        android:interpolator="@interpolator/linear_out_slow_in"
-        android:duration="@integer/config_shortAnimTime" />
+        android:background="#ff000000"
+        android:detachWallpaper="true"
+        android:shareInterpolator="false"
+        android:startOffset="100">
+
+    <translate android:fromYDelta="110%" android:toYDelta="0"
+            android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+            android:interpolator="@interpolator/decelerate_quint"
+            android:duration="300" />
 </set>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
new file mode 100644
index 0000000..09d8001
--- /dev/null
+++ b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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:detachWallpaper="true" android:shareInterpolator="false" android:startOffset="100">
+    <alpha
+        android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:fillEnabled="true" android:fillBefore="true"
+        android:interpolator="@interpolator/decelerate_quint"
+        android:duration="400"/>
+    <scale
+        android:fromXScale="0.94" android:toXScale="1.0"
+        android:fromYScale="0.94" android:toYScale="1.0"
+        android:pivotX="50%" android:pivotY="100%"
+        android:fillEnabled="true" android:fillBefore="true"
+        android:interpolator="@interpolator/decelerate_quint"
+        android:duration="400" />
+
+    <translate android:fromYDelta="5%" android:toYDelta="0"
+        android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+        android:interpolator="@interpolator/decelerate_quint"
+        android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_screen_wallpaper_exit.xml b/core/res/res/anim/lock_screen_wallpaper_exit.xml
new file mode 100644
index 0000000..49d0327
--- /dev/null
+++ b/core/res/res/anim/lock_screen_wallpaper_exit.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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" android:startOffset="100">
+    <alpha
+        android:fromAlpha="1.0" android:toAlpha="0.0"
+        android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_linear_in"
+        android:duration="150"/>
+
+    <!-- Empty animation so the animation has same duration as lock_screen_behind_enter animation
+         -->
+    <translate android:fromYDelta="0" android:toYDelta="0"
+        android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_default_mtrl_alpha.png b/core/res/res/drawable-hdpi/btn_code_lock_default_mtrl_alpha.png
deleted file mode 100644
index 7cc3c11..0000000
--- a/core/res/res/drawable-hdpi/btn_code_lock_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_touched_mtrl_alpha.png b/core/res/res/drawable-hdpi/btn_code_lock_touched_mtrl_alpha.png
deleted file mode 100644
index 70397d21..0000000
--- a/core/res/res/drawable-hdpi/btn_code_lock_touched_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png b/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
deleted file mode 100644
index b9b400f..0000000
--- a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_mtrl_alpha.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
deleted file mode 100644
index b1601f4..0000000
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_mtrl_alpha.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_mtrl_alpha.png
deleted file mode 100644
index a038a13..0000000
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default_mtrl_alpha.png b/core/res/res/drawable-mdpi/btn_code_lock_default_mtrl_alpha.png
deleted file mode 100644
index 14d0b32..0000000
--- a/core/res/res/drawable-mdpi/btn_code_lock_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched_mtrl_alpha.png b/core/res/res/drawable-mdpi/btn_code_lock_touched_mtrl_alpha.png
deleted file mode 100644
index 9cfbdf9..0000000
--- a/core/res/res/drawable-mdpi/btn_code_lock_touched_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
deleted file mode 100644
index 2fb1325..0000000
--- a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_mtrl_alpha.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
deleted file mode 100644
index 07d4afd..0000000
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_mtrl_alpha.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_mtrl_alpha.png
deleted file mode 100644
index ea8c2b4..0000000
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_default_mtrl_alpha.png b/core/res/res/drawable-xhdpi/btn_code_lock_default_mtrl_alpha.png
deleted file mode 100644
index 0c457b4..0000000
--- a/core/res/res/drawable-xhdpi/btn_code_lock_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_touched_mtrl_alpha.png b/core/res/res/drawable-xhdpi/btn_code_lock_touched_mtrl_alpha.png
deleted file mode 100644
index 020d699..0000000
--- a/core/res/res/drawable-xhdpi/btn_code_lock_touched_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png b/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
deleted file mode 100644
index fda5e37..0000000
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_mtrl_alpha.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
deleted file mode 100644
index 75d0221..0000000
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_mtrl_alpha.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_mtrl_alpha.png
deleted file mode 100644
index 225799b..0000000
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_code_lock_default_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/btn_code_lock_default_mtrl_alpha.png
deleted file mode 100755
index 1b6c9b5..0000000
--- a/core/res/res/drawable-xxhdpi/btn_code_lock_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_code_lock_touched_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/btn_code_lock_touched_mtrl_alpha.png
deleted file mode 100755
index dd13af8..0000000
--- a/core/res/res/drawable-xxhdpi/btn_code_lock_touched_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
deleted file mode 100644
index d3e80be..0000000
--- a/core/res/res/drawable-xxhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_default_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
deleted file mode 100644
index a11b6dd..0000000
--- a/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_default_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_mtrl_alpha.png
deleted file mode 100644
index eae7ea8..0000000
--- a/core/res/res/drawable-xxhdpi/indicator_code_lock_point_area_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png b/core/res/res/drawable-xxxhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
deleted file mode 100644
index 23214fa..0000000
--- a/core/res/res/drawable-xxxhdpi/indicator_code_lock_drag_direction_up_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8517ad5..bf97ca5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1590,7 +1590,6 @@
          -->
     <string-array translatable="false" name="config_globalActionsList">
         <item>power</item>
-        <item>lockdown</item>
         <item>bugreport</item>
         <item>users</item>
     </string-array>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index afe180f..bacdc3f 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -389,4 +389,8 @@
      used on circular displays. In the case where there is no "chin", this will default
      to 0 -->
      <dimen name="circular_display_mask_offset">0px</dimen>
+
+     <dimen name="lock_pattern_dot_line_width">3dp</dimen>
+     <dimen name="lock_pattern_dot_size">12dp</dimen>
+     <dimen name="lock_pattern_dot_size_activated">28dp</dimen>
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index e693d91..35baf9c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1359,8 +1359,8 @@
         <item name="lightY">-200dp</item>
         <item name="lightZ">800dp</item>
         <item name="lightRadius">800dp</item>
-        <item name="ambientShadowAlpha">0.0471</item>
-        <item name="spotShadowAlpha">0.1765</item>
+        <item name="ambientShadowAlpha">0.06</item>
+        <item name="spotShadowAlpha">0.22</item>
     </style>
 
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 641d545..0ebf0b5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1041,14 +1041,12 @@
   <java-symbol type="drawable" name="text_edit_side_paste_window" />
   <java-symbol type="drawable" name="text_edit_paste_window" />
   <java-symbol type="drawable" name="btn_check_off" />
-  <java-symbol type="drawable" name="btn_code_lock_default_mtrl_alpha" />
-  <java-symbol type="drawable" name="btn_code_lock_touched_mtrl_alpha" />
-  <java-symbol type="drawable" name="indicator_code_lock_point_area_default_mtrl_alpha" />
-  <java-symbol type="drawable" name="indicator_code_lock_point_area_mtrl_alpha" />
-  <java-symbol type="drawable" name="indicator_code_lock_drag_direction_up_mtrl_alpha" />
   <java-symbol type="color" name="lock_pattern_view_regular_color" />
   <java-symbol type="color" name="lock_pattern_view_success_color" />
   <java-symbol type="color" name="lock_pattern_view_error_color" />
+  <java-symbol type="dimen" name="lock_pattern_dot_line_width" />
+  <java-symbol type="dimen" name="lock_pattern_dot_size" />
+  <java-symbol type="dimen" name="lock_pattern_dot_size_activated" />
   <java-symbol type="drawable" name="clock_dial" />
   <java-symbol type="drawable" name="clock_hand_hour" />
   <java-symbol type="drawable" name="clock_hand_minute" />
@@ -1722,6 +1720,8 @@
   <java-symbol type="anim" name="push_up_in" />
   <java-symbol type="anim" name="push_up_out" />
   <java-symbol type="anim" name="lock_screen_behind_enter" />
+  <java-symbol type="anim" name="lock_screen_behind_enter_wallpaper" />
+  <java-symbol type="anim" name="lock_screen_wallpaper_exit" />
 
   <java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
   <java-symbol type="dimen" name="status_bar_icon_size" />
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 2a2417a..1e5fc4d 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -64,7 +64,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on July 7, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014.
 <br/>Any versions with less than 0.1% distribution are not shown.</em>
 </p>
 
@@ -95,7 +95,7 @@
 </div>
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on July 7, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014.
 <br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
 
 
@@ -114,7 +114,7 @@
 
 
 <img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C81.7%2C18.2&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
+src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C80.2%2C19.7&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
 
 <p>To declare which version of OpenGL ES your application requires, you should use the {@code
 android:glEsVersion} attribute of the <a
@@ -136,17 +136,17 @@
 </tr>
 <tr>
 <td>2.0</th>
-<td>81.7%</td>
+<td>80.2%</td>
 </tr>
 <tr>
 <td>3.0</th>
-<td>18.2%</td>
+<td>19.7%</td>
 </tr>
 </table>
 
 
 
-<p style="clear:both"><em>Data collected during a 7-day period ending on July 7, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on August 12, 2014</em></p>
 
 
 
@@ -164,7 +164,7 @@
 var VERSION_DATA =
 [
   {
-    "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chf=bg%2Cs%2C00000000&chd=t%3A0.7%2C13.5%2C11.4%2C56.5%2C17.9&chco=c4df9b%2C6fad0c&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat",
+    "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A0.7%2C13.6%2C10.6%2C54.2%2C20.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c",
     "data": [
       {
         "api": 8,
@@ -174,32 +174,32 @@
       {
         "api": 10,
         "name": "Gingerbread",
-        "perc": "13.5"
+        "perc": "13.6"
       },
       {
         "api": 15,
         "name": "Ice Cream Sandwich",
-        "perc": "11.4"
+        "perc": "10.6"
       },
       {
         "api": 16,
         "name": "Jelly Bean",
-        "perc": "27.8"
+        "perc": "26.5"
       },
       {
         "api": 17,
         "name": "Jelly Bean",
-        "perc": "19.7"
+        "perc": "19.8"
       },
       {
         "api": 18,
         "name": "Jelly Bean",
-        "perc": "9.0"
+        "perc": "7.9"
       },
       {
         "api": 19,
         "name": "KitKat",
-        "perc": "17.9"
+        "perc": "20.9"
       }
     ]
   }
@@ -215,28 +215,28 @@
     "data": {
       "Large": {
         "hdpi": "0.6",
-        "ldpi": "0.6",
-        "mdpi": "4.5",
-        "tvdpi": "1.7",
-        "xhdpi": "0.6"
+        "ldpi": "0.5",
+        "mdpi": "4.2",
+        "tvdpi": "1.6",
+        "xhdpi": "0.5"
       },
       "Normal": {
-        "hdpi": "34.5",
-        "mdpi": "11.4",
-        "xhdpi": "19.4",
-        "xxhdpi": "15.3"
+        "hdpi": "35.5",
+        "mdpi": "11.8",
+        "xhdpi": "18.4",
+        "xxhdpi": "15.2"
       },
       "Small": {
-        "ldpi": "6.8"
+        "ldpi": "7.4"
       },
       "Xlarge": {
         "hdpi": "0.3",
-        "mdpi": "3.9",
+        "mdpi": "3.6",
         "xhdpi": "0.4"
       }
     },
-    "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chf=bg%2Cs%2C00000000&chd=t%3A7.4%2C19.8%2C1.7%2C35.4%2C20.4%2C15.3&chco=c4df9b%2C6fad0c&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
-    "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chf=bg%2Cs%2C00000000&chd=t%3A4.6%2C8.0%2C80.6%2C6.8&chco=c4df9b%2C6fad0c&chl=Xlarge%7CLarge%7CNormal%7CSmall"
+    "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A7.9%2C19.6%2C1.6%2C36.4%2C19.3%2C15.2&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c",
+    "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.3%2C7.4%2C80.9%2C7.4&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c"
   }
 ];
 
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index a6dbcb0..0aa1b0d 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -609,16 +610,17 @@
             // Empty constructor.
         }
 
-        NinePatchState(NinePatch ninePatch, Rect padding) {
+        NinePatchState(@NonNull NinePatch ninePatch, @Nullable Rect padding) {
             this(ninePatch, padding, null, DEFAULT_DITHER, false);
         }
 
-        NinePatchState(NinePatch ninePatch, Rect padding, Rect opticalInsets) {
+        NinePatchState(@NonNull NinePatch ninePatch, @Nullable Rect padding,
+                @Nullable Rect opticalInsets) {
             this(ninePatch, padding, opticalInsets, DEFAULT_DITHER, false);
         }
 
-        NinePatchState(NinePatch ninePatch, Rect padding, Rect opticalInsets, boolean dither,
-                boolean autoMirror) {
+        NinePatchState(@NonNull NinePatch ninePatch, @Nullable Rect padding,
+                @Nullable Rect opticalInsets, boolean dither, boolean autoMirror) {
             mNinePatch = ninePatch;
             mPadding = padding;
             mOpticalInsets = Insets.of(opticalInsets);
@@ -626,7 +628,7 @@
             mAutoMirrored = autoMirror;
 
             // Sanity check for valid padding when we have optical insets.
-            if (!opticalInsets.isEmpty()) {
+            if (opticalInsets != null && !opticalInsets.isEmpty()) {
                 if (mPadding == null) {
                     mPadding = new Rect();
                 }
@@ -643,7 +645,7 @@
 
         // Copy constructor
 
-        NinePatchState(NinePatchState state) {
+        NinePatchState(@NonNull NinePatchState state) {
             // We don't deep-copy any fields because they are all immutable.
             mNinePatch = state.mNinePatch;
             mTint = state.mTint;
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index f359fdd..4c513e9 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -16,6 +16,8 @@
 
 package android.graphics.drawable;
 
+import com.android.internal.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -116,32 +118,27 @@
     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
 
-        TypedArray a = r.obtainAttributes(attrs,
-                com.android.internal.R.styleable.StateListDrawable);
+        final TypedArray a = r.obtainAttributes(attrs, R.styleable.StateListDrawable);
 
         super.inflateWithAttributes(r, parser, a,
-                com.android.internal.R.styleable.StateListDrawable_visible);
+                R.styleable.StateListDrawable_visible);
 
         mStateListState.setVariablePadding(a.getBoolean(
-                com.android.internal.R.styleable.StateListDrawable_variablePadding, false));
+                R.styleable.StateListDrawable_variablePadding, false));
         mStateListState.setConstantSize(a.getBoolean(
-                com.android.internal.R.styleable.StateListDrawable_constantSize, false));
+                R.styleable.StateListDrawable_constantSize, false));
         mStateListState.setEnterFadeDuration(a.getInt(
-                com.android.internal.R.styleable.StateListDrawable_enterFadeDuration, 0));
+                R.styleable.StateListDrawable_enterFadeDuration, 0));
         mStateListState.setExitFadeDuration(a.getInt(
-                com.android.internal.R.styleable.StateListDrawable_exitFadeDuration, 0));
+                R.styleable.StateListDrawable_exitFadeDuration, 0));
 
-        setDither(a.getBoolean(com.android.internal.R.styleable.StateListDrawable_dither,
-                               DEFAULT_DITHER));
-
-        setAutoMirrored(a.getBoolean(
-                com.android.internal.R.styleable.StateListDrawable_autoMirrored, false));
+        setDither(a.getBoolean(R.styleable.StateListDrawable_dither, DEFAULT_DITHER));
+        setAutoMirrored(a.getBoolean(R.styleable.StateListDrawable_autoMirrored, false));
 
         a.recycle();
 
-        int type;
-
         final int innerDepth = parser.getDepth() + 1;
+        int type;
         int depth;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                 && ((depth = parser.getDepth()) >= innerDepth
@@ -163,7 +160,7 @@
             for (i = 0; i < numAttrs; i++) {
                 final int stateResId = attrs.getAttributeNameResource(i);
                 if (stateResId == 0) break;
-                if (stateResId == com.android.internal.R.attr.drawable) {
+                if (stateResId == R.attr.drawable) {
                     drawableRes = attrs.getAttributeResourceValue(i, 0);
                 } else {
                     states[j++] = attrs.getAttributeBooleanValue(i, false)
@@ -173,9 +170,9 @@
             }
             states = StateSet.trimStateSet(states, j);
 
-            Drawable dr;
+            final Drawable dr;
             if (drawableRes != 0) {
-                dr = r.getDrawable(drawableRes);
+                dr = r.getDrawable(drawableRes, theme);
             } else {
                 while ((type = parser.next()) == XmlPullParser.TEXT) {
                 }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index b210e64..f0a6e55 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -176,15 +176,15 @@
 status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
     // dirty is an out parameter and should not be recorded,
     // it matters only when replaying the display list
+    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
+    int opIndex = addDrawOp(op);
+    mDisplayListData->addChild(op);
 
     if (renderNode->stagingProperties().isProjectionReceiver()) {
         // use staging property, since recording on UI thread
-        mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size();
+        mDisplayListData->projectionReceiveIndex = opIndex;
     }
 
-    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
-    addDrawOp(op);
-    mDisplayListData->addChild(op);
     return DrawGlInfo::kStatusDone;
 }
 
@@ -447,11 +447,11 @@
     }
 }
 
-void DisplayListRenderer::addStateOp(StateOp* op) {
-    addOpInternal(op);
+int DisplayListRenderer::addStateOp(StateOp* op) {
+    return addOpInternal(op);
 }
 
-void DisplayListRenderer::addDrawOp(DrawOp* op) {
+int DisplayListRenderer::addDrawOp(DrawOp* op) {
     Rect localBounds;
     if (op->getLocalBounds(localBounds)) {
         bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
@@ -460,7 +460,7 @@
     }
 
     mDisplayListData->hasDrawOps = true;
-    addOpInternal(op);
+    return addOpInternal(op);
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 1b3a48a..b5c0159 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -158,12 +158,14 @@
     void insertTranslate();
 
     LinearAllocator& alloc() { return mDisplayListData->allocator; }
-    void addStateOp(StateOp* op);
-    void addDrawOp(DrawOp* op);
-    void addOpInternal(DisplayListOp* op) {
+
+    // Each method returns final index of op
+    int addStateOp(StateOp* op);
+    int addDrawOp(DrawOp* op);
+    int addOpInternal(DisplayListOp* op) {
         insertRestoreToCount();
         insertTranslate();
-        mDisplayListData->displayListOps.add(op);
+        return mDisplayListData->displayListOps.add(op);
     }
 
     template<class T>
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 636f218..7123bfe 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1641,8 +1641,9 @@
     mCaches.disableTexCoordsVertexArray();
 }
 
-void OpenGLRenderer::setupDrawAA() {
+void OpenGLRenderer::setupDrawAA(bool useShadowInterp) {
     mDescription.isAA = true;
+    mDescription.isShadowAA = useShadowInterp;
 }
 
 void OpenGLRenderer::setupDrawColor(int color, int alpha) {
@@ -2365,7 +2366,7 @@
 }
 
 status_t OpenGLRenderer::drawVertexBuffer(float translateX, float translateY,
-        const VertexBuffer& vertexBuffer, const SkPaint* paint, bool useOffset) {
+        const VertexBuffer& vertexBuffer, const SkPaint* paint, int displayFlags) {
     // not missing call to quickReject/dirtyLayer, always done at a higher level
     if (!vertexBuffer.getVertexCount()) {
         // no vertices to draw
@@ -2381,13 +2382,14 @@
 
     setupDraw();
     setupDrawNoTexture();
-    if (isAA) setupDrawAA();
+    if (isAA) setupDrawAA((displayFlags & kVertexBuffer_ShadowAA));
     setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
     setupDrawColorFilter(getColorFilter(paint));
     setupDrawShader(getShader(paint));
     setupDrawBlending(paint, isAA);
     setupDrawProgram();
-    setupDrawModelView(kModelViewMode_Translate, useOffset, translateX, translateY, 0, 0);
+    setupDrawModelView(kModelViewMode_Translate, (displayFlags & kVertexBuffer_Offset),
+            translateX, translateY, 0, 0);
     setupDrawColorUniforms(getShader(paint));
     setupDrawColorFilterUniforms(getColorFilter(paint));
     setupDrawShaderUniforms(getShader(paint));
@@ -2397,7 +2399,6 @@
     mCaches.bindPositionVertexPointer(true, vertices, isAA ? gAlphaVertexStride : gVertexStride);
     mCaches.resetTexCoordsVertexPointer();
 
-
     int alphaSlot = -1;
     if (isAA) {
         void* alphaCoords = ((GLbyte*) vertices) + gVertexAlphaOffset;
@@ -2466,8 +2467,8 @@
         return DrawGlInfo::kStatusDone;
     }
 
-    bool useOffset = !paint->isAntiAlias();
-    return drawVertexBuffer(buffer, paint, useOffset);
+    int displayFlags = paint->isAntiAlias() ? 0 : kVertexBuffer_Offset;
+    return drawVertexBuffer(buffer, paint, displayFlags);
 }
 
 status_t OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
@@ -2483,8 +2484,8 @@
         return DrawGlInfo::kStatusDone;
     }
 
-    bool useOffset = !paint->isAntiAlias();
-    return drawVertexBuffer(buffer, paint, useOffset);
+    int displayFlags = paint->isAntiAlias() ? 0 : kVertexBuffer_Offset;
+    return drawVertexBuffer(buffer, paint, displayFlags);
 }
 
 status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
@@ -3167,12 +3168,12 @@
 
     if (ambientShadowVertexBuffer && mAmbientShadowAlpha > 0) {
         paint.setARGB(casterAlpha * mAmbientShadowAlpha, 0, 0, 0);
-        drawVertexBuffer(*ambientShadowVertexBuffer, &paint);
+        drawVertexBuffer(*ambientShadowVertexBuffer, &paint, kVertexBuffer_ShadowAA);
     }
 
     if (spotShadowVertexBuffer && mSpotShadowAlpha > 0) {
         paint.setARGB(casterAlpha * mSpotShadowAlpha, 0, 0, 0);
-        drawVertexBuffer(*spotShadowVertexBuffer, &paint);
+        drawVertexBuffer(*spotShadowVertexBuffer, &paint, kVertexBuffer_ShadowAA);
     }
 
     return DrawGlInfo::kStatusDrew;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index fd228db..2a9badd 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -94,6 +94,11 @@
     kClipSide_ConservativeFull = 0x1F
 };
 
+enum VertexBufferDisplayFlags {
+    kVertexBuffer_Offset = 0x1,
+    kVertexBuffer_ShadowAA = 0x2,
+};
+
 /**
  * Defines additional transformation that should be applied by the model view matrix, beyond that of
  * the currentTransform()
@@ -656,17 +661,17 @@
      *
      * @param vertexBuffer The VertexBuffer to be drawn
      * @param paint The paint to render with
-     * @param useOffset Offset the vertexBuffer (used in drawing non-AA lines)
+     * @param flags flags with which to draw
      */
     status_t drawVertexBuffer(float translateX, float translateY, const VertexBuffer& vertexBuffer,
-            const SkPaint* paint, bool useOffset = false);
+            const SkPaint* paint, int flags = 0);
 
     /**
      * Convenience for translating method
      */
     status_t drawVertexBuffer(const VertexBuffer& vertexBuffer,
-            const SkPaint* paint, bool useOffset = false) {
-        return drawVertexBuffer(0.0f, 0.0f, vertexBuffer, paint, useOffset);
+            const SkPaint* paint, int flags = 0) {
+        return drawVertexBuffer(0.0f, 0.0f, vertexBuffer, paint, flags);
     }
 
     /**
@@ -842,7 +847,7 @@
     void setupDrawWithTextureAndColor(bool isAlpha8 = false);
     void setupDrawWithExternalTexture();
     void setupDrawNoTexture();
-    void setupDrawAA();
+    void setupDrawAA(bool useShadowInterp);
     void setupDrawColor(int color, int alpha);
     void setupDrawColor(float r, float g, float b, float a);
     void setupDrawAlpha8Color(int color, int alpha);
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 3e191d0..1d95c40 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -72,19 +72,20 @@
 #define PROGRAM_MODULATE_SHIFT 35
 
 #define PROGRAM_HAS_AA_SHIFT 36
+#define PROGRAM_HAS_SHADOW_AA_SHIFT 37
 
-#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 37
-#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 38
+#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
+#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39
 
-#define PROGRAM_HAS_GAMMA_CORRECTION 39
+#define PROGRAM_HAS_GAMMA_CORRECTION 40
 
-#define PROGRAM_IS_SIMPLE_GRADIENT 40
+#define PROGRAM_IS_SIMPLE_GRADIENT 41
 
-#define PROGRAM_HAS_COLORS 41
+#define PROGRAM_HAS_COLORS 42
 
-#define PROGRAM_HAS_DEBUG_HIGHLIGHT 42
-#define PROGRAM_EMULATE_STENCIL 43
-#define PROGRAM_HAS_ROUND_RECT_CLIP 44
+#define PROGRAM_HAS_DEBUG_HIGHLIGHT 43
+#define PROGRAM_EMULATE_STENCIL 44
+#define PROGRAM_HAS_ROUND_RECT_CLIP 45
 
 ///////////////////////////////////////////////////////////////////////////////
 // Types
@@ -135,6 +136,7 @@
     bool isBitmapNpot;
 
     bool isAA; // drawing with a per-vertex alpha
+    bool isShadowAA; // drawing per vertex alpha with shadow interpolation
 
     bool hasGradient;
     Gradient gradientType;
@@ -175,6 +177,7 @@
         hasColors = false;
 
         isAA = false;
+        isShadowAA = false;
 
         modulate = false;
 
@@ -262,6 +265,7 @@
         if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
         if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
         if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
+        if (isShadowAA) key |= programid(0x1) << PROGRAM_HAS_SHADOW_AA_SHIFT;
         if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
         if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 3ef2a71..2dd89b8 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -121,8 +121,12 @@
 const char* gVS_Main_Position =
         "    vec4 transformedPosition = projection * transform * position;\n"
         "    gl_Position = transformedPosition;\n";
+
+const char* gVS_Main_ShadowAAVertexShape =
+        "    alpha = pow(vtxAlpha, 0.667);\n";
 const char* gVS_Main_AAVertexShape =
         "    alpha = vtxAlpha;\n";
+
 const char* gVS_Main_HasRoundRectClip =
         "    roundRectPos = (roundRectInvTransform * transformedPosition).xy;\n";
 const char* gVS_Footer =
@@ -237,6 +241,8 @@
         "    fragColor *= color.a;\n";
 const char* gFS_Main_AccountForAAVertexShape =
         "    fragColor *= alpha;\n";
+const char* gFS_Main_AccountForShadowAAVertexShape =
+        "    fragColor *= pow(alpha, 1.5);\n";
 
 const char* gFS_Main_FetchTexture[2] = {
         // Don't modulate
@@ -515,7 +521,11 @@
             shader.append(gVS_Main_OutTexCoords);
         }
         if (description.isAA) {
-            shader.append(gVS_Main_AAVertexShape);
+            if (description.isShadowAA) {
+                shader.append(gVS_Main_ShadowAAVertexShape);
+            } else {
+                shader.append(gVS_Main_AAVertexShape);
+            }
         }
         if (description.hasColors) {
             shader.append(gVS_Main_OutColors);
@@ -750,7 +760,11 @@
         shader.append(gFS_Main_ApplyColorOp[description.colorOp]);
 
         if (description.isAA) {
-            shader.append(gFS_Main_AccountForAAVertexShape);
+            if (description.isShadowAA) {
+                shader.append(gFS_Main_AccountForShadowAAVertexShape);
+            } else {
+                shader.append(gFS_Main_AccountForAAVertexShape);
+            }
         }
 
         // Output the fragment
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index c59b010..e3732a1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -741,15 +741,24 @@
     const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
     int restoreTo = renderer.getSaveCount();
 
+    LinearAllocator& alloc = handler.allocator();
+    handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
+            PROPERTY_SAVECOUNT, properties().getClipToBounds());
+
+    // Transform renderer to match background we're projecting onto
+    // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
+    const DisplayListOp* op =
+            (mDisplayListData->displayListOps[mDisplayListData->projectionReceiveIndex]);
+    const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op);
+    const RenderProperties& backgroundProps = backgroundOp->mRenderNode->properties();
+    renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
+
     // If the projection reciever has an outline, we mask each of the projected rendernodes to it
     // Either with clipRect, or special saveLayer masking
-    LinearAllocator& alloc = handler.allocator();
     if (projectionReceiverOutline != NULL) {
         const SkRect& outlineBounds = projectionReceiverOutline->getBounds();
         if (projectionReceiverOutline->isRect(NULL)) {
             // mask to the rect outline simply with clipRect
-            handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
-                    PROPERTY_SAVECOUNT, properties().getClipToBounds());
             ClipRectOp* clipOp = new (alloc) ClipRectOp(
                     outlineBounds.left(), outlineBounds.top(),
                     outlineBounds.right(), outlineBounds.bottom(), SkRegion::kIntersect_Op);
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index 375cf32..e822c82 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -175,4 +175,7 @@
 
     <!-- The vertical margin between the date and the owner info. -->
     <dimen name="date_owner_info_margin">10dp</dimen>
+
+    <!-- The translation for disappearing security views after having solved them. -->
+    <dimen name="disappear_y_translation">-32dp</dimen>
 </resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java b/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java
index e664fb9..b685c73 100644
--- a/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java
+++ b/packages/Keyguard/src/com/android/keyguard/AppearAnimationUtils.java
@@ -36,8 +36,7 @@
 
     public AppearAnimationUtils(Context ctx) {
         this(ctx, DEFAULT_APPEAR_DURATION,
-                ctx.getResources().getDimensionPixelSize(R.dimen.appear_y_translation_start),
-                1.0f,
+                1.0f, 1.0f,
                 AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in));
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 2c9247a..a411df3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -24,10 +24,7 @@
 import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.View;
-import android.view.inputmethod.EditorInfo;
 import android.widget.LinearLayout;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
 
 import com.android.internal.widget.LockPatternUtils;
 
@@ -196,5 +193,10 @@
         KeyguardSecurityViewHelper.
                 hideBouncer(mSecurityMessageDisplay, mEcaView, mBouncerFrame, duration);
     }
+
+    @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        return false;
+    }
 }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java
index 2432509..5cb3b9b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAccountView.java
@@ -332,5 +332,10 @@
     public void startAppearAnimation() {
         // TODO.
     }
+
+    @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        return false;
+    }
 }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
index c9fe93c..b3e9f77 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
@@ -17,7 +17,6 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.TelephonyManager;
@@ -353,4 +352,9 @@
     public void startAppearAnimation() {
         // TODO.
     }
+
+    @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        return false;
+    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
index ec5d040eb..66c30c7 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java
@@ -17,13 +17,10 @@
 package com.android.keyguard;
 
 import android.content.Context;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.TextView.OnEditorActionListener;
+import android.view.animation.AnimationUtils;
 
 /**
  * Displays a PIN pad for unlocking.
@@ -37,6 +34,7 @@
     private ViewGroup mRow2;
     private ViewGroup mRow3;
     private View mDivider;
+    private int mDisappearYTranslation;
 
     public KeyguardPINView(Context context) {
         this(context, null);
@@ -45,6 +43,8 @@
     public KeyguardPINView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mAppearAnimationUtils = new AppearAnimationUtils(context);
+        mDisappearYTranslation = getResources().getDimensionPixelSize(
+                R.dimen.disappear_y_translation);
     }
 
     protected void resetState() {
@@ -117,6 +117,18 @@
                 });
     }
 
+    @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        animate()
+                .alpha(0f)
+                .translationY(mDisappearYTranslation)
+                .setInterpolator(AnimationUtils
+                        .loadInterpolator(mContext, android.R.interpolator.fast_out_linear_in))
+                .setDuration(100)
+                .withEndAction(finishRunnable);
+        return true;
+    }
+
     private void enableClipping(boolean enable) {
         mKeyguardBouncerFrame.setClipToPadding(enable);
         mKeyguardBouncerFrame.setClipChildren(enable);
@@ -125,4 +137,9 @@
         mRow3.setClipToPadding(enable);
         setClipChildren(enable);
     }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
index 99ff6a7..5f5d25c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java
@@ -245,6 +245,11 @@
     }
 
     @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        return false;
+    }
+
+    @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
         if (mCallback != null) {
             mCallback.userActivity();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 12bbd35..3b05d11 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -37,6 +37,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.Button;
@@ -95,6 +96,7 @@
     private Drawable mBouncerFrame;
     private ViewGroup mKeyguardBouncerFrame;
     private KeyguardMessageArea mHelpMessage;
+    private int mDisappearYTranslation;
 
     enum FooterMode {
         Normal,
@@ -113,6 +115,8 @@
                 AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 1.5f /* delayScale */,
                 2.0f /* transitionScale */, AnimationUtils.loadInterpolator(
                         mContext, android.R.interpolator.linear_out_slow_in));
+        mDisappearYTranslation = getResources().getDimensionPixelSize(
+                R.dimen.disappear_y_translation);
     }
 
     public void setKeyguardCallback(KeyguardSecurityCallback callback) {
@@ -412,6 +416,11 @@
     @Override
     public void startAppearAnimation() {
         enableClipping(false);
+        setTranslationY(mAppearAnimationUtils.getStartTranslation());
+        animate()
+                .setDuration(500)
+                .setInterpolator(mAppearAnimationUtils.getInterpolator())
+                .translationY(0);
         mAppearAnimationUtils.startAppearAnimation(
                 mLockPatternView.getCellStates(),
                 new Runnable() {
@@ -430,6 +439,19 @@
         }
     }
 
+    @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        mLockPatternView.clearPattern();
+        animate()
+                .alpha(0f)
+                .translationY(-100)
+                .setInterpolator(AnimationUtils.loadInterpolator(
+                        mContext, android.R.interpolator.fast_out_linear_in))
+                .setDuration(100)
+                .withEndAction(finishRunnable);
+        return true;
+    }
+
     private void enableClipping(boolean enable) {
         setClipChildren(enable);
         mKeyguardBouncerFrame.setClipToPadding(enable);
@@ -477,4 +499,9 @@
         animator.start();
         mLockPatternView.invalidate();
     }
+
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 1835b8e..119471b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -91,6 +91,14 @@
         }
     }
 
+    public boolean startDisappearAnimation(Runnable onFinishRunnable) {
+        if (mCurrentSecuritySelection != SecurityMode.None) {
+            return getSecurityView(mCurrentSecuritySelection).startDisappearAnimation(
+                    onFinishRunnable);
+        }
+        return false;
+    }
+
     void updateSecurityViews(boolean isBouncing) {
         int children = mSecurityViewFlipper.getChildCount();
         for (int i = 0; i < children; i++) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
index 86bd877..78fcb9f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
@@ -89,4 +89,13 @@
      * Starts the animation which should run when the security view appears.
      */
     void startAppearAnimation();
+
+    /**
+     * Starts the animation which should run when the security view disappears.
+     *
+     * @param finishRunnable the runnable to be run when the animation ended
+     * @return true if an animation started and {@code finishRunnable} will be run, false if no
+     *         animation started and {@code finishRunnable} will not be run
+     */
+    boolean startDisappearAnimation(Runnable finishRunnable);
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 178ca5e..ea5c304 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -167,6 +167,16 @@
     }
 
     @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            return ksv.startDisappearAnimation(finishRunnable);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
         return p instanceof LayoutParams;
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index e8e3b19..5a0fdb2 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -26,14 +26,9 @@
 import android.app.ProgressDialog;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
 import android.util.AttributeSet;
-import android.view.View;
 import android.util.Log;
 import android.view.WindowManager;
-import android.widget.TextView.OnEditorActionListener;
 
 /**
  * Displays a PIN pad for unlocking.
@@ -237,5 +232,10 @@
     public void startAppearAnimation() {
         // noop.
     }
+
+    @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        return false;
+    }
 }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index b956e99..f0c5805 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -23,14 +23,9 @@
 import android.app.ProgressDialog;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.text.InputType;
-import android.text.TextWatcher;
-import android.text.method.DigitsKeyListener;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.view.WindowManager;
-import android.widget.TextView.OnEditorActionListener;
 
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.PhoneConstants;
@@ -306,6 +301,11 @@
     public void startAppearAnimation() {
         // noop.
     }
+
+    @Override
+    public boolean startDisappearAnimation(Runnable finishRunnable) {
+        return false;
+    }
 }
 
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index 276f795..d9c5a53 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -236,6 +236,12 @@
         mSecurityContainer.startAppearAnimation();
     }
 
+    public void startDisappearAnimation(Runnable finishRunnable) {
+        if (!mSecurityContainer.startDisappearAnimation(finishRunnable)) {
+            finishRunnable.run();
+        }
+    }
+
     /**
      * Verify that the user can get past the keyguard securely.  This is called,
      * for example, when the phone disables the keyguard but then wants to launch
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e48aef1..b8836a0 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -327,7 +327,7 @@
         <activity
             android:name=".settings.BrightnessDialog"
             android:label="@string/quick_settings_brightness_dialog_title"
-            android:theme="@android:style/Theme.DeviceDefault.Light.Dialog"
+            android:theme="@android:style/Theme.DeviceDefault.Dialog"
             android:finishOnCloseSystemDialogs="true"
             android:launchMode="singleInstance"
             android:excludeFromRecents="true"
diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
new file mode 100644
index 0000000..dc978fe
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="28.0dp"
+        android:height="28.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="m18.250000,12.000000a6.250000,6.250000 0.000000,1.000000 1.000000,-12.500000 0.000000,6.250000 6.250000,0.000000 1.000000,1.000000 12.500000,0.000000z"
+        android:fillColor="@color/system_primary_color" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M20.000000,8.700000L20.000000,4.000000L15.300000,4.000000L12.000000,0.700000 8.700000,4.000000L4.000000,4.000000L4.000000,8.700000L0.700000,12.000000 4.000000,15.300000L4.000000,20.000000L8.700000,20.000000L12.000000,23.299999 15.300000,20.000000L20.000000,20.000000L20.000000,15.300000L23.299999,12.000000 20.000000,8.700000zM12.000000,18.000000C8.700000,18.000000 6.000000,15.300000 6.000000,12.000000 6.000000,8.700000 8.700000,6.000000 12.000000,6.000000c3.300000,0.000000 6.000000,2.700000 6.000000,6.000000 0.000000,3.300000 -2.700000,6.000000 -6.000000,6.000000zM12.000000,8.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000 0.000000,2.200000 1.800000,4.000000 4.000000,4.000000 2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000 0.000000,-2.200000 -1.800000,-4.000000 -4.000000,-4.000000z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index 7ded708..f776a87 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -15,6 +15,8 @@
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"
     style="@style/BrightnessDialogContainer">
 
     <ImageView
@@ -24,7 +26,8 @@
         android:layout_gravity="center_vertical"
         android:layout_marginEnd="8dp"
         android:src="@drawable/ic_qs_brightness_auto_off"
-        android:contentDescription="@null" />
+        android:contentDescription="@null"
+        android:visibility="gone" />
 
     <com.android.systemui.settings.ToggleSlider
         android:id="@+id/brightness_slider"
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
index 1928506..062e6cb 100644
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
@@ -41,6 +41,10 @@
         android:layout_alignParentEnd="true"
         android:paddingStart="20dp"
         android:paddingEnd="20dp"
+        android:paddingTop="16dp"
+        android:paddingBottom="16dp"
+        android:thumb="@drawable/ic_brightness_thumb"
+        android:splitTrack="false"
         />
     <TextView
         android:id="@+id/label"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4a4fa41..3db0a2b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -175,6 +175,7 @@
     <dimen name="qs_panel_padding_bottom">8dp</dimen>
     <dimen name="qs_detail_item_height">48dp</dimen>
     <dimen name="qs_detail_item_height_twoline">72dp</dimen>
+    <dimen name="qs_brightness_padding_top">6dp</dimen>
 
 
     <dimen name="segmented_button_spacing">4dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 93ed231..72886c6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -782,4 +782,7 @@
     <!-- Monitoring dialog legacy VPN with device owner text [CHAR LIMIT=300] -->
     <string name="monitoring_description_legacy_vpn_device_owned">This device is managed by:\n<xliff:g id="organization">%1$s</xliff:g>\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites. For more information, contact your administrator.\n\nAlso, you\'re connected to a VPN (\"<xliff:g id="application">%2$s</xliff:g>\"). Your VPN service provider can monitor network activity too.</string>
 
+    <!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] -->
+    <string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string>
+
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index baaa379..0d3a487 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -211,7 +211,6 @@
     <style name="BaseBrightnessDialogContainer">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:padding">16dp</item>
         <item name="android:layout_alignParentBottom">true</item>
     </style>
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6c00f4c..117515b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1200,23 +1200,29 @@
     private void handleHide() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleHide");
-            try {
-                mHiding = true;
-                if (mShowing && !mOccluded) {
 
-                    // Don't actually hide the Keyguard at the moment, wait for window manager until
-                    // it tells us it's safe to do so with startKeyguardExitAnimation.
-                    mWM.keyguardGoingAway();
-                } else {
+            mHiding = true;
+            if (mShowing && !mOccluded) {
+                mStatusBarKeyguardViewManager.startPreHideAnimation(new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            // Don't actually hide the Keyguard at the moment, wait for window
+                            // manager until it tells us it's safe to do so with
+                            // startKeyguardExitAnimation.
+                            mWM.keyguardGoingAway();
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "Error while calling WindowManager", e);
+                        }
+                    }
+                });
+            } else {
 
-                    // Don't try to rely on WindowManager - if Keyguard wasn't showing, window
-                    // manager won't start the exit animation.
-                    handleStartKeyguardExitAnimation(
-                            SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
-                            mHideAnimation.getDuration());
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error while calling WindowManager", e);
+                // Don't try to rely on WindowManager - if Keyguard wasn't showing, window
+                // manager won't start the exit animation.
+                handleStartKeyguardExitAnimation(
+                        SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
+                        mHideAnimation.getDuration());
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 6d88214..c3144c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -61,6 +61,7 @@
     private int mLargeCellHeight;
     private int mPanelPaddingBottom;
     private int mDualTileUnderlap;
+    private int mBrightnessPaddingTop;
     private boolean mExpanded;
     private boolean mListening;
 
@@ -136,6 +137,7 @@
         mLargeCellWidth = (int)(mLargeCellHeight * TILE_ASPECT);
         mPanelPaddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom);
         mDualTileUnderlap = res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical);
+        mBrightnessPaddingTop = res.getDimensionPixelSize(R.dimen.qs_brightness_padding_top);
         if (mColumns != columns) {
             mColumns = columns;
             postInvalidate();
@@ -320,6 +322,7 @@
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int width = MeasureSpec.getSize(widthMeasureSpec);
         mBrightnessView.measure(exactly(width), MeasureSpec.UNSPECIFIED);
+        final int brightnessHeight = mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop;
         mFooter.getView().measure(exactly(width), MeasureSpec.UNSPECIFIED);
         int r = -1;
         int c = -1;
@@ -348,9 +351,9 @@
             final int ch = record.row == 0 ? mLargeCellHeight : mCellHeight;
             record.tileView.measure(exactly(cw), exactly(ch));
         }
-        int h = rows == 0 ? mBrightnessView.getHeight() : (getRowTop(rows) + mPanelPaddingBottom);
+        int h = rows == 0 ? brightnessHeight : (getRowTop(rows) + mPanelPaddingBottom);
         if (mFooter.hasFooter()) {
-            h += mFooter.getView().getHeight();
+            h += mFooter.getView().getMeasuredHeight();
         }
         mDetail.measure(exactly(width), MeasureSpec.UNSPECIFIED);
         if (mDetail.getMeasuredHeight() < h) {
@@ -366,8 +369,9 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         final int w = getWidth();
-        mBrightnessView.layout(0, 0,
-                mBrightnessView.getMeasuredWidth(), mBrightnessView.getMeasuredHeight());
+        mBrightnessView.layout(0, mBrightnessPaddingTop,
+                mBrightnessView.getMeasuredWidth(),
+                mBrightnessPaddingTop + mBrightnessView.getMeasuredHeight());
         for (TileRecord record : mRecords) {
             if (record.tileView.getVisibility() == GONE) continue;
             final int cols = getColumnCount(record.row);
@@ -389,8 +393,8 @@
     }
 
     private int getRowTop(int row) {
-        if (row <= 0) return mBrightnessView.getHeight();
-        return mBrightnessView.getHeight()
+        if (row <= 0) return mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop;
+        return mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop
                 + mLargeCellHeight - mDualTileUnderlap + (row - 1) * mCellHeight;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 6779e4e..4a6bfa10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -401,7 +401,9 @@
             Interpolator interpolator, Runnable runnable) {
         cancelAnimator(mAlphaAnimator);
         int endAlpha = (int) (alpha * 255);
+        final Drawable background = getBackground();
         if (!animate) {
+            if (background != null) background.mutate().setAlpha(endAlpha);
             setImageAlpha(endAlpha);
         } else {
             int currentAlpha = getImageAlpha();
@@ -410,7 +412,9 @@
             animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                 @Override
                 public void onAnimationUpdate(ValueAnimator animation) {
-                    setImageAlpha((int) animation.getAnimatedValue());
+                    int alpha = (int) animation.getAnimatedValue();
+                    if (background != null) background.mutate().setAlpha(alpha);
+                    setImageAlpha(alpha);
                 }
             });
             animator.addListener(mAlphaEndListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 79f9da4..e11f20f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -38,6 +38,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.policy.PreviewInflater;
@@ -72,6 +73,7 @@
     private LockPatternUtils mLockPatternUtils;
     private FlashlightController mFlashlightController;
     private PreviewInflater mPreviewInflater;
+    private KeyguardIndicationController mIndicationController;
     private boolean mFaceUnlockRunning;
 
     public KeyguardBottomAreaView(Context context) {
@@ -111,6 +113,7 @@
         setClipToPadding(false);
         mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
         inflatePreviews();
+        mLockIcon.setOnClickListener(this);
     }
 
     public void setActivityStarter(ActivityStarter activityStarter) {
@@ -204,6 +207,10 @@
             launchCamera();
         } else if (v == mPhoneImageView) {
             launchPhone();
+        } if (v == mLockIcon) {
+            mIndicationController.showTransientIndication(
+                    R.string.keyguard_indication_trust_disabled);
+            mLockPatternUtils.requireCredentialEntry(mLockPatternUtils.getCurrentUser());
         }
     }
 
@@ -244,6 +251,7 @@
         boolean trustManaged = mUnlockMethodCache.isTrustManaged();
         mLockIcon.setBackgroundResource(trustManaged && !mFaceUnlockRunning
                 ? R.drawable.trust_circle : 0);
+        mLockIcon.setClickable(trustManaged);
     }
 
     public KeyguardAffordanceView getPhoneView() {
@@ -318,4 +326,9 @@
             updateLockIcon();
         }
     };
+
+    public void setKeyguardIndicationController(
+            KeyguardIndicationController keyguardIndicationController) {
+        mIndicationController = keyguardIndicationController;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3b140823..db42b9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -92,27 +92,14 @@
         }
     }
 
-    public void animateHide(long delay, long duration) {
-        if (isShowing()) {
-            mFadingOut = true;
-            mKeyguardView.animate()
-                    .alpha(0)
-                    .withLayer()
-
-                    // Make it disappear faster, as the focus should be on the activity behind.
-                    .setDuration(duration / 2)
-                    .setInterpolator(PhoneStatusBar.ALPHA_OUT)
-                    .setStartDelay(delay)
-                    .withEndAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            mFadingOut = false;
-                            hide(true /* destroyView */);
-                        }
-                    })
-                    .start();
+    /**
+     * See {@link StatusBarKeyguardViewManager#startPreHideAnimation}.
+     */
+    public void startPreHideAnimation(Runnable runnable) {
+        if (mKeyguardView != null) {
+            mKeyguardView.startDisappearAnimation(runnable);
         } else {
-            hide(true /* destroyView */);
+            runnable.run();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index f8319c2..caecf1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -721,6 +721,7 @@
         mKeyguardIndicationController = new KeyguardIndicationController(mContext,
                 (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
                         R.id.keyguard_indication_text));
+        mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
 
         mTickerEnabled = res.getBoolean(R.bool.enable_ticker);
         if (mTickerEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index a9fc3d8..455c336 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -24,6 +24,7 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewTreeObserver;
+import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
@@ -38,7 +39,8 @@
     private static final boolean DEBUG = false;
 
     private static final float SCRIM_BEHIND_ALPHA = 0.62f;
-    private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.5f;
+    private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.55f;
+    private static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f;
     private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
     private static final long ANIMATION_DURATION = 220;
     private static final int TAG_KEY_ANIM = R.id.scrim;
@@ -71,11 +73,14 @@
     private boolean mDozing;
     private int mPulsesRemaining;
     private final Interpolator mInterpolator = new DecelerateInterpolator();
+    private final Interpolator mLinearOutSlowInInterpolator;
 
     public ScrimController(View scrimBehind, View scrimInFront) {
         mScrimBehind = scrimBehind;
         mScrimInFront = scrimInFront;
         mUnlockMethodCache = UnlockMethodCache.getInstance(scrimBehind.getContext());
+        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(scrimBehind.getContext(),
+                android.R.interpolator.linear_out_slow_in);
     }
 
     public void setKeyguardShowing(boolean showing) {
@@ -171,6 +176,8 @@
         if (mExpanding && mDarkenWhileDragging) {
             float behindFraction = Math.max(0, Math.min(mFraction, 1));
             float fraction = 1 - behindFraction;
+            fraction = (float) Math.pow(fraction, 0.8f);
+            behindFraction = (float) Math.pow(behindFraction, 0.8f);
             setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
             setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD);
         } else if (mBouncerShowing) {
@@ -179,8 +186,11 @@
         } else if (mDozing) {
             setScrimInFrontColor(1);
         } else {
+            float fraction = Math.max(0, Math.min(mFraction, 1));
             setScrimInFrontColor(0f);
-            setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD);
+            setScrimBehindColor(fraction
+                    * (SCRIM_BEHIND_ALPHA_KEYGUARD - SCRIM_BEHIND_ALPHA_UNLOCKING)
+                    + SCRIM_BEHIND_ALPHA_UNLOCKING);
         }
     }
 
@@ -239,7 +249,9 @@
                 scrim.setBackgroundColor(Color.argb(value, 0, 0, 0));
             }
         });
-        anim.setInterpolator(mInterpolator);
+        anim.setInterpolator(mAnimateKeyguardFadingOut
+                ? mLinearOutSlowInInterpolator
+                : mInterpolator);
         anim.setStartDelay(mAnimationDelay);
         anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION);
         anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6831933..68dd4f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -39,6 +39,10 @@
  * {@link com.android.keyguard.KeyguardViewBase}.
  */
 public class StatusBarKeyguardViewManager {
+
+    // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
+    private static final long HIDE_TIMING_CORRECTION_MS = -3 * 16;
+
     private static String TAG = "StatusBarKeyguardViewManager";
 
     private final Context mContext;
@@ -199,13 +203,27 @@
     }
 
     /**
+     * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
+     * security view of the bouncer.
+     *
+     * @param finishRunnable the runnable to be run after the animation finished
+     */
+    public void startPreHideAnimation(Runnable finishRunnable) {
+        if (mBouncer.isShowing()) {
+            mBouncer.startPreHideAnimation(finishRunnable);
+        } else {
+            finishRunnable.run();
+        }
+    }
+
+    /**
      * Hides the keyguard view
      */
     public void hide(long startTime, final long fadeoutDuration) {
         mShowing = false;
 
         long uptimeMillis = SystemClock.uptimeMillis();
-        long delay = Math.max(0, startTime - uptimeMillis);
+        long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
 
         if (mPhoneStatusBar.isInLaunchTransition() ) {
             mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
@@ -213,8 +231,7 @@
                 public void run() {
                     mStatusBarWindowManager.setKeyguardShowing(false);
                     mStatusBarWindowManager.setKeyguardFadingAway(true);
-                    mBouncer.animateHide(PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
-                            PhoneStatusBar.FADE_KEYGUARD_DURATION);
+                    mBouncer.hide(true /* destroyView */);
                     updateStates();
                     mScrimController.animateKeyguardFadingOut(
                             PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
@@ -245,7 +262,7 @@
                 mPhoneStatusBar.finishKeyguardFadingAway();
             }
             mStatusBarWindowManager.setKeyguardShowing(false);
-            mBouncer.animateHide(delay, fadeoutDuration);
+            mBouncer.hide(true /* destroyView */);
             mViewMediatorCallback.keyguardGone();
             updateStates();
         }
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 56a8f7c..da8ec2a 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -283,7 +283,7 @@
                 addUsersToMenu(mItems);
             } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
                 mItems.add(getSettingsAction());
-            } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey) && hasTrustAgents()) {
+            } else if (GLOBAL_ACTION_KEY_LOCKDOWN.equals(actionKey)) {
                 mItems.add(getLockdownAction());
             } else {
                 Log.e(TAG, "Invalid global action key " + actionKey);
@@ -323,11 +323,6 @@
         return dialog;
     }
 
-    private boolean hasTrustAgents() {
-        // TODO: Add implementation.
-        return true;
-    }
-
     private final class PowerAction extends SinglePressAction implements LongPressAction {
         private PowerAction() {
             super(com.android.internal.R.drawable.ic_lock_power_off,
diff --git a/policy/src/com/android/internal/policy/impl/LogDecelerateInterpolator.java b/policy/src/com/android/internal/policy/impl/LogDecelerateInterpolator.java
new file mode 100644
index 0000000..1f3e1de
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/LogDecelerateInterpolator.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 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
+ */
+
+package com.android.internal.policy.impl;
+
+import android.view.animation.Interpolator;
+
+public class LogDecelerateInterpolator implements Interpolator {
+
+    private int mBase;
+    private int mDrift;
+    private final float mLogScale;
+
+    public LogDecelerateInterpolator(int base, int drift) {
+        mBase = base;
+        mDrift = drift;
+
+        mLogScale = 1f / computeLog(1, mBase, mDrift);
+    }
+
+    private static float computeLog(float t, int base, int drift) {
+        return (float) -Math.pow(base, -t) + 1 + (drift * t);
+    }
+
+    @Override
+    public float getInterpolation(float t) {
+        return computeLog(t, mBase, mDrift) * mLogScale;
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 14f6c5a..ca260ec 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -99,7 +99,9 @@
 import android.view.WindowManagerPolicy;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
 import android.view.animation.AnimationUtils;
 
 import com.android.internal.R;
@@ -528,6 +530,9 @@
     private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
             new SparseArray<KeyCharacterMap.FallbackAction>();
 
+    private final LogDecelerateInterpolator mLogDecelerateInterpolator
+            = new LogDecelerateInterpolator(100, 0);
+
     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -2060,8 +2065,31 @@
 
     @Override
     public Animation createForceHideEnterAnimation(boolean onWallpaper) {
-        return AnimationUtils.loadAnimation(mContext,
-                com.android.internal.R.anim.lock_screen_behind_enter);
+        if (onWallpaper) {
+            Animation a = AnimationUtils.loadAnimation(mContext,
+                    R.anim.lock_screen_behind_enter_wallpaper);
+            AnimationSet set = (AnimationSet) a;
+
+            // TODO: Use XML interpolators when we have log interpolators available in XML.
+            set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
+            set.getAnimations().get(1).setInterpolator(mLogDecelerateInterpolator);
+            set.getAnimations().get(2).setInterpolator(mLogDecelerateInterpolator);
+            return set;
+        } else {
+            Animation a = AnimationUtils.loadAnimation(mContext,
+                    R.anim.lock_screen_behind_enter);
+            AnimationSet set = (AnimationSet) a;
+
+            // TODO: Use XML interpolators when we have log interpolators available in XML.
+            set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
+            return set;
+        }
+    }
+
+
+    @Override
+    public Animation createForceHideWallpaperExitAnimation() {
+        return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit);
     }
 
     private static void awakenDreams() {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 08cb791..b229c4f3 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4470,11 +4470,6 @@
                                 1000);
                     }
                 }
-
-                // this will cause us to come up initially as unconnected and switching
-                // to connected after our normal pause unless somebody reports us as
-                // really disconnected
-                mDefaultInetConditionPublished = 0;
                 // TODO - read the tcp buffer size config string from somewhere
                 // updateNetworkSettings();
             }
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 9b69ce2..5b05d53 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.os.RemoteException;
 import android.util.Slog;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 27fff1d..32e8afe 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -220,6 +220,7 @@
         final WindowList windows = mService.getWindowListLocked(displayId);
         ArrayList<WindowStateAnimator> unForceHiding = null;
         boolean wallpaperInUnForceHiding = false;
+        WindowState wallpaper = null;
 
         if (mKeyguardGoingAway) {
             for (int i = windows.size() - 1; i >= 0; i--) {
@@ -378,6 +379,9 @@
                     appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
                 }
             }
+            if (win.mIsWallpaper) {
+                wallpaper = win;
+            }
         } // end forall windows
 
         // If we have windows that are being show due to them no longer
@@ -389,7 +393,7 @@
                 if (a != null) {
                     final WindowStateAnimator winAnimator = unForceHiding.get(i);
                     winAnimator.setAnimation(a);
-                    winAnimator.mAnimationIsEntrance = true;
+                    winAnimator.keyguardGoingAwayAnimation = true;
                     if (startKeyguardExit && mKeyguardGoingAway) {
                         // Do one time only.
                         mPolicy.startKeyguardExitAnimation(mCurrentTime + a.getStartOffset(),
@@ -399,6 +403,12 @@
                     }
                 }
             }
+
+            // Wallpaper is going away in un-force-hide motion, animate it as well.
+            if (!wallpaperInUnForceHiding && wallpaper != null) {
+                WindowStateAnimator animator = wallpaper.mWinAnimator;
+                animator.setAnimation(mPolicy.createForceHideWallpaperExitAnimation());
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4e711ba..e7ebae7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1695,7 +1695,13 @@
             }
             if (DEBUG_WALLPAPER) Slog.v(TAG, "Win #" + i + " " + w + ": isOnScreen="
                     + w.isOnScreen() + " mDrawState=" + w.mWinAnimator.mDrawState);
-            if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isOnScreen()
+
+            // If the app is executing an animation because the keyguard is going away, keep the
+            // wallpaper during the animation so it doesn't flicker out.
+            final boolean hasWallpaper = (w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0
+                    || (w.mAppToken != null
+                            && w.mWinAnimator.keyguardGoingAwayAnimation);
+            if (hasWallpaper && w.isOnScreen()
                     && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
                 if (DEBUG_WALLPAPER) Slog.v(TAG,
                         "Found wallpaper target: #" + i + "=" + w);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 85dc810..61c50d67 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -140,6 +140,8 @@
     // an enter animation.
     boolean mEnterAnimationPending;
 
+    boolean keyguardGoingAwayAnimation;
+
     /** This is set when there is no Surface */
     static final int NO_SURFACE = 0;
     /** This is set after the Surface has been created but before the window has been drawn. During
@@ -220,6 +222,7 @@
             mLocalAnimating = false;
             mAnimation.cancel();
             mAnimation = null;
+            keyguardGoingAwayAnimation = false;
         }
     }
 
@@ -341,6 +344,7 @@
             + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
 
         mAnimating = false;
+        keyguardGoingAwayAnimation = false;
         mLocalAnimating = false;
         if (mAnimation != null) {
             mAnimation.cancel();
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index c38391a..82e837d 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -311,11 +311,15 @@
             final int userId = UserHandle.getCallingUserId();
             final long token = Binder.clearCallingIdentity();
             try {
-                return new ParceledListSlice<>(UsageStatsService.this.queryUsageStats(
-                        userId, bucketType, beginTime, endTime));
+                final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
+                        userId, bucketType, beginTime, endTime);
+                if (results != null) {
+                    return new ParceledListSlice<>(results);
+                }
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
+            return null;
         }
 
         @Override
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 2dfd0f6..e489fb3 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -181,7 +181,7 @@
 
         final List<UsageStats> results = mDatabase.queryUsageStats(bucketType, beginTime, endTime);
         if (DEBUG) {
-            Slog.d(TAG, mLogPrefix + "Results: " + results.size());
+            Slog.d(TAG, mLogPrefix + "Results: " + (results == null ? 0 : results.size()));
         }
         return results;
     }
diff --git a/telecomm/java/android/telecomm/StatusHints.java b/telecomm/java/android/telecomm/StatusHints.java
index 50f525a..496a38c 100644
--- a/telecomm/java/android/telecomm/StatusHints.java
+++ b/telecomm/java/android/telecomm/StatusHints.java
@@ -27,6 +27,7 @@
 import android.util.DisplayMetrics;
 
 import java.util.MissingResourceException;
+import java.util.Objects;
 
 /**
  * Contains status label and icon displayed in the in-call UI.
@@ -127,4 +128,22 @@
             return null;
         }
     }
+
+    @Override
+    public boolean equals(Object other) {
+        if (other != null && other instanceof StatusHints) {
+            StatusHints otherHints = (StatusHints) other;
+            return Objects.equals(otherHints.getComponentName(), getComponentName()) &&
+                    Objects.equals(otherHints.getLabel(), getLabel()) &&
+                    otherHints.getIconId() == getIconId() &&
+                    Objects.equals(otherHints.getExtras(), getExtras());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(mComponentName) + Objects.hashCode(mLabel) + mIconId +
+                Objects.hashCode(mExtras);
+    }
 }