Fix 2336057: Provide a way for the user to return to a call from LockScreen.

This makes the "Emergency call" button dual-purpose. If there's a call in progress,
the button will show "Return to call" and take them back to the call.
diff --git a/phone/com/android/internal/policy/impl/AccountUnlockScreen.java b/phone/com/android/internal/policy/impl/AccountUnlockScreen.java
index 26419dd..1aaef83 100644
--- a/phone/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/phone/com/android/internal/policy/impl/AccountUnlockScreen.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
+import android.telephony.TelephonyManager;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.LoginFilter;
@@ -51,7 +52,7 @@
  * account's login/password to unlock the phone (and reset their lock pattern).
  */
 public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen,
-        View.OnClickListener, TextWatcher {
+        KeyguardUpdateMonitor.InfoCallback,View.OnClickListener, TextWatcher {
     private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
     private static final String LOCK_PATTERN_CLASS =
             "com.android.settings.ChooseLockPattern";
@@ -108,6 +109,7 @@
 
         mEmergencyCall = (Button) findViewById(R.id.emergencyCall);
         mEmergencyCall.setOnClickListener(this);
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
     }
 
     public void afterTextChanged(Editable s) {
@@ -143,6 +145,7 @@
         mLogin.setText("");
         mPassword.setText("");
         mLogin.requestFocus();
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
     }
 
     /** {@inheritDoc} */
@@ -314,4 +317,24 @@
         }
         return mCheckingDialog;
     }
+
+    public void onPhoneStateChanged(String newState) {
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
+    }
+
+    public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
+
+    }
+
+    public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
+
+    }
+
+    public void onRingerModeChanged(int state) {
+
+    }
+
+    public void onTimeChanged() {
+
+    }
 }
diff --git a/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 9729eda..b7187a4 100644
--- a/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/phone/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -38,6 +38,8 @@
 
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.TelephonyIntents;
+
+import android.telephony.TelephonyManager;
 import android.util.Log;
 import com.android.internal.R;
 import com.google.android.collect.Lists;
@@ -96,6 +98,7 @@
     private static final int MSG_CARRIER_INFO_UPDATE = 303;
     private static final int MSG_SIM_STATE_CHANGE = 304;
     private static final int MSG_RINGER_MODE_CHANGED = 305;
+    private static final int MSG_PHONE_STATE_CHANGED = 306;
 
 
     /**
@@ -165,6 +168,9 @@
                     case MSG_RINGER_MODE_CHANGED:
                         handleRingerModeChange(msg.arg1);
                         break;
+                    case MSG_PHONE_STATE_CHANGED:
+                        handlePhoneStateChanged((String)msg.obj);
+                        break;
                 }
             }
         };
@@ -221,6 +227,7 @@
         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
         filter.addAction(SPN_STRINGS_UPDATED_ACTION);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         context.registerReceiver(new BroadcastReceiver() {
@@ -255,11 +262,21 @@
                 } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(action)) {
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_RINGER_MODE_CHANGED,
                             intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1), 0));
+                } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
+                    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_PHONE_STATE_CHANGED, state));
                 }
             }
         }, filter);
     }
 
+    protected void handlePhoneStateChanged(String newState) {
+        if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
+        for (int i = 0; i < mInfoCallbacks.size(); i++) {
+            mInfoCallbacks.get(i).onPhoneStateChanged(newState);
+        }
+    }
+
     protected void handleRingerModeChange(int mode) {
         if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
         for (int i = 0; i < mInfoCallbacks.size(); i++) {
@@ -478,6 +495,14 @@
          * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
          */
         void onRingerModeChanged(int state);
