Improve scrim handling

Bug: 15163546
Change-Id: I0d2c05b035f832f4b4e6a2fc34113fe9d5677525
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e73e904..b2872fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -62,6 +62,7 @@
 import com.android.keyguard.analytics.Session;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarWindowManager;
 
@@ -1316,9 +1317,10 @@
     }
 
     public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatusBar,
-            ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+            ViewGroup container, StatusBarWindowManager statusBarWindowManager,
+            ScrimController scrimController) {
         mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
-                statusBarWindowManager);
+                statusBarWindowManager, scrimController);
         return mStatusBarKeyguardViewManager;
     }
 
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 5e9ce21..714ad06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -29,18 +29,11 @@
 import android.provider.MediaStore;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
 
 /**
@@ -48,7 +41,8 @@
  * text.
  */
 public class KeyguardBottomAreaView extends FrameLayout
-        implements SwipeAffordanceView.AffordanceListener {
+        implements SwipeAffordanceView.AffordanceListener,
+        UnlockMethodCache.OnUnlockMethodChangedListener {
 
     final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
 
@@ -60,9 +54,7 @@
 
     private PowerManager mPowerManager;
     private ActivityStarter mActivityStarter;
-
-    private LockPatternUtils mLockPatternUtils;
-    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private UnlockMethodCache mUnlockMethodCache;
 
     public KeyguardBottomAreaView(Context context) {
         super(context);
@@ -89,13 +81,12 @@
         mLockIcon = (ImageView) findViewById(R.id.lock_icon);
         mCameraButton.setAffordanceListener(this);
         mPhoneButton.setAffordanceListener(this);
-        mLockPatternUtils = new LockPatternUtils(getContext());
-        mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
-        KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mCallback);
         watchForDevicePolicyChanges();
         watchForAccessibilityChanges();
         updateCameraVisibility();
         updatePhoneVisibility();
+        mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
+        mUnlockMethodCache.addListener(this);
         updateTrust();
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
     }
@@ -211,28 +202,14 @@
         if (getVisibility() != VISIBLE) {
             return;
         }
-        int user = mLockPatternUtils.getCurrentUser();
-        boolean trust = !mLockPatternUtils.isSecure() ||
-                mKeyguardUpdateMonitor.getUserHasTrust(user);
-
-        int iconRes = trust ? R.drawable.ic_lock_open_24dp : R.drawable.ic_lock_24dp;
+        int iconRes = mUnlockMethodCache.isMethodInsecure()
+                ? R.drawable.ic_lock_open_24dp
+                : R.drawable.ic_lock_24dp;
         mLockIcon.setImageResource(iconRes);
     }
 
-    final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
-        @Override
-        public void onScreenTurnedOn() {
-            updateTrust();
-        }
-
-        @Override
-        public void onUserSwitchComplete(int userId) {
-            updateTrust();
-        }
-
-        @Override
-        public void onTrustChanged(int userId) {
-            updateTrust();
-        }
-    };
+    @Override
+    public void onMethodSecureChanged(boolean methodSecure) {
+        updateTrust();
+    }
 }
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 28367d0..7208523 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -372,6 +372,7 @@
 
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
     private ViewMediatorCallback mKeyguardViewMediatorCallback;
+    private ScrimController mScrimController;
 
     private final Runnable mAutohide = new Runnable() {
         @Override
@@ -638,9 +639,12 @@
         SpeedBumpView speedBump = (SpeedBumpView) LayoutInflater.from(mContext).inflate(
                         R.layout.status_bar_notification_speed_bump, mStackScroller, false);
         mStackScroller.setSpeedBumpView(speedBump);
-
         mExpandedContents = mStackScroller;
 
+        mScrimController = new ScrimController(mStatusBarWindow.findViewById(R.id.scrim_behind),
+                mStatusBarWindow.findViewById(R.id.scrim_in_front));
+        mStatusBarView.setScrimController(mScrimController);
+
         mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
         mHeader.setActivityStarter(this);
         mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
@@ -775,7 +779,7 @@
     private void startKeyguard() {
         KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
-                mStatusBarWindow, mStatusBarWindowManager);
+                mStatusBarWindow, mStatusBarWindowManager, mScrimController);
         mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
     }
 
@@ -1446,6 +1450,10 @@
         startActivityDismissingKeyguard(intent, false);
     }
 
