merge in klp-factoryrom-release history after reset to klp-release
diff --git a/InCallUI/res/layout/primary_call_info.xml b/InCallUI/res/layout/primary_call_info.xml
index fd8b83a..681519b 100644
--- a/InCallUI/res/layout/primary_call_info.xml
+++ b/InCallUI/res/layout/primary_call_info.xml
@@ -167,7 +167,7 @@
                       android:textAppearance="?android:attr/textAppearanceSmall"
                       android:textColor="@color/incall_call_banner_text_color"
                       android:textAllCaps="true"
-                      android:background="@android:color/transparent"
+                      android:background="@color/incall_secondary_info_background"
                       android:singleLine="true"
                       android:ellipsize="end"/>
         </LinearLayout>
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index d96e411..9c772cb 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -167,9 +167,20 @@
     }
 
     @Override
+    public void setPrimaryGateway(String gatewayLabel, String gatewayNumber) {
+        if (!TextUtils.isEmpty(gatewayLabel) && !TextUtils.isEmpty(gatewayNumber)) {
+            mProviderLabel.setText(gatewayLabel);
+            mProviderNumber.setText(gatewayNumber);
+            mProviderInfo.setVisibility(View.VISIBLE);
+        } else {
+            mProviderInfo.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
     public void setPrimary(String number, String name, boolean nameIsNumber, String label,
-            Drawable photo, boolean isConference) {
-        Log.d(this, "Setting primary call");
+            Drawable photo, boolean isConference, String gatewayLabel, String gatewayNumber) {
+        Log.d(this, "Setting primary call [" + gatewayLabel + "][" + gatewayNumber + "]");
 
         if (isConference) {
             name = getView().getResources().getString(R.string.card_title_conf_call);
@@ -179,6 +190,9 @@
 
         setPrimaryPhoneNumber(number);
 
+        // Set any gateway information
+        setPrimaryGateway(gatewayLabel, gatewayNumber);
+
         // set the name field.
         setPrimaryName(name, nameIsNumber);
 
@@ -222,8 +236,7 @@
     }
 
     @Override
-    public void setCallState(int state, Call.DisconnectCause cause, boolean bluetoothOn,
-            String gatewayLabel, String gatewayNumber) {
+    public void setCallState(int state, Call.DisconnectCause cause, boolean bluetoothOn) {
         String callStateLabel = null;
 
         // States other than disconnected not yet supported
@@ -232,23 +245,25 @@
         Log.v(this, "setCallState ", callStateLabel);
         Log.v(this, "DisconnectCause ", cause);
         Log.v(this, "bluetooth on ", bluetoothOn);
-        Log.v(this, "gateway " + gatewayLabel + gatewayNumber);
 
-        // There are cases where we totally skip the animation, in which case remove the transition
-        // animation here and restore it afterwards.
-        final boolean skipAnimation = (state == Call.State.DIALING
-                || state == Call.State.DISCONNECTED);
-        LayoutTransition transition = null;
-        if (skipAnimation) {
-            transition = mSupplementaryInfoContainer.getLayoutTransition();
-            mSupplementaryInfoContainer.setLayoutTransition(null);
-        }
-
-        // Update the call state label.
         if (!TextUtils.isEmpty(callStateLabel)) {
+            // There are cases where we totally skip the animation
+            final boolean skipAnimation = (state == Call.State.DIALING
+                    || state == Call.State.DISCONNECTED);
+
+            LayoutTransition transition = null;
+            if (skipAnimation) {
+                transition = mSupplementaryInfoContainer.getLayoutTransition();
+                mSupplementaryInfoContainer.setLayoutTransition(null);
+            }
+
             mCallStateLabel.setVisibility(View.VISIBLE);
             mCallStateLabel.setText(callStateLabel);
 
+            if (skipAnimation) {
+                mSupplementaryInfoContainer.setLayoutTransition(transition);
+            }
+
             if (Call.State.INCOMING == state) {
                 setBluetoothOn(bluetoothOn);
             }
@@ -263,20 +278,6 @@
                 mCallStateLabel.setGravity(Gravity.END);
             }
         }
-
-        // Provider info: (e.g. "Calling via <gatewayLabel>")
-        if (!TextUtils.isEmpty(gatewayLabel) && !TextUtils.isEmpty(gatewayNumber)) {
-            mProviderLabel.setText(gatewayLabel);
-            mProviderNumber.setText(gatewayNumber);
-            mProviderInfo.setVisibility(View.VISIBLE);
-        } else {
-            mProviderInfo.setVisibility(View.GONE);
-        }
-
-        // Restore the animation.
-        if (skipAnimation) {
-            mSupplementaryInfoContainer.setLayoutTransition(transition);
-        }
     }
 
     @Override
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index f56d4e1..6c8056b 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -188,10 +188,9 @@
         if (mPrimary != null) {
             final boolean bluetoothOn =
                     (AudioModeProvider.getInstance().getAudioMode() == AudioMode.BLUETOOTH);
-            ui.setCallState(mPrimary.getState(), mPrimary.getDisconnectCause(), bluetoothOn,
-                    getGatewayLabel(), getGatewayNumber());
+            ui.setCallState(mPrimary.getState(), mPrimary.getDisconnectCause(), bluetoothOn);
         } else {
-            ui.setCallState(Call.State.IDLE, Call.DisconnectCause.UNKNOWN, false, null, null);
+            ui.setCallState(Call.State.IDLE, Call.DisconnectCause.UNKNOWN, false);
         }
     }
 
@@ -200,8 +199,7 @@
         if (mPrimary != null && getUi() != null) {
             final boolean bluetoothOn = (AudioMode.BLUETOOTH == mode);
 
-            getUi().setCallState(mPrimary.getState(), mPrimary.getDisconnectCause(), bluetoothOn,
-                    getGatewayLabel(), getGatewayNumber());
+            getUi().setCallState(mPrimary.getState(), mPrimary.getDisconnectCause(), bluetoothOn);
         }
     }
 
@@ -352,12 +350,15 @@
             final String name = getNameForCall(entry);
             final String number = getNumberForCall(entry);
             final boolean nameIsNumber = name != null && name.equals(entry.number);
+            final String gatewayLabel = getGatewayLabel();
+            final String gatewayNumber = getGatewayNumber();
 
             ui.setPrimary(number, name, nameIsNumber, entry.label,
-                    entry.photo, isConference);
+                    entry.photo, isConference, gatewayLabel,
+                    gatewayNumber);
         } else {
             // reset to nothing (like at end of call)
-            ui.setPrimary(null, null, false, null, null, false);
+            ui.setPrimary(null, null, false, null, null, false, null, null);
         }
 
     }
