Merge "Small clean-up of stream items utility class."
diff --git a/res/drawable-hdpi/sym_action_audiochat_holo_dark.png b/res/drawable-hdpi/sym_action_audiochat_holo_dark.png
new file mode 100644
index 0000000..d4e3329
--- /dev/null
+++ b/res/drawable-hdpi/sym_action_audiochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/sym_action_videochat_holo_dark.png b/res/drawable-hdpi/sym_action_videochat_holo_dark.png
new file mode 100644
index 0000000..821940a
--- /dev/null
+++ b/res/drawable-hdpi/sym_action_videochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/sym_action_audiochat_holo_dark.png b/res/drawable-mdpi/sym_action_audiochat_holo_dark.png
new file mode 100644
index 0000000..848404d
--- /dev/null
+++ b/res/drawable-mdpi/sym_action_audiochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/sym_action_videochat_holo_dark.png b/res/drawable-mdpi/sym_action_videochat_holo_dark.png
new file mode 100644
index 0000000..9112e87
--- /dev/null
+++ b/res/drawable-mdpi/sym_action_videochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/sym_action_audiochat_holo_dark.png b/res/drawable-xhdpi/sym_action_audiochat_holo_dark.png
new file mode 100644
index 0000000..216d34f
--- /dev/null
+++ b/res/drawable-xhdpi/sym_action_audiochat_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/sym_action_videochat_holo_dark.png b/res/drawable-xhdpi/sym_action_videochat_holo_dark.png
new file mode 100644
index 0000000..5011489
--- /dev/null
+++ b/res/drawable-xhdpi/sym_action_videochat_holo_dark.png
Binary files differ
diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java
index ae70c0b..c2c7c12 100644
--- a/src/com/android/contacts/calllog/CallLogFragment.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -163,7 +163,6 @@
     private CallLogAdapter mAdapter;
     private CallLogQueryHandler mCallLogQueryHandler;
     private String mVoiceMailNumber;
-    private String mCurrentCountryIso;
     private boolean mScrollToTop;
 
     private boolean mShowOptionsMenu;
@@ -228,11 +227,15 @@
     }
 
     /** Adapter class to fill in data for the Call Log */
