Move launch, verification and menu logic to base class
- Add simplified KeyguardHostView
- Move common functions to KeyguardViewBase.java
- Create new KeyguardSimpleHostView class for simplified view
implementation.

Bug 12135931

Change-Id: I8d6b0a61c36a0c7ceb87da4da54b1dfbed0054ff
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 1548dee..316a7ec 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -17,15 +17,14 @@
 package com.android.keyguard;
 
 import android.nfc.NfcUnlock;
+
 import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
 
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.app.AlertDialog;
 import android.app.SearchManager;
 import android.app.admin.DevicePolicyManager;
 import android.appwidget.AppWidgetHost;
@@ -39,7 +38,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
-import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.media.RemoteControlClient;
 import android.os.Looper;
@@ -51,12 +49,9 @@
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.Slog;
-
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.WindowManager;
 import android.widget.RemoteViews.OnClickHandler;
 
 import java.io.File;
@@ -65,6 +60,8 @@
 
 public class KeyguardHostView extends KeyguardViewBase {
     private static final String TAG = "KeyguardHostView";
+    public static boolean DEBUG = KeyguardViewMediator.DEBUG;
+    public static boolean DEBUGXPORT = true; // debug music transport control
 
     // Transport control states.
     static final int TRANSPORT_GONE = 0;
@@ -73,13 +70,8 @@
 
     private int mTransportState = TRANSPORT_GONE;
 
-    // Use this to debug all of keyguard
-    public static boolean DEBUG = KeyguardViewMediator.DEBUG;
-    public static boolean DEBUGXPORT = true; // debug music transport control
-
     // Found in KeyguardAppWidgetPickActivity.java
     static final int APPWIDGET_HOST_ID = 0x4B455947;
-
     private final int MAX_WIDGETS = 5;
 
     private AppWidgetHost mAppWidgetHost;
@@ -89,18 +81,13 @@
     private int mAppWidgetToShow;
 
     protected int mFailedAttempts;
-    private LockPatternUtils mLockPatternUtils;
 
     private KeyguardViewStateManager mViewStateManager;
 
     private Rect mTempRect = new Rect();
-
     private int mDisabledFeatures;
-
     private boolean mCameraDisabled;
-
     private boolean mSafeModeEnabled;
-
     private boolean mUserSetupCompleted;
 
     // User for whom this host view was created.  Final because we should never change the
@@ -119,8 +106,6 @@
 
     private Runnable mPostBootCompletedRunnable;
 
-    private OnDismissAction mDismissAction;
-
     /*package*/ interface UserSwitcherCallback {
         void hideSecurityView(int duration);
         void showSecurityView();
@@ -309,27 +294,18 @@
 
     private SlidingChallengeLayout mSlidingChallengeLayout;
     private MultiPaneChallengeLayout mMultiPaneChallengeLayout;
-    private KeyguardSecurityContainer mSecurityContainer;
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean result = super.onTouchEvent(ev);
         mTempRect.set(0, 0, 0, 0);
-        offsetRectIntoDescendantCoords(mSecurityContainer, mTempRect);
+        offsetRectIntoDescendantCoords(getSecurityContainer(), mTempRect);
         ev.offsetLocation(mTempRect.left, mTempRect.top);
-        result = mSecurityContainer.dispatchTouchEvent(ev) || result;
+        result = getSecurityContainer().dispatchTouchEvent(ev) || result;
         ev.offsetLocation(-mTempRect.left, -mTempRect.top);
         return result;
     }
 
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-        if (mViewMediatorCallback != null) {
-            mViewMediatorCallback.keyguardDoneDrawing();
-        }
-    }
-
     private int getWidgetPosition(int id) {
         final KeyguardWidgetPager appWidgetContainer = mAppWidgetContainer;
         final int children = appWidgetContainer.getChildCount();
@@ -347,6 +323,8 @@
 
     @Override
     protected void onFinishInflate() {
+        super.onFinishInflate();
+
         // Grab instances of and make any necessary changes to the main layouts. Create
         // view state manager and wire up necessary listeners / callbacks.
         View deleteDropTarget = findViewById(R.id.keyguard_widget_pager_delete_target);
@@ -372,49 +350,7 @@
         mViewStateManager.setPagedView(mAppWidgetContainer);
         mViewStateManager.setChallengeLayout(challenge);
 
-        mSecurityContainer =
-                (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
-        mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
-        mSecurityContainer.setSecurityCallback(new SecurityCallback() {
-            @Override
-            public void userActivity(long timeout) {
-                if (mViewMediatorCallback != null) {
-                    mViewMediatorCallback.userActivity(timeout);
-                }
-            }
-
-            @Override
-            public void dismiss(boolean authenticated) {
-                KeyguardHostView.this.dismiss(authenticated);
-            }
-
-            @Override
-            public void finish() {
-
-                // If the alternate unlock was suppressed, it can now be safely
-                // enabled because the user has left keyguard.
-                KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
-
-                // If there's a pending runnable because the user interacted with a widget
-                // and we're leaving keyguard, then run it.
-                boolean deferKeyguardDone = false;
-                if (mDismissAction != null) {
-                    deferKeyguardDone = mDismissAction.onDismiss();
-                    mDismissAction = null;
-                }
-                if (mViewMediatorCallback != null) {
-                    if (deferKeyguardDone) {
-                        mViewMediatorCallback.keyguardDonePending();
-                    } else {
-                        mViewMediatorCallback.keyguardDone(true);
-                    }
-                }
-            }
-        });
-
-        mViewStateManager.setSecurityViewContainer(mSecurityContainer);
-
-        setBackButtonEnabled(false);
+        mViewStateManager.setSecurityViewContainer(getSecurityContainer());
 
         if (KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
             updateAndAddWidgets();
@@ -429,8 +365,7 @@
             };
         }
 
-        mSecurityContainer.showPrimarySecurityScreen(false);
-        mSecurityContainer.updateSecurityViews(mViewStateManager.isBouncing());
+        getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
         enableUserSelectorIfNecessary();
     }
 
@@ -459,17 +394,38 @@
         }
     }
 