+    public ScrimController getScrimController() {
+        return mScrimController;
+    }
+
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
@@ -2771,10 +2779,12 @@
             mKeyguardBottomArea.setVisibility(View.VISIBLE);
             mHeader.setKeyguardShowing(true);
             mNotificationPanel.setKeyguardShowing(true);
+            mScrimController.setKeyguardShowing(true);
         } else {
             mKeyguardBottomArea.setVisibility(View.GONE);
             mHeader.setKeyguardShowing(false);
             mNotificationPanel.setKeyguardShowing(false);
+            mScrimController.setKeyguardShowing(false);
         }
 
         updateStackScrollerState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 084bfcf..5fdf5bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -36,21 +36,16 @@
     private static final boolean DEBUG_GESTURES = true;
 
     PhoneStatusBar mBar;
-    int mScrimColor;
-    int mScrimColorKeyguard;
 
-    PanelView mFadingPanel = null;
     PanelView mLastFullyOpenedPanel = null;
     PanelView mNotificationPanel;
-    private boolean mShouldFade;
     private final PhoneStatusBarTransitions mBarTransitions;
+    private ScrimController mScrimController;
 
     public PhoneStatusBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         Resources res = getContext().getResources();
-        mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
-        mScrimColorKeyguard = res.getColor(R.color.notification_panel_scrim_color_keyguard);
         mBarTransitions = new PhoneStatusBarTransitions(this);
     }
 
@@ -62,6 +57,10 @@
         mBar = bar;
     }
 
+    public void setScrimController(ScrimController scrimController) {
+        mScrimController = scrimController;
+    }
+
     @Override
     public void onFinishInflate() {
         mBarTransitions.init();
@@ -110,27 +109,11 @@
     }
 
     @Override
-    public void startOpeningPanel(PanelView panel) {
-        super.startOpeningPanel(panel);
-        // we only want to start fading if this is the "first" or "last" panel,
-        // which is kind of tricky to determine
-        mShouldFade = (mFadingPanel == null || mFadingPanel.isFullyExpanded());
-        if (DEBUG) {
-            Log.v(TAG, "start opening: " + panel + " shouldfade=" + mShouldFade);
-        }
-        mFadingPanel = panel;
-    }
-
-    @Override
     public void onAllPanelsCollapsed() {
         super.onAllPanelsCollapsed();
         // give animations time to settle
         mBar.makeExpandedInvisibleSoon();
-        mFadingPanel = null;
         mLastFullyOpenedPanel = null;
-        if (mScrimColor != 0 && ActivityManager.isHighEndGfx() && mBar.mStatusBarWindow != null) {
-            mBar.mStatusBarWindow.setBackgroundColor(0);
-        }
     }
 
     @Override
@@ -139,9 +122,7 @@
         if (openPanel != mLastFullyOpenedPanel) {
             openPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         }
-        mFadingPanel = openPanel;
         mLastFullyOpenedPanel = openPanel;
-        mShouldFade = true; // now you own the fade, mister
     }
 
     @Override
@@ -163,6 +144,7 @@
     public void onTrackingStarted(PanelView panel) {
         super.onTrackingStarted(panel);
         mBar.onTrackingStarted();
+        mScrimController.onTrackingStarted();
     }
 
     @Override
@@ -184,27 +166,7 @@
             Log.v(TAG, "panelExpansionChanged: f=" + frac);
         }
 
