Merge "Edit contact: work around incorrect gravity in RTL" into lmp-dev
diff --git a/res/layout/quickcontact_content.xml b/res/layout/quickcontact_content.xml
index 494b93b..5ead702 100644
--- a/res/layout/quickcontact_content.xml
+++ b/res/layout/quickcontact_content.xml
@@ -23,7 +23,7 @@
     android:background="@color/card_margin_color">
 
     <!-- All the cards should be inserted into this LinearLayout -->
-    <LinearLayout
+    <view class="com.android.contacts.common.widget.ActivityTouchLinearLayout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
@@ -54,6 +54,6 @@
             android:visibility="gone"
             cardview:cardCornerRadius="@dimen/expanding_entry_card_card_corner_radius" />
 
-    </LinearLayout>
+    </view>
 
 </com.android.contacts.widget.TouchlessScrollView>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 43b31da..52918d5 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -151,6 +151,8 @@
     <dimen name="expanding_entry_card_title_text_size">16sp</dimen>
     <!-- Padding for the title text for a ExpandingEntryCardView -->
     <dimen name="expanding_entry_card_title_padding">16dp</dimen>
+    <!-- Extra top padding if the title is set to null -->
+    <dimen name="expanding_entry_card_null_title_top_extra_padding">2dp</dimen>
 
     <!-- Height of the separator between entries in an ExpandingEntryCardView -->
     <dimen name="expanding_entry_card_item_separator_height">1dp</dimen>