-    private void setBackButtonEnabled(boolean enabled) {
-        if (mContext instanceof Activity) return;  // always enabled in activity mode
-        setSystemUiVisibility(enabled ?
-                getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
-                getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
-    }
-
     private boolean shouldEnableAddWidget() {
         return numWidgets() < MAX_WIDGETS && mUserSetupCompleted;
     }
 
+    @Override
+    protected boolean dismiss(boolean authenticated) {
+        // TODO Auto-generated method stub
+        boolean finished = super.dismiss(authenticated);
+        if (!finished) {
+            mViewStateManager.showBouncer(true);
+
+            // Enter full screen mode if we're in SIM or Account screen
+            SecurityMode securityMode = getSecurityContainer().getSecurityMode();
+            boolean isFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
+            boolean isSimOrAccount = securityMode == SecurityMode.SimPin
+                    || securityMode == SecurityMode.SimPuk
+                    || securityMode == SecurityMode.Account;
+            mAppWidgetContainer.setVisibility(
+                    isSimOrAccount && isFullScreen ? View.GONE : View.VISIBLE);
+
+            // Don't show camera or search in navbar when SIM or Account screen is showing
+            setSystemUiVisibility(isSimOrAccount ?
+                    (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH)
+                    : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH));
+
+            if (mSlidingChallengeLayout != null) {
+                mSlidingChallengeLayout.setChallengeInteractive(!isFullScreen);
+            }
+        }
+        return finished;
+    }
+
     private int getDisabledFeatures(DevicePolicyManager dpm) {
         int disabledFeatures = DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE;
         if (dpm != null) {
@@ -494,8 +450,8 @@
 
     void setLockPatternUtils(LockPatternUtils utils) {
         mLockPatternUtils = utils;
-        mSecurityContainer.setLockPatternUtils(utils);
-        mSecurityContainer.updateSecurityViews(mViewStateManager.isBouncing());
+        getSecurityContainer().setLockPatternUtils(utils);
+        getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
     }
 
     @Override
@@ -582,8 +538,6 @@
         return -1;
     }
 
-
-
     private static class MyOnClickHandler extends OnClickHandler {
 
         // weak reference to the hostView to avoid keeping a live reference
@@ -641,75 +595,31 @@
 
     @Override
     public void onScreenTurnedOn() {
-        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
-        mSecurityContainer.showPrimarySecurityScreen(false);
-        mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
-
-        // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
-        // layout is blank but forcing a layout causes it to reappear (e.g. with with
-        // hierarchyviewer).
-        requestLayout();
-
+        super.onScreenTurnedOn();
         if (mViewStateManager != null) {
             mViewStateManager.showUsabilityHints();
         }
-
-        requestFocus();
     }
 
     @Override
     public void onScreenTurnedOff() {
-        if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
-                Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
-        // Once the screen turns off, we no longer consider this to be first boot and we want the
-        // biometric unlock to start next time keyguard is shown.
-        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+        super.onScreenTurnedOff();
         // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
         // turns off we reset that behavior
         clearAppWidgetToShow();
         if (KeyguardUpdateMonitor.getInstance(mContext).hasBootCompleted()) {
             checkAppWidgetConsistency();
         }
-        mSecurityContainer.showPrimarySecurityScreen(true);
-        mSecurityContainer.onPause();
         CameraWidgetFrame cameraPage = findCameraPage();
         if (cameraPage != null) {
             cameraPage.onScreenTurnedOff();
         }
-
-        clearFocus();
     }
 
     public void clearAppWidgetToShow() {
         mAppWidgetToShow = AppWidgetManager.INVALID_APPWIDGET_ID;
     }
 
-    @Override
-    public void show() {
-        if (DEBUG) Log.d(TAG, "show()");
-        mSecurityContainer.showPrimarySecurityScreen(false);
-    }
-
-    @Override
-    public void verifyUnlock() {
-        SecurityMode securityMode = mSecurityContainer.getSecurityMode();
-        if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
-            if (mViewMediatorCallback != null) {
-                mViewMediatorCallback.keyguardDone(true);
-            }
-        } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
-                && securityMode != KeyguardSecurityModel.SecurityMode.PIN
-                && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
-            // can only verify unlock when in pattern/password mode
-            if (mViewMediatorCallback != null) {
-                mViewMediatorCallback.keyguardDone(false);
-            }
-        } else {
-            // otherwise, go to the unlock screen, see if they can verify it
-            mSecurityContainer.verifyUnlock();
-        }
-    }
-
     private boolean addWidget(int appId, int pageIndex, boolean updateDbIfFailed) {
         AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appId);
         if (appWidgetInfo != null) {
@@ -757,28 +667,6 @@
             }
         };
 