-        if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()
-                && mBar.mStatusBarWindow != null) {
-            if (mShouldFade) {
-                int scrimColor = (mBar.getBarState() == StatusBarState.KEYGUARD
-                        || mBar.getBarState() == StatusBarState.SHADE_LOCKED)
-                        ? mScrimColorKeyguard
-                        : mScrimColor;
-                frac = mPanelExpandedFractionSum; // don't judge me
-                // let's start this 20% of the way down the screen
-                frac = frac * 1.2f - 0.2f;
-                if (frac <= 0) {
-                    mBar.mStatusBarWindow.setBackgroundColor(0);
-                } else {
-                    // woo, special effects
-                    final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
-                    // attenuate background color alpha by k
-                    final int color = (int) ((scrimColor >>> 24) * k) << 24 | (scrimColor & 0xFFFFFF);
-                    mBar.mStatusBarWindow.setBackgroundColor(color);
-                }
-            }
-        }
+        mScrimController.setPanelExpansion(frac);
 
         // fade out the panel as it gets buried into the status bar to avoid overdrawing the
         // status bar on the last frame of a close animation
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
new file mode 100644
index 0000000..95255d5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -0,0 +1,187 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnimationUtils;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+
+/**
+ * Controls both the scrim behind the notifications and in front of the notifications (when a
+ * security method gets shown).
+ */
+public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
+
+    private static final float SCRIM_BEHIND_ALPHA = 0.62f;
+    private static final float SCRIM_BEHIND_ALPHA_KEYGUARD = 0.5f;
+    private static final float SCRIM_IN_FRONT_ALPHA = 0.75f;
+    private static final long ANIMATION_DURATION = 220;
+
+    private final View mScrimBehind;
+    private final View mScrimInFront;
+    private final UnlockMethodCache mUnlockMethodCache;
+
+    private boolean mKeyguardShowing;
+    private float mFraction;
+
+    private boolean mDarkenWhileDragging;
+    private boolean mBouncerShowing;
+    private boolean mAnimateChange;
+    private boolean mUpdatePending;
+
+    private final Interpolator mInterpolator = new DecelerateInterpolator();
+
+    public ScrimController(View scrimBehind, View scrimInFront) {
+        mScrimBehind = scrimBehind;
+        mScrimInFront = scrimInFront;
+        mUnlockMethodCache = UnlockMethodCache.getInstance(scrimBehind.getContext());
+    }
+
+    public void setKeyguardShowing(boolean showing) {
+        mKeyguardShowing = showing;
+        scheduleUpdate();
+    }
+
+    public void onTrackingStarted() {
+        mDarkenWhileDragging = !mUnlockMethodCache.isMethodInsecure();
+    }
+
+    public void setPanelExpansion(float fraction) {
+        mFraction = fraction;
+        scheduleUpdate();
+    }
+
+    public void setBouncerShowing(boolean showing) {
+        mBouncerShowing = showing;
+        mAnimateChange = true;
+        scheduleUpdate();
+    }
+
+    private void scheduleUpdate() {
+        if (mUpdatePending) return;
+        mScrimBehind.getViewTreeObserver().addOnPreDrawListener(this);
+        mUpdatePending = true;
+    }
+
+    private void updateScrims() {
+        if (!mKeyguardShowing) {
+            updateScrimNormal();
+            setScrimInFrontColor(0);
+        } else {
+            updateScrimKeyguard();
+        }
+        mAnimateChange = false;
+    }
+
+    private void updateScrimKeyguard() {
+        if (mBouncerShowing) {
+            setScrimInFrontColor(SCRIM_IN_FRONT_ALPHA);
+            setScrimBehindColor(0f);
+        } else if (mDarkenWhileDragging) {
+            float behindFraction = Math.max(0, Math.min(mFraction, 1));
+            float fraction = 1 - behindFraction;
+            setScrimInFrontColor(fraction * SCRIM_IN_FRONT_ALPHA);
+            setScrimBehindColor(behindFraction * SCRIM_BEHIND_ALPHA_KEYGUARD);
+        } else {
+            setScrimInFrontColor(0f);
+            setScrimBehindColor(SCRIM_BEHIND_ALPHA_KEYGUARD);
+        }
+    }
+
+    private void updateScrimNormal() {
+        float frac = mFraction;
+        // let's start this 20% of the way down the screen
+        frac = frac * 1.2f - 0.2f;
+        if (frac <= 0) {
+            setScrimBehindColor(0);
+        } else {
+            // woo, special effects
+            final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
+            setScrimBehindColor(k * SCRIM_BEHIND_ALPHA);
+        }
+    }
+
+    private void setScrimBehindColor(float alpha) {
+        setScrimColor(mScrimBehind, alpha);
+    }
+
+    private void setScrimInFrontColor(float alpha) {
+        setScrimColor(mScrimInFront, alpha);
+        if (alpha == 0f) {
+            mScrimInFront.setClickable(false);
+        } else {
+
+            // Eat touch events.
+            mScrimInFront.setClickable(true);
+        }
+    }
+
+    private void setScrimColor(View scrim, float alpha) {
+        int color = Color.argb((int) (alpha * 255), 0, 0, 0);
+        if (mAnimateChange) {
+            startScrimAnimation(scrim, color);
+        } else {
+            scrim.setBackgroundColor(color);
+        }
+    }
+
+    private void startScrimAnimation(final View scrim, int targetColor) {
+        int current = getBackgroundAlpha(scrim);
+        int target = Color.alpha(targetColor);
+        if (current == targetColor) {
+            return;
+        }
+        ValueAnimator anim = ValueAnimator.ofInt(current, target);
+        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                int value = (int) animation.getAnimatedValue();
+                scrim.setBackgroundColor(Color.argb(value, 0, 0, 0));
+            }
+        });
+        anim.setInterpolator(mInterpolator);
+        anim.setDuration(ANIMATION_DURATION);
+        anim.start();
+    }
+
+    private int getBackgroundAlpha(View scrim) {
+        if (scrim.getBackground() instanceof ColorDrawable) {
+            ColorDrawable drawable = (ColorDrawable) scrim.getBackground();
+            return Color.alpha(drawable.getColor());
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public boolean onPreDraw() {
+        mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
+        mUpdatePending = false;
+        updateScrims();
+        return true;
+    }
+}
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 3f76d26..c3430c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -45,6 +45,7 @@
     private LockPatternUtils mLockPatternUtils;
     private ViewMediatorCallback mViewMediatorCallback;
     private PhoneStatusBar mPhoneStatusBar;
+    private ScrimController mScrimController;
 
     private ViewGroup mContainer;
     private StatusBarWindowManager mStatusBarWindowManager;
@@ -68,10 +69,12 @@
     }
 
     public void registerStatusBar(PhoneStatusBar phoneStatusBar,
-            ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+            ViewGroup container, StatusBarWindowManager statusBarWindowManager,
+            ScrimController scrimController) {
         mPhoneStatusBar = phoneStatusBar;
         mContainer = container;
         mStatusBarWindowManager = statusBarWindowManager;
+        mScrimController = scrimController;
         mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
                 mStatusBarWindowManager, container);
     }