@@ -505,16 +506,16 @@
     public interface CallCardUi extends Ui {
         void setVisible(boolean on);
         void setPrimary(String number, String name, boolean nameIsNumber, String label,
-                Drawable photo, boolean isConference);
+                Drawable photo, boolean isConference, String gatewayLabel, String gatewayNumber);
         void setSecondary(boolean show, String name, boolean nameIsNumber, String label,
                 Drawable photo, boolean isConference);
         void setSecondaryImage(Bitmap bitmap);
-        void setCallState(int state, Call.DisconnectCause cause, boolean bluetoothOn,
-                String gatewayLabel, String gatewayNumber);
+        void setCallState(int state, Call.DisconnectCause cause, boolean bluetoothOn);
         void setPrimaryCallElapsedTime(boolean show, String duration);
         void setPrimaryName(String name, boolean nameIsNumber);
         void setPrimaryImage(Bitmap bitmap);
         void setPrimaryPhoneNumber(String phoneNumber);
         void setPrimaryLabel(String label);
+        void setPrimaryGateway(String label, String number);
     }
 }
diff --git a/InCallUI/src/com/android/incallui/CallHandlerService.java b/InCallUI/src/com/android/incallui/CallHandlerService.java
index 82702db..d50635d 100644
--- a/InCallUI/src/com/android/incallui/CallHandlerService.java
+++ b/InCallUI/src/com/android/incallui/CallHandlerService.java
@@ -46,7 +46,7 @@
     private static final int ON_DISCONNECT_CALL = 6;
     private static final int ON_BRING_TO_FOREGROUND = 7;
     private static final int ON_POST_CHAR_WAIT = 8;
-    private static final int ON_CREATE = 9;
+    private static final int ON_START = 9;
     private static final int ON_DESTROY = 10;
 
     private static final int LARGEST_MSG_ID = ON_DESTROY;