-    private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
-        @Override
-        Context getContext() {
-            return mContext;
-        }
-
-        @Override
-        void setOnDismissAction(OnDismissAction action) {
-            mDismissAction = action;
-        }
-
-        @Override
-        LockPatternUtils getLockPatternUtils() {
-            return mLockPatternUtils;
-        }
-
-        @Override
-        void requestDismissKeyguard() {
-            KeyguardHostView.this.dismiss(false);
-        }
-    };
-
     private int numWidgets() {
         final int childCount = mAppWidgetContainer.getChildCount();
         int widgetCount = 0;
@@ -800,7 +688,7 @@
                 @Override
                 public void onClick(View v) {
                     // Pass in an invalid widget id... the picker will allocate an ID for us
-                    mActivityLauncher.launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
+                    getActivityLauncher().launchWidgetPicker(AppWidgetManager.INVALID_APPWIDGET_ID);
                 }
             });
         }
@@ -810,8 +698,8 @@
         // inflate system-provided camera?
         if (!mSafeModeEnabled && !cameraDisabledByDpm() && mUserSetupCompleted
                 && mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
-            View cameraWidget =
-                    CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks, mActivityLauncher);
+            View cameraWidget = CameraWidgetFrame.create(mContext, mCameraWidgetCallbacks,
+                    getActivityLauncher());
             if (cameraWidget != null) {
                 mAppWidgetContainer.addWidget(cameraWidget);
             }
