Fix jank when pin/pattern is shown

- Only update layout params of status bar window when needed
- Do not update security method all the time, only when needed (only
  when reset gets called)
- Check for actual used security method when updating states for
  bouncer

Bug: 18505838
Change-Id: Ib3d0021c0cc364fa5598e06e0a2bae059ae79cbe
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 979c377..faecaed 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -399,8 +399,6 @@
                     showPrimarySecurityScreen(false);
                     break;
             }
-        } else {
-            showPrimarySecurityScreen(false);
         }
         if (finish) {
             mSecurityCallback.finish();
@@ -556,6 +554,10 @@
         return mSecurityModel.getSecurityMode();
     }
 
+    public SecurityMode getCurrentSecurityMode() {
+        return mCurrentSecuritySelection;
+    }
+
     public void verifyUnlock() {
         mIsVerifyUnlockOnly = true;
         showSecurityScreen(getSecurityMode());
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index e35b2b2..e1e1cfc 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -112,7 +112,7 @@
     /**
      * Called when the view needs to be shown.
      */
-    public void show() {
+    public void showPrimarySecurityScreen() {
         if (DEBUG) Log.d(TAG, "show()");
         mSecurityContainer.showPrimarySecurityScreen(false);
     }
@@ -224,7 +224,6 @@
      */
     public void onResume() {
         if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
-        mSecurityContainer.showPrimarySecurityScreen(false);
         mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
         requestFocus();
     }
@@ -473,6 +472,10 @@
         return mSecurityContainer.getSecurityMode();
     }
 
+    public SecurityMode getCurrentSecurityMode() {
+        return mSecurityContainer.getCurrentSecurityMode();
+    }
+
     protected abstract void onUserSwitching(boolean switching);
 
     protected abstract void onCreateOptions(Bundle options);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4e034ae..206fc43 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -957,6 +957,7 @@
         // if the keyguard is already showing, don't bother
         if (mStatusBarKeyguardViewManager.isShowing()) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
+            resetStateLocked();
             return;
         }
 
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 5507944..3292f9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -57,13 +57,14 @@
         mWindowManager = windowManager;
     }
 
-    public void show() {
+    public void show(boolean resetSecuritySelection) {
         ensureView();
+        if (resetSecuritySelection) {
+            // showPrimarySecurityScreen() updates the current security method. This is needed in
+            // case we are already showing and the current security method changed.
+            mKeyguardView.showPrimarySecurityScreen();
+        }
         if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
-
-            // show() updates the current security method. This is needed in case we are already
-            // showing and the current security method changed.
-            mKeyguardView.show();
             return;
         }
 
@@ -74,7 +75,7 @@
 
             // Split up the work over multiple frames.
             mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable,
-                    null, 48);
+                    null, 16);
         }
     }
 
@@ -96,7 +97,7 @@
     public void showWithDismissAction(OnDismissAction r) {
         ensureView();
         mKeyguardView.setOnDismissAction(r);
-        show();
+        show(false /* resetSecuritySelection */);
     }
 
     public void hide(boolean destroyView) {
@@ -152,7 +153,11 @@
     }
 
     public void prepare() {
+        boolean wasInitialized = mRoot != null;
         ensureView();
+        if (wasInitialized) {
+            mKeyguardView.showPrimarySecurityScreen();
+        }
     }
 
     private void ensureView() {
@@ -184,14 +189,25 @@
     }
 
     /**
-     * @return True if and only if the current security method should be shown before showing
-     *         the notifications on Keyguard, like SIM PIN/PUK.
+     * @return True if and only if the security method should be shown before showing the
+     * notifications on Keyguard, like SIM PIN/PUK.
      */
     public boolean needsFullscreenBouncer() {
         if (mKeyguardView != null) {
             SecurityMode mode = mKeyguardView.getSecurityMode();
-            return mode == SecurityMode.SimPin
-                    || mode == SecurityMode.SimPuk;
+            return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
+        }
+        return false;
+    }
+
+    /**
+     * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which
+     * makes this method much faster.
+     */
+    public boolean isFullscreenBouncer() {
+        if (mKeyguardView != null) {
+            SecurityMode mode = mKeyguardView.getCurrentSecurityMode();
+            return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
         }
         return false;
     }
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 0e6f1b9..77da70a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -110,7 +110,7 @@
 
             // The keyguard might be showing (already). So we need to hide it.
             mPhoneStatusBar.hideKeyguard();
