Add logic support for manage conference screen. (Part 2 of 4)

Changes:
  - Add conference call resource photo
  - Move logic to determine the name/numbers to show in the Call card
    from CallCardFragment to CallCardPresenter.
  - CallCardPresenter now tells CallCardFragment if the primary call is
    a conference call.
  - Updated the primary/secondary call order do that Active Calls are
    primary instead of Disconnected calls when both exist.
  - Cleaned up some excessive logging.
  - The CallCard code uses a whitelist to know which callcard to show.
    The change in services/Telephony to add CONFERENCED state is what
    causes the new child calls to now show since that is not added to
    the whitelist in this CL (by design).

bug: 10334739
Change-Id: Iaeab3f8bc9bda7693fa4a27bb8d3fe5de4dc9dfc
diff --git a/InCallUI/res/drawable-hdpi/picture_conference.png b/InCallUI/res/drawable-hdpi/picture_conference.png
new file mode 100644
index 0000000..93743e6
--- /dev/null
+++ b/InCallUI/res/drawable-hdpi/picture_conference.png
Binary files differ
diff --git a/InCallUI/res/drawable-ldrtl-hdpi/picture_conference.png b/InCallUI/res/drawable-ldrtl-hdpi/picture_conference.png
new file mode 100644
index 0000000..ca250fd
--- /dev/null
+++ b/InCallUI/res/drawable-ldrtl-hdpi/picture_conference.png
Binary files differ
diff --git a/InCallUI/res/drawable-ldrtl-mdpi/picture_conference.png b/InCallUI/res/drawable-ldrtl-mdpi/picture_conference.png
new file mode 100644
index 0000000..2876d0f
--- /dev/null
+++ b/InCallUI/res/drawable-ldrtl-mdpi/picture_conference.png
Binary files differ
diff --git a/InCallUI/res/drawable-ldrtl-xhdpi/picture_conference.png b/InCallUI/res/drawable-ldrtl-xhdpi/picture_conference.png
new file mode 100644
index 0000000..50b4e35
--- /dev/null
+++ b/InCallUI/res/drawable-ldrtl-xhdpi/picture_conference.png
Binary files differ
diff --git a/InCallUI/res/drawable-mdpi/picture_conference.png b/InCallUI/res/drawable-mdpi/picture_conference.png
new file mode 100644
index 0000000..8f7ecd5
--- /dev/null
+++ b/InCallUI/res/drawable-mdpi/picture_conference.png
Binary files differ
diff --git a/InCallUI/res/drawable-xhdpi/picture_conference.png b/InCallUI/res/drawable-xhdpi/picture_conference.png
new file mode 100644
index 0000000..1906b9b
--- /dev/null
+++ b/InCallUI/res/drawable-xhdpi/picture_conference.png
Binary files differ
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java
index 3598aaf..18b51d9 100644
--- a/InCallUI/src/com/android/incallui/CallCardFragment.java
+++ b/InCallUI/src/com/android/incallui/CallCardFragment.java
@@ -100,14 +100,12 @@
     }
 
     @Override