@@ -1198,18 +1086,18 @@
                 UserSwitcherCallback callback = new UserSwitcherCallback() {
                     @Override
                     public void hideSecurityView(int duration) {
-                        mSecurityContainer.animate().alpha(0).setDuration(duration);
+                        getSecurityContainer().animate().alpha(0).setDuration(duration);
                     }
 
                     @Override
                     public void showSecurityView() {
-                        mSecurityContainer.setAlpha(1.0f);
+                        getSecurityContainer().setAlpha(1.0f);
                     }
 
                     @Override
                     public void showUnlockHint() {
-                        if (mSecurityContainer != null) {
-                            mSecurityContainer.showUsabilityHint();
+                        if (getSecurityContainer() != null) {
+                            getSecurityContainer().showUsabilityHint();
                         }
                     }
 
@@ -1244,124 +1132,19 @@
         }
     }
 
-    /**
-     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
-     * some cases where we wish to disable it, notably when the menu button placement or technology
-     * is prone to false positives.
-     *
-     * @return true if the menu key should be enabled
-     */
-    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
-    private boolean shouldEnableMenuKey() {
-        final Resources res = getResources();
-        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
-        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
-        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
-        return !configDisabled || isTestHarness || fileOverride;
-    }
-
     public void goToWidget(int appWidgetId) {
         mAppWidgetToShow = appWidgetId;
         mSwitchPageRunnable.run();
     }
 
-    public boolean handleMenuKey() {
-        // The following enables the MENU key to work for testing automation
-        if (shouldEnableMenuKey()) {
-            dismiss();
-            return true;
-        }
-        return false;
-    }
-
-    public boolean handleBackKey() {
-        if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
-            // go back to primary screen and re-disable back
-            setBackButtonEnabled(false);
-            mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
-            return true;
-        }
-        if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
-            mSecurityContainer.dismiss(false);
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     *  Dismisses the keyguard by going to the next screen or making it gone.
-     */
-    public void dismiss() {
-        dismiss(false);
-    }
-
-    private void dismiss(boolean authenticated) {
-        boolean finished = mSecurityContainer.showNextSecurityScreenOrFinish(authenticated);
-        if (!finished) {
-            updateAfterSecuritySelection();
-            mViewStateManager.showBouncer(true);
-        }
-    }
-
-    void setOnDismissAction(OnDismissAction action) {
-        mDismissAction = action;
-    }
-
-    public void announceCurrentSecurityMethod() {
-        mSecurityContainer.announceCurrentSecurityMethod();
-    }
-
-    private void updateAfterSecuritySelection() {
-        // Enable or disable the back button based on security mode
-        if (mSecurityContainer.getSecurityMode() == SecurityMode.Account
-                && !mLockPatternUtils.isPermanentlyLocked()) {
-            // we're showing account as a backup, provide a way to get back to primary
-            setBackButtonEnabled(true);
-        }
-
-        // Enter full screen mode if we're in SIM or Account screen
-        SecurityMode securityMode = mSecurityContainer.getSecurityMode();
-        boolean isFullScreen = getResources().getBoolean(R.bool.kg_sim_puk_account_full_screen);
-        boolean isSimOrAccount = securityMode == SecurityMode.SimPin
-                || securityMode == SecurityMode.SimPuk
-                || securityMode == SecurityMode.Account;
-        mAppWidgetContainer.setVisibility(
-                isSimOrAccount && isFullScreen ? View.GONE : View.VISIBLE);
-
-        // Don't show camera or search in navbar when SIM or Account screen is showing
-        setSystemUiVisibility(isSimOrAccount ?
-                (getSystemUiVisibility() | View.STATUS_BAR_DISABLE_SEARCH)
-                : (getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_SEARCH));
-
-        if (mSlidingChallengeLayout != null) {
-            mSlidingChallengeLayout.setChallengeInteractive(!isFullScreen);
-        }
-
-        if (mViewMediatorCallback != null) {
-            mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
-        }
-    }
-
-    public void showAssistant() {
-        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
-          .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
-
-        if (intent == null) return;
-
-        final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
-                R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
-                getHandler(), null);
-
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mActivityLauncher.launchActivityWithAnimation(intent, false, opts.toBundle(), null, null);
+    @Override
+    protected void showBouncer(boolean show) {
+        super.showBouncer(show);
+        mViewStateManager.showBouncer(show);
     }
 
     public void dispatch(MotionEvent event) {
         mAppWidgetContainer.handleExternalCameraEvent(event);
     }
 
