am c5c2e537: Merge "resolved conflicts for merge of 803a6dc0 to lmp-mr1-ub-dev" into lmp-mr1-ub-dev

* commit 'c5c2e53779c2c2b6d889bdad5d11d47da9e72789':
  Make IKeyguardService interface asynchronous
diff --git a/Android.mk b/Android.mk
index 327a371..ce72a85 100644
--- a/Android.mk
+++ b/Android.mk
@@ -273,6 +273,7 @@
 	core/java/com/android/internal/policy/IKeyguardShowCallback.aidl \
 	core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \
 	core/java/com/android/internal/policy/IKeyguardService.aidl \
+	core/java/com/android/internal/policy/IKeyguardStateCallback.aidl \
 	core/java/com/android/internal/os/IDropBoxManagerService.aidl \
 	core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \
 	core/java/com/android/internal/os/IResultReceiver.aidl \
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 64f3bea..f93b1a1 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -15,47 +15,34 @@
  */
 package com.android.internal.policy;
 
-import android.view.MotionEvent;
-
 import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.policy.IKeyguardStateCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 
 import android.os.Bundle;
 
-interface IKeyguardService {
-    boolean isShowing();
-    boolean isSecure();
-    boolean isShowingAndNotOccluded();
-    boolean isInputRestricted();
-    boolean isDismissable();
-    oneway void verifyUnlock(IKeyguardExitCallback callback);
-    oneway void keyguardDone(boolean authenticated, boolean wakeup);
-
+oneway interface IKeyguardService {
     /**
      * Sets the Keyguard as occluded when a window dismisses the Keyguard with flag
      * FLAG_SHOW_ON_LOCK_SCREEN.
      *
      * @param isOccluded Whether the Keyguard is occluded by another window.
-     * @return See IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_*. This is needed because
-     *         PhoneWindowManager needs to set these flags immediately and can't wait for the
-     *         Keyguard thread to pick it up. In the hidden case, PhoneWindowManager is solely
-     *         responsible to make sure that the flags are unset.
      */
-    int setOccluded(boolean isOccluded);
+    void setOccluded(boolean isOccluded);
 
-    oneway void dismiss();
-    oneway void onDreamingStarted();
-    oneway void onDreamingStopped();
-    oneway void onScreenTurnedOff(int reason);
-    oneway void onScreenTurnedOn(IKeyguardShowCallback callback);
-    oneway void setKeyguardEnabled(boolean enabled);
-    oneway void onSystemReady();
-    oneway void doKeyguardTimeout(in Bundle options);
-    oneway void setCurrentUser(int userId);
-    oneway void showAssistant();
-    oneway void dispatch(in MotionEvent event);
-    oneway void launchCamera();
-    oneway void onBootCompleted();
+    void addStateMonitorCallback(IKeyguardStateCallback callback);
+    void verifyUnlock(IKeyguardExitCallback callback);
+    void keyguardDone(boolean authenticated, boolean wakeup);
+    void dismiss();
+    void onDreamingStarted();
+    void onDreamingStopped();
+    void onScreenTurnedOff(int reason);
+    void onScreenTurnedOn(IKeyguardShowCallback callback);
+    void setKeyguardEnabled(boolean enabled);
+    void onSystemReady();
+    void doKeyguardTimeout(in Bundle options);
+    void setCurrentUser(int userId);
+    void onBootCompleted();
 
     /**
      * Notifies that the activity behind has now been drawn and it's safe to remove the wallpaper
@@ -64,11 +51,11 @@
      * @param startTime the start time of the animation in uptime milliseconds
      * @param fadeoutDuration the duration of the exit animation, in milliseconds
      */
-    oneway void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
+    void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
 
     /**
      * Notifies the Keyguard that the activity that was starting has now been drawn and it's safe
      * to start the keyguard dismiss sequence.
      */
-    oneway void onActivityDrawn();
+    void onActivityDrawn();
 }
diff --git a/core/java/com/android/internal/policy/IKeyguardServiceConstants.java b/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
deleted file mode 100644
index b88174a..0000000
--- a/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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;
-
-/**
- * @hide
- */
-public class IKeyguardServiceConstants {
-
-    /**
-     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
-     * Don't change the keyguard window flags.
-     */
-    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE = 0;
-
-    /**
-     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
-     * Set the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
-     */
-    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS = 1;
-
-    /**
-     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
-     * Unset the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
-     */
-    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS = 2;
-}
diff --git a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl
new file mode 100644
index 0000000..db3b40b
--- /dev/null
+++ b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+interface IKeyguardStateCallback {
+    void onShowingStateChanged(boolean showing);
+    void onSimSecureStateChanged(boolean simSecure);
+    void onInputRestrictedStateChanged(boolean inputRestricted);
+}
\ No newline at end of file
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index 0c9dbc4..ab69a0c 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -71,4 +71,10 @@
      * Play the "device trusted" sound.
      */
     void playTrustedSound();
+
+    /**
+     * @return true if and only if Keyguard is showing or if Keyguard is disabled by an external app
+     *         (legacy API)
+     */
+    boolean isInputRestricted();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 98d4112..73fa2ed 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -24,12 +24,11 @@
 import android.os.IBinder;
 import android.os.Process;
 import android.util.Log;
-import android.view.MotionEvent;
 
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
-import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.policy.IKeyguardStateCallback;
 import com.android.systemui.SystemUIApplication;
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -66,143 +65,85 @@
 
     private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
 
-        private boolean mIsOccluded;
-
-        @Override
-        public boolean isShowing() {
-            return mKeyguardViewMediator.isShowing();
+        @Override // Binder interface
+        public void addStateMonitorCallback(IKeyguardStateCallback callback) {
+            checkPermission();
+            mKeyguardViewMediator.addStateMonitorCallback(callback);
         }
 
-        @Override
-        public boolean isSecure() {
-            return mKeyguardViewMediator.isSecure();
-        }
-
-        @Override
-        public boolean isShowingAndNotOccluded() {
-            return mKeyguardViewMediator.isShowingAndNotOccluded();
-        }
-
-        @Override
-        public boolean isInputRestricted() {
-            return mKeyguardViewMediator.isInputRestricted();
-        }
-
-        @Override
+        @Override // Binder interface
         public void verifyUnlock(IKeyguardExitCallback callback) {
             checkPermission();
             mKeyguardViewMediator.verifyUnlock(callback);
         }
 
-        @Override
+        @Override // Binder interface
         public void keyguardDone(boolean authenticated, boolean wakeup) {
             checkPermission();
             mKeyguardViewMediator.keyguardDone(authenticated, wakeup);
         }
 
-        @Override
-        public int setOccluded(boolean isOccluded) {
+        @Override // Binder interface
+        public void setOccluded(boolean isOccluded) {
             checkPermission();
-            synchronized (this) {
-                int result;
-                if (isOccluded && mKeyguardViewMediator.isShowing()
-                        && !mIsOccluded) {
-                    result = IKeyguardServiceConstants
-                            .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS;
-                } else if (!isOccluded && mKeyguardViewMediator.isShowing()
-                        && mIsOccluded) {
-                    result = IKeyguardServiceConstants
-                            .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS;
-                } else {
-                    result = IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
-                }
-                if (mIsOccluded != isOccluded) {
-                    mKeyguardViewMediator.setOccluded(isOccluded);
-
-                    // Cache the value so we always have a fresh view in whether Keyguard is occluded.
-                    // If we would just call mKeyguardViewMediator.isOccluded(), this might be stale
-                    // because that value gets updated in another thread.
-                    mIsOccluded = isOccluded;
-                }
-                return result;
-            }
+            mKeyguardViewMediator.setOccluded(isOccluded);
         }
 
-        @Override
+        @Override // Binder interface
         public void dismiss() {
             checkPermission();
             mKeyguardViewMediator.dismiss();
         }
 
-        @Override
+        @Override // Binder interface
         public void onDreamingStarted() {
             checkPermission();
             mKeyguardViewMediator.onDreamingStarted();
         }
 
-        @Override
+        @Override // Binder interface
         public void onDreamingStopped() {
             checkPermission();
             mKeyguardViewMediator.onDreamingStopped();
         }
 
-        @Override
+        @Override // Binder interface
         public void onScreenTurnedOff(int reason) {
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOff(reason);
         }
 
-        @Override
+        @Override // Binder interface
         public void onScreenTurnedOn(IKeyguardShowCallback callback) {
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOn(callback);
         }
 
-        @Override
+        @Override // Binder interface
         public void setKeyguardEnabled(boolean enabled) {
             checkPermission();
             mKeyguardViewMediator.setKeyguardEnabled(enabled);
         }
 
-        @Override
-        public boolean isDismissable() {
-            return mKeyguardViewMediator.isDismissable();
-        }
-
-        @Override
+        @Override // Binder interface
         public void onSystemReady() {
             checkPermission();
             mKeyguardViewMediator.onSystemReady();
         }
 
-        @Override
+        @Override // Binder interface
         public void doKeyguardTimeout(Bundle options) {
             checkPermission();
             mKeyguardViewMediator.doKeyguardTimeout(options);
         }
 
-        @Override
+        @Override // Binder interface
         public void setCurrentUser(int userId) {
             checkPermission();
             mKeyguardViewMediator.setCurrentUser(userId);
         }
 
         @Override
-        public void showAssistant() {
-            checkPermission();
-        }
-
-        @Override
-        public void dispatch(MotionEvent event) {
-            checkPermission();
-        }
-
-        @Override
-        public void launchCamera() {
-            checkPermission();
-        }
-
-        @Override
         public void onBootCompleted() {
             checkPermission();
             mKeyguardViewMediator.onBootCompleted();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d8f8727..4e034ae 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -56,6 +56,7 @@
 import android.view.animation.AnimationUtils;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.policy.IKeyguardStateCallback;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardConstants;
@@ -70,6 +71,8 @@
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarWindowManager;
 
+import java.util.ArrayList;
+
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
 
 
@@ -224,6 +227,9 @@
     // answer whether the input should be restricted)
     private boolean mShowing;
 
+    /** Cached value of #isInputRestricted */
+    private boolean mInputRestricted;
+
     // true if the keyguard is hidden by another window
     private boolean mOccluded = false;
 
@@ -293,6 +299,8 @@
      */
     private KeyguardDisplayManager mKeyguardDisplayManager;
 
+    private final ArrayList<IKeyguardStateCallback> mKeyguardStateCallbacks = new ArrayList<>();
+
     KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
@@ -360,6 +368,7 @@
         @Override
         public void onDeviceProvisioned() {
             sendUserPresentBroadcast();
+            updateInputRestricted();
         }
 
         @Override
@@ -370,6 +379,16 @@
                         + ",state=" + simState + ")");
             }
 
+            try {
+                int size = mKeyguardStateCallbacks.size();
+                boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
+                for (int i = 0; i < size; i++) {
+                    mKeyguardStateCallbacks.get(i).onSimSecureStateChanged(simPinSecure);
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to call onSimSecureStateChanged", e);
+            }
+
             switch (simState) {
                 case NOT_READY:
                 case ABSENT:
@@ -377,7 +396,7 @@
                     // gone through setup wizard
                     synchronized (this) {
                         if (shouldWaitForProvisioning()) {
-                            if (!isShowing()) {
+                            if (!mShowing) {
                                 if (DEBUG_SIM_STATES) Log.d(TAG, "ICC_ABSENT isn't showing,"
                                         + " we need to show the keyguard since the "
                                         + "device isn't provisioned yet.");
@@ -391,7 +410,7 @@
                 case PIN_REQUIRED:
                 case PUK_REQUIRED:
                     synchronized (this) {
-                        if (!isShowing()) {
+                        if (!mShowing) {
                             if (DEBUG_SIM_STATES) Log.d(TAG,
                                     "INTENT_VALUE_ICC_LOCKED and keygaurd isn't "
                                     + "showing; need to show keyguard so user can enter sim pin");
@@ -403,7 +422,7 @@
                     break;
                 case PERM_DISABLED:
                     synchronized (this) {
-                        if (!isShowing()) {
+                        if (!mShowing) {
                             if (DEBUG_SIM_STATES) Log.d(TAG, "PERM_DISABLED and "
                                   + "keygaurd isn't showing.");
                             doKeyguardLocked(null);
@@ -416,7 +435,7 @@
                     break;
                 case READY:
                     synchronized (this) {
-                        if (isShowing()) {
+                        if (mShowing) {
                             resetStateLocked();
                         }
                     }
@@ -488,13 +507,18 @@
         public void playTrustedSound() {
             KeyguardViewMediator.this.playTrustedSound();
         }
+
+        @Override
+        public boolean isInputRestricted() {
+            return KeyguardViewMediator.this.isInputRestricted();
+        }
     };
 
     public void userActivity() {
         mPM.userActivity(SystemClock.uptimeMillis(), false);
     }
 
-    private void setup() {
+    private void setupLocked() {
         mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWM = WindowManagerGlobal.getWindowManagerService();
         mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
@@ -514,7 +538,7 @@
         mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure...
-        mShowing = !shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled();
+        setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled());
         mTrustManager.reportKeyguardShowingChanged();
 
         mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
@@ -556,7 +580,9 @@
 
     @Override
     public void start() {
-        setup();
+        synchronized (this) {
+            setupLocked();
+        }
         putComponent(KeyguardViewMediator.class, this);
     }
 
@@ -760,12 +786,14 @@
                 if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
                         + "disabling status bar expansion");
                 mNeedToReshowWhenReenabled = true;
+                updateInputRestrictedLocked();
                 hideLocked();
             } else if (enabled && mNeedToReshowWhenReenabled) {
                 // reenabled after previously hidden, reshow
                 if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
                         + "status bar expansion");
                 mNeedToReshowWhenReenabled = false;
+                updateInputRestrictedLocked();
 
                 if (mExitSecureCallback != null) {
                     if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
@@ -837,17 +865,6 @@
     }
 
     /**
-     * Is the keyguard currently showing?
-     */
-    public boolean isShowing() {
-        return mShowing;
-    }
-
-    public boolean isOccluded() {
-        return mOccluded;
-    }
-
-    /**
      * Is the keyguard currently showing and not being force hidden?
      */
     public boolean isShowingAndNotOccluded() {
@@ -897,6 +914,26 @@
         return mShowing || mNeedToReshowWhenReenabled || shouldWaitForProvisioning();
     }
 
+    private void updateInputRestricted() {
+        synchronized (this) {
+            updateInputRestrictedLocked();
+        }
+    }
+    private void updateInputRestrictedLocked() {
+        boolean inputRestricted = isInputRestricted();
+        if (mInputRestricted != inputRestricted) {
+            mInputRestricted = inputRestricted;
+            try {
+                int size = mKeyguardStateCallbacks.size();
+                for (int i = 0; i < size; i++) {
+                    mKeyguardStateCallbacks.get(i).onInputRestrictedStateChanged(inputRestricted);
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
+            }
+        }
+    }
+
     /**
      * Enable the keyguard if the settings are appropriate.
      */
@@ -947,7 +984,7 @@
         if (mLockPatternUtils.checkVoldPassword()) {
             if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
             // Without this, settings is not enabled until the lock screen first appears
-            setShowing(false);
+            setShowingLocked(false);
             hideLocked();
             return;
         }
@@ -1168,6 +1205,7 @@
                 // the keyguard when they've released the lock
                 mExternallyEnabled = true;
                 mNeedToReshowWhenReenabled = false;
+                updateInputRestricted();
             }
         }
 
@@ -1263,9 +1301,9 @@
                 if (DEBUG) Log.d(TAG, "handleShow");
             }
 
+            setShowingLocked(true);
             mStatusBarKeyguardViewManager.show(options);
             mHiding = false;
-            setShowing(true);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             updateActivityLockScreenState();
@@ -1343,8 +1381,8 @@
                 playSounds(false);
             }
 
+            setShowingLocked(false);
             mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
-            setShowing(false);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             updateActivityLockScreenState();
@@ -1404,8 +1442,8 @@
     private void handleVerifyUnlock() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
+            setShowingLocked(true);
             mStatusBarKeyguardViewManager.verifyUnlock();
-            setShowing(true);
             updateActivityLockScreenState();
         }
     }
@@ -1432,15 +1470,6 @@
         }
     }
 
-    public boolean isDismissable() {
-        return mKeyguardDonePending || !isSecure();
-    }
-
-    private boolean isAssistantAvailable() {
-        return mSearchManager != null
-                && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
-    }
-
     private void resetKeyguardDonePendingLocked() {
         mKeyguardDonePending = false;
         mHandler.removeMessages(KEYGUARD_DONE_PENDING_TIMEOUT);
@@ -1488,11 +1517,31 @@
         }
     }
 
-    private void setShowing(boolean showing) {
-        boolean changed = (showing != mShowing);
-        mShowing = showing;
-        if (changed) {
+    private void setShowingLocked(boolean showing) {
+        if (showing != mShowing) {
+            mShowing = showing;
+            try {
+                int size = mKeyguardStateCallbacks.size();
+                for (int i = 0; i < size; i++) {
+                    mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing);
+                }
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to call onShowingStateChanged", e);
+            }
+            updateInputRestrictedLocked();
             mTrustManager.reportKeyguardShowingChanged();
         }
     }
+
+    public void addStateMonitorCallback(IKeyguardStateCallback callback) {
+        synchronized (this) {
+            mKeyguardStateCallbacks.add(callback);
+            try {
+                callback.onSimSecureStateChanged(mUpdateMonitor.isSimPinSecure());
+                callback.onShowingStateChanged(mShowing);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged", e);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index a2796c6..4a16f8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -92,7 +92,6 @@
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
 import com.android.systemui.statusbar.phone.NavigationBarView;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
@@ -2090,13 +2089,13 @@
         boolean accessibilityForcesLaunch = isFullscreen
                 && mAccessibilityManager.isTouchExplorationEnabled();
 
-        final KeyguardTouchDelegate keyguard = KeyguardTouchDelegate.getInstance(mContext);
         boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
                 && isAllowed
                 && !accessibilityForcesLaunch
                 && mPowerManager.isScreenOn()
-                && !keyguard.isShowingAndNotOccluded()
-                && !keyguard.isInputRestricted();
+                && (!mStatusBarKeyguardViewManager.isShowing()
+                        || mStatusBarKeyguardViewManager.isOccluded())
+                && !mStatusBarKeyguardViewManager.isInputRestricted();
         try {
             interrupt = interrupt && !mDreamManager.isDreaming();
         } catch (RemoteException e) {
@@ -2106,10 +2105,6 @@
         return interrupt;
     }
 
-    public boolean inKeyguardRestrictedInputMode() {
-        return KeyguardTouchDelegate.getInstance(mContext).isInputRestricted();
-    }
-
     public void setInteracting(int barWindow, boolean interacting) {
         // hook for subclasses
     }
@@ -2167,4 +2162,8 @@
             // Ignore.
         }
     }
+
+    public boolean isKeyguardSecure() {
+        return mStatusBarKeyguardViewManager.isSecure();
+    }
 }
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 fddbee2..503f588 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -257,7 +257,7 @@
                 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
                 final  boolean disabledBecauseKeyguardSecure =
                         (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
-                                && KeyguardTouchDelegate.getInstance(getContext()).isSecure();
+                                && mPhoneStatusBar.isKeyguardSecure();
                 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
             } catch (RemoteException e) {
                 Log.e(TAG, "Can't get userId", e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
deleted file mode 100644
index 754075a..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2013 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.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.Slog;
-import android.view.MotionEvent;
-
-import com.android.internal.policy.IKeyguardService;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * Facilitates event communication between navigation bar and keyguard.  Currently used to
- * control WidgetPager in keyguard to expose the camera widget.
- *
- */
-public class KeyguardTouchDelegate {
-    // TODO: propagate changes to these to {@link KeyguardServiceDelegate}
-    static final String KEYGUARD_PACKAGE = "com.android.systemui";
-    static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
-
-    private static KeyguardTouchDelegate sInstance;
-    private static final List<OnKeyguardConnectionListener> sConnectionListeners =
-            new ArrayList<OnKeyguardConnectionListener>();
-
-    private volatile IKeyguardService mService;
-
-    protected static final boolean DEBUG = false;
-    protected static final String TAG = "KeyguardTouchDelegate";
-
-    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            Slog.v(TAG, "Connected to keyguard");
-            mService = IKeyguardService.Stub.asInterface(service);
-
-            for (int i = 0; i < sConnectionListeners.size(); i++) {
-                OnKeyguardConnectionListener listener = sConnectionListeners.get(i);
-                listener.onKeyguardServiceConnected(KeyguardTouchDelegate.this);
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            Slog.v(TAG, "Disconnected from keyguard");
-            mService = null;
-            sInstance = null; // force reconnection if this goes away
-
-            for (int i = 0; i < sConnectionListeners.size(); i++) {
-                OnKeyguardConnectionListener listener = sConnectionListeners.get(i);
-                listener.onKeyguardServiceDisconnected(KeyguardTouchDelegate.this);
-            }
-        }
-
-    };
-
-    private KeyguardTouchDelegate(Context context) {
-        Intent intent = new Intent();
-        intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS);
-        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
-                Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
-            if (DEBUG) Slog.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
-        } else {
-            if (DEBUG) Slog.v(TAG, "*** Keyguard started");
-        }
-    }
-
-    public static KeyguardTouchDelegate getInstance(Context context) {
-        KeyguardTouchDelegate instance = sInstance;
-        if (instance == null) {
-            instance = sInstance = new KeyguardTouchDelegate(context);
-        }
-        return instance;
-    }
-
-    public boolean isSecure() {
-        final IKeyguardService service = mService;
-        if (service != null) {
-            try {
-                return service.isSecure();
-            } catch (RemoteException e) {
-                Slog.e(TAG, "RemoteException calling keyguard.isSecure()!", e);
-            }
-        } else {
-            Slog.w(TAG, "isSecure(): NO SERVICE!");
-        }
-        return false;
-    }
-
-    public boolean dispatch(MotionEvent event) {
-        final IKeyguardService service = mService;
-        if (service != null) {
-            try {
-                service.dispatch(event);
-                return true;
-            } catch (RemoteException e) {
-                // What to do?
-                Slog.e(TAG, "RemoteException sending event to keyguard!", e);
-            }
-        } else {
-            Slog.w(TAG, "dispatch(event): NO SERVICE!");
-        }
-        return false;
-    }
-
-    public boolean isInputRestricted() {
-        final IKeyguardService service = mService;
-        if (service != null) {
-            try {
-                return service.isInputRestricted();
-            } catch (RemoteException e) {
-                Slog.w(TAG , "Remote Exception", e);
-            }
-        } else {
-            Slog.w(TAG, "isInputRestricted(): NO SERVICE!");
-        }
-        return false;
-    }
-
-    public boolean isShowingAndNotOccluded() {
-        final IKeyguardService service = mService;
-        if (service != null) {
-            try {
-                return service.isShowingAndNotOccluded();
-            } catch (RemoteException e) {
-                Slog.w(TAG , "Remote Exception", e);
-            }
-        } else {
-            Slog.w(TAG, "isShowingAndNotOccluded(): NO SERVICE!");
-        }
-        return false;
-    }
-
-    public void showAssistant() {
-        final IKeyguardService service = mService;
-        if (service != null) {
-            try {
-                service.showAssistant();
-            } catch (RemoteException e) {
-                // What to do?
-                Slog.e(TAG, "RemoteException launching assistant!", e);
-            }
-        } else {
-            Slog.w(TAG, "showAssistant(event): NO SERVICE!");
-        }
-    }
-
-    public void launchCamera() {
-        final IKeyguardService service = mService;
-        if (service != null) {
-            try {
-                service.launchCamera();
-            } catch (RemoteException e) {
-                // What to do?
-                Slog.e(TAG, "RemoteException launching camera!", e);
-            }
-        } else {
-            Slog.w(TAG, "launchCamera(): NO SERVICE!");
-        }
-    }
-
-    public void dismiss() {
-        final IKeyguardService service = mService;
-        if (service != null) {
-            try {
-                service.dismiss();
-            } catch (RemoteException e) {
-                // What to do?
-                Slog.e(TAG, "RemoteException dismissing keyguard!", e);
-            }
-        } else {
-            Slog.w(TAG, "dismiss(): NO SERVICE!");
-        }
-    }
-
-    public static void addListener(OnKeyguardConnectionListener listener) {
-        sConnectionListeners.add(listener);
-    }
-
-    public interface OnKeyguardConnectionListener {
-
-        void onKeyguardServiceConnected(KeyguardTouchDelegate keyguardTouchDelegate);
-        void onKeyguardServiceDisconnected(KeyguardTouchDelegate keyguardTouchDelegate);
-    }
-}
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 cec1559..0e6f1b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -430,4 +430,8 @@
     public boolean isSecure(int userId) {
         return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
     }
+
+    public boolean isInputRestricted() {
+        return mViewMediatorCallback.isInputRestricted();
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0e1a4a2..114e908 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -103,8 +103,6 @@
 import android.view.animation.AnimationUtils;
 
 import com.android.internal.R;
-import com.android.internal.policy.IKeyguardService;
-import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
@@ -483,6 +481,9 @@
     boolean mShowingLockscreen;
     boolean mShowingDream;
     boolean mDreamingLockscreen;
+    boolean mKeyguardSecure;
+    boolean mKeyguardSecureIncludingHidden;
+    volatile boolean mKeyguardOccluded;
     boolean mHomePressed;
     boolean mHomeConsumed;
     boolean mHomeDoubleTapPending;
@@ -1108,7 +1109,7 @@
         if (mGlobalActions == null) {
             mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
         }
-        final boolean keyguardShowing = keyguardIsShowingTq();
+        final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
         mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
         if (keyguardShowing) {
             // since it took two seconds of long press to bring this up,
@@ -1973,7 +1974,8 @@
     @Override
     public boolean isForceHiding(WindowManager.LayoutParams attrs) {
         return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
-                (isKeyguardHostWindow(attrs) && isKeyguardSecureIncludingHidden()) ||
+                (isKeyguardHostWindow(attrs) &&
+                        (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
                 (attrs.type == TYPE_KEYGUARD_SCRIM);
     }
 
@@ -2377,7 +2379,7 @@
     }
 
     boolean keyguardOn() {
-        return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
+        return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
     }
 
     private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
@@ -2961,7 +2963,7 @@
      * given the situation with the keyguard.
      */
     void launchHomeFromHotKey() {
-        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotOccluded()) {
+        if (isKeyguardShowingAndNotOccluded()) {
             // don't launch home if keyguard showing
         } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
             // when in keyguard restricted mode, must first verify unlock
@@ -3995,6 +3997,9 @@
         mShowingLockscreen = false;
         mShowingDream = false;
         mWinShowWhenLocked = null;
+        mKeyguardSecure = isKeyguardSecure();
+        mKeyguardSecureIncludingHidden = mKeyguardSecure
+                && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
     }
 
     /** {@inheritDoc} */
@@ -4037,20 +4042,19 @@
 
             final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
             final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
-            final boolean secureKeyguard = isKeyguardSecure();
             if (appWindow) {
                 final IApplicationToken appToken = win.getAppToken();
                 if (showWhenLocked) {
                     // Remove any previous windows with the same appToken.
                     mAppsToBeHidden.remove(appToken);
                     mAppsThatDismissKeyguard.remove(appToken);
-                    if (mAppsToBeHidden.isEmpty() && isKeyguardSecureIncludingHidden()) {
+                    if (mAppsToBeHidden.isEmpty() && mKeyguardSecureIncludingHidden) {
                         mWinShowWhenLocked = win;
                         mHideLockScreen = true;
                         mForceStatusBarFromKeyguard = false;
                     }
                 } else if (dismissKeyguard) {
-                    if (secureKeyguard) {
+                    if (mKeyguardSecure) {
                         mAppsToBeHidden.add(appToken);
                     } else {
                         mAppsToBeHidden.remove(appToken);
@@ -4071,7 +4075,7 @@
                         mDismissKeyguard = mWinDismissingKeyguard == win ?
                                 DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
                         mWinDismissingKeyguard = win;
-                        mForceStatusBarFromKeyguard = mShowingLockscreen && secureKeyguard;
+                        mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
                     } else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
                         if (DEBUG_LAYOUT) Slog.v(TAG,
                                 "Setting mHideLockScreen to true by win " + win);
@@ -4182,9 +4186,9 @@
         if (mKeyguardDelegate != null && mStatusBar != null) {
             if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
                     + mHideLockScreen);
-            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
+            if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
                 mKeyguardHidden = true;
-                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
+                if (setKeyguardOccludedLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
@@ -4199,7 +4203,7 @@
                 }
             } else if (mHideLockScreen) {
                 mKeyguardHidden = true;
-                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
+                if (setKeyguardOccludedLw(true)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
@@ -4209,7 +4213,7 @@
                 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
                     // Only launch the next keyguard unlock window once per window.
                     mKeyguardHidden = false;
-                    if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
+                    if (setKeyguardOccludedLw(false)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT
                                 | FINISH_LAYOUT_REDO_CONFIG
                                 | FINISH_LAYOUT_REDO_WALLPAPER;
@@ -4224,7 +4228,7 @@
             } else {
                 mWinDismissingKeyguard = null;
                 mKeyguardHidden = false;
-                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
+                if (setKeyguardOccludedLw(false)) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
@@ -4244,23 +4248,22 @@
     }
 
     /**
-     * Processes the result code of {@link IKeyguardService#setOccluded}. This is needed because we
-     * immediately need to put the wallpaper directly behind the Keyguard when a window with flag
-     * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} gets dismissed. If we
-     * would wait for Keyguard to change the flags, that would be running asynchronously and thus be
-     * too late so the user might see the window behind.
+     * Updates the occluded state of the Keyguard.
      *
-     * @param setHiddenResult The result code from {@link IKeyguardService#setOccluded}.
      * @return Whether the flags have changed and we have to redo the layout.
      */
-    private boolean processKeyguardSetHiddenResultLw(int setHiddenResult) {
-        if (setHiddenResult
-                == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS) {
+    private boolean setKeyguardOccludedLw(boolean isOccluded) {
+        boolean wasOccluded = mKeyguardOccluded;
+        boolean showing = mKeyguardDelegate.isShowing();
+        if (wasOccluded && !isOccluded && showing) {
+            mKeyguardOccluded = false;
+            mKeyguardDelegate.setOccluded(false);
             mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
             mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
             return true;
-        } else if (setHiddenResult
-                == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS) {
+        } else if (!wasOccluded && isOccluded && showing) {
+            mKeyguardOccluded = true;
+            mKeyguardDelegate.setOccluded(true);
             mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
             mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
             return true;
@@ -4471,7 +4474,7 @@
         // when the keyguard is hidden by another activity.
         final boolean keyguardActive = (mKeyguardDelegate == null ? false :
                                             (interactive ?
-                                                mKeyguardDelegate.isShowingAndNotOccluded() :
+                                                isKeyguardShowingAndNotOccluded() :
                                                 mKeyguardDelegate.isShowing()));
 
         if (DEBUG_INPUT) {
@@ -4811,7 +4814,8 @@
 
     private boolean shouldDispatchInputWhenNonInteractive() {
         // Send events to keyguard while the screen is on.
-        if (keyguardIsShowingTq() && mDisplay != null && mDisplay.getState() != Display.STATE_OFF) {
+        if (isKeyguardShowingAndNotOccluded() && mDisplay != null
+                && mDisplay.getState() != Display.STATE_OFF) {
             return true;
         }
 
@@ -5183,12 +5187,11 @@
         }
     }
 
-    private boolean keyguardIsShowingTq() {
+    private boolean isKeyguardShowingAndNotOccluded() {
         if (mKeyguardDelegate == null) return false;
-        return mKeyguardDelegate.isShowingAndNotOccluded();
+        return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
     }
 
-
     /** {@inheritDoc} */
     @Override
     public boolean isKeyguardLocked() {
@@ -5202,11 +5205,6 @@
         return mKeyguardDelegate.isSecure();
     }
 
-    // Returns true if keyguard is currently locked whether or not it is currently hidden.
-    private boolean isKeyguardSecureIncludingHidden() {
-        return mKeyguardDelegate.isSecure() && mKeyguardDelegate.isShowing();
-    }
-
     /** {@inheritDoc} */
     @Override
     public boolean inKeyguardRestrictedKeyInputMode() {
@@ -5521,7 +5519,7 @@
     /** {@inheritDoc} */
     @Override
     public void systemReady() {
-        mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
+        mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
         mKeyguardDelegate.onSystemReady();
 
         readCameraLensCoverState();
@@ -5968,7 +5966,7 @@
 
     @Override
     public void keepScreenOnStoppedLw() {
-        if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotOccluded()) {
+        if (isKeyguardShowingAndNotOccluded()) {
             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
         }
     }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 50fe7c7..618ba1e 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -18,9 +18,8 @@
 import android.view.WindowManagerPolicy.OnKeyguardExitResult;
 
 import com.android.internal.policy.IKeyguardExitCallback;
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.policy.IKeyguardService;
-import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.policy.IKeyguardShowCallback;
 
 /**
  * A local class that keeps a cache of keyguard state that can be restored in the event
@@ -28,15 +27,16 @@
  * local or remote instances of keyguard.
  */
 public class KeyguardServiceDelegate {
-    // TODO: propagate changes to these to {@link KeyguardTouchDelegate}
     public static final String KEYGUARD_PACKAGE = "com.android.systemui";
     public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
 
     private static final String TAG = "KeyguardServiceDelegate";
     private static final boolean DEBUG = true;
+
     protected KeyguardServiceWrapper mKeyguardService;
-    private View mScrim; // shown if keyguard crashes
-    private KeyguardState mKeyguardState = new KeyguardState();
+    private final Context mContext;
+    private final View mScrim; // shown if keyguard crashes
+    private final KeyguardState mKeyguardState = new KeyguardState();
 
     /* package */ static final class KeyguardState {
         KeyguardState() {
@@ -101,7 +101,8 @@
         }
     };
 
-    public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) {
+    public KeyguardServiceDelegate(Context context) {
+        mContext = context;
         mScrim = createScrim(context);
     }
 
@@ -123,7 +124,7 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
-            mKeyguardService = new KeyguardServiceWrapper(
+            mKeyguardService = new KeyguardServiceWrapper(mContext,
                     IKeyguardService.Stub.asInterface(service));
             if (mKeyguardState.systemIsReady) {
                 // If the system is ready, it means keyguard crashed and restarted.
@@ -151,13 +152,6 @@
         return mKeyguardState.showing;
     }
 
-    public boolean isShowingAndNotOccluded() {
-        if (mKeyguardService != null) {
-            mKeyguardState.showingAndNotOccluded = mKeyguardService.isShowingAndNotOccluded();
-        }
-        return mKeyguardState.showingAndNotOccluded;
-    }
-
     public boolean isInputRestricted() {
         if (mKeyguardService != null) {
             mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted();
@@ -177,13 +171,11 @@
         }
     }
 
-    public int setOccluded(boolean isOccluded) {
-        int result = 0;
+    public void setOccluded(boolean isOccluded) {
         if (mKeyguardService != null) {
-            result = mKeyguardService.setOccluded(isOccluded);
+            mKeyguardService.setOccluded(isOccluded);
         }
         mKeyguardState.occluded = isOccluded;
-        return result;
     }
 
     public void dismiss() {
@@ -242,13 +234,6 @@
         mKeyguardState.enabled = enabled;
     }
 
-    public boolean isDismissable() {
-        if (mKeyguardService != null) {
-            mKeyguardState.dismissable = mKeyguardService.isDismissable();
-        }
-        return mKeyguardState.dismissable;
-    }
-
     public void onSystemReady() {
         if (mKeyguardService != null) {
             mKeyguardService.onSystemReady();
@@ -263,12 +248,6 @@
         }
     }
 
-    public void showAssistant() {
-        if (mKeyguardService != null) {
-            mKeyguardService.showAssistant();
-        }
-    }
-
     public void setCurrentUser(int newUserId) {
         if (mKeyguardService != null) {
             mKeyguardService.setCurrentUser(newUserId);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 2778b15..b3b7684 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -16,16 +16,16 @@
 
 package com.android.internal.policy.impl.keyguard;
 
+import android.content.Context;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
-import android.view.MotionEvent;
 
-import com.android.internal.policy.IKeyguardServiceConstants;
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.policy.IKeyguardStateCallback;
 
 /**
  * A wrapper class for KeyguardService.  It implements IKeyguardService to ensure the interface
@@ -33,58 +33,16 @@
  *
  */
 public class KeyguardServiceWrapper implements IKeyguardService {
+    private KeyguardStateMonitor mKeyguardStateMonitor;
     private IKeyguardService mService;
     private String TAG = "KeyguardServiceWrapper";
 
-    public KeyguardServiceWrapper(IKeyguardService service) {
+    public KeyguardServiceWrapper(Context context, IKeyguardService service) {
         mService = service;
+        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
     }
 
-    public boolean isShowing() {
-        try {
-            return mService.isShowing();
-        } catch (RemoteException e) {
-            Slog.w(TAG , "Remote Exception", e);
-        }
-        return false;
-    }
-
-    public boolean isSecure() {
-        try {
-            return mService.isSecure();
-        } catch (RemoteException e) {
-            Slog.w(TAG , "Remote Exception", e);
-        }
-        return false; // TODO cache state
-    }
-
-    public boolean isShowingAndNotOccluded() {
-        try {
-            return mService.isShowingAndNotOccluded();
-        } catch (RemoteException e) {
-            Slog.w(TAG , "Remote Exception", e);
-        }
-        return false; // TODO cache state
-    }
-
-    public boolean isInputRestricted() {
-        try {
-            return mService.isInputRestricted();
-        } catch (RemoteException e) {
-            Slog.w(TAG , "Remote Exception", e);
-        }
-        return false; // TODO cache state
-    }
-
-    public boolean isDismissable() {
-        try {
-            return mService.isDismissable();
-        } catch (RemoteException e) {
-            Slog.w(TAG , "Remote Exception", e);
-        }
-        return true; // TODO cache state
-    }
-
+    @Override // Binder interface
     public void verifyUnlock(IKeyguardExitCallback callback) {
         try {
             mService.verifyUnlock(callback);
@@ -93,6 +51,7 @@
         }
     }
 
+    @Override // Binder interface
     public void keyguardDone(boolean authenticated, boolean wakeup) {
         try {
             mService.keyguardDone(authenticated, wakeup);
@@ -101,15 +60,25 @@
         }
     }
 
-    public int setOccluded(boolean isOccluded) {
+    @Override // Binder interface
+    public void setOccluded(boolean isOccluded) {
         try {
-            return mService.setOccluded(isOccluded);
+            mService.setOccluded(isOccluded);
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
-            return IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
         }
     }
 
+    @Override
+    public void addStateMonitorCallback(IKeyguardStateCallback callback) {
+        try {
+            mService.addStateMonitorCallback(callback);
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
+    @Override // Binder interface
     public void dismiss() {
         try {
             mService.dismiss();
@@ -118,6 +87,7 @@
         }
     }
 
+    @Override // Binder interface
     public void onDreamingStarted() {
         try {
             mService.onDreamingStarted();
@@ -126,6 +96,7 @@
         }
     }
 
+    @Override // Binder interface
     public void onDreamingStopped() {
         try {
             mService.onDreamingStopped();
@@ -134,6 +105,7 @@
         }
     }
 
+    @Override // Binder interface
     public void onScreenTurnedOff(int reason) {
         try {
             mService.onScreenTurnedOff(reason);
@@ -142,6 +114,7 @@
         }
     }
 
+    @Override // Binder interface
     public void onScreenTurnedOn(IKeyguardShowCallback result) {
         try {
             mService.onScreenTurnedOn(result);
@@ -150,6 +123,7 @@
         }
     }
 
+    @Override // Binder interface
     public void setKeyguardEnabled(boolean enabled) {
         try {
             mService.setKeyguardEnabled(enabled);
@@ -158,6 +132,7 @@
         }
     }
 
+    @Override // Binder interface
     public void onSystemReady() {
         try {
             mService.onSystemReady();
@@ -166,6 +141,7 @@
         }
     }
 
+    @Override // Binder interface
     public void doKeyguardTimeout(Bundle options) {
         try {
             mService.doKeyguardTimeout(options);
@@ -174,7 +150,9 @@
         }
     }
 
+    @Override // Binder interface
     public void setCurrentUser(int userId) {
+        mKeyguardStateMonitor.setCurrentUser(userId);
         try {
             mService.setCurrentUser(userId);
         } catch (RemoteException e) {
@@ -182,6 +160,7 @@
         }
     }
 
+    @Override // Binder interface
     public void onBootCompleted() {
         try {
             mService.onBootCompleted();
@@ -190,6 +169,7 @@
         }
     }
 
+    @Override // Binder interface
     public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
         try {
             mService.startKeyguardExitAnimation(startTime, fadeoutDuration);
@@ -198,6 +178,7 @@
         }
     }
 
+    @Override // Binder interface
     public void onActivityDrawn() {
         try {
             mService.onActivityDrawn();
@@ -206,21 +187,20 @@
         }
     }
 
-    public void showAssistant() {
-        // Not used by PhoneWindowManager
-    }
-
-    public void dispatch(MotionEvent event) {
-        // Not used by PhoneWindowManager.  See code in {@link NavigationBarView}
-    }
-
-    public void launchCamera() {
-        // Not used by PhoneWindowManager.  See code in {@link NavigationBarView}
-    }
-
-    @Override
+    @Override // Binder interface
     public IBinder asBinder() {
         return mService.asBinder();
     }
 
+    public boolean isShowing() {
+        return mKeyguardStateMonitor.isShowing();
+    }
+
+    public boolean isSecure() {
+        return mKeyguardStateMonitor.isSecure();
+    }
+
+    public boolean isInputRestricted() {
+        return mKeyguardStateMonitor.isInputRestricted();
+    }
 }
\ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStateMonitor.java
new file mode 100644
index 0000000..6f9c617
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStateMonitor.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 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.keyguard;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardStateCallback;
+import com.android.internal.widget.LockPatternUtils;
+
+/**
+ * Maintains a cached copy of Keyguard's state.
+ * @hide
+ */
+public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub {
+    private static final String TAG = "KeyguardStateMonitor";
+
+    // These cache the current state of Keyguard to improve performance and avoid deadlock. After
+    // Keyguard changes its state, it always triggers a layout in window manager. Because
+    // IKeyguardStateCallback is synchronous and because these states are declared volatile, it's
+    // guaranteed that window manager picks up the new state all the time in the layout caused by
+    // the state change of Keyguard.
+    private volatile boolean mIsShowing;
+    private volatile boolean mSimSecure;
+    private volatile boolean mInputRestricted;
+
+    private final LockPatternUtils mLockPatternUtils;
+
+    public KeyguardStateMonitor(Context context, IKeyguardService service) {
+        mLockPatternUtils = new LockPatternUtils(context);
+        mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
+        try {
+            service.addStateMonitorCallback(this);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Remote Exception", e);
+        }
+    }
+
+    public boolean isShowing() {
+        return mIsShowing;
+    }
+
+    public boolean isSecure() {
+        return mLockPatternUtils.isSecure() || mSimSecure;
+    }
+
+    public boolean isInputRestricted() {
+        return mInputRestricted;
+    }
+
+    @Override // Binder interface
+    public void onShowingStateChanged(boolean showing) {
+        mIsShowing = showing;
+    }
+
+    @Override // Binder interface
+    public void onSimSecureStateChanged(boolean simSecure) {
+        mSimSecure = simSecure;
+    }
+
+    public void setCurrentUser(int userId) {
+        mLockPatternUtils.setCurrentUser(userId);
+    }
+
+    @Override // Binder interface
+    public void onInputRestrictedStateChanged(boolean inputRestricted) {
+        mInputRestricted = inputRestricted;
+    }
+}
\ No newline at end of file