Partial Fix for 2416967: Fix potential memory leak in PasswordUnlockScreen.

PasswordUnlockScreen was previously registering for multiple callbacks which *sometimes*
caused a memory leak because a reference stuck around in the callback list.  I wasn't able to
track down the cause, but it looks like an interaction between switching between various lockscreen
modes and ordering of CONFIGURATION_CHANGED events.

I found one instance where the callback was being registered twice (fixed).  However, I'm
still able to reproduce the bug but far less frequently.

As a workaround, I've added code to prevent adding additional callbacks and added logging to
detect when a callback is already registered.

Also fixed an instance where we'd recreate the password unlock screen in LockPatternKeyguardView.updateScreen()
so it should be quite a bit faster switching orientations now.

Renamed UnlockScreen.java to PatternUnlockScreen.java for consistency.
diff --git a/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 3483405..9729eda 100644
--- a/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -492,7 +492,11 @@
      * @param callback The callback.
      */
     public void registerConfigurationChangeCallback(ConfigurationChangeCallback callback) {
-        mConfigurationChangeCallbacks.add(callback);
+        if (!mConfigurationChangeCallbacks.contains(callback)) {
+            mConfigurationChangeCallbacks.add(callback);
+        } else {
+            Log.e(TAG, "Object tried to add another CONFIG callback", new Exception("Whoops"));
+        }
     }
 
     /**
@@ -501,7 +505,11 @@
      * @param callback The callback.
      */
     public void registerInfoCallback(InfoCallback callback) {
-        mInfoCallbacks.add(callback);
+        if (!mInfoCallbacks.contains(callback)) {
+            mInfoCallbacks.add(callback);
+        } else {
+            Log.e(TAG, "Object tried to add another INFO callback", new Exception("Whoops"));
+        }
     }
 
     /**
@@ -509,7 +517,11 @@
      * @param callback The callback.
      */
     public void registerSimStateCallback(SimStateCallback callback) {
-        mSimStateCallbacks.add(callback);
+        if (!mSimStateCallbacks.contains(callback)) {
+            mSimStateCallbacks.add(callback);
+        } else {
+            Log.e(TAG, "Object tried to add another SIM callback", new Exception("Whoops"));
+        }
     }
 
     public IccCard.State getSimState() {
diff --git a/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java b/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java
index a7fc6b6..cdac278 100644
--- a/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -173,8 +173,8 @@
 
         if (mUnlockScreen == null) {
             Log.w(TAG, "no unlock screen when receiving AccountManager information");
-        } else if (mUnlockScreen instanceof UnlockScreen) {
-            ((UnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
+        } else if (mUnlockScreen instanceof PatternUnlockScreen) {
+            ((PatternUnlockScreen)mUnlockScreen).setEnableFallback(mEnableFallback);
         }
     }
 
@@ -411,7 +411,6 @@
         }
     }
 
-
     private void recreateScreens() {
         if (mLockScreen.getVisibility() == View.VISIBLE) {
             ((KeyguardScreen) mLockScreen).onPause();
@@ -504,8 +503,7 @@
         mMode = mode;
 
         final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : mLockScreen;
-        final View visibleScreen = (mode == Mode.LockScreen)
-                ? mLockScreen : getUnlockScreenForCurrentUnlockMode();
+        final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : mUnlockScreen;
 
         // do this before changing visibility so focus isn't requested before the input
         // flag is set
@@ -544,7 +542,7 @@
         mIsPortrait = getResources().getBoolean(R.bool.lockscreen_isPortrait);
 
         if (unlockMode == UnlockMode.Pattern) {
-            UnlockScreen view = new UnlockScreen(
+            PatternUnlockScreen view = new PatternUnlockScreen(
                     mContext,
                     mLockPatternUtils,
                     mUpdateMonitor,
diff --git a/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java b/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 560a000..9094ed6 100644
--- a/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -53,6 +53,7 @@
     private LockPatternUtils mLockPatternUtils;
     private PasswordEntryKeyboardView mKeyboardView;
     private PasswordEntryKeyboardHelper mKeyboardHelper;
+    private boolean mIsInPortrait;
 
     // To avoid accidental lockout due to events while the device in in the pocket, ignore
     // any passwords with length less than or equal to this length.
@@ -66,10 +67,10 @@
         mCreatedWithKeyboardOpen = mUpdateMonitor.isKeyboardOpen();
 
         LayoutInflater layoutInflater = LayoutInflater.from(context);
-        if (mCreatedWithKeyboardOpen) {
-            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
-        } else {
+        if (mUpdateMonitor.isInPortrait()) {
             layoutInflater.inflate(R.layout.keyguard_screen_password_portrait, this, true);
+        } else {
+            layoutInflater.inflate(R.layout.keyguard_screen_password_landscape, this, true);
         }
 
         boolean isAlpha = lockPatternUtils.getPasswordMode() == LockPatternUtils.MODE_PASSWORD;
@@ -85,7 +86,7 @@
         mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
                 : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
 
-        updateMonitor.registerConfigurationChangeCallback(this);
+        mKeyboardView.setVisibility(mCreatedWithKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
         mPasswordEntry.requestFocus();
     }
 
@@ -144,13 +145,12 @@
     }
 
     public void onOrientationChange(boolean inPortrait) {
-
+        mCallback.recreateMe();
     }
 
     public void onKeyboardChange(boolean isKeyboardOpen) {
-        if (isKeyboardOpen != mCreatedWithKeyboardOpen) {
-            mCallback.recreateMe();
-        }
+        // Don't show the soft keyboard when the real keyboard is open
+        mKeyboardView.setVisibility(isKeyboardOpen ? View.INVISIBLE : View.VISIBLE);
     }
 
     public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
diff --git a/phone/com/android/internal/policy/impl/UnlockScreen.java b/phone/com/android/internal/policy/impl/PatternUnlockScreen.java
similarity index 99%
rename from phone/com/android/internal/policy/impl/UnlockScreen.java
rename to phone/com/android/internal/policy/impl/PatternUnlockScreen.java
index f2a2c95..2e3aa84 100644
--- a/phone/com/android/internal/policy/impl/UnlockScreen.java
+++ b/phone/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -42,7 +42,7 @@
  * This is the screen that shows the 9 circle unlock widget and instructs
  * the user how to unlock their device, or make an emergency call.
  */
-class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
+class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
         implements KeyguardScreen, KeyguardUpdateMonitor.ConfigurationChangeCallback,
         KeyguardUpdateMonitor.InfoCallback, KeyguardUpdateMonitor.SimStateCallback {
 
@@ -160,7 +160,7 @@
      *        their pattern (e.g they have a google account so we can show them the account based
      *        backup option).
      */
-    UnlockScreen(Context context,
+    PatternUnlockScreen(Context context,
                  LockPatternUtils lockPatternUtils,
                  KeyguardUpdateMonitor updateMonitor,
                  KeyguardScreenCallback callback,