@@ -57,10 +57,11 @@
     private Object mHandlerInitLock = new Object();
     private InCallPresenter mInCallPresenter;
     private AudioModeProvider mAudioModeProvider;
+    private boolean mServiceStarted = false;
 
     @Override
     public void onCreate() {
-        Log.i(this, "onCreate");
+        Log.i(TAG, "onCreate");
         super.onCreate();
 
         synchronized(mHandlerInitLock) {
@@ -69,50 +70,47 @@
             }
         }
 
-        // Creation (and destruction) are sent to the message handler.  The reason for this is that
-        // at any time the service could potentially unbind for both legitimate reasons as well as
-        // app crashes and it's better to queue up create/destroy because:
-        // (1) Previous actions like onUpdate/onDisconnect could be queued up and we dont want to
-        //     destroy the system from a different thread in the middle of executing those actions.
-        // (2) If we queue up destruction we must also queue up creation or else we risk having a
-        //     second "create" happen before the first "destroy".
-        //     (e.g., create1, queue destroy1, create2, do destroy1)
-        mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_CREATE));
-
-        // TODO: consider optimization of checking to see if any ON_DESTROY messages exist
-        // in the queue and in those cases simply remove the pending message.
     }
 
     @Override
     public void onDestroy() {
-        Log.i(this, "onDestroy");
+        Log.i(TAG, "onDestroy");
 
+        // onDestroy will get called when:
+        // 1) there are no more calls
+        // 2) the client (TeleService) crashes.
+        //
+        // Because onDestroy is not sequenced with calls to CallHandlerService binder,
+        // we cannot know which is happening.
+        // Thats okay since in both cases we want to end all calls and let the UI know it can tear
+        // itself down when it's ready. Start the destruction sequence.
         mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_DESTROY));
     }
 
 
     @Override
     public IBinder onBind(Intent intent) {
-        Log.i(this, "onBind");
+        Log.i(TAG, "onBind");
         return mBinder;
     }
 
     @Override
     public boolean onUnbind(Intent intent) {
-        Log.i(this, "onUnbind");
+        Log.i(TAG, "onUnbind");
 
         // Returning true here means we get called on rebind, which is a feature we do not need.
-        // Return false so that all reconections happen with a call to onBind().
+        // Return false so that all reconnections happen with a call to onBind().
         return false;
     }
 
     private final ICallHandlerService.Stub mBinder = new ICallHandlerService.Stub() {
 
         @Override
-        public void setCallCommandService(ICallCommandService service) {
+        public void startCallService(ICallCommandService service) {
             try {
-                Log.d(CallHandlerService.this, "onConnected: " + service.toString());
-                CallCommandClient.getInstance().setService(service);
+                Log.d(TAG, "startCallService: " + service.toString());
+
+                mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_START, service));
             } catch (Exception e) {
                 Log.e(TAG, "Error processing setCallCommandservice() call", e);
             }
@@ -121,7 +119,7 @@
         @Override
         public void onDisconnect(Call call) {
             try {
-                Log.i(CallHandlerService.this, "onDisconnected: " + call);
+                Log.i(TAG, "onDisconnected: " + call);
                 mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_DISCONNECT_CALL, call));
             } catch (Exception e) {
                 Log.e(TAG, "Error processing onDisconnect() call.", e);
@@ -131,7 +129,7 @@
         @Override
         public void onIncoming(Call call, List<String> textResponses) {
             try {
-                Log.i(CallHandlerService.this, "onIncomingCall: " + call);
+                Log.i(TAG, "onIncomingCall: " + call);
                 Map.Entry<Call, List<String>> incomingCall
                         = new AbstractMap.SimpleEntry<Call, List<String>>(call, textResponses);
                 mMainHandler.sendMessage(mMainHandler.obtainMessage(
@@ -144,7 +142,7 @@
         @Override
         public void onUpdate(List<Call> calls) {
             try {
-                Log.i(CallHandlerService.this, "onUpdate: " + calls);
+                Log.i(TAG, "onUpdate: " + calls);
                 mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_MULTI_CALL, calls));
             } catch (Exception e) {
                 Log.e(TAG, "Error processing onUpdate() call.", e);
@@ -154,7 +152,7 @@
         @Override
         public void onAudioModeChange(int mode, boolean muted) {
             try {
-                Log.i(CallHandlerService.this, "onAudioModeChange : " +
+                Log.i(TAG, "onAudioModeChange : " +
                         AudioMode.toString(mode));
                 mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_AUDIO_MODE, mode,
                             muted ? 1 : 0, null));
@@ -166,7 +164,7 @@
         @Override
         public void onSupportedAudioModeChange(int modeMask) {
             try {
-                Log.i(CallHandlerService.this, "onSupportedAudioModeChange : " +
+                Log.i(TAG, "onSupportedAudioModeChange : " +
                         AudioMode.toString(modeMask));
                 mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_SUPPORTED_AUDIO_MODE,
                         modeMask, 0, null));
@@ -187,24 +185,39 @@
         }
     };
 
-    private void doCreate() {
-        Log.i(this, "doCreate");
+    private void doStart(ICallCommandService service) {
+        Log.i(TAG, "doStart");
+
+        // always setup the new callcommandservice
+        CallCommandClient.getInstance().setService(service);
+
+        // If we have a new service when one is already started, we can continue
+        // using the service that we already have.
+        if (mServiceStarted) {
+            Log.i(TAG, "Starting a service before another one is completed");
+            doStop();
+        }
 
         mCallList = CallList.getInstance();
         mAudioModeProvider = AudioModeProvider.getInstance();
         mInCallPresenter = InCallPresenter.getInstance();
 
         mInCallPresenter.setUp(getApplicationContext(), mCallList, mAudioModeProvider);
+
+        mServiceStarted = true;
     }
 
-    public void doDestroy() {
-        Log.i(this, "doDestroy");
+    public void doStop() {
+        Log.i(TAG, "doStop");
 
-        // The service gets disconnected under two circumstances:
-        // 1. When there are no more calls
-        // 2. When the phone app crashes.
-        // If (2) happens, we can't leave the UI thinking that there are still
-        // live calls.  So we will tell the callList to clear as a final request.
+        if (!mServiceStarted) {
+            return;
+        }
+
+        mServiceStarted = false;
+
+        // We are disconnected, clear the call list so that UI can start
+        // tearing itself down.
         mCallList.clearOnDisconnect();
         mCallList = null;
 
@@ -232,55 +245,61 @@
         if (msg.what > LARGEST_MSG_ID) {
             // If you got here, you may have added a new message and forgotten to
             // update LARGEST_MSG_ID
-            Log.wtf(this, "Cannot handle message larger than LARGEST_MSG_ID.");
+            Log.wtf(TAG, "Cannot handle message larger than LARGEST_MSG_ID.");
         }
 
-        Log.d(this, "executeMessage " + msg.what);
+        // If we are not initialized, ignore all messages except start up
+        if (!mServiceStarted && msg.what != ON_START) {
+            Log.i(TAG, "System not initialized.  Ignoring message: " + msg.what);
+            return;
+        }
+
+        Log.d(TAG, "executeMessage " + msg.what);
 
         switch (msg.what) {
             case ON_UPDATE_CALL:
-                Log.i(CallHandlerService.this, "ON_UPDATE_CALL: " + msg.obj);
+                Log.i(TAG, "ON_UPDATE_CALL: " + msg.obj);
                 mCallList.onUpdate((Call) msg.obj);
                 break;
             case ON_UPDATE_MULTI_CALL:
-                Log.i(CallHandlerService.this, "ON_UPDATE_MULTI_CALL: " + msg.obj);
+                Log.i(TAG, "ON_UPDATE_MULTI_CALL: " + msg.obj);
                 mCallList.onUpdate((List<Call>) msg.obj);
                 break;
             case ON_UPDATE_CALL_WITH_TEXT_RESPONSES:
                 AbstractMap.SimpleEntry<Call, List<String>> entry
                         = (AbstractMap.SimpleEntry<Call, List<String>>) msg.obj;
-                Log.i(CallHandlerService.this, "ON_INCOMING_CALL: " + entry.getKey());
+                Log.i(TAG, "ON_INCOMING_CALL: " + entry.getKey());
                 mCallList.onIncoming(entry.getKey(), entry.getValue());
                 break;
             case ON_DISCONNECT_CALL:
-                Log.i(CallHandlerService.this, "ON_DISCONNECT_CALL: " + msg.obj);
+                Log.i(TAG, "ON_DISCONNECT_CALL: " + msg.obj);
                 mCallList.onDisconnect((Call) msg.obj);
                 break;
             case ON_POST_CHAR_WAIT:
                 mInCallPresenter.onPostDialCharWait(msg.arg1, (String) msg.obj);
                 break;
             case ON_AUDIO_MODE:
-                Log.i(CallHandlerService.this, "ON_AUDIO_MODE: " +
+                Log.i(TAG, "ON_AUDIO_MODE: " +
                         AudioMode.toString(msg.arg1) + ", muted (" + (msg.arg2 == 1) + ")");
                 mAudioModeProvider.onAudioModeChange(msg.arg1, msg.arg2 == 1);
                 break;
             case ON_SUPPORTED_AUDIO_MODE:
-                Log.i(CallHandlerService.this, "ON_SUPPORTED_AUDIO_MODE: " + AudioMode.toString(
+                Log.i(TAG, "ON_SUPPORTED_AUDIO_MODE: " + AudioMode.toString(
                         msg.arg1));
 
                 mAudioModeProvider.onSupportedAudioModeChange(msg.arg1);
                 break;
             case ON_BRING_TO_FOREGROUND:
-                Log.i(CallHandlerService.this, "ON_BRING_TO_FOREGROUND");
+                Log.i(TAG, "ON_BRING_TO_FOREGROUND");
                 if (mInCallPresenter != null) {
                     mInCallPresenter.bringToForeground();
                 }
                 break;
-            case ON_CREATE:
-                doCreate();
+            case ON_START:
+                doStart((ICallCommandService) msg.obj);
                 break;
             case ON_DESTROY:
-                doDestroy();
+                doStop();
                 break;
             default:
                 break;
diff --git a/InCallUI/src/com/android/incallui/Log.java b/InCallUI/src/com/android/incallui/Log.java
index 3099ea5..c859e5c 100644
--- a/InCallUI/src/com/android/incallui/Log.java
+++ b/InCallUI/src/com/android/incallui/Log.java
@@ -27,10 +27,11 @@
     public static final boolean DEBUG = android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
     public static final boolean VERBOSE = android.util.Log.isLoggable(TAG,
             android.util.Log.VERBOSE);
+    public static final String TAG_DELIMETER = " - ";
 
     public static void d(String tag, String msg) {
         if (DEBUG) {
-            android.util.Log.d(TAG, tag + " - " + msg);
+            android.util.Log.d(TAG, delimit(tag) + msg);
         }
     }
 
@@ -59,11 +60,11 @@
     }
 
     public static void e(String tag, String msg, Exception e) {
-        android.util.Log.e(TAG, tag + msg, e);
+        android.util.Log.e(TAG, delimit(tag) + msg, e);
     }
 
     public static void e(String tag, String msg) {
-        android.util.Log.e(TAG, tag + msg);
+        android.util.Log.e(TAG, delimit(tag) + msg);
     }
 
     public static void e(Object obj, String msg, Exception e) {
@@ -75,7 +76,7 @@
     }
 
     public static void i(String tag, String msg) {
-        android.util.Log.i(TAG, tag + msg);
+        android.util.Log.i(TAG, delimit(tag) + msg);
     }
 
     public static void i(Object obj, String msg) {
@@ -91,6 +92,10 @@
     }
 
     private static String getPrefix(Object obj) {
-        return (obj == null ? "" : (obj.getClass().getSimpleName() + " - "));
+        return (obj == null ? "" : (obj.getClass().getSimpleName() + TAG_DELIMETER));
+    }
+
+    private static String delimit(String tag) {
+        return tag + TAG_DELIMETER;
     }
 }
diff --git a/InCallUI/src/com/android/incallui/ProximitySensor.java b/InCallUI/src/com/android/incallui/ProximitySensor.java
index c28a69e..0dc54dc 100644
--- a/InCallUI/src/com/android/incallui/ProximitySensor.java
+++ b/InCallUI/src/com/android/incallui/ProximitySensor.java
@@ -210,7 +210,7 @@
                         .add("hor", horizontal ? 1 : 0).toString());
 
                 if (mIsPhoneOffhook && !screenOnImmediately) {
-                    final String logStr = "turning off proximity sensor: ";
+                    final String logStr = "turning on proximity sensor: ";
                     // Phone is in use!  Arrange for the screen to turn off
                     // automatically when the sensor detects a close object.
                     if (!mProximityWakeLock.isHeld()) {