diff --git a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
index a536f8c..7501bb8 100644
--- a/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
+++ b/src/com/android/contacts/quickcontact/ExpandingEntryCardView.java
@@ -67,7 +67,7 @@
      */
     public static final class Entry {
 
-        private final int mViewId;
+        private final int mId;
         private final Drawable mIcon;
         private final String mHeader;
         private final String mSubHeader;
@@ -82,21 +82,21 @@
         private final boolean mIsEditable;
         private final EntryContextMenuInfo mEntryContextMenuInfo;
 
-        public Entry(int viewId, Drawable icon, String header, String subHeader, String text,
+        public Entry(int id, Drawable icon, String header, String subHeader, String text,
                 Intent intent, Drawable alternateIcon, Intent alternateIntent,
                 String alternateContentDescription, boolean shouldApplyColor,
                 boolean isEditable, EntryContextMenuInfo entryContextMenuInfo) {
-            this(viewId, icon, header, subHeader, null, text, null, intent, alternateIcon,
+            this(id, icon, header, subHeader, null, text, null, intent, alternateIcon,
                     alternateIntent, alternateContentDescription, shouldApplyColor, isEditable,
                     entryContextMenuInfo);
         }
 
-        public Entry(int viewId, Drawable mainIcon, String header, String subHeader,
+        public Entry(int id, Drawable mainIcon, String header, String subHeader,
                 Drawable subHeaderIcon, String text, Drawable textIcon, Intent intent,
                 Drawable alternateIcon, Intent alternateIntent, String alternateContentDescription,
                 boolean shouldApplyColor, boolean isEditable,
                 EntryContextMenuInfo entryContextMenuInfo) {
-            mViewId = viewId;
+            mId = id;
             mIcon = mainIcon;
             mHeader = header;
             mSubHeader = subHeader;
@@ -160,8 +160,8 @@
             return mIsEditable;
         }
 
-        int getViewId() {
-            return mViewId;
+        int getId() {
+            return mId;
         }
 
         EntryContextMenuInfo getEntryContextMenuInfo() {
@@ -182,6 +182,10 @@
     private OnClickListener mOnClickListener;
     private OnCreateContextMenuListener mOnCreateContextMenuListener;
     private boolean mIsExpanded = false;
+    /**
+     * The max number of entries to show in a collapsed card. If there are less entries passed in,
+     * then they are all shown.
+     */
     private int mCollapsedEntriesCount;
     private ExpandingEntryCardViewListener mListener;
     private List<List<Entry>> mEntries;
@@ -255,11 +259,6 @@
             mEntryViews.add(new ArrayList<View>());
         }
         mCollapsedEntriesCount = Math.min(numInitialVisibleEntries, mNumEntries);
-        // Only show the head of each entry list if the initial visible number falls between the
-        // number of lists and the total number of entries
-        if (mCollapsedEntriesCount > mEntries.size()) {
-            mCollapsedEntriesCount = mEntries.size();
-        }
         mListener = listener;
         mAnimationViewGroup = animationViewGroup;
 
@@ -321,11 +320,28 @@
                 }
             }
         } else {
-            for (int i = 0; i < mCollapsedEntriesCount; i++) {
+            // We want to insert mCollapsedEntriesCount entries into the group. extraEntries is the
+            // number of entries that need to be added that are not the head element of a list
+            // to reach mCollapsedEntriesCount.
+            int numInViewGroup = 0;
+            int extraEntries = mCollapsedEntriesCount - mEntryViews.size();
+            for (int i = 0; i < mEntryViews.size() && numInViewGroup < mCollapsedEntriesCount;
+                    i++) {
+                List<View> entryViewList = mEntryViews.get(i);
                 if (i > 0) {
-                    addSeparator(mEntryViews.get(i).get(0));
+                    addSeparator(entryViewList.get(0));
                 }
-                addEntry(mEntryViews.get(i).get(0));
+                addEntry(entryViewList.get(0));
+                numInViewGroup++;
+                // Insert entries in this list to hit mCollapsedEntriesCount.
+                for (int j = 1;
+                        j < entryViewList.size() && numInViewGroup < mCollapsedEntriesCount &&
+                        extraEntries > 0;
+                        j++) {
+                    addEntry(entryViewList.get(j));
+                    numInViewGroup++;
+                    extraEntries--;
+                }
             }
         }
 
@@ -337,6 +353,15 @@
     }
 
     private void addEntry(View entry) {
+        // If no title and the first entry in the group, add extra padding
+        if (TextUtils.isEmpty(mTitleTextView.getText()) &&
+                mEntriesViewGroup.getChildCount() == 0) {
+            entry.setPadding(entry.getPaddingLeft(),
+                    entry.getPaddingTop() + getResources().getDimensionPixelSize(
+                            R.dimen.expanding_entry_card_null_title_top_extra_padding),
+                    entry.getPaddingRight(),
+                    entry.getPaddingBottom());
+        }
         mEntriesViewGroup.addView(entry);
     }
 
@@ -392,9 +417,24 @@
             inflateAllEntries(layoutInflater);
         } else {
             // Otherwise inflate the top entry from each list
-            for (int i = 0; i < mCollapsedEntriesCount; i++) {
-                mEntryViews.get(i).add(createEntryView(layoutInflater, mEntries.get(i).get(0),
+            // extraEntries is used to add extra entries until mCollapsedEntriesCount is reached.
+            int numInflated = 0;
+            int extraEntries = mCollapsedEntriesCount - mEntries.size();
+            for (int i = 0; i < mEntries.size() && numInflated < mCollapsedEntriesCount; i++) {
+                List<Entry> entryList = mEntries.get(i);
+                List<View> entryViewList = mEntryViews.get(i);
+
+                entryViewList.add(createEntryView(layoutInflater, entryList.get(0),
                         /* showIcon = */ View.VISIBLE));
+                numInflated++;
+                // Inflate entries in this list to hit mCollapsedEntriesCount.
+                for (int j = 1; j < entryList.size() && numInflated < mCollapsedEntriesCount &&
+                        extraEntries > 0; j++) {
+                    entryViewList.add(createEntryView(layoutInflater, entryList.get(j),
+                            /* showIcon = */ View.VISIBLE));
+                    numInflated++;
+                    extraEntries--;
+                }
             }
         }
     }
@@ -491,7 +531,6 @@
                 R.layout.expanding_entry_card_item, this, false);
 
         view.setContextMenuInfo(entry.getEntryContextMenuInfo());
-        view.setId(entry.getViewId());
 
         final ImageView icon = (ImageView) view.findViewById(R.id.icon);
         icon.setVisibility(iconVisibility);
@@ -535,7 +574,7 @@
 
         if (entry.getIntent() != null) {
             view.setOnClickListener(mOnClickListener);
-            view.setTag(entry.getIntent());
+            view.setTag(new EntryTag(entry.getId(), entry.getIntent()));
         }
 
         // If only the header is visible, add a top margin to match icon's top margin.
@@ -555,8 +594,7 @@
         if (entry.getAlternateIcon() != null && entry.getAlternateIntent() != null) {
             alternateIcon.setImageDrawable(entry.getAlternateIcon());
             alternateIcon.setOnClickListener(mOnClickListener);
-            alternateIcon.setTag(entry.getAlternateIntent());
-            alternateIcon.setId(entry.getViewId());
+            alternateIcon.setTag(new EntryTag(entry.getId(), entry.getAlternateIntent()));
             alternateIcon.setVisibility(View.VISIBLE);
             alternateIcon.setContentDescription(entry.getAlternateContentDescription());
 
@@ -757,13 +795,30 @@
         if (mTitleTextView == null) {
             Log.e(TAG, "mTitleTextView is null");
         }
-        if (title == null) {
-            mTitleTextView.setVisibility(View.GONE);
-            findViewById(R.id.title_separator).setVisibility(View.GONE);
-        }
         mTitleTextView.setText(title);
-        mTitleTextView.setVisibility(View.VISIBLE);
-        findViewById(R.id.title_separator).setVisibility(View.VISIBLE);
+        mTitleTextView.setVisibility(TextUtils.isEmpty(title) ? View.GONE : View.VISIBLE);
+        findViewById(R.id.title_separator).setVisibility(TextUtils.isEmpty(title) ?
+                View.GONE : View.VISIBLE);
+        // If the title is set after children have been added, reset the top entry's padding to
+        // the default. Else if the title is cleared after children have been added, set
+        // the extra top padding
+        if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
+            View firstEntry = mEntriesViewGroup.getChildAt(0);
+            firstEntry.setPadding(firstEntry.getPaddingLeft(),
+                    getResources().getDimensionPixelSize(
+                            R.dimen.expanding_entry_card_item_padding_top),
+                    firstEntry.getPaddingRight(),
+                    firstEntry.getPaddingBottom());
+        } else if (!TextUtils.isEmpty(title) && mEntriesViewGroup.getChildCount() > 0) {
+            View firstEntry = mEntriesViewGroup.getChildAt(0);
+            firstEntry.setPadding(firstEntry.getPaddingLeft(),
+                    getResources().getDimensionPixelSize(
+                            R.dimen.expanding_entry_card_item_padding_top) +
+                            getResources().getDimensionPixelSize(
+                                    R.dimen.expanding_entry_card_null_title_top_extra_padding),
+                    firstEntry.getPaddingRight(),
+                    firstEntry.getPaddingBottom());
+        }
     }
 
     public boolean shouldShow() {
@@ -808,4 +863,22 @@
             return mCopyLabel;
         }
     }