+
+        /**
+         * Called when the phone state changes. String will be one of:
+         * {@link TelephonyManager#EXTRA_STATE_IDLE}
+         * {@link TelephonyManager@EXTRA_STATE_RINGING}
+         * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
+         */
+        void onPhoneStateChanged(String newState);
     }
 
     /**
diff --git a/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java b/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java
index cdac278..48abe63 100644
--- a/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/phone/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.SystemProperties;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -60,6 +61,9 @@
 public class LockPatternKeyguardView extends KeyguardViewBase
         implements AccountManagerCallback<Account[]> {
 
+    // time after launching EmergencyDialer before the screen goes blank.
+    private static final int EMERGENCY_CALL_TIMEOUT = 10000;
+
     // intent action for launching emergency dialer activity.
     static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
 
@@ -251,10 +255,16 @@
             }
 
             public void takeEmergencyCallAction() {
-                Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
-                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-                getContext().startActivity(intent);
+                pokeWakelock(EMERGENCY_CALL_TIMEOUT);
+                if (TelephonyManager.getDefault().getCallState()
+                        == TelephonyManager.CALL_STATE_OFFHOOK) {
+                    mLockPatternUtils.resumeCall();
+                } else {
+                    Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+                    getContext().startActivity(intent);
+                }
             }
 
             public void pokeWakelock() {
@@ -556,7 +566,8 @@
             return new SimUnlockScreen(
                     mContext,
                     mUpdateMonitor,
-                    mKeyguardScreenCallback);
+                    mKeyguardScreenCallback,
+                    mLockPatternUtils);
         } else if (unlockMode == UnlockMode.Account) {
             try {
                 return new AccountUnlockScreen(
@@ -589,32 +600,6 @@
         }
     }
 
-    private View getUnlockScreenForCurrentUnlockMode() {
-        final UnlockMode unlockMode = getUnlockMode();
-
-        // if a screen exists for the correct mode, we're done
-        if (unlockMode == mUnlockScreenMode) {
-            return mUnlockScreen;
-        }
-
-        // remember the mode
-        mUnlockScreenMode = unlockMode;
-
-        // unlock mode has changed and we have an existing old unlock screen
-        // to clean up
-        if (mScreenOn && (mUnlockScreen.getVisibility() == View.VISIBLE)) {
-            ((KeyguardScreen) mUnlockScreen).onPause();
-        }
-        ((KeyguardScreen) mUnlockScreen).cleanUp();
-        removeViewInLayout(mUnlockScreen);
-
-        // create the new one
-        mUnlockScreen = createUnlockScreenFor(unlockMode);
-        mUnlockScreen.setVisibility(View.INVISIBLE);
-        addView(mUnlockScreen);
-        return mUnlockScreen;
-    }
-
     /**
      * Given the current state of things, what should be the initial mode of
      * the lock screen (lock or unlock).
diff --git a/phone/com/android/internal/policy/impl/LockScreen.java b/phone/com/android/internal/policy/impl/LockScreen.java
index ba6b3b3..7724816 100644
--- a/phone/com/android/internal/policy/impl/LockScreen.java
+++ b/phone/com/android/internal/policy/impl/LockScreen.java
@@ -18,12 +18,15 @@
 
 import com.android.internal.R;
 import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.Phone.State;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.SlidingTab;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.ColorStateList;
+import android.telephony.TelephonyManager;
 import android.text.format.DateFormat;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -190,6 +193,7 @@
 
         mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
         mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
         mScreenLocked = (TextView) findViewById(R.id.screenLocked);
         mSelector = (SlidingTab) findViewById(R.id.tab_selector);
         mSelector.setHoldAfterTrigger(true, false);
@@ -248,6 +252,7 @@
 
         refreshBatteryStringAndIcon();
         refreshAlarmDisplay();
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
 
         mTimeFormat = DateFormat.getTimeFormat(getContext());
         mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
@@ -610,6 +615,7 @@
     /** {@inheritDoc} */
     public void onResume() {
         resetStatusInfo(mUpdateMonitor);
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
     }
 
     /** {@inheritDoc} */
@@ -625,4 +631,8 @@
             updateRightTabResources();
         }
     }
+
+    public void onPhoneStateChanged(String newState) {
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+    }
 }
diff --git a/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java b/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 841c2e4..a721c47 100644
--- a/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/phone/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -22,10 +22,12 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.PasswordEntryKeyboardView;
 
+import android.telephony.TelephonyManager;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -39,7 +41,8 @@
  * an unlock password
  */
 public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener,
