Fix an obscure scenario where a single CALL request would cause two outgoing call attempts.

Background: OutgoingCallBroadcaster is an invisible activity which receives
the CALL intent (from the dialer, contacts, etc.) and translates it into a
special broadcast called NEW_OUTGOING_CALL, which ultimately launches the
in-call UI.

Unfortunately if an orientation change happened at the exact right moment, the
ActivityManager would destroy and recreate the OutgoingCallBroadcaster, which
resulted in a *second* separate NEW_OUTGOING_CALL broadcast, which resulted in
two separate CALL intents coming in to the InCallScreen.  In some phone
states, that 2nd call would fail, causing an error dialog to come up saying
"Call not sent".  See bug 2202413 for the full analysis.

There are two parts of the fix:

(1) Fix OutgoingCallBroadcaster to gracefully handle the situation where it
    gets killed and re-created, i.e. when icicle != null in onCreate().
    In that case we just do nothing, since the NEW_OUTGOING_CALL broadcast was
    already sent the first time that onCreate() ran.

(2) Set android:configChanges="orientation|keyboardHidden" in the manifest for
    the OutgoingCallBroadcaster activity.  This prevents the ActivityManager
    from killing and restarting us in the first place.

Note that either part by itself actually fixes this bug (and I did test them
separately), but they're both technically correct, so this change contains
both.

BUG=2202413 ('call not sent' prompt displayed when we add call in landscape mode)

TESTED:
  Both GSM and CDMA:
    - Making an outgoing call from contacts
    - Making an outgoing call from the dialer
    - Making an outgoing call from the call log
    - Making an outgoing call from the emergency dialer
    - Making a 2nd outgoing call while on a call
  CDMA only:
    - Sending an empty flash (pressing DIAL in the dialer without any
      digits, while a call is already in progress)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5beef61..38700eb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -111,7 +111,8 @@
 
         <activity android:name="OutgoingCallBroadcaster"
                 android:permission="android.permission.CALL_PHONE"
-                android:theme="@android:style/Theme.NoDisplay">
+                android:theme="@android:style/Theme.NoDisplay"
+                android:configChanges="orientation|keyboardHidden">
             <!-- CALL action intent filters, for the various ways
                  of initiating an outgoing call. -->
             <intent-filter>
diff --git a/src/com/android/phone/OutgoingCallBroadcaster.java b/src/com/android/phone/OutgoingCallBroadcaster.java
index d93ed57..4ee0f9f 100644
--- a/src/com/android/phone/OutgoingCallBroadcaster.java
+++ b/src/com/android/phone/OutgoingCallBroadcaster.java
@@ -20,6 +20,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemProperties;
@@ -162,7 +163,38 @@
         super.onCreate(icicle);
 
         Intent intent = getIntent();
-        if (DBG) Log.v(TAG, "onCreate: getIntent() = " + intent);
+        final Configuration configuration = getResources().getConfiguration();
+
+        if (DBG) Log.v(TAG, "onCreate: this = " + this + ", icicle = " + icicle);
+        if (DBG) Log.v(TAG, " - getIntent() = " + intent);
+        if (DBG) Log.v(TAG, " - configuration = " + configuration);
+
+        if (icicle != null) {
+            // A non-null icicle means that this activity is being
+            // re-initialized after previously being shut down.
+            //
+            // In practice this happens very rarely (because the lifetime
+            // of this activity is so short!), but it *can* happen if the
+            // framework detects a configuration change at exactly the
+            // right moment; see bug 2202413.
+            //
+            // In this case, do nothing.  Our onCreate() method has already
+            // run once (with icicle==null the first time), which means
+            // that the NEW_OUTGOING_CALL broadcast for this new call has
+            // already been sent.
+            Log.i(TAG, "onCreate: non-null icicle!  "
+                  + "Bailing out, not sending NEW_OUTGOING_CALL broadcast...");
+
+            // No need to finish() here, since the OutgoingCallReceiver from
+            // our original instance will do that.  (It'll actually call
+            // finish() on our original instance, which apparently works fine
+            // even though the ActivityManager has already shut that instance
+            // down.  And note that if we *do* call finish() here, that just
+            // results in an "ActivityManager: Duplicate finish request"
+            // warning when the OutgoingCallReceiver runs.)
+
+            return;
+        }
 
         String action = intent.getAction();
         String number = PhoneNumberUtils.getNumberFromIntent(intent, this);
@@ -253,10 +285,12 @@
          * number, so there's no point in allowing apps to modify the number. */
         if (number == null || TextUtils.isEmpty(number)) {
             if (intent.getBooleanExtra(EXTRA_SEND_EMPTY_FLASH, false)) {
+                Log.i(TAG, "onCreate: SEND_EMPTY_FLASH...");
                 PhoneUtils.sendEmptyFlash(PhoneApp.getInstance().phone);
                 finish();
                 return;
             } else {
+                Log.i(TAG, "onCreate: null or empty number, setting callNow=true...");
                 callNow = true;
             }
         }
@@ -280,4 +314,13 @@
                 new OutgoingCallReceiver(), null, Activity.RESULT_OK, number, null);
         // The receiver will finish our activity when it finally runs.
     }
+
+    // Implement onConfigurationChanged() purely for debugging purposes,
+    // to make sure that the android:configChanges element in our manifest
+    // is working properly.
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (DBG) Log.v(TAG, "onConfigurationChanged: newConfig = " + newConfig);
+    }
 }