-    public final class CallLogAdapter extends GroupingListAdapter
+    public static final class CallLogAdapter extends GroupingListAdapter
             implements Runnable, ViewTreeObserver.OnPreDrawListener, GroupCreator {
         /** The time in millis to delay starting the thread processing requests. */
         private static final int START_PROCESSING_REQUESTS_DELAY_MILLIS = 1000;
 
+        private final Context mContext;
+        private final String mCurrentCountryIso;
+        private final CallLogQueryHandler mCallLogQueryHandler;
+
         /**
          * A cache of the contact details for the phone numbers in the call log.
          * <p>
@@ -275,7 +278,7 @@
             public void onClick(View view) {
                 IntentProvider intentProvider = (IntentProvider) view.getTag();
                 if (intentProvider != null) {
-                    startActivity(intentProvider.getIntent(CallLogFragment.this.getActivity()));
+                    mContext.startActivity(intentProvider.getIntent(mContext));
                 }
             }
         };
@@ -304,18 +307,23 @@
             }
         };
 
-        public CallLogAdapter() {
-            super(getActivity());
+        public CallLogAdapter(Context context, CallLogQueryHandler callLogQueryHandler,
+                String currentCountryIso, String voicemailNumber) {
+            super(context);
+
+            mContext = context;
+            mCurrentCountryIso = currentCountryIso;
+            mCallLogQueryHandler = callLogQueryHandler;
 
             mContactInfoCache = ExpirableCache.create(CONTACT_INFO_CACHE_SIZE);
             mRequests = new LinkedList<String>();
             mPreDrawListener = null;
 
-            Resources resources = getResources();
+            Resources resources = mContext.getResources();
             CallTypeHelper callTypeHelper = new CallTypeHelper(resources);
 
-            mContactPhotoManager = ContactPhotoManager.getInstance(getActivity());
-            mPhoneNumberHelper = new PhoneNumberHelper(getResources(), mVoiceMailNumber);
+            mContactPhotoManager = ContactPhotoManager.getInstance(mContext);
+            mPhoneNumberHelper = new PhoneNumberHelper(resources, voicemailNumber);
             PhoneCallDetailsHelper phoneCallDetailsHelper = new PhoneCallDetailsHelper(
                     resources, callTypeHelper, mPhoneNumberHelper);
             mCallLogViewsHelper =
@@ -329,7 +337,8 @@
         @Override
         protected void onContentChanged() {
             // Start async requery
-            startCallsQuery();
+            setLoading(true);
+            mCallLogQueryHandler.fetchAllCalls();
         }
 
         void setLoading(boolean loading) {
@@ -427,7 +436,7 @@
             String[] selectionArgs = new String[] { sipAddress.toUpperCase() };
 
             Cursor dataTableCursor =
-                    getActivity().getContentResolver().query(
+                    mContext.getContentResolver().query(
                             contactRef,
                             null,  // projection
                             selection,  // selection
@@ -492,7 +501,7 @@
             // "number" is a regular phone number, so use the
             // PhoneLookup table:
             Cursor phonesCursor =
-                    getActivity().getContentResolver().query(
+                    mContext.getContentResolver().query(
                         Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
                                 Uri.encode(number)),
                                 PhoneQuery._PROJECTION, null, null, null);
@@ -824,6 +833,32 @@
         public void addGroup(int cursorPosition, int size, boolean expanded) {
             super.addGroup(cursorPosition, size, expanded);
         }
+
+        /**
+         * Format the given phone number
+         *
+         * @param number the number to be formatted.
+         * @param normalizedNumber the normalized number of the given number.
+         * @param countryIso the ISO 3166-1 two letters country code, the country's
+         *        convention will be used to format the number if the normalized
+         *        phone is null.
+         *
+         * @return the formatted number, or the given number if it was formatted.
+         */
+        private String formatPhoneNumber(String number, String normalizedNumber,
+                String countryIso) {
+            if (TextUtils.isEmpty(number)) {
+                return "";
+            }
+            // If "number" is really a SIP address, don't try to do any formatting at all.
+            if (PhoneNumberUtils.isUriNumber(number)) {
+                return number;
+            }
+            if (TextUtils.isEmpty(countryIso)) {
+                countryIso = mCurrentCountryIso;
+            }
+            return PhoneNumberUtils.formatNumber(number, normalizedNumber, countryIso);
+        }
     }
 
     @Override
@@ -834,8 +869,6 @@
                 Context.TELEPHONY_SERVICE)).getVoiceMailNumber();
         mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), this);
 
-        mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(getActivity());
-
         setHasOptionsMenu(true);
     }
 
@@ -881,7 +914,9 @@
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        mAdapter = new CallLogAdapter();
+        String currentCountryIso = ContactsUtils.getCurrentCountryIso(getActivity());
+        mAdapter = new CallLogAdapter(getActivity(), mCallLogQueryHandler, currentCountryIso,
+                getVoiceMailNumber());
         setListAdapter(mAdapter);
     }
 
@@ -941,31 +976,6 @@
         mAdapter.changeCursor(null);
     }
 
-    /**
-     * Format the given phone number
-     *
-     * @param number the number to be formatted.
-     * @param normalizedNumber the normalized number of the given number.
-     * @param countryIso the ISO 3166-1 two letters country code, the country's
-     *        convention will be used to format the number if the normalized
-     *        phone is null.
-     *
-     * @return the formatted number, or the given number if it was formatted.
-     */
-    private String formatPhoneNumber(String number, String normalizedNumber, String countryIso) {
-        if (TextUtils.isEmpty(number)) {
-            return "";
-        }
-        // If "number" is really a SIP address, don't try to do any formatting at all.
-        if (PhoneNumberUtils.isUriNumber(number)) {
-            return number;
-        }
-        if (TextUtils.isEmpty(countryIso)) {
-            countryIso = mCurrentCountryIso;
-        }
-        return PhoneNumberUtils.formatNumber(number, normalizedNumber, countryIso);
-    }
-
     private void resetNewCallsFlag() {
         mCallLogQueryHandler.markNewCallsAsOld();
     }
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index 6f719af..827016f 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -2,8 +2,9 @@
 
 import com.android.contacts.ContactsUtils;
 import com.android.contacts.R;
-import com.android.contacts.model.DataKind;
 import com.android.contacts.model.AccountType.EditType;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
 import com.android.contacts.util.Constants;
 import com.android.contacts.util.PhoneCapabilityTester;
 
@@ -15,12 +16,12 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.net.WebAddress;
-import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Im;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.Website;
+import android.provider.ContactsContract.Data;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -142,13 +143,12 @@
                 mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
             }
 
-        } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)
-                || Constants.MIME_TYPE_VIDEO_CHAT.equals(mimeType)) {
+        } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
             final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(
                     getAsString(cursor, Data.MIMETYPE));
             if (isEmail || isProtocolValid(cursor)) {
                 final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK :
-                    getAsInt(cursor, Im.PROTOCOL);
+                        getAsInt(cursor, Im.PROTOCOL);
 
                 if (isEmail) {
                     // Use Google Talk string when using Email, and clear data
@@ -165,17 +165,29 @@
                     host = ContactsUtils.lookupProviderNameFromId(protocol);
                 }
 
-                if (Constants.MIME_TYPE_VIDEO_CHAT.equals(mimeType)) {
-                    if (!TextUtils.isEmpty(data)) {
-                        mIntent = new Intent(Intent.ACTION_SENDTO);
-                        mIntent.setDataAndType(Uri.parse("xmpp:" + data + "?call"),
-                                Constants.MIME_TYPE_VIDEO_CHAT);
-                    }
-                } else if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
+                if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
                     final String authority = host.toLowerCase();
                     final Uri imUri = new Uri.Builder().scheme(Constants.SCHEME_IMTO).authority(
                             authority).appendPath(data).build();
                     mIntent = new Intent(Intent.ACTION_SENDTO, imUri);
+
+                    // If the address is also available for a video chat, we'll show the capability
+                    // as a secondary action.
+                    final int chatCapability = getAsInt(cursor, Data.CHAT_CAPABILITY);
+                    final boolean isVideoChatCapable =
+                            (chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0;
+                    final boolean isAudioChatCapable =
+                            (chatCapability & Im.CAPABILITY_HAS_VOICE) != 0;
+                    if (isVideoChatCapable || isAudioChatCapable) {
+                        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
+                                context.getApplicationContext());
+                        mAlternateIntent = new Intent(
+                                Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
+                        // Use Holo dark theme since the background is darker than usual.
+                        mAlternateIconRes = (isVideoChatCapable
+                                ? R.drawable.sym_action_videochat_holo_dark
+                                : R.drawable.sym_action_audiochat_holo_dark);
+                    }
                 }
             }
         }
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 1ef40db..d8f9c2c 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -467,8 +467,6 @@
                 }
             }
 
-            boolean isIm = Im.CONTENT_ITEM_TYPE.equals(mimeType);
-
             // Handle Email rows with presence data as Im entry
             final boolean hasPresence = !cursor.isNull(DataQuery.PRESENCE);
             if (hasPresence && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
@@ -478,20 +476,6 @@
                     final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE, imKind,
                             dataId, cursor);
                     considerAdd(action, cache);
-                    isIm = true;
-                }
-            }
-
-            if (hasPresence && isIm) {
-                int chatCapability = cursor.getInt(DataQuery.CHAT_CAPABILITY);
-                if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
-                    final DataKind imKind = accountTypes.getKindOrFallback(accountType, dataSet,
-                            Im.CONTENT_ITEM_TYPE);
-                    if (imKind != null) {
-                        final DataAction chatAction = new DataAction(context,
-                                Constants.MIME_TYPE_VIDEO_CHAT, imKind, dataId, cursor);
-                        considerAdd(chatAction, cache);
-                    }
                 }
             }
         }