-        KeyguardUpdateMonitor.ConfigurationChangeCallback, OnEditorActionListener {
+        KeyguardUpdateMonitor.ConfigurationChangeCallback, KeyguardUpdateMonitor.InfoCallback,
+        OnEditorActionListener {
 
     private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
 
@@ -49,7 +52,7 @@
     private final boolean mCreatedWithKeyboardOpen;
 
     private EditText mPasswordEntry;
-    private TextView mEmergencyCallButton;
+    private Button mEmergencyCallButton;
     private LockPatternUtils mLockPatternUtils;
     private PasswordEntryKeyboardView mKeyboardView;
     private PasswordEntryKeyboardHelper mKeyboardHelper;
@@ -64,6 +67,7 @@
         mUpdateMonitor = updateMonitor;
         mCallback = callback;
         mCreatedWithKeyboardOpen = mUpdateMonitor.isKeyboardOpen();
+        mLockPatternUtils = lockPatternUtils;
 
         LayoutInflater layoutInflater = LayoutInflater.from(context);
         if (mUpdateMonitor.isInPortrait()) {
@@ -76,10 +80,10 @@
         mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
         mPasswordEntry = (EditText) findViewById(R.id.passwordEntry);
         mPasswordEntry.setOnEditorActionListener(this);
-        mEmergencyCallButton = (TextView) findViewById(R.id.emergencyCall);
+        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
         mEmergencyCallButton.setOnClickListener(this);
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
         mUpdateMonitor.registerConfigurationChangeCallback(this);
-        mLockPatternUtils = lockPatternUtils;
 
         mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this);
         mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
@@ -90,6 +94,7 @@
 
         mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ?
                 com.android.internal.R.array.config_virtualKeyVibePattern : 0);
+
     }
 
     @Override
@@ -113,6 +118,7 @@
         // start fresh
         mPasswordEntry.setText("");
         mPasswordEntry.requestFocus();
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
     }
 
     /** {@inheritDoc} */
@@ -164,4 +170,24 @@
         return false;
     }
 
+    public void onPhoneStateChanged(String newState) {
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+    }
+
+    public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
+
+    }
+
+    public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
+
+    }
+
+    public void onRingerModeChanged(int state) {
+
+    }
+
+    public void onTimeChanged() {
+
+    }
+
 }
diff --git a/phone/com/android/internal/policy/impl/PatternUnlockScreen.java b/phone/com/android/internal/policy/impl/PatternUnlockScreen.java
index 2e3aa84..30fb8b8 100644
--- a/phone/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/phone/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -25,6 +25,7 @@
 import android.view.MotionEvent;
 import android.widget.Button;
 import android.widget.TextView;
+import android.telephony.TelephonyManager;
 import android.text.format.DateFormat;
 import android.text.TextUtils;
 import android.util.Log;
@@ -126,6 +127,8 @@
     };
 
     private Button mForgotPatternButton;
+    private Button mEmergencyAlone;
+    private Button mEmergencyTogether;
 
     enum FooterMode {
         Normal,
@@ -205,16 +208,17 @@
         // emergency call buttons
         final OnClickListener emergencyClick = new OnClickListener() {
             public void onClick(View v) {
-                mCallback.pokeWakelock();
                 mCallback.takeEmergencyCallAction();
             }
         };
-        Button emergencyAlone = (Button) findViewById(R.id.emergencyCallAlone);
-        emergencyAlone.setFocusable(false); // touch only!
-        emergencyAlone.setOnClickListener(emergencyClick);
-        Button emergencyTogether = (Button) findViewById(R.id.emergencyCallTogether);
-        emergencyTogether.setFocusable(false);
-        emergencyTogether.setOnClickListener(emergencyClick);
+
+        mEmergencyAlone = (Button) findViewById(R.id.emergencyCallAlone);
+        mEmergencyAlone.setFocusable(false); // touch only!
+        mEmergencyAlone.setOnClickListener(emergencyClick);
+        mEmergencyTogether = (Button) findViewById(R.id.emergencyCallTogether);
+        mEmergencyTogether.setFocusable(false);
+        mEmergencyTogether.setOnClickListener(emergencyClick);
+        refreshEmergencyButtonText();
 
         mForgotPatternButton = (Button) findViewById(R.id.forgotPattern);
         mForgotPatternButton.setText(R.string.lockscreen_forgot_pattern_button_text);
@@ -259,6 +263,11 @@
                         mUpdateMonitor.getTelephonySpn()));
     }
 