-    public void launchCamera() {
-        mActivityLauncher.launchCamera(getHandler(), null);
-    }
-
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
new file mode 100644
index 0000000..f1058d2
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
@@ -0,0 +1,30 @@
+package com.android.keyguard;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+public class KeyguardSimpleHostView extends KeyguardViewBase {
+
+    public KeyguardSimpleHostView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void verifyUnlock() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void cleanUp() {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public long getUserActivityTimeout() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index bff1f93..79297d6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -17,18 +17,34 @@
 package com.android.keyguard;
 
 import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.SearchManager;
 import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Canvas;
 import android.media.AudioManager;
 import android.media.IAudioService;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
 import android.view.KeyEvent;
+import android.view.View;
 import android.widget.FrameLayout;
 
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+
+import java.io.File;
+
 /**
  * Base class for keyguard view.  {@link #reset} is where you should
  * reset the state of your view.  Use the {@link KeyguardViewCallback} via
@@ -43,11 +59,17 @@
     private AudioManager mAudioManager;
     private TelephonyManager mTelephonyManager = null;
     protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+    protected LockPatternUtils mLockPatternUtils;
+    private OnDismissAction mDismissAction;
 
     // Whether the volume keys should be handled by keyguard. If true, then
     // they will be handled here for specific media types such as music, otherwise
     // the audio service will bring up the volume dialog.
     private static final boolean KEYGUARD_MANAGES_VOLUME = true;
+    private static final boolean DEBUG = false;
+    private static final String TAG = "KeyguardViewBase";
+
+    private KeyguardSecurityContainer mSecurityContainer;
 
     public KeyguardViewBase(Context context) {
         this(context, null);
@@ -57,20 +79,196 @@
         super(context, attrs);
     }
 
-    /**
-     * Called when the screen turned off.
-     */
-    abstract public void onScreenTurnedOff();
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.keyguardDoneDrawing();
+        }
+    }
 
     /**
-     * Called when the screen turned on.
+     * Sets an action to run when keyguard finishes.
+     *
+     * @param action
      */
-    abstract public void onScreenTurnedOn();
+    public void setOnDismissAction(OnDismissAction action) {
+        mDismissAction = action;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        mSecurityContainer =
+                (KeyguardSecurityContainer) findViewById(R.id.keyguard_security_container);
+        mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
+        mSecurityContainer.setSecurityCallback(new SecurityCallback() {
+            @Override
+            public void userActivity(long timeout) {
+                KeyguardViewBase.this.userActivity(timeout);
+            }
+
+            @Override
+            public void dismiss(boolean authenticated) {
+                KeyguardViewBase.this.dismiss(authenticated);
+            }
+
+            @Override
+            public void finish() {
+                KeyguardViewBase.this.finish();
+            }
+        });
+        mSecurityContainer.showPrimarySecurityScreen(false);
+        // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
+        setBackButtonEnabled(false);
+    }
 
     /**
      * Called when the view needs to be shown.
      */