-    public void setPrimary(String number, String name, String label, Drawable photo) {
-        boolean nameIsNumber = false;
+    public void setPrimary(String number, String name, boolean nameIsNumber, String label,
+            Drawable photo, boolean isConference) {
 
-        // If there is no name, then use the number as the name;
-        if (TextUtils.isEmpty(name)) {
-            name = number;
-            number = null;
-            nameIsNumber = true;
+        if (isConference) {
+            name = getView().getResources().getString(R.string.card_title_conf_call);
+            photo = getView().getResources().getDrawable(R.drawable.picture_conference);
         }
 
         // Set the number
@@ -147,14 +145,10 @@
     }
 
     @Override
-    public void setSecondary(boolean show, String number, String name, String label,
-            Drawable photo) {
+    public void setSecondary(boolean show, String name, String label, Drawable photo) {
 
         if (show) {
             showAndInitializeSecondaryCallInfo();
-            if (TextUtils.isEmpty(name)) {
-                name = number;
-            }
 
             mSecondaryCallName.setText(name);
             setDrawableToImageView(mSecondaryPhoto, photo);
@@ -275,7 +269,7 @@
             callStateLabel = getCallFailedString(cause);
 
         } else {
-            Logger.wtf(this, "updateCallStateWidgets: unexpected call state: " + state);
+            Logger.wtf(this, "updateCallStateWidgets: unexpected call: " + state);
         }
 
         return callStateLabel;
diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java
index 60486f4..bf27a1b 100644
--- a/InCallUI/src/com/android/incallui/CallCardPresenter.java
+++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java
@@ -16,8 +16,8 @@
 
 package com.android.incallui;
 
-import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.text.format.DateUtils;
 
 import com.android.incallui.AudioModeProvider.AudioModeListener;
@@ -28,6 +28,7 @@
 
 import com.android.services.telephony.common.AudioMode;
 import com.android.services.telephony.common.Call;
+import com.android.services.telephony.common.Call.DisconnectCause;
 
 /**
  * Presenter for the Call Card Fragment.
@@ -95,10 +96,10 @@
 
             // getCallToDisplay doesn't go through outgoing or incoming calls. It will return the
             // highest priority call to display as the secondary call.
-            secondary = getCallToDisplay(callList, null);
+            secondary = getCallToDisplay(callList, null, true);
         } else if (state == InCallState.INCALL) {
-            primary = getCallToDisplay(callList, null);
-            secondary = getCallToDisplay(callList, primary);
+            primary = getCallToDisplay(callList, null, false);
+            secondary = getCallToDisplay(callList, primary, true);
         }
 
         Logger.d(this, "Primary call: " + primary);
@@ -129,7 +130,7 @@
                     mAudioModeProvider.getAudioMode() == AudioMode.BLUETOOTH;
             ui.setCallState(mPrimary.getState(), mPrimary.getDisconnectCause(), bluetoothOn);
         } else {
-            ui.setCallState(Call.State.INVALID, Call.DisconnectCause.UNKNOWN, false);
+            ui.setCallState(Call.State.IDLE, Call.DisconnectCause.UNKNOWN, false);
         }
     }
 
@@ -194,19 +195,22 @@
      *
      * @param ignore A call to ignore if found.
      */
-    private Call getCallToDisplay(CallList callList, Call ignore) {
+    private Call getCallToDisplay(CallList callList, Call ignore, boolean skipDisconnected) {
 
-        // Disconnected calls get primary position to let user know quickly
-        // what call has disconnected. Disconnected calls are very short lived.
-        Call retval = callList.getDisconnectedCall();
+        // Active calls come second.  An active call always gets precedent.
+        Call retval = callList.getActiveCall();
         if (retval != null && retval != ignore) {
             return retval;
         }
 
-        // Active calls come second.  An active call always gets precedent.
-        retval = callList.getActiveCall();
-        if (retval != null && retval != ignore) {
-            return retval;
+        // Disconnected calls get primary position if there are no active calls
+        // to let user know quickly what call has disconnected. Disconnected
+        // calls are very short lived.
+        if (!skipDisconnected) {
+            retval = callList.getDisconnectedCall();
+            if (retval != null && retval != ignore) {
+                return retval;
+            }
         }
 
         // Then we go to background call (calls on hold)
@@ -226,11 +230,6 @@
      */
     @Override
     public void onContactInfoComplete(int callId, ContactCacheEntry entry) {
-        Logger.d(this, "onContactInfoComplete: ", entry.name);
-        Logger.d(this, "onContactInfoComplete: ", entry.number);
-        Logger.d(this, "onContactInfoComplete: ", entry.label);
-        Logger.d(this, "onContactInfoComplete: ", entry.photo);
-
         if (mPrimary != null && mPrimary.getCallId() == callId) {
             mPrimaryContactInfo = entry;
             updatePrimaryDisplayInfo();
@@ -249,15 +248,40 @@
         }
 
         if (mPrimaryContactInfo != null) {
-            ui.setPrimary(mPrimaryContactInfo.number, mPrimaryContactInfo.name,
-                    mPrimaryContactInfo.label, mPrimaryContactInfo.photo);
+            final String name = getNameForCall(mPrimaryContactInfo);
+            final String number = getNumberForCall(mPrimaryContactInfo);
+            final boolean nameIsNumber = name != null && name.equals(mPrimaryContactInfo.number);
+            ui.setPrimary(number, name, nameIsNumber, mPrimaryContactInfo.label,
+                    mPrimaryContactInfo.photo, mPrimary.isConferenceCall());
         } else {
             // reset to nothing (like at end of call)
-            ui.setPrimary(null, null, null, null);
+            ui.setPrimary(null, null, false, null, null, false);
         }
 
     }
 
+    /**
+     * Gets the name to display for the call.
+     */
+    private static String getNameForCall(ContactCacheEntry contactInfo) {
+        if (TextUtils.isEmpty(contactInfo.name)) {
+            return contactInfo.number;
+        }
+        return contactInfo.name;
+    }
+
+    /**
+     * Gets the number to display for a call.
+     */
+    private static String getNumberForCall(ContactCacheEntry contactInfo) {
+        // If the name is empty, we use the number for the name...so dont show a second
+        // number in the number field
+        if (TextUtils.isEmpty(contactInfo.name)) {
+            return null;
+        }
+        return contactInfo.number;
+    }
+
     private void updateSecondaryDisplayInfo() {
         final CallCardUi ui = getUi();
         if (ui == null) {
@@ -265,11 +289,12 @@
         }
 
         if (mSecondaryContactInfo != null) {
-            ui.setSecondary(true, mSecondaryContactInfo.number, mSecondaryContactInfo.name,
+            final String name = getNameForCall(mSecondaryContactInfo);
+            ui.setSecondary(true, getNameForCall(mSecondaryContactInfo),
                     mSecondaryContactInfo.label, mSecondaryContactInfo.photo);
         } else {
             // reset to nothing so that it starts off blank next time we use it.
-            ui.setSecondary(false, null, null, null, null);
+            ui.setSecondary(false, null, null, null);
         }
     }
 
@@ -280,8 +305,9 @@
 
     public interface CallCardUi extends Ui {
         void setVisible(boolean on);
-        void setPrimary(String number, String name, String label, Drawable photo);
-        void setSecondary(boolean show, String number, String name, String label, Drawable photo);
+        void setPrimary(String number, String name, boolean nameIsNumber, String label,
+                Drawable photo, boolean isConference);
+        void setSecondary(boolean show, String name, String label, Drawable photo);
         void setCallState(int state, Call.DisconnectCause cause, boolean bluetoothOn);
         void setPrimaryCallElapsedTime(boolean show, String duration);
     }
diff --git a/InCallUI/src/com/android/incallui/CallHandlerService.java b/InCallUI/src/com/android/incallui/CallHandlerService.java
index 3b8631b..bdee328 100644
--- a/InCallUI/src/com/android/incallui/CallHandlerService.java
+++ b/InCallUI/src/com/android/incallui/CallHandlerService.java
@@ -85,12 +85,14 @@
 
         @Override
         public void onDisconnect(Call call) {
-            Logger.d(CallHandlerService.this, "onDisconnected");
+            Logger.d(CallHandlerService.this, "onDisconnected: " + call);
             mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_DISCONNECT_CALL, 0, 0, call));
         }
 
         @Override
         public void onIncoming(Call call, List<String> textResponses) {
+            Logger.d(CallHandlerService.this, "onIncomingCall: " + call);
+
             // TODO(klp): Add text responses to the call object.
             Map.Entry<Call, List<String> > incomingCall = new AbstractMap.SimpleEntry<Call,
                     List<String> >(call, textResponses);
@@ -100,7 +102,7 @@
 
         @Override
         public void onUpdate(List<Call> calls, boolean fullUpdate) {
-            Logger.d(CallHandlerService.this, "onUpdate ");
+            Logger.d(CallHandlerService.this, "onUpdate " + calls.toString());
 
             if (Logger.VERBOSE) {
                 for (Call c : calls) {
diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java
index eb05cdb..f692bf6 100644
--- a/InCallUI/src/com/android/incallui/CallList.java
+++ b/InCallUI/src/com/android/incallui/CallList.java
@@ -240,17 +240,17 @@
         final Integer id = new Integer(call.getCallId());
 
         if (call.getState() == Call.State.DISCONNECTED) {
-            // For disconnected calls, we want to keep them alive for a few seconds so that the UI
-            // has a chance to display anything it needs when a call is disconnected.
 
-            // Set up a timer to destroy the call after X seconds.
-            Message msg = mHandler.obtainMessage(EVENT_DISCONNECTED_TIMEOUT, call);
-            boolean sent = mHandler.sendMessageDelayed(msg, DISCONNECTED_CALL_TIMEOUT_MS);
-
-            Logger.d(this, "Retval from sendMessageDelayed: ", Boolean.toString(sent));
-
-            // Don't add disconnected calls that do not already exist in the map
+            // update existing (but do not add!!) disconnected calls
             if (mCallMap.containsKey(id)) {
+
+                // For disconnected calls, we want to keep them alive for a few seconds so that the
+                // UI has a chance to display anything it needs when a call is disconnected.
+
+                // Set up a timer to destroy the call after X seconds.
+                final Message msg = mHandler.obtainMessage(EVENT_DISCONNECTED_TIMEOUT, call);
+                mHandler.sendMessageDelayed(msg, DISCONNECTED_CALL_TIMEOUT_MS);
+
                 mCallMap.put(id, call);
             }
         } else if (!isCallDead(call)) {
diff --git a/InCallUI/src/com/android/incallui/InCallPresenter.java b/InCallUI/src/com/android/incallui/InCallPresenter.java
index 3ae4d3a..d709ba4 100644
--- a/InCallUI/src/com/android/incallui/InCallPresenter.java
+++ b/InCallUI/src/com/android/incallui/InCallPresenter.java
@@ -70,6 +70,8 @@
         addListener(mStatusBarNotifier);
 
         mAudioModeProvider = audioModeProvider;
+
+        Logger.d(this, "Finished InCallPresenter.setUp");
     }
 
     public void tearDown() {
@@ -85,6 +87,8 @@
         mInCallActivity = null;
 
         mListeners.clear();
+
+        Logger.d(this, "Finished InCallPresenter.tearDown");
     }
 
     public void setActivity(InCallActivity inCallActivity) {