-            mBouncer.show();
+            mBouncer.show(true /* resetSecuritySelection */);
         } else {
             mPhoneStatusBar.showKeyguard();
             mBouncer.hide(false /* destroyView */);
@@ -120,7 +120,7 @@
 
     private void showBouncer() {
         if (mShowing) {
-            mBouncer.show();
+            mBouncer.show(false /* resetSecuritySelection */);
         }
         updateStates();
     }
@@ -130,7 +130,7 @@
             if (!afterKeyguardGone) {
                 mBouncer.showWithDismissAction(r);
             } else {
-                mBouncer.show();
+                mBouncer.show(false /* resetSecuritySelection */);
                 mAfterKeyguardGoneAction = r;
             }
         }
@@ -354,7 +354,7 @@
         boolean showing = mShowing;
         boolean occluded = mOccluded;
         boolean bouncerShowing = mBouncer.isShowing();
-        boolean bouncerDismissible = !mBouncer.needsFullscreenBouncer();
+        boolean bouncerDismissible = !mBouncer.isFullscreenBouncer();
 
         if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing)
                 || mFirstUpdate) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 4053c1e..0dbdca1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -39,6 +39,7 @@
     private final WindowManager mWindowManager;
     private View mStatusBarView;
     private WindowManager.LayoutParams mLp;
+    private WindowManager.LayoutParams mLpChanged;
     private int mBarHeight;
     private final boolean mKeyguardScreenRotation;
 
@@ -85,41 +86,43 @@
         mStatusBarView = statusBarView;
         mBarHeight = barHeight;
         mWindowManager.addView(mStatusBarView, mLp);
+        mLpChanged = new WindowManager.LayoutParams();
+        mLpChanged.copyFrom(mLp);
     }
 
     private void applyKeyguardFlags(State state) {
         if (state.keyguardShowing) {
-            mLp.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-            mLp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+            mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         } else {
-            mLp.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-            mLp.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+            mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
     }
 
     private void adjustScreenOrientation(State state) {
         if (state.isKeyguardShowingAndNotOccluded()) {
             if (mKeyguardScreenRotation) {
-                mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
             } else {
-                mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+                mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
             }
         } else {
-            mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+            mLpChanged.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
         }
     }
 
     private void applyFocusableFlag(State state) {
         if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput
                 && state.bouncerShowing) {
-            mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-            mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) {
-            mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-            mLp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         } else {
-            mLp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-            mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         }
     }
 
@@ -127,9 +130,9 @@
         boolean expanded = state.isKeyguardShowingAndNotOccluded() || state.statusBarExpanded
                 || state.keyguardFadingAway || state.bouncerShowing;
         if (expanded) {
-            mLp.height = ViewGroup.LayoutParams.MATCH_PARENT;
+            mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT;
         } else {
-            mLp.height = mBarHeight;
+            mLpChanged.height = mBarHeight;
         }
     }
 
@@ -141,9 +144,9 @@
         if (state.isKeyguardShowingAndNotOccluded()
                 && state.statusBarState == StatusBarState.KEYGUARD
                 && !state.qsExpanded) {
-            mLp.userActivityTimeout = state.keyguardUserActivityTimeout;
+            mLpChanged.userActivityTimeout = state.keyguardUserActivityTimeout;
         } else {
-            mLp.userActivityTimeout = -1;
+            mLpChanged.userActivityTimeout = -1;
         }
     }
 
@@ -151,9 +154,11 @@
         if (state.isKeyguardShowingAndNotOccluded()
                 && state.statusBarState == StatusBarState.KEYGUARD
                 && !state.qsExpanded) {
-            mLp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+            mLpChanged.inputFeatures |=
+                    WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
         } else {
-            mLp.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+            mLpChanged.inputFeatures &=
+                    ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
         }
     }
 
@@ -165,7 +170,9 @@
         applyUserActivityTimeout(state);
         applyInputFeatures(state);
         applyFitsSystemWindows(state);
-        mWindowManager.updateViewLayout(mStatusBarView, mLp);
+        if (mLp.copyFrom(mLpChanged) != 0) {
+            mWindowManager.updateViewLayout(mStatusBarView, mLp);
+        }
     }
 
     public void setKeyguardShowing(boolean showing) {