Code drop from //branches/cupcake/...@124589
diff --git a/policy/Android.mk b/policy/Android.mk
index 462431f..29f62b8 100644
--- a/policy/Android.mk
+++ b/policy/Android.mk
@@ -7,6 +7,7 @@
 LOCAL_SRC_FILES := \
             $(call all-subdir-java-files)
 
-LOCAL_MODULE:= android.policy
+LOCAL_MODULE := android.policy_phone
+LOCAL_UNINSTALLABLE_MODULE := true
 
 include $(BUILD_JAVA_LIBRARY)
diff --git a/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java b/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java
index 832288b..b46b37d 100644
--- a/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java
+++ b/policy/com/android/internal/policy/impl/KeyguardScreenCallback.java
@@ -58,4 +58,9 @@
      */
     void reportFailedPatternAttempt();
 
+    /**
+     * Report whether we there's another way to unlock the device.
+     * @return true 
+     */
+    boolean doesFallbackUnlockScreenExist();
 }
diff --git a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index ab7c744..4671957 100644
--- a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -160,8 +160,8 @@
             }
         };
 
-        mDeviceProvisioned = Settings.System.getInt(
-                mContext.getContentResolver(), Settings.System.DEVICE_PROVISIONED, 0) != 0;
+        mDeviceProvisioned = Settings.Secure.getInt(
+                mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
      
         // Since device can't be un-provisioned, we only need to register a content observer
         // to update mDeviceProvisioned when we are...
@@ -170,8 +170,8 @@
                 @Override
                 public void onChange(boolean selfChange) {
                     super.onChange(selfChange);
-                    mDeviceProvisioned = Settings.System.getInt(mContext.getContentResolver(), 
-                            Settings.System.DEVICE_PROVISIONED, 0) != 0;
+                    mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(), 
+                        Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
                     if (mDeviceProvisioned && mContentObserver != null) {
                         // We don't need the observer anymore...
                         mContext.getContentResolver().unregisterContentObserver(mContentObserver);
@@ -182,13 +182,13 @@
             };
             
             mContext.getContentResolver().registerContentObserver(
-                    Settings.System.getUriFor(Settings.System.DEVICE_PROVISIONED),
+                    Settings.Secure.getUriFor(Settings.Secure.DEVICE_PROVISIONED),
                     false, mContentObserver);
             
             // prevent a race condition between where we check the flag and where we register the
             // observer by grabbing the value once again...
-            mDeviceProvisioned = Settings.System.getInt(mContext.getContentResolver(), 
-                    Settings.System.DEVICE_PROVISIONED, 0) != 0;
+            mDeviceProvisioned = Settings.Secure.getInt(mContext.getContentResolver(), 
+                Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
         }
         
         mInPortrait = queryInPortrait();
diff --git a/policy/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/com/android/internal/policy/impl/KeyguardViewBase.java
index 491300e..5a3ebde 100644
--- a/policy/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -131,7 +131,13 @@
         final int keyCode = event.getKeyCode();
         if (event.getAction() == KeyEvent.ACTION_DOWN) {
             switch (keyCode) {
-                case KeyEvent.KEYCODE_HEADSETHOOK: {
+                case KeyEvent.KEYCODE_HEADSETHOOK: 
+                case KeyEvent.KEYCODE_PLAYPAUSE: 
+                case KeyEvent.KEYCODE_STOP: 
+                case KeyEvent.KEYCODE_NEXTSONG: 
+                case KeyEvent.KEYCODE_PREVIOUSSONG: 
+                case KeyEvent.KEYCODE_REWIND: 
+                case KeyEvent.KEYCODE_FORWARD: {
                     Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                     intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
                     getContext().sendOrderedBroadcast(intent, null);
@@ -161,7 +167,13 @@
             }
         } else if (event.getAction() == KeyEvent.ACTION_UP) {
             switch (keyCode) {
-                case KeyEvent.KEYCODE_HEADSETHOOK: {
+                case KeyEvent.KEYCODE_HEADSETHOOK: 
+                case KeyEvent.KEYCODE_PLAYPAUSE: 
+                case KeyEvent.KEYCODE_STOP: 
+                case KeyEvent.KEYCODE_NEXTSONG: 
+                case KeyEvent.KEYCODE_PREVIOUSSONG: 
+                case KeyEvent.KEYCODE_REWIND: 
+                case KeyEvent.KEYCODE_FORWARD: {
                     Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                     intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
                     getContext().sendOrderedBroadcast(intent, null);
diff --git a/policy/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/com/android/internal/policy/impl/KeyguardViewMediator.java
index ac816b0..2431ffe 100644
--- a/policy/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -131,6 +131,8 @@
     private Context mContext;
     private AlarmManager mAlarmManager;
 
+    private boolean mSystemReady;
+    
     /** Low level access to the power manager for enableUserActivity.  Having this
      * requires that we run in the system process.  */
     LocalPowerManager mRealPowerManager;
@@ -254,6 +256,7 @@
     public void onSystemReady() {
         synchronized (this) {
             if (DEBUG) Log.d(TAG, "onSystemReady");
+            mSystemReady = true;
             doKeyguard();
         }
     }
@@ -638,7 +641,13 @@
         switch (keyCode) {
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_DOWN:
-            case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_HEADSETHOOK: 
+            case KeyEvent.KEYCODE_PLAYPAUSE: 
+            case KeyEvent.KEYCODE_STOP: 
+            case KeyEvent.KEYCODE_NEXTSONG: 
+            case KeyEvent.KEYCODE_PREVIOUSSONG: 
+            case KeyEvent.KEYCODE_REWIND: 
+            case KeyEvent.KEYCODE_FORWARD:
             case KeyEvent.KEYCODE_CAMERA:
                 return false;
         }
@@ -806,6 +815,8 @@
     private void handleShow() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleShow");
+            if (!mSystemReady) return;
+            
             // while we're showing, we control the wake state, so ask the power
             // manager not to honor request for userActivity.
             mRealPowerManager.enableUserActivity(false);
@@ -875,6 +886,7 @@
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
             mKeyguardViewManager.verifyUnlock();
+            mShowing = true;
         }
     }
 
diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 66a4c4e..4ff87e3 100644
--- a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -16,9 +16,15 @@
 
 package com.android.internal.policy.impl;
 
+import android.accounts.AccountsServiceConstants;
+import android.accounts.IAccountsService;
 import android.app.AlertDialog;
+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.SystemProperties;
 import com.android.internal.telephony.SimCard;
 import android.text.TextUtils;
@@ -51,6 +57,8 @@
     private View mUnlockScreen;
 
     private boolean mScreenOn = false;
+    private boolean mHasAccount = false; // assume they don't have an account until we know better
+
 
     /**
      * The current {@link KeyguardScreen} will use this to communicate back to us.
@@ -114,6 +122,10 @@
      */
     private final LockPatternUtils mLockPatternUtils;
 
+    /**
+     * Used to fetch accounts from GLS.
+     */
+    private ServiceConnection mServiceConnection;
 
     /**
      * @return Whether we are stuck on the lock screen because the sim is
@@ -137,7 +149,9 @@
             KeyguardUpdateMonitor updateMonitor,
             LockPatternUtils lockPatternUtils) {
         super(context);
-
+        
+        asyncCheckForAccount();
+        
         mRequiresSim =
                 TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
 
@@ -145,6 +159,7 @@
         mLockPatternUtils = lockPatternUtils;
 
         mMode = getInitialMode();
+        
         mKeyguardScreenCallback = new KeyguardScreenCallback() {
 
             public void goToLockScreen() {
@@ -210,10 +225,11 @@
             public void reportFailedPatternAttempt() {
                 mUpdateMonitor.reportFailedAttempt();
                 final int failedAttempts = mUpdateMonitor.getFailedAttempts();
-                if (failedAttempts ==
-                        (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
+                if (mHasAccount && failedAttempts ==
+                        (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET 
+                                - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
                     showAlmostAtAccountLoginDialog();
-                } else if (failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
+                } else if (mHasAccount && failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
                     mLockPatternUtils.setPermanentlyLocked(true);
                     updateScreen(mMode);
                 } else if ((failedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)
@@ -221,6 +237,10 @@
                     showTimeoutDialog();
                 }
             }
+            
+            public boolean doesFallbackUnlockScreenExist() {
+                return mHasAccount;
+            }
         };
 
         /**
@@ -241,6 +261,36 @@
         updateScreen(mMode);
     }
 
+    /** 
+     * Asynchronously checks for at least one account. This will set mHasAccount
+     * to true if an account is found.
+     */
+    private void asyncCheckForAccount() {
+        
+        mServiceConnection = new ServiceConnection() {
+            public void onServiceConnected(ComponentName className, IBinder service) {
+                try {
+                    IAccountsService accountsService = IAccountsService.Stub.asInterface(service);
+                    String accounts[] = accountsService.getAccounts();
+                    mHasAccount = (accounts.length > 0);
+                } catch (RemoteException e) {
+                    // Not much we can do here...
+                    Log.e(TAG, "Gls died while attempting to get accounts: " + e);
+                } finally {
+                    getContext().unbindService(mServiceConnection);
+                    mServiceConnection = null;
+                }
+            }
+
+            public void onServiceDisconnected(ComponentName className) {
+                // nothing to do here
+            }
+        };
+        boolean status = getContext().bindService(AccountsServiceConstants.SERVICE_INTENT,
+                mServiceConnection, Context.BIND_AUTO_CREATE);
+        if (!status) Log.e(TAG, "Failed to bind to GLS while checking for account");
+    }
+
     @Override
     public void reset() {
         mIsVerifyUnlockOnly = false;
diff --git a/policy/com/android/internal/policy/impl/LockScreen.java b/policy/com/android/internal/policy/impl/LockScreen.java
index c717cc3..0825c3b 100644
--- a/policy/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/com/android/internal/policy/impl/LockScreen.java
@@ -20,7 +20,7 @@
 import com.android.internal.widget.LockPatternUtils;
 
 import android.content.Context;
-import android.pim.DateFormat;
+import android.text.format.DateFormat;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -299,7 +299,7 @@
                 mHeaderSimOk1.setVisibility(View.VISIBLE);
                 mHeaderSimOk1.setText(plmn);
             } else {
-                mHeaderSimOk2.setVisibility(View.GONE);
+                mHeaderSimOk1.setVisibility(View.GONE);
             }
 
             if (spn != null) {
diff --git a/policy/com/android/internal/policy/impl/PhoneWindow.java b/policy/com/android/internal/policy/impl/PhoneWindow.java
index 2d5bd31..dfc4b6c 100644
--- a/policy/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindow.java
@@ -41,7 +41,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
-import android.provider.CallLog.Calls;
 import android.util.AndroidRuntimeException;
 import android.util.Config;
 import android.util.EventLog;
@@ -66,6 +65,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_RESTORED_STATE;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.widget.FrameLayout;
@@ -482,7 +482,8 @@
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 WRAP_CONTENT, WRAP_CONTENT,
                 st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
-                WindowManager.LayoutParams.FLAG_DITHER,
+                WindowManager.LayoutParams.FLAG_DITHER
+                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                 st.decorView.mDefaultOpacity);
 
         lp.gravity = st.gravity;
@@ -493,7 +494,11 @@
 
     @Override
     public final void closePanel(int featureId) {
-        closePanel(getPanelState(featureId, true), true);
+        if (featureId == FEATURE_CONTEXT_MENU) {
+            closeContextMenu();
+        } else {
+            closePanel(getPanelState(featureId, true), true);
+        }
     }
 
     /**
@@ -628,8 +633,23 @@
 
         closeContextMenu();
     }
-    
+
+    /**
+     * Closes the context menu. This notifies the menu logic of the close, along
+     * with dismissing it from the UI.
+     */
     private synchronized void closeContextMenu() {
+        if (mContextMenu != null) {
+            mContextMenu.close();
+            dismissContextMenu();
+        }
+    }
+
+    /**
+     * Dismisses just the context menu UI. To close the context menu, use
+     * {@link #closeContextMenu()}.
+     */
+    private synchronized void dismissContextMenu() {
         mContextMenu = null;
         
         if (mContextMenuHelper != null) {
@@ -1117,7 +1137,13 @@
                 return true;
             }
 
-            case KeyEvent.KEYCODE_HEADSETHOOK: {
+            case KeyEvent.KEYCODE_HEADSETHOOK: 
+            case KeyEvent.KEYCODE_PLAYPAUSE: 
+            case KeyEvent.KEYCODE_STOP: 
+            case KeyEvent.KEYCODE_NEXTSONG: 
+            case KeyEvent.KEYCODE_PREVIOUSSONG: 
+            case KeyEvent.KEYCODE_REWIND: 
+            case KeyEvent.KEYCODE_FORWARD: {
                 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                 intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
                 getContext().sendOrderedBroadcast(intent, null);
@@ -1226,7 +1252,13 @@
                 return true;
             }
 
-            case KeyEvent.KEYCODE_HEADSETHOOK: {
+            case KeyEvent.KEYCODE_HEADSETHOOK: 
+            case KeyEvent.KEYCODE_PLAYPAUSE: 
+            case KeyEvent.KEYCODE_STOP: 
+            case KeyEvent.KEYCODE_NEXTSONG: 
+            case KeyEvent.KEYCODE_PREVIOUSSONG: 
+            case KeyEvent.KEYCODE_REWIND: 
+            case KeyEvent.KEYCODE_FORWARD: {
                 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
                 intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
                 getContext().sendOrderedBroadcast(intent, null);
@@ -1344,6 +1376,8 @@
             return;
         }
 
+        setFlags(FLAG_RESTORED_STATE, FLAG_RESTORED_STATE);
+        
         SparseArray<Parcelable> savedStates
                 = savedInstanceState.getSparseParcelableArray(VIEWS_TAG);
         if (savedStates != null) {
@@ -1503,7 +1537,7 @@
                          * If not handled, then pass it to the view hierarchy
                          * and anyone else that may be interested.
                          */
-                        handled = dispatchKeyShortcut(event);
+                        handled = dispatchKeyShortcutEvent(event);
 
                         if (handled && mPreparedPanel != null) {
                             mPreparedPanel.isHandled = true;
@@ -1534,11 +1568,6 @@
                     : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
         }
         
-        private boolean dispatchKeyShortcut(KeyEvent event) {
-            View focusedView = findFocus();
-            return focusedView == null ? false : focusedView.dispatchKeyShortcutEvent(event);
-        }
-
         @Override
         public boolean dispatchTouchEvent(MotionEvent ev) {
             final Callback cb = getCallback();
@@ -1884,7 +1913,6 @@
     protected ViewGroup generateLayout(DecorView decor) {
         // Apply data from current theme.
 
-        final Context c = getContext();
         TypedArray a = getWindowStyle();
 
         if (false) {
@@ -1903,19 +1931,10 @@
         if (mIsFloating) {
             setLayout(WRAP_CONTENT, WRAP_CONTENT);
             setFlags(0, flagsToUpdate);
-            
-            /* All dialogs should have the window dimmed */
-            WindowManager.LayoutParams params = getAttributes();
-            TypedArray attrs = c.obtainStyledAttributes(
-                    com.android.internal.R.styleable.Theme);
-            params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
-            params.dimAmount = attrs.getFloat(
-                    android.R.styleable.Theme_backgroundDimAmount, 0.5f);
-            attrs.recycle();
         } else {
             setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
         }
-
+        
         if (a.getBoolean(com.android.internal.R.styleable.Window_windowNoTitle, false)) {
             requestFeature(FEATURE_NO_TITLE);
         }
@@ -1924,6 +1943,28 @@
             setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags()));
         }
 
+        WindowManager.LayoutParams params = getAttributes();
+        
+        if (!hasSoftInputMode()) {
+            params.softInputMode = (byte)a.getInt(
+                    com.android.internal.R.styleable.Window_windowSoftInputMode,
+                    params.softInputMode);
+        }
+        
+        if (a.getBoolean(com.android.internal.R.styleable.Window_backgroundDimEnabled,
+                mIsFloating)) {
+            /* All dialogs should have the window dimmed */
+            if ((getForcedWindowFlags()&WindowManager.LayoutParams.FLAG_DIM_BEHIND) == 0) {
+                params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+            }
+            params.dimAmount = a.getFloat(
+                    android.R.styleable.Window_backgroundDimAmount, 0.5f);
+        }
+
+        params.windowAnimations = a.getResourceId(
+                com.android.internal.R.styleable.Window_windowAnimationStyle,
+                params.windowAnimations);
+        
         // The rest are only done if this window is not embedded; otherwise,
         // the values are inherited from our container.
         if (getContainer() == null) {
@@ -2529,6 +2570,7 @@
      */
     private final class ContextMenuCallback implements MenuBuilder.Callback {
         private int mFeatureId;
+        private MenuDialogHelper mSubMenuHelper;
         
         public ContextMenuCallback(int featureId) {
             mFeatureId = featureId;
@@ -2540,7 +2582,13 @@
                 if (callback != null) callback.onPanelClosed(mFeatureId, menu);
                 
                 if (menu == mContextMenu) {
-                    closeContextMenu();
+                    dismissContextMenu();
+                }
+                
+                // Dismiss the submenu, if it is showing
+                if (mSubMenuHelper != null) {
+                    mSubMenuHelper.dismiss();
+                    mSubMenuHelper = null;
                 }
             }
         }
@@ -2553,7 +2601,6 @@
         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
             Callback callback = getCallback();
             return (callback != null) && callback.onMenuItemSelected(mFeatureId, item);
-
         }
 
         public void onMenuModeChange(MenuBuilder menu) {
@@ -2564,7 +2611,8 @@
             subMenu.setCallback(this);
 
             // The window manager will give us a valid window token
-            new MenuDialogHelper(subMenu).show(null);
+            mSubMenuHelper = new MenuDialogHelper(subMenu);
+            mSubMenuHelper.show(null);
             
             return true;
         }
diff --git a/policy/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
index 250d2d4..603b221 100644
--- a/policy/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -23,14 +23,13 @@
 import android.content.BroadcastReceiver;
 import android.content.ContentQueryMap;
 import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.database.Cursor;
+import android.database.ContentObserver;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.IBinder;
@@ -41,13 +40,13 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import static android.provider.Settings.System.END_BUTTON_BEHAVIOR;
 
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.telephony.ITelephony;
 import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.IWindowManager;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -64,10 +63,13 @@
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
@@ -77,6 +79,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import android.view.WindowManagerImpl;
@@ -91,117 +95,159 @@
  * WindowManagerPolicy implementation for the Android phone UI.
  */
 public class PhoneWindowManager implements WindowManagerPolicy {
-    private static final String TAG = "WindowManager";
-    private static final boolean DEBUG = false;
-    private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
-    private static final boolean SHOW_STARTING_ANIMATIONS = true;
-    private static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
+    static final String TAG = "WindowManager";
+    static final boolean DEBUG = false;
+    static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean SHOW_STARTING_ANIMATIONS = true;
+    static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
     
-    private static final int APPLICATION_LAYER = 1;
-    private static final int PHONE_LAYER = 2;
-    private static final int SEARCH_BAR_LAYER = 3;
-    private static final int STATUS_BAR_PANEL_LAYER = 4;
+    static final int APPLICATION_LAYER = 1;
+    static final int PHONE_LAYER = 2;
+    static final int SEARCH_BAR_LAYER = 3;
+    static final int STATUS_BAR_PANEL_LAYER = 4;
     // toasts and the plugged-in battery thing
-    private static final int TOAST_LAYER = 5;
-    private static final int STATUS_BAR_LAYER = 6;
+    static final int TOAST_LAYER = 5;
+    static final int STATUS_BAR_LAYER = 6;
     // SIM errors and unlock.  Not sure if this really should be in a high layer.
-    private static final int PRIORITY_PHONE_LAYER = 7;
+    static final int PRIORITY_PHONE_LAYER = 7;
     // like the ANR / app crashed dialogs
-    private static final int SYSTEM_ALERT_LAYER = 8;
+    static final int SYSTEM_ALERT_LAYER = 8;
     // system-level error dialogs
-    private static final int SYSTEM_ERROR_LAYER = 9;
+    static final int SYSTEM_ERROR_LAYER = 9;
+    // on-screen keyboards and other such input method user interfaces go here.
+    static final int INPUT_METHOD_LAYER = 10;
+    // on-screen keyboards and other such input method user interfaces go here.
+    static final int INPUT_METHOD_DIALOG_LAYER = 11;
     // the keyguard; nothing on top of these can take focus, since they are
     // responsible for power management when displayed.
-    private static final int KEYGUARD_LAYER = 10;
-    private static final int KEYGUARD_DIALOG_LAYER = 11;
+    static final int KEYGUARD_LAYER = 12;
+    static final int KEYGUARD_DIALOG_LAYER = 13;
     // things in here CAN NOT take focus, but are shown on top of everything else.
-    private static final int SYSTEM_OVERLAY_LAYER = 12;
+    static final int SYSTEM_OVERLAY_LAYER = 14;
 
-    private static final int APPLICATION_PANEL_SUBLAYER = 1;
-    private static final int APPLICATION_MEDIA_SUBLAYER = -1;
-    private static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
+    static final int APPLICATION_PANEL_SUBLAYER = 1;
+    static final int APPLICATION_MEDIA_SUBLAYER = -1;
+    static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
 
-    private static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f;
+    static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f;
+    
+    // Debugging: set this to have the system act like there is no hard keyboard.
+    static final boolean KEYBOARD_ALWAYS_HIDDEN = false;
     
     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
 
-    private Context mContext;
-    private IWindowManager mWindowManager;
-    private LocalPowerManager mPowerManager;
+    Context mContext;
+    IWindowManager mWindowManager;
+    LocalPowerManager mPowerManager;
 
     /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
-    private boolean mEnableShiftMenuBugReports = false;
+    boolean mEnableShiftMenuBugReports = false;
     
-    private WindowState mStatusBar = null;
-    private WindowState mSearchBar = null;
-    private WindowState mKeyguard = null;
-    private KeyguardViewMediator mKeyguardMediator;
-    private GlobalActions mGlobalActions;
-    private boolean mShouldTurnOffOnKeyUp;
-    private RecentApplicationsDialog mRecentAppsDialog;
-    private Handler mHandler;
+    WindowState mStatusBar = null;
+    WindowState mSearchBar = null;
+    WindowState mKeyguard = null;
+    KeyguardViewMediator mKeyguardMediator;
+    GlobalActions mGlobalActions;
+    boolean mShouldTurnOffOnKeyUp;
+    RecentApplicationsDialog mRecentAppsDialog;
+    Handler mHandler;
 
-    private boolean mLidOpen;
-    private int mSensorOrientation = OrientationListener.ORIENTATION_UNKNOWN;
-    private int mSensorRotation = -1;
-    private boolean mScreenOn = false;
-    private boolean mOrientationSensorEnabled = false;
-    private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    boolean mLidOpen;
+    int mSensorRotation = -1;
+    boolean mScreenOn = false;
+    boolean mOrientationSensorEnabled = false;
+    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
+    int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
+    boolean mHasSoftInput = false;
     
-    private int mW, mH;
-    private int mCurLeft, mCurTop, mCurRight, mCurBottom;
-    private WindowState mTopFullscreenOpaqueWindowState;
-    private boolean mForceStatusBar;
-    private boolean mHomePressed;
-    private Intent mHomeIntent;
-    private boolean mSearchKeyPressed;
-    private boolean mConsumeSearchKeyUp;
+    // The current size of the screen.
+    int mW, mH;
+    // During layout, the current screen borders with all outer decoration
+    // (status bar, input method dock) accounted for.
+    int mCurLeft, mCurTop, mCurRight, mCurBottom;
+    // During layout, the frame in which content should be displayed
+    // to the user, accounting for all screen decoration except for any
+    // space they deem as available for other content.  This is usually
+    // the same as mCur*, but may be larger if the screen decor has supplied
+    // content insets.
+    int mContentLeft, mContentTop, mContentRight, mContentBottom;
+    // During layout, the current screen borders along with input method
+    // windows are placed.
+    int mDockLeft, mDockTop, mDockRight, mDockBottom;
+    // During layout, the layer at which the doc window is placed.
+    int mDockLayer;
+    
+    static final Rect mTmpParentFrame = new Rect();
+    static final Rect mTmpDisplayFrame = new Rect();
+    static final Rect mTmpContentFrame = new Rect();
+    static final Rect mTmpVisibleFrame = new Rect();
+    
+    WindowState mTopFullscreenOpaqueWindowState;
+    boolean mForceStatusBar;
+    boolean mHomePressed;
+    Intent mHomeIntent;
+    boolean mSearchKeyPressed;
+    boolean mConsumeSearchKeyUp;
 
-    private static final int ENDCALL_HOME = 0x1;
-    private static final int ENDCALL_SLEEPS = 0x2;
-    private static final int DEFAULT_ENDCALL_BEHAVIOR = ENDCALL_SLEEPS;
-    private int mEndcallBehavior;
+    static final int ENDCALL_HOME = 0x1;
+    static final int ENDCALL_SLEEPS = 0x2;
+    static final int DEFAULT_ENDCALL_BEHAVIOR = ENDCALL_SLEEPS;
+    int mEndcallBehavior;
 
-    private ShortcutManager mShortcutManager;
-    private PowerManager.WakeLock mBroadcastWakeLock;
+    ShortcutManager mShortcutManager;
+    PowerManager.WakeLock mBroadcastWakeLock;
 
-    private class SettingsObserver implements Observer {
+    class SettingsObserver extends ContentObserver {
         private ContentQueryMap mSettings;
 
+        SettingsObserver(Handler handler) {
+            super(handler);
+        }
+        
         void observe() {
             ContentResolver resolver = mContext.getContentResolver();
-            Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
-                    Settings.System.NAME + "=?",
-                    new String[] { END_BUTTON_BEHAVIOR},
-                    null);
-            mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
-            mSettings.addObserver(this);
-
-            // pretend that the settings changed so we will get their initial state
-            update(mSettings, null);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.END_BUTTON_BEHAVIOR), false, this);
+            resolver.registerContentObserver(Settings.System.getUriFor(
+                    Settings.System.ACCELEROMETER_ROTATION), false, this);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
+            update();
         }
 
-        private int getInt(String name, int def) {
-            ContentValues row = mSettings.getValues(name);
-            if (row != null) {
-                Integer ret = row.getAsInteger(Settings.System.VALUE);
-                if(ret == null) {
-                    return def;
-                }
-                return ret;
-            } else {
-                return def;
+        @Override public void onChange(boolean selfChange) {
+            update();
+            try {
+                mWindowManager.setRotation(USE_LAST_ROTATION, false);
+            } catch (RemoteException e) {
+                // Ignore
             }
         }
-      
-        public void update(Observable o, Object arg) {
-            mEndcallBehavior = getInt(END_BUTTON_BEHAVIOR, DEFAULT_ENDCALL_BEHAVIOR);
+
+        public void update() {
+            ContentResolver resolver = mContext.getContentResolver();
+            mEndcallBehavior = Settings.System.getInt(resolver,
+                    Settings.System.END_BUTTON_BEHAVIOR, DEFAULT_ENDCALL_BEHAVIOR);
+            int accelerometerDefault = Settings.System.getInt(resolver,
+                    Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
+            if (mAccelerometerDefault != accelerometerDefault) {
+                mAccelerometerDefault = accelerometerDefault;
+                updateOrientationListener();
+            }
+            String imId = Settings.Secure.getString(resolver,
+                    Settings.Secure.DEFAULT_INPUT_METHOD);
+            boolean hasSoftInput = imId != null && imId.length() > 0;
+            if (mHasSoftInput != hasSoftInput) {
+                mHasSoftInput = hasSoftInput;
+                updateRotation();
+            }
         }
     }
     
-    private class MyOrientationListener extends OrientationListener {
+    class MyOrientationListener extends OrientationListener {
 
         MyOrientationListener(Context context) {
             super(context);
@@ -214,7 +260,6 @@
             // portrait range is 270+45 to 359 and 0 to 45
             // landscape range is 270-45 to 270+45
             if ((orientation >= 0 && orientation <= 45) || (orientation >= 270 - 45)) {
-                mSensorOrientation = orientation;
                 int rotation =  (orientation >= 270 - 45
                         && orientation <= 270 + 45)
                         ? Surface.ROTATION_90 : Surface.ROTATION_0;
@@ -233,8 +278,20 @@
             }
         }                                      
     }
-    private MyOrientationListener mOrientationListener;
+    MyOrientationListener mOrientationListener;
 
+    boolean useSensorForOrientation() {
+        if(mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
+            return true;
+        }
+        if (mAccelerometerDefault != 0 && (
+                mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_USER ||
+                mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
+            return true;
+        }
+        return false;
+    }
+    
     /*
      * Various use cases for invoking this function
      * screen turning off, should always disable listeners if already enabled
@@ -245,7 +302,7 @@
      * screen turning on and current app has sensor based orientation, enable listeners if needed
      * screen turning on and current app has nosensor based orientation, do nothing
      */
-    private void updateOrientationListener() {
+    void updateOrientationListener() {
         //Could have been invoked due to screen turning on or off or
         //change of the currently visible window's orientation
         if(localLOGV) Log.i(TAG, "Screen status="+mScreenOn+
@@ -253,7 +310,7 @@
                 ", SensorEnabled="+mOrientationSensorEnabled);
         boolean disable = true;
         if(mScreenOn) {
-            if(mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
+            if(useSensorForOrientation()) {
                 disable = false;
                 //enable listener if not already enabled
                 if(!mOrientationSensorEnabled) {
@@ -271,7 +328,7 @@
         }
     }
 
-    private Runnable mEndCallLongPress = new Runnable() {
+    Runnable mEndCallLongPress = new Runnable() {
         public void run() {
             mShouldTurnOffOnKeyUp = false;
             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
@@ -279,7 +336,7 @@
         }
     };
 
-    private void showGlobalActionsDialog() {
+    void showGlobalActionsDialog() {
         if (mGlobalActions == null) {
             mGlobalActions = new GlobalActions(mContext, mPowerManager);
         }
@@ -292,15 +349,15 @@
         }
     }
 
-    private boolean isDeviceProvisioned() {
-        return Settings.System.getInt(
-                mContext.getContentResolver(), Settings.System.DEVICE_PROVISIONED, 0) != 0;
+    boolean isDeviceProvisioned() {
+        return Settings.Secure.getInt(
+                mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
     }
 
     /**
      * When a home-key longpress expires, close other system windows and launch the recent apps
      */
-    private Runnable mHomeLongPress = new Runnable() {
+    Runnable mHomeLongPress = new Runnable() {
         public void run() {
             /*
              * Eat the longpress so it won't dismiss the recent apps dialog when
@@ -315,7 +372,7 @@
     /**
      * Create (if necessary) and launch the recent apps dialog
      */
-    private void showRecentAppsDialog() {
+    void showRecentAppsDialog() {
         if (mRecentAppsDialog == null) {
             mRecentAppsDialog = new RecentApplicationsDialog(mContext);
         }
@@ -331,7 +388,7 @@
         mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
         mHandler = new Handler();
         mOrientationListener = new MyOrientationListener(mContext);
-        SettingsObserver settingsObserver = new SettingsObserver();
+        SettingsObserver settingsObserver = new SettingsObserver(mHandler);
         settingsObserver.observe();
         mShortcutManager = new ShortcutManager(context, mHandler);
         mShortcutManager.observe();
@@ -359,6 +416,9 @@
                 // this...  should introduce a token to let the system
                 // monitor/control what they are doing.
                 break;
+            case TYPE_INPUT_METHOD:
+                // The window manager will check this.
+                break;
             case TYPE_PHONE:
             case TYPE_PRIORITY_PHONE:
             case TYPE_SYSTEM_ALERT:
@@ -389,7 +449,7 @@
         }
     }
     
-    private void readLidState() {
+    void readLidState() {
         try {
             int sw = mWindowManager.getSwitchState(0);
             if (sw >= 0) {
@@ -403,8 +463,12 @@
     /** {@inheritDoc} */
     public void adjustConfigurationLw(Configuration config) {
         readLidState();
-        mPowerManager.setKeyboardVisibility(mLidOpen);
-        config.keyboardHidden = mLidOpen
+        final boolean lidOpen = !KEYBOARD_ALWAYS_HIDDEN && mLidOpen;
+        mPowerManager.setKeyboardVisibility(lidOpen);
+        config.keyboardHidden = (lidOpen || mHasSoftInput)
+            ? Configuration.KEYBOARDHIDDEN_NO
+            : Configuration.KEYBOARDHIDDEN_YES;
+        config.hardKeyboardHidden = lidOpen
             ? Configuration.KEYBOARDHIDDEN_NO
             : Configuration.KEYBOARDHIDDEN_YES;
         if (keyguardIsShowingTq()) {
@@ -438,10 +502,6 @@
             return APPLICATION_LAYER;
         }
         switch (type) {
-        case TYPE_APPLICATION_PANEL:
-            return APPLICATION_LAYER;
-        case TYPE_APPLICATION_SUB_PANEL:
-            return APPLICATION_LAYER;
         case TYPE_STATUS_BAR:
             return STATUS_BAR_LAYER;
         case TYPE_STATUS_BAR_PANEL:
@@ -458,6 +518,10 @@
             return SYSTEM_ALERT_LAYER;
         case TYPE_SYSTEM_ERROR:
             return SYSTEM_ERROR_LAYER;
+        case TYPE_INPUT_METHOD:
+            return INPUT_METHOD_LAYER;
+        case TYPE_INPUT_METHOD_DIALOG:
+            return INPUT_METHOD_DIALOG_LAYER;
         case TYPE_SYSTEM_OVERLAY:
             return SYSTEM_OVERLAY_LAYER;
         case TYPE_PRIORITY_PHONE:
@@ -473,6 +537,7 @@
     public int subWindowTypeToLayerLw(int type) {
         switch (type) {
         case TYPE_APPLICATION_PANEL:
+        case TYPE_APPLICATION_ATTACHED_DIALOG:
             return APPLICATION_PANEL_SUBLAYER;
         case TYPE_APPLICATION_MEDIA:
             return APPLICATION_MEDIA_SUBLAYER;
@@ -514,6 +579,11 @@
     	}
     	
         Window win = PolicyManager.makeNewWindow(context);
+        if (win.getWindowStyle().getBoolean(
+                com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
+            return null;
+        }
+        
         Resources r = context.getResources();
         win.setTitle(r.getText(labelRes, nonLocalizedLabel));
 
@@ -634,7 +704,7 @@
         }
     }
 
-    private static final boolean PRINT_ANIM = false;
+    static final boolean PRINT_ANIM = false;
     
     /** {@inheritDoc} */
     public int selectAnimationLw(WindowState win, int transit) {
@@ -650,15 +720,15 @@
         return 0;
     }
 
-    private static ITelephony getPhoneInterface() {
+    static ITelephony getPhoneInterface() {
         return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE));
     }
 
-    private static IAudioService getAudioInterface() {
+    static IAudioService getAudioInterface() {
         return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE));
     }
 
-    private boolean keyguardOn() {
+    boolean keyguardOn() {
         return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
     }
 
@@ -826,7 +896,7 @@
      * A home key -> launch home action was detected.  Take the appropriate action
      * given the situation with the keyguard.
      */
-    private void launchHomeFromHotKey() {
+    void launchHomeFromHotKey() {
         if (mKeyguardMediator.isShowing()) {
             // don't launch home if keyguard showing
         } else if (mKeyguardMediator.isInputRestricted()) {
@@ -847,15 +917,15 @@
         }
     }
 
-    public void getCoveredInsetHintLw(WindowManager.LayoutParams attrs, Rect coveredInset) {
+    public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
         final int fl = attrs.flags;
         
         if ((fl &
                 (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
-            coveredInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
+            contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
         } else {
-            coveredInset.setEmpty();
+            contentInset.setEmpty();
         }
     }
     
@@ -863,19 +933,75 @@
     public void beginLayoutLw(int displayWidth, int displayHeight) {
         mW = displayWidth;
         mH = displayHeight;
-        mCurLeft = 0;
-        mCurTop = 0;
-        mCurRight = displayWidth;
-        mCurBottom = displayHeight;
+        mDockLeft = mContentLeft = mCurLeft = 0;
+        mDockTop = mContentTop = mCurTop = 0;
+        mDockRight = mContentRight = mCurRight = displayWidth;
+        mDockBottom = mContentBottom = mCurBottom = displayHeight;
+        mDockLayer = 0x10000000;
 
         // decide where the status bar goes ahead of time
         if (mStatusBar != null) {
-            mStatusBar.computeFrameLw(0, 0, displayWidth, displayHeight,
-                                    0, 0, displayWidth, displayHeight);
-            mCurTop = mStatusBar.getFrameLw().bottom;
+            final Rect pf = mTmpParentFrame;
+            final Rect df = mTmpDisplayFrame;
+            final Rect vf = mTmpVisibleFrame;
+            pf.left = df.left = vf.left = 0;
+            pf.top = df.top = vf.top = 0;
+            pf.right = df.right = vf.right = displayWidth;
+            pf.bottom = df.bottom = vf.bottom = displayHeight;
+            
+            mStatusBar.computeFrameLw(pf, df, vf, vf);
+            mDockTop = mContentTop = mCurTop = mStatusBar.getFrameLw().bottom;
         }
     }
 
+    void setAttachedWindowFrames(WindowState win, int fl, int sim,
+            WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
+        if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
+            // Here's a special case: if this attached window is a panel that is
+            // above the dock window, and the window it is attached to is below
+            // the dock window, then the frames we computed for the window it is
+            // attached to can not be used because the dock is effectively part
+            // of the underlying window and the attached window is floating on top
+            // of the whole thing.  So, we ignore the attached window and explicitly
+            // compute the frames that would be appropriate without the dock.
+            df.left = cf.left = vf.left = mDockLeft;
+            df.top = cf.top = vf.top = mDockTop;
+            df.right = cf.right = vf.right = mDockRight;
+            df.bottom = cf.bottom = vf.bottom = mDockBottom;
+        } else {
+            // The effective display frame of the attached window depends on
+            // whether it is taking care of insetting its content.  If not,
+            // we need to use the parent's content frame so that the entire
+            // window is positioned within that content.  Otherwise we can use
+            // the display frame and let the attached window take care of
+            // positioning its content appropriately.
+            if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+                cf.set(attached.getDisplayFrameLw());
+            } else {
+                // If the window is resizing, then we want to base the content
+                // frame on our attached content frame to resize...  however,
+                // things can be tricky if the attached window is NOT in resize
+                // mode, in which case its content frame will be larger.
+                // Ungh.  So to deal with that, make sure the content frame
+                // we end up using is not covering the IM dock.
+                cf.set(attached.getContentFrameLw());
+                if (attached.getSurfaceLayer() < mDockLayer) {
+                    if (cf.left < mContentLeft) cf.left = mContentLeft;
+                    if (cf.top < mContentTop) cf.top = mContentTop;
+                    if (cf.right > mContentRight) cf.right = mContentRight;
+                    if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
+                }
+            }
+            df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
+            vf.set(attached.getVisibleFrameLw());
+        }
+        // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
+        // window should be positioned relative to its parent or the entire
+        // screen.
+        pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
+                ? attached.getFrameLw() : df);
+    }
+    
     /** {@inheritDoc} */
     public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs, WindowState attached) {
         // we've already done the status bar
@@ -883,52 +1009,132 @@
             return;
         }
 
+        if (false) {
+            if ("com.google.android.youtube".equals(attrs.packageName)
+                    && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+                Log.i(TAG, "GOTCHA!");
+            }
+        }
+        
         final int fl = attrs.flags;
+        final int sim = attrs.softInputMode;
         
-        int dl, dt, dr, db;
-        if ((fl & FLAG_LAYOUT_IN_SCREEN) == 0) {
-            // Make sure this window doesn't intrude into the status bar.
-            dl = mCurLeft;
-            dt = mCurTop;
-            dr = mCurRight;
-            db = mCurBottom;
-        } else {
-            dl = 0;
-            dt = 0;
-            dr = mW;
-            db = mH;
-        }
+        final Rect pf = mTmpParentFrame;
+        final Rect df = mTmpDisplayFrame;
+        final Rect cf = mTmpContentFrame;
+        final Rect vf = mTmpVisibleFrame;
         
-        if ((fl &
-                (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
-                == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
-            win.setCoveredInsetsLw(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
+        if (attrs.type == TYPE_INPUT_METHOD) {
+            pf.left = df.left = cf.left = vf.left = mDockLeft;
+            pf.top = df.top = cf.top = vf.top = mDockTop;
+            pf.right = df.right = cf.right = vf.right = mDockRight;
+            pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
+            // IM dock windows always go to the bottom of the screen.
+            attrs.gravity = Gravity.BOTTOM;
+            mDockLayer = win.getSurfaceLayer();
         } else {
-            win.setCoveredInsetsLw(0, 0, 0, 0);
-        }
-
-        int pl, pt, pr, pb;
-        if (attached != null && (fl & (FLAG_LAYOUT_IN_SCREEN)) == 0) {
-            final Rect r = attached.getFrameLw();
-            pl = r.left;
-            pt = r.top;
-            pr = r.right;
-            pb = r.bottom;
-        } else {
-            pl = dl;
-            pt = dt;
-            pr = dr;
-            pb = db;
+            if ((fl &
+                    (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
+                    == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
+                // This is the case for a normal activity window: we want it
+                // to cover all of the screen space, and it can take care of
+                // moving its contents to account for screen decorations that
+                // intrude into that space.
+                if (attached != null) {
+                    // If this window is attached to another, our display
+                    // frame is the same as the one we are attached to.
+                    setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
+                } else {
+                    pf.left = df.left = 0;
+                    pf.top = df.top = 0;
+                    pf.right = df.right = mW;
+                    pf.bottom = df.bottom = mH;
+                    if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+                        cf.left = mDockLeft;
+                        cf.top = mDockTop;
+                        cf.right = mDockRight;
+                        cf.bottom = mDockBottom;
+                    } else {
+                        cf.left = mContentLeft;
+                        cf.top = mContentTop;
+                        cf.right = mContentRight;
+                        cf.bottom = mContentBottom;
+                    }
+                    vf.left = mCurLeft;
+                    vf.top = mCurTop;
+                    vf.right = mCurRight;
+                    vf.bottom = mCurBottom;
+                }
+            } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
+                // A window that has requested to fill the entire screen just
+                // gets everything, period.
+                pf.left = df.left = cf.left = 0;
+                pf.top = df.top = cf.top = 0;
+                pf.right = df.right = cf.right = mW;
+                pf.bottom = df.bottom = cf.bottom = mH;
+                vf.left = mCurLeft;
+                vf.top = mCurTop;
+                vf.right = mCurRight;
+                vf.bottom = mCurBottom;
+            } else if (attached != null) {
+                // A child window should be placed inside of the same visible
+                // frame that its parent had.
+                setAttachedWindowFrames(win, fl, sim, attached, false, pf, df, cf, vf);
+            } else {
+                // Otherwise, a normal window must be placed inside the content
+                // of all screen decorations.
+                pf.left = mContentLeft;
+                pf.top = mContentTop;
+                pf.right = mContentRight;
+                pf.bottom = mContentBottom;
+                if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
+                    df.left = cf.left = mDockLeft;
+                    df.top = cf.top = mDockTop;
+                    df.right = cf.right = mDockRight;
+                    df.bottom = cf.bottom = mDockBottom;
+                } else {
+                    df.left = cf.left = mContentLeft;
+                    df.top = cf.top = mContentTop;
+                    df.right = cf.right = mContentRight;
+                    df.bottom = cf.bottom = mContentBottom;
+                }
+                vf.left = mCurLeft;
+                vf.top = mCurTop;
+                vf.right = mCurRight;
+                vf.bottom = mCurBottom;
+            }
         }
         
         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
-            dl = -100000;
-            dt = -100000;
-            dr = 100000;
-            db = 100000;
+            df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
+            df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
         }
 
-        win.computeFrameLw(pl, pt, pr, pb, dl, dt, dr, db);
+        if (false) {
+            if ("com.google.android.youtube".equals(attrs.packageName)
+                    && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
+                if (true || localLOGV) Log.v(TAG, "Computing frame of " + win +
+                        ": pf=" + pf.toShortString() + " df=" + df.toShortString()
+                        + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
+            }
+        }
+        
+        win.computeFrameLw(pf, df, cf, vf);
+        
+        // Dock windows carve out the bottom of the screen, so normal windows
+        // can't appear underneath them.
+        if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
+            int top = win.getContentFrameLw().top;
+            top += win.getGivenContentInsetsLw().top;
+            if (mContentBottom > top) {
+                mContentBottom = top;
+            }
+            top = win.getVisibleFrameLw().top;
+            top += win.getGivenVisibleInsetsLw().top;
+            if (mCurBottom > top) {
+                mCurBottom = top;
+            }
+        }
     }
 
     /** {@inheritDoc} */
@@ -1011,7 +1217,7 @@
     /**
      * @return Whether a telephone call is in progress right now.
      */
-    private boolean isInCall() {
+    boolean isInCall() {
         final ITelephony phone = getPhoneInterface();
         if (phone == null) {
             Log.w(TAG, "couldn't get ITelephony reference");
@@ -1028,7 +1234,7 @@
     /**
      * @return Whether music is being played right now.
      */
-    private boolean isMusicActive() {
+    boolean isMusicActive() {
         final IAudioService audio = getAudioInterface();
         if (audio == null) {
             Log.w(TAG, "isMusicActive: couldn't get IAudioService reference");
@@ -1046,7 +1252,7 @@
      * Tell the audio service to adjust the volume appropriate to the event.
      * @param keycode
      */
-    private void sendVolToMusic(int keycode) {
+    void sendVolToMusic(int keycode) {
         final IAudioService audio = getAudioInterface();
         if (audio == null) {
             Log.w(TAG, "sendVolToMusic: couldn't get IAudioService reference");
@@ -1069,7 +1275,20 @@
             mBroadcastWakeLock.release();
         }
     }
-
+    
+    static boolean isMediaKey(int code) {
+        if (code == KeyEvent.KEYCODE_HEADSETHOOK || 
+                code == KeyEvent.KEYCODE_PLAYPAUSE ||
+                code == KeyEvent.KEYCODE_STOP || 
+                code == KeyEvent.KEYCODE_NEXTSONG ||
+                code == KeyEvent.KEYCODE_PREVIOUSSONG || 
+                code == KeyEvent.KEYCODE_PREVIOUSSONG ||
+                code == KeyEvent.KEYCODE_FORWARD) {
+            return true;
+        }
+        return false;    
+    }
+ 
     /** {@inheritDoc} */
     public int interceptKeyTq(RawInputEvent event, boolean screenIsOn) {
         int result = ACTION_PASS_TO_USER;
@@ -1165,7 +1384,7 @@
                         result &= ~ACTION_PASS_TO_USER;
                     }
                 }
-            } else if (code == KeyEvent.KEYCODE_HEADSETHOOK) {
+            } else if (isMediaKey(code)) {
                 // This key needs to be handled even if the screen is off.
                 // If others need to be handled while it's off, this is a reasonable
                 // pattern to follow.
@@ -1175,7 +1394,7 @@
                     // only do it if the showing app doesn't process the key on its own.
                     KeyEvent keyEvent = new KeyEvent(event.when, event.when,
                             down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
-                            KeyEvent.KEYCODE_HEADSETHOOK, 0);
+                            code, 0);
                     mBroadcastWakeLock.acquire();
                     mHandler.post(new PassHeadsetKey(keyEvent));
                 }
@@ -1200,7 +1419,7 @@
         }
     }
 
-    private BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
+    BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
             mBroadcastWakeLock.release();
         }
@@ -1298,20 +1517,17 @@
             case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
                 //always return portrait if orientation set to portrait
                 return Surface.ROTATION_0;
-            case ActivityInfo.SCREEN_ORIENTATION_SENSOR:
-                if(mOrientationSensorEnabled) {
-                    //consider only sensor based orientation keyboard slide ignored
-                    return mSensorRotation >= 0 ? mSensorRotation : Surface.ROTATION_0;
-                }
-                //if orientation sensor is disabled fall back to default behaviour
-                //based on lid
         }
         // case for nosensor meaning ignore sensor and consider only lid
         // or orientation sensor disabled
         //or case.unspecified
-        if(mLidOpen) {
+        if (mLidOpen) {
             return Surface.ROTATION_90;
         } else {
+            if (useSensorForOrientation()) {
+                // If the user has enabled auto rotation by default, do it.
+                return mSensorRotation >= 0 ? mSensorRotation : Surface.ROTATION_0;
+            }
             return Surface.ROTATION_0;
         }
     }
@@ -1325,11 +1541,11 @@
                 // If the user is holding the menu key code, then we are
                 // going to boot into safe mode.
                 ActivityManagerNative.getDefault().enterSafeMode();
-            } else {
-                // tell the keyguard
-                mKeyguardMediator.onSystemReady();
-                android.os.SystemProperties.set("dev.bootcomplete", "1"); 
             }
+            // tell the keyguard
+            mKeyguardMediator.onSystemReady();
+            android.os.SystemProperties.set("dev.bootcomplete", "1"); 
+            updateOrientationListener();
         } catch (RemoteException e) {
             // Ignore
         }
@@ -1341,7 +1557,7 @@
         updateRotation();
     }
     
-    private void updateRotation() {
+    void updateRotation() {
         mPowerManager.setKeyboardVisibility(mLidOpen);
         int rotation=  Surface.ROTATION_0;
         if (mLidOpen) {
diff --git a/policy/com/android/internal/policy/impl/Policy.java b/policy/com/android/internal/policy/impl/Policy.java
index f537186..17f3e91 100644
--- a/policy/com/android/internal/policy/impl/Policy.java
+++ b/policy/com/android/internal/policy/impl/Policy.java
@@ -17,6 +17,7 @@
 package com.android.internal.policy.impl;
 
 import android.content.Context;
+import android.util.Log;
 
 import com.android.internal.policy.IPolicy;
 import com.android.internal.policy.impl.PhoneLayoutInflater;
@@ -30,6 +31,29 @@
 // Simple implementation of the policy interface that spawns the right
 // set of objects
 public class Policy implements IPolicy {
+    private static final String TAG = "PhonePolicy";
+
+    private static final String[] preload_classes = {
+        "com.android.internal.policy.impl.PhoneLayoutInflater",
+        "com.android.internal.policy.impl.PhoneWindow",
+        "com.android.internal.policy.impl.PhoneWindow$1",
+        "com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback",
+        "com.android.internal.policy.impl.PhoneWindow$DecorView",
+        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
+        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
+    };
+
+    static {
+        // For performance reasons, preload some policy specific classes when
+        // the policy gets loaded.
+        for (String s : preload_classes) {
+            try {
+                Class.forName(s);
+            } catch (ClassNotFoundException ex) {
+                Log.e(TAG, "Could not preload class for phone policy: " + s);
+            }
+        }
+    }
 
     public PhoneWindow makeNewWindow(Context context) {
         return new PhoneWindow(context);
diff --git a/policy/com/android/internal/policy/impl/SimUnlockScreen.java b/policy/com/android/internal/policy/impl/SimUnlockScreen.java
index 4c71392..fceec5f 100644
--- a/policy/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -101,11 +101,19 @@
     public void onResume() {
         // start fresh
         mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
+
+        // make sure that the number of entered digits is consistent when we
+        // erase the SIM unlock code, including orientation changes.
         mPinText.setText("");
+        mEnteredDigits = 0;
     }
 
     /** {@inheritDoc} */
     public void cleanUp() {
+        // hide the dialog.
+        if (mSimUnlockProgressDialog != null) {
+            mSimUnlockProgressDialog.hide();
+        }
         mUpdateMonitor.removeCallback(this);
     }
 
@@ -143,7 +151,7 @@
             }
         }
     }
-    
+
     public void onClick(View v) {
         if (v == mBackSpaceButton) {
             final Editable digits = mPinText.getText();
@@ -191,7 +199,9 @@
 
         new CheckSimPin(mPinText.getText().toString()) {
             void onSimLockChangedResponse(boolean success) {
-                getSimUnlockProgressDialog().hide();
+                if (mSimUnlockProgressDialog != null) {
+                    mSimUnlockProgressDialog.hide();
+                }
                 if (success) {
                     // before closing the keyguard, report back that
                     // the sim is unlocked so it knows right away
diff --git a/policy/com/android/internal/policy/impl/UnlockScreen.java b/policy/com/android/internal/policy/impl/UnlockScreen.java
index bd0b6d5..65ab439 100644
--- a/policy/com/android/internal/policy/impl/UnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/UnlockScreen.java
@@ -16,9 +16,14 @@
 
 package com.android.internal.policy.impl;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.ServiceConnection;
 import android.os.CountDownTimer;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -85,6 +90,8 @@
 
     private Button mForgotPatternButton;
 
+    private ServiceConnection mServiceConnection;
+
 
     enum FooterMode {
         Normal,
@@ -177,6 +184,9 @@
         // stealth mode will be the same for the life of this screen
         mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled());
 
+        // vibrate mode will be the same for the life of this screen
+        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
+
         // assume normal footer mode for now
         updateFooter(FooterMode.Normal);
 
@@ -237,6 +247,10 @@
         mLockPatternView.enableInput();
         mLockPatternView.setEnabled(true);
         mLockPatternView.clearPattern();
+        
+        // show "forgot pattern?" button if we have an alternate authentication method
+        mForgotPatternButton.setVisibility(mCallback.doesFallbackUnlockScreenExist() 
+                ? View.VISIBLE : View.INVISIBLE);
 
         // if the user is currently locked out, enforce it.
         long deadline = mLockPatternUtils.getLockoutAttemptDeadline();