@@ -252,6 +255,7 @@
         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
             mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
             mPhoneStatusBar.setBouncerShowing(bouncerShowing);
+            mScrimController.setBouncerShowing(bouncerShowing);
         }
 
         KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
new file mode 100644
index 0000000..bfd657b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -0,0 +1,107 @@
+/*
+ * 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.systemui.statusbar.phone;
+
+import android.content.Context;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+
+import java.util.ArrayList;
+
+/**
+ * Caches whether the current unlock method is insecure, taking trust into account. This information
+ * might be a little bit out of date and should not be used for actual security decisions; it should
+ * be only used for visual indications.
+ */
+public class UnlockMethodCache {
+
+    private static UnlockMethodCache sInstance;
+
+    private final LockPatternUtils mLockPatternUtils;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final ArrayList<OnUnlockMethodChangedListener> mListeners = new ArrayList<>();
+    private boolean mMethodInsecure;
+
+    private UnlockMethodCache(Context ctx) {
+        mLockPatternUtils = new LockPatternUtils(ctx);
+        mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(ctx);
+        KeyguardUpdateMonitor.getInstance(ctx).registerCallback(mCallback);
+        updateMethodSecure(true /* updateAlways */);
+    }
+
+    public static UnlockMethodCache getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new UnlockMethodCache(context);
+        }
+        return sInstance;
+    }
+
+    /**
+     * @return whether the current security method is secure, i. e. the bouncer will be shown
+     */
+    public boolean isMethodInsecure() {
+        return mMethodInsecure;
+    }
+
+    public void addListener(OnUnlockMethodChangedListener listener) {
+        mListeners.add(listener);
+    }
+
+    public void removeListener(OnUnlockMethodChangedListener listener) {
+        mListeners.remove(listener);
+    }
+
+    private void updateMethodSecure(boolean updateAlways) {
+        int user = mLockPatternUtils.getCurrentUser();
+        boolean methodInsecure = !mLockPatternUtils.isSecure() ||
+                mKeyguardUpdateMonitor.getUserHasTrust(user);
+        boolean changed = methodInsecure != mMethodInsecure;
+        if (changed || updateAlways) {
+            mMethodInsecure = methodInsecure;
+            notifyListeners(mMethodInsecure);
+        }
+    }
+
+    private void notifyListeners(boolean secure) {
+        for (OnUnlockMethodChangedListener listener : mListeners) {
+            listener.onMethodSecureChanged(secure);
+        }
+    }
+
+    private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onUserSwitchComplete(int userId) {
+            updateMethodSecure(false /* updateAlways */);
+        }
+
+        @Override
+        public void onTrustChanged(int userId) {
+            updateMethodSecure(false /* updateAlways */);
+        }
+
+        @Override
+        public void onScreenTurnedOn() {
+            updateMethodSecure(false /* updateAlways */);
+        }
+    };
+
+    public static interface OnUnlockMethodChangedListener {
+        void onMethodSecureChanged(boolean methodSecure);
+    }
+}