+
+    static final class EntryTag {
+        private final int mId;
+        private final Intent mIntent;
+
+        public EntryTag(int id, Intent intent) {
+            mId = id;
+            mIntent = intent;
+        }
+
+        public int getId() {
+            return mId;
+        }
+
+        public Intent getIntent() {
+            return mIntent;
+        }
+    }
 }
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 8b4e124..6577fdc 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -34,6 +34,7 @@
 import android.content.pm.ResolveInfo;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.Point;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.BitmapDrawable;
@@ -67,6 +68,7 @@
 import android.provider.ContactsContract.QuickContact;
 import android.provider.ContactsContract.RawContacts;
 import android.support.v7.graphics.Palette;
+import android.telecomm.TelecommManager;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -93,6 +95,7 @@
 import com.android.contacts.common.Collapser;
 import com.android.contacts.common.ContactsUtils;
 import com.android.contacts.common.editor.SelectAccountDialogFragment;
+import com.android.contacts.common.interactions.TouchPointManager;
 import com.android.contacts.common.lettertiles.LetterTileDrawable;
 import com.android.contacts.common.list.ShortcutIntentBuilder;
 import com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
@@ -128,6 +131,7 @@
 import com.android.contacts.interactions.SmsInteractionsLoader;
 import com.android.contacts.quickcontact.ExpandingEntryCardView.Entry;
 import com.android.contacts.quickcontact.ExpandingEntryCardView.EntryContextMenuInfo;