+    private void refreshEmergencyButtonText() {
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyAlone);
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyTogether);
+    }
+
     public void setEnableFallback(boolean state) {
         if (DEBUG) Log.d(TAG, "setEnableFallback(" + state + ")");
         mEnableFallback = state;
@@ -447,6 +456,8 @@
         } else {
             updateFooter(FooterMode.Normal);
         }
+
+        refreshEmergencyButtonText();
     }
 
     /** {@inheritDoc} */
@@ -549,4 +560,8 @@
             }
         }.start();
     }
+
+    public void onPhoneStateChanged(String newState) {
+        refreshEmergencyButtonText();
+    }
 }
diff --git a/phone/com/android/internal/policy/impl/SimUnlockScreen.java b/phone/com/android/internal/policy/impl/SimUnlockScreen.java
index 8c738a7..d5da274 100644
--- a/phone/com/android/internal/policy/impl/SimUnlockScreen.java
+++ b/phone/com/android/internal/policy/impl/SimUnlockScreen.java
@@ -22,11 +22,14 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.widget.LockPatternUtils;
+
 import android.text.Editable;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
+import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 import com.android.internal.R;
@@ -35,7 +38,7 @@
  * Displays a dialer like interface to unlock the SIM PIN.
  */
 public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, View.OnClickListener,
-        KeyguardUpdateMonitor.ConfigurationChangeCallback {
+        KeyguardUpdateMonitor.ConfigurationChangeCallback, KeyguardUpdateMonitor.InfoCallback {
 
     private static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
 
@@ -48,7 +51,7 @@
     private TextView mPinText;
 
     private TextView mOkButton;
-    private TextView mEmergencyCallButton;
+    private Button mEmergencyCallButton;
 
     private View mBackSpaceButton;
 
@@ -57,14 +60,17 @@
 
     private ProgressDialog mSimUnlockProgressDialog = null;
 
+    private LockPatternUtils mLockPatternUtils;
+
     private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
 
     public SimUnlockScreen(Context context, KeyguardUpdateMonitor updateMonitor,
-            KeyguardScreenCallback callback) {
+            KeyguardScreenCallback callback, LockPatternUtils lockpatternutils) {
         super(context);
         mUpdateMonitor = updateMonitor;
         mCallback = callback;
         mCreatedWithKeyboardOpen = mUpdateMonitor.isKeyboardOpen();
+        mLockPatternUtils = lockpatternutils;
 
         if (mCreatedWithKeyboardOpen) {
             LayoutInflater.from(context).inflate(R.layout.keyguard_screen_sim_pin_landscape, this, true);
@@ -78,7 +84,8 @@
         mBackSpaceButton = findViewById(R.id.backspace);
         mBackSpaceButton.setOnClickListener(this);
 
-        mEmergencyCallButton = (TextView) findViewById(R.id.emergencyCall);
+        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCall);
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
         mOkButton = (TextView) findViewById(R.id.ok);
 
         mHeaderText.setText(R.string.keyguard_password_enter_pin_code);
@@ -95,7 +102,7 @@
     public boolean needsInput() {
         return true;
     }
-    
+
     /** {@inheritDoc} */
     public void onPause() {
 
@@ -110,6 +117,8 @@
         // erase the SIM unlock code, including orientation changes.
         mPinText.setText("");
         mEnteredDigits = 0;
+
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
     }
 
     /** {@inheritDoc} */
@@ -166,7 +175,6 @@
             }
             mCallback.pokeWakelock();
         } else if (v == mEmergencyCallButton) {
-            mCallback.pokeWakelock();
             mCallback.takeEmergencyCallAction();
         } else if (v == mOkButton) {
             checkPin();
@@ -366,4 +374,24 @@
             return digit;
         }
     }
+
+    public void onPhoneStateChanged(String newState) {
+        mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
+    }
+
+    public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
+
+    }
+
+    public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
+
+    }
+
+    public void onRingerModeChanged(int state) {
+
+    }
+
+    public void onTimeChanged() {
+
+    }
 }