-    abstract public void show();
+    public void show() {
+        if (DEBUG) Log.d(TAG, "show()");
+        mSecurityContainer.showPrimarySecurityScreen(false);
+    }
+
+    /**
+     *  Dismisses the keyguard by going to the next screen or making it gone.
+     */
+    public void dismiss() {
+        dismiss(false);
+    }
+
+    protected boolean dismiss(boolean authenticated) {
+        boolean finished = getSecurityContainer().showNextSecurityScreenOrFinish(authenticated);
+        if (!finished) {
+            updateAfterSecuritySelection();
+        }
+        return finished;
+    }
+
+    private void setBackButtonEnabled(boolean enabled) {
+        setSystemUiVisibility(enabled ?
+                getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
+                getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
+    }
+
+    protected void showBouncer(boolean show) {
+        CharSequence what = getContext().getResources().getText(
+                show ? R.string.keyguard_accessibility_show_bouncer
+                        : R.string.keyguard_accessibility_hide_bouncer);
+        announceForAccessibility(what);
+        announceCurrentSecurityMethod();
+    }
+
+    public boolean handleBackKey() {
+        if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
+            // go back to primary screen and re-disable back
+            setBackButtonEnabled(false);
+            mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
+            return true;
+        }
+        if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) {
+            mSecurityContainer.dismiss(false);
+            return true;
+        }
+        return false;
+    }
+
+    protected void announceCurrentSecurityMethod() {
+        mSecurityContainer.announceCurrentSecurityMethod();
+    }
+
+    private void updateAfterSecuritySelection() {
+        // Enable or disable the back button based on security mode
+        if (getSecurityContainer().getSecurityMode() == SecurityMode.Account
+                && !mLockPatternUtils.isPermanentlyLocked()) {
+            // we're showing account as a backup, provide a way to get back to primary
+            setBackButtonEnabled(true);
+        }
+
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.setNeedsInput(getSecurityContainer().needsInput());
+        }
+    }
+
+    protected KeyguardSecurityContainer getSecurityContainer() {
+        return mSecurityContainer;
+    }
+
+    /**
+     * Authentication has happened and it's time to dismiss keyguard. This function
+     * should clean up and inform KeyguardViewMediator.
+     */
+    public void finish() {
+        // If the alternate unlock was suppressed, it can now be safely
+        // enabled because the user has left keyguard.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+
+        // If there's a pending runnable because the user interacted with a widget
+        // and we're leaving keyguard, then run it.
+        boolean deferKeyguardDone = false;
+        if (mDismissAction != null) {
+            deferKeyguardDone = mDismissAction.onDismiss();
+            mDismissAction = null;
+        }
+        if (mViewMediatorCallback != null) {
+            if (deferKeyguardDone) {
+                mViewMediatorCallback.keyguardDonePending();
+            } else {
+                mViewMediatorCallback.keyguardDone(true);
+            }
+        }
+    }
+
+    /**
+     * Extend display timeout
+     * @param timeout duration to delay timeout, in ms.
+     */
+    protected void userActivity(long timeout) {
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.userActivity(timeout);
+        }
+    }
+
+    protected void userActivity() {
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.userActivity();
+        }
+    }
+
+    protected void onUserActivityTimeoutChanged() {
+        if (mViewMediatorCallback != null) {
+            mViewMediatorCallback.onUserActivityTimeoutChanged();
+        }
+    }
+
+    /**
+     * Called when the screen turned off.
+     */
+    protected void onScreenTurnedOff() {
+        if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
+                Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
+        // Once the screen turns off, we no longer consider this to be first boot and we want the
+        // biometric unlock to start next time keyguard is shown.
+        KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
+        mSecurityContainer.showPrimarySecurityScreen(true);
+        mSecurityContainer.onPause();
+        clearFocus();
+    }
+
+    /**
+     * Called when the screen turned on.
+     */
+    protected void onScreenTurnedOn() {
+        if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
+        mSecurityContainer.showPrimarySecurityScreen(false);
+        mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
+
+        // This is a an attempt to fix bug 7137389 where the device comes back on but the entire
+        // layout is blank but forcing a layout causes it to reappear (e.g. with with
+        // hierarchyviewer).
+        requestLayout();
+        requestFocus();
+    }
 
     /**
      * Verify that the user can get past the keyguard securely.  This is called,
@@ -79,7 +277,24 @@
      *
      * The result will be propogated back via {@link KeyguardViewCallback#keyguardDone(boolean)}
      */
-    abstract public void verifyUnlock();
+    public void verifyUnlock() {
+        SecurityMode securityMode = getSecurityContainer().getSecurityMode();
+        if (securityMode == KeyguardSecurityModel.SecurityMode.None) {
+            if (mViewMediatorCallback != null) {
+                mViewMediatorCallback.keyguardDone(true);
+            }
+        } else if (securityMode != KeyguardSecurityModel.SecurityMode.Pattern
+                && securityMode != KeyguardSecurityModel.SecurityMode.PIN
+                && securityMode != KeyguardSecurityModel.SecurityMode.Password) {
+            // can only verify unlock when in pattern/password mode
+            if (mViewMediatorCallback != null) {
+                mViewMediatorCallback.keyguardDone(false);
+            }
+        } else {
+            // otherwise, go to the unlock screen, see if they can verify it
+            mSecurityContainer.verifyUnlock();
+        }
+    }
 
     /**
      * Called before this view is being removed.
@@ -183,7 +398,7 @@
         return false;
     }
 
-    void handleMediaKeyEvent(KeyEvent keyEvent) {
+    private void handleMediaKeyEvent(KeyEvent keyEvent) {
         IAudioService audioService = IAudioService.Stub.asInterface(
                 ServiceManager.checkService(Context.AUDIO_SERVICE));
         if (audioService != null) {
@@ -206,8 +421,78 @@
         }
     }
 
+    /**
+     * In general, we enable unlocking the insecure keyguard with the menu key. However, there are
+     * some cases where we wish to disable it, notably when the menu button placement or technology
+     * is prone to false positives.
+     *
+     * @return true if the menu key should be enabled
+     */
+    private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
+    private boolean shouldEnableMenuKey() {
+        final Resources res = getResources();
+        final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
+        final boolean isTestHarness = ActivityManager.isRunningInTestHarness();
+        final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
+        return !configDisabled || isTestHarness || fileOverride;
+    }
+
+    public boolean handleMenuKey() {
+        // The following enables the MENU key to work for testing automation
+        if (shouldEnableMenuKey()) {
+            dismiss();
+            return true;
+        }
+        return false;
+    }
+
     public void setViewMediatorCallback(
             KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
         mViewMediatorCallback = viewMediatorCallback;
     }
+
+    protected KeyguardActivityLauncher getActivityLauncher() {
+        return mActivityLauncher;
+    }
+
+    private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
+        @Override
+        Context getContext() {
+            return mContext;
+        }
+
+        @Override
+        void setOnDismissAction(OnDismissAction action) {
+            KeyguardViewBase.this.setOnDismissAction(action);
+        }
+
+        @Override
+        LockPatternUtils getLockPatternUtils() {
+            return mLockPatternUtils;
+        }
+
+        @Override
+        void requestDismissKeyguard() {
+            KeyguardViewBase.this.dismiss(false);
+        }
+    };
+
+    public void showAssistant() {
+        final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+          .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
+
+        if (intent == null) return;
+
+        final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+                R.anim.keyguard_action_assist_enter, R.anim.keyguard_action_assist_exit,
+                getHandler(), null);
+
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mActivityLauncher.launchActivityWithAnimation(intent, false, opts.toBundle(), null, null);
+    }
+
+    public void launchCamera() {
+        mActivityLauncher.launchCamera(getHandler(), null);
+    }
+
 }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
index a7b72e2..e47edf3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java
@@ -105,11 +105,6 @@
     }
 
     public void showBouncer(boolean show) {
-        CharSequence what = mKeyguardHostView.getContext().getResources().getText(
-                show ? R.string.keyguard_accessibility_show_bouncer
-                        : R.string.keyguard_accessibility_hide_bouncer);
-        mKeyguardHostView.announceForAccessibility(what);
-        mKeyguardHostView.announceCurrentSecurityMethod();
         mChallengeLayout.showBouncer();
     }