+import com.android.contacts.quickcontact.ExpandingEntryCardView.EntryTag;
 import com.android.contacts.quickcontact.ExpandingEntryCardView.ExpandingEntryCardViewListener;
 import com.android.contacts.util.ImageViewDrawableSetter;
 import com.android.contacts.util.PhoneCapabilityTester;
@@ -135,6 +139,7 @@
 import com.android.contacts.util.StructuredPostalUtils;
 import com.android.contacts.widget.MultiShrinkScroller;
 import com.android.contacts.widget.MultiShrinkScroller.MultiShrinkScrollerListener;
+
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 
@@ -287,18 +292,19 @@
     final OnClickListener mEntryClickHandler = new OnClickListener() {
         @Override
         public void onClick(View v) {
-            // Data Id is stored as the entry view id
-            final int dataId = v.getId();
+            final Object entryTagObject = v.getTag();
+            if (entryTagObject == null || !(entryTagObject instanceof EntryTag)) {
+                Log.w(TAG, "EntryTag was not used correctly");
+                return;
+            }
+            final EntryTag entryTag = (EntryTag) entryTagObject;
+            final Intent intent = entryTag.getIntent();
+            final int dataId = entryTag.getId();
+
             if (dataId == CARD_ENTRY_ID_EDIT_CONTACT) {
                 editContact();
                 return;
             }
-            final Object intentObject = v.getTag();
-            if (intentObject == null || !(intentObject instanceof Intent)) {
-                Log.w(TAG, "Intent tag was not used correctly");
-                return;
-            }
-            final Intent intent = (Intent) intentObject;
 
             // Default to USAGE_TYPE_CALL. Usage is summed among all types for sorting each data id
             // so the exact usage type is not necessary in all cases
@@ -326,6 +332,17 @@
                 Log.w(TAG, "Invalid Data ID");
             }
 
+            // Pass the touch point through the intent for use in the InCallUI
+            if (Intent.ACTION_CALL.equals(intent.getAction())) {
+                final Point touchPoint = TouchPointManager.getInstance().getPoint();
+
+                if (touchPoint.x != 0 || touchPoint.y != 0) {
+                    Bundle extras = new Bundle();
+                    extras.putParcelable(TouchPointManager.TOUCH_POINT, touchPoint);
+                    intent.putExtra(TelecommManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
+                }
+            }
+
             startActivity(intent);
         }
     };
@@ -1310,6 +1327,7 @@
             return null;
         }
 
+        // Ignore dataIds from the Me profile.
         final int dataId = dataItem.getId() > Integer.MAX_VALUE ?
                 -1 : (int) dataItem.getId();
 
diff --git a/src/com/android/contacts/widget/MultiShrinkScroller.java b/src/com/android/contacts/widget/MultiShrinkScroller.java
index ff84b2f..faa7e41 100644
--- a/src/com/android/contacts/widget/MultiShrinkScroller.java
+++ b/src/com/android/contacts/widget/MultiShrinkScroller.java
@@ -954,10 +954,14 @@
         // How offset the title should be from the bottom of the toolbar
         final int pretendBottomMargin =  (int) (mCollapsedTitleBottomMargin * (1 - x)
                 + mMaximumTitleMargin * x) ;
-        // Calculate how offset the title should be from the top of the screen.
+        // Calculate how offset the title should be from the top of the screen. Instead of
+        // calling mLargeTextView.getHeight() use the mMaximumHeaderTextSize for this calculation.
+        // The getHeight() value acts unexpectedly when mLargeTextView is partially clipped by
+        // its parent.
         titleLayoutParams.topMargin = getTransparentViewHeight()
                 + toolbarLayoutParams.height - pretendBottomMargin
-                - mLargeTextView.getHeight();
+                - mMaximumHeaderTextSize;
+        titleLayoutParams.bottomMargin = 0;
         mLargeTextView.setLayoutParams(titleLayoutParams);
     }