am c5adb847: am 7b0193f0: am 43622e05: am eefddcff: am 09874cf9: am 18cfd4bd: Fix ShortcutIntentBuilder to use LetterTileDrawables

* commit 'c5adb8474f90c57fcdb449ae5eb2a12785b25936':
  Fix ShortcutIntentBuilder to use LetterTileDrawables
diff --git a/src/com/android/contacts/common/ContactPhotoManager.java b/src/com/android/contacts/common/ContactPhotoManager.java
index 916c9b5..ce02a0b 100644
--- a/src/com/android/contacts/common/ContactPhotoManager.java
+++ b/src/com/android/contacts/common/ContactPhotoManager.java
@@ -16,6 +16,7 @@
 
 package com.android.contacts.common;
 
+import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -51,7 +52,6 @@
 
 import com.android.contacts.common.lettertiles.LetterTileDrawable;
 import com.android.contacts.common.util.BitmapUtil;
-import com.android.contacts.common.util.MemoryUtils;
 import com.android.contacts.common.util.UriUtils;
 
 import com.google.common.collect.Lists;
@@ -556,8 +556,6 @@
     /** Cache size for {@link #mBitmapCache} for devices with "large" RAM. */
     private static final int BITMAP_CACHE_SIZE = 36864 * 48; // 1728K
 
-    private static final int LARGE_RAM_THRESHOLD = 640 * 1024 * 1024;
-
     /** For debug: How many times we had to reload cached photo for a stale entry */
     private final AtomicInteger mStaleCacheOverwrite = new AtomicInteger();
 
@@ -567,8 +565,11 @@
     public ContactPhotoManagerImpl(Context context) {
         mContext = context;
 
-        final float cacheSizeAdjustment =
-                (MemoryUtils.getTotalMemorySize() >= LARGE_RAM_THRESHOLD) ? 1.0f : 0.5f;
+        final ActivityManager am = ((ActivityManager) context.getSystemService(
+                Context.ACTIVITY_SERVICE));
+
+        final float cacheSizeAdjustment = (am.isLowRamDevice()) ? 0.5f : 1.0f;
+
         final int bitmapCacheSize = (int) (cacheSizeAdjustment * BITMAP_CACHE_SIZE);
         mBitmapCache = new LruCache<Object, Bitmap>(bitmapCacheSize) {
             @Override protected int sizeOf(Object key, Bitmap value) {
diff --git a/src/com/android/contacts/common/GeoUtil.java b/src/com/android/contacts/common/GeoUtil.java
index 5ca04b0..6c41d24 100644
--- a/src/com/android/contacts/common/GeoUtil.java
+++ b/src/com/android/contacts/common/GeoUtil.java
@@ -20,10 +20,10 @@
 import android.location.Country;
 import android.location.CountryDetector;
 
-import com.android.i18n.phonenumbers.NumberParseException;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
-import com.android.i18n.phonenumbers.Phonenumber;
-import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
+import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber;
 
 import java.util.Locale;
 
@@ -52,8 +52,6 @@
     public static String getGeocodedLocationFor(Context context,  String phoneNumber) {
         final PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();
         final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
-        final CountryDetector countryDetector =
-                (CountryDetector) context.getSystemService(Context.COUNTRY_DETECTOR);
         try {
             final Phonenumber.PhoneNumber structuredPhoneNumber =
                     phoneNumberUtil.parse(phoneNumber, getCurrentCountryIso(context));
diff --git a/src/com/android/contacts/common/MoreContactUtils.java b/src/com/android/contacts/common/MoreContactUtils.java
index accd73c..5a83467 100644
--- a/src/com/android/contacts/common/MoreContactUtils.java
+++ b/src/com/android/contacts/common/MoreContactUtils.java
@@ -16,8 +16,8 @@
 
 package com.android.contacts.common;
 
-import com.android.i18n.phonenumbers.NumberParseException;
-import com.android.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
 
 import android.content.Context;
 import android.content.Intent;
@@ -169,16 +169,15 @@
      * how the target {@link android.graphics.Rect} is calculated in
      * {@link android.provider.ContactsContract.QuickContact#showQuickContact}.
      */
-    public static Rect getTargetRectFromView(Context context, View view) {
-        final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
+    public static Rect getTargetRectFromView(View view) {
         final int[] pos = new int[2];
         view.getLocationOnScreen(pos);
 
         final Rect rect = new Rect();
-        rect.left = (int) (pos[0] * appScale + 0.5f);
-        rect.top = (int) (pos[1] * appScale + 0.5f);
-        rect.right = (int) ((pos[0] + view.getWidth()) * appScale + 0.5f);
-        rect.bottom = (int) ((pos[1] + view.getHeight()) * appScale + 0.5f);
+        rect.left = pos[0];
+        rect.top = pos[1];
+        rect.right = pos[0] + view.getWidth();
+        rect.bottom = pos[1] + view.getHeight();
         return rect;
     }
 
diff --git a/src/com/android/contacts/common/list/ContactListItemView.java b/src/com/android/contacts/common/list/ContactListItemView.java
index 6b9492b..9fdb24d 100644
--- a/src/com/android/contacts/common/list/ContactListItemView.java
+++ b/src/com/android/contacts/common/list/ContactListItemView.java
@@ -34,7 +34,6 @@
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.MotionEvent;
@@ -51,6 +50,8 @@
 import com.android.contacts.common.R;
 import com.android.contacts.common.format.TextHighlighter;
 import com.android.contacts.common.util.SearchUtil;
+import com.android.contacts.common.util.ViewUtil;
+
 import com.google.common.collect.Lists;
 
 import java.util.ArrayList;
@@ -233,14 +234,12 @@
 
     public ContactListItemView(Context context) {
         super(context);
-        mContext = context;
 
         mTextHighlighter = new TextHighlighter(Typeface.BOLD);
     }
 
     public ContactListItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mContext = context;
 
         // Read all style values
         TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ContactListItemView);
@@ -306,8 +305,8 @@
 
         a.recycle();
 
-        a = getContext().obtainStyledAttributes(android.R.styleable.Theme);
-        mSecondaryTextColor = a.getColorStateList(android.R.styleable.Theme_textColorSecondary);
+        a = getContext().obtainStyledAttributes(R.styleable.Theme);
+        mSecondaryTextColor = a.getColorStateList(R.styleable.Theme_android_textColorSecondary);
         a.recycle();
 
         mHorizontalDividerHeight = mHorizontalDividerDrawable.getIntrinsicHeight();
@@ -500,7 +499,7 @@
         int leftBound = getPaddingLeft();
         int rightBound = width - getPaddingRight();
 
-        final boolean isLayoutRtl = isLayoutRtl();
+        final boolean isLayoutRtl = ViewUtil.isViewLayoutRtl(this);
 
         // Put the header in the top of the contact view (Text + underline view)
         if (mHeaderVisible) {
@@ -777,16 +776,16 @@
     public void setSectionHeader(String title) {
         if (!TextUtils.isEmpty(title)) {
             if (mHeaderTextView == null) {
-                mHeaderTextView = new TextView(mContext);
+                mHeaderTextView = new TextView(getContext());
                 mHeaderTextView.setTextColor(mHeaderTextColor);
                 mHeaderTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mHeaderTextSize);
-                mHeaderTextView.setTextAppearance(mContext, R.style.SectionHeaderStyle);
+                mHeaderTextView.setTextAppearance(getContext(), R.style.SectionHeaderStyle);
                 mHeaderTextView.setGravity(Gravity.CENTER_VERTICAL);
                 mHeaderTextView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
                 addView(mHeaderTextView);
             }
             if (mHeaderDivider == null) {
-                mHeaderDivider = new View(mContext);
+                mHeaderDivider = new View(getContext());
                 mHeaderDivider.setBackgroundColor(mHeaderUnderlineColor);
                 addView(mHeaderDivider);
             }
@@ -814,10 +813,10 @@
             throw new IllegalStateException("QuickContact is disabled for this view");
         }
         if (mQuickContact == null) {
-            mQuickContact = new QuickContactBadge(mContext);
+            mQuickContact = new QuickContactBadge(getContext());
             mQuickContact.setLayoutParams(getDefaultPhotoLayoutParams());
             if (mNameTextView != null) {
-                mQuickContact.setContentDescription(mContext.getString(
+                mQuickContact.setContentDescription(getContext().getString(
                         R.string.description_quick_contact_for, mNameTextView.getText()));
             }
 
@@ -832,7 +831,7 @@
      */
     public ImageView getPhotoView() {
         if (mPhotoView == null) {
-            mPhotoView = new ImageView(mContext);
+            mPhotoView = new ImageView(getContext());
             mPhotoView.setLayoutParams(getDefaultPhotoLayoutParams());
             // Quick contact style used above will set a background - remove it
             mPhotoView.setBackground(null);
@@ -913,10 +912,10 @@
      */
     public TextView getNameTextView() {
         if (mNameTextView == null) {
-            mNameTextView = new TextView(mContext);
+            mNameTextView = new TextView(getContext());
             mNameTextView.setSingleLine(true);
             mNameTextView.setEllipsize(getTextEllipsis());
-            mNameTextView.setTextAppearance(mContext, R.style.TextAppearanceMedium);
+            mNameTextView.setTextAppearance(getContext(), R.style.TextAppearanceMedium);
             // Manually call setActivated() since this view may be added after the first
             // setActivated() call toward this whole item view.
             mNameTextView.setActivated(isActivated());
@@ -948,10 +947,10 @@
      */
     public TextView getPhoneticNameTextView() {
         if (mPhoneticNameTextView == null) {
-            mPhoneticNameTextView = new TextView(mContext);
+            mPhoneticNameTextView = new TextView(getContext());
             mPhoneticNameTextView.setSingleLine(true);
             mPhoneticNameTextView.setEllipsize(getTextEllipsis());
-            mPhoneticNameTextView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
+            mPhoneticNameTextView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small);
             mPhoneticNameTextView.setTypeface(mPhoneticNameTextView.getTypeface(), Typeface.BOLD);
             mPhoneticNameTextView.setActivated(isActivated());
             mPhoneticNameTextView.setId(R.id.cliv_phoneticname_textview);
@@ -980,10 +979,10 @@
      */
     public TextView getLabelView() {
         if (mLabelView == null) {
-            mLabelView = new TextView(mContext);
+            mLabelView = new TextView(getContext());
             mLabelView.setSingleLine(true);
             mLabelView.setEllipsize(getTextEllipsis());
-            mLabelView.setTextAppearance(mContext, R.style.TextAppearanceSmall);
+            mLabelView.setTextAppearance(getContext(), R.style.TextAppearanceSmall);
             if (mPhotoPosition == PhotoPosition.LEFT) {
                 //mLabelView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mCountViewTextSize);
                 mLabelView.setAllCaps(true);
@@ -1069,10 +1068,10 @@
      */
     public TextView getDataView() {
         if (mDataView == null) {
-            mDataView = new TextView(mContext);
+            mDataView = new TextView(getContext());
             mDataView.setSingleLine(true);
             mDataView.setEllipsize(getTextEllipsis());
-            mDataView.setTextAppearance(mContext, R.style.TextAppearanceSmall);
+            mDataView.setTextAppearance(getContext(), R.style.TextAppearanceSmall);
             mDataView.setActivated(isActivated());
             mDataView.setId(R.id.cliv_data_view);
             addView(mDataView);
@@ -1099,10 +1098,10 @@
      */
     public TextView getSnippetView() {
         if (mSnippetView == null) {
-            mSnippetView = new TextView(mContext);
+            mSnippetView = new TextView(getContext());
             mSnippetView.setSingleLine(true);
             mSnippetView.setEllipsize(getTextEllipsis());
-            mSnippetView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
+            mSnippetView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small);
             mSnippetView.setActivated(isActivated());
             addView(mSnippetView);
         }
@@ -1114,10 +1113,10 @@
      */
     public TextView getStatusView() {
         if (mStatusView == null) {
-            mStatusView = new TextView(mContext);
+            mStatusView = new TextView(getContext());
             mStatusView.setSingleLine(true);
             mStatusView.setEllipsize(getTextEllipsis());
-            mStatusView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
+            mStatusView.setTextAppearance(getContext(), android.R.style.TextAppearance_Small);
             mStatusView.setTextColor(mSecondaryTextColor);
             mStatusView.setActivated(isActivated());
             mStatusView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
@@ -1131,10 +1130,10 @@
      */
     public TextView getCountView() {
         if (mCountView == null) {
-            mCountView = new TextView(mContext);
+            mCountView = new TextView(getContext());
             mCountView.setSingleLine(true);
             mCountView.setEllipsize(getTextEllipsis());
-            mCountView.setTextAppearance(mContext, android.R.style.TextAppearance_Medium);
+            mCountView.setTextAppearance(getContext(), android.R.style.TextAppearance_Medium);
             mCountView.setTextColor(R.color.people_app_theme_color);
             addView(mCountView);
         }
@@ -1180,7 +1179,7 @@
     public void setPresence(Drawable icon) {
         if (icon != null) {
             if (mPresenceIcon == null) {
-                mPresenceIcon = new ImageView(mContext);
+                mPresenceIcon = new ImageView(getContext());
                 addView(mPresenceIcon);
             }
             mPresenceIcon.setImageDrawable(icon);
@@ -1205,7 +1204,7 @@
         // no guarantee that when the quick contact is initialized the display name is already set,
         // do it here too.
         if (mQuickContact != null) {
-            mQuickContact.setContentDescription(mContext.getString(
+            mQuickContact.setContentDescription(getContext().getString(
                     R.string.description_quick_contact_for, mNameTextView.getText()));
         }
     }
@@ -1537,10 +1536,15 @@
         // If the touch event's coordinates are not within the view's header, then delegate
         // to super.onTouchEvent so that regular view behavior is preserved. Otherwise, consume
         // and ignore the touch event.
-        if (mBoundsWithoutHeader.contains((int) x, (int) y) || !pointInView(x, y, 0)) {
+        if (mBoundsWithoutHeader.contains((int) x, (int) y) || !pointIsInView(x, y)) {
             return super.onTouchEvent(event);
         } else {
             return true;
         }
     }
+
+    private final boolean pointIsInView(float localX, float localY) {
+        return localX >= 0 && localX < (mRight - mLeft)
+                && localY >= 0 && localY < (mBottom - mTop);
+    }
 }
diff --git a/src/com/android/contacts/common/list/ContactListPinnedHeaderView.java b/src/com/android/contacts/common/list/ContactListPinnedHeaderView.java
index ea52822..401b3e3 100644
--- a/src/com/android/contacts/common/list/ContactListPinnedHeaderView.java
+++ b/src/com/android/contacts/common/list/ContactListPinnedHeaderView.java
@@ -29,6 +29,7 @@
 import android.widget.TextView;
 
 import com.android.contacts.common.R;
+import com.android.contacts.common.util.ViewUtil;
 
 /**
  * A custom view for the pinned section header shown at the top of the contact list.
@@ -123,7 +124,7 @@
         int leftCountTextView = 0;
         int rightCountTextView = 0;
 
-        if (isLayoutRtl()) {
+        if (ViewUtil.isViewLayoutRtl(this)) {
             rightHeaderTextView = width - mPaddingRight - mHeaderTextIndent;
             leftHeaderTextView = rightHeaderTextView - mHeaderTextView.getMeasuredWidth();
 
diff --git a/src/com/android/contacts/common/list/ContactTilePhoneFrequentView.java b/src/com/android/contacts/common/list/ContactTilePhoneFrequentView.java
index 742ce1c..aec93ab 100644
--- a/src/com/android/contacts/common/list/ContactTilePhoneFrequentView.java
+++ b/src/com/android/contacts/common/list/ContactTilePhoneFrequentView.java
@@ -65,8 +65,7 @@
                 if (TextUtils.isEmpty(mPhoneNumberString)) {
                     // Copy "superclass" implementation
                     mListener.onContactSelected(getLookupUri(), MoreContactUtils
-                            .getTargetRectFromView(
-                                    mContext, ContactTilePhoneFrequentView.this));
+                            .getTargetRectFromView(ContactTilePhoneFrequentView.this));
                 } else {
                     // When you tap a frequently-called contact, you want to
                     // call them at the number that you usually talk to them
diff --git a/src/com/android/contacts/common/list/ContactTileView.java b/src/com/android/contacts/common/list/ContactTileView.java
index 4645f78..a7d3d35 100644
--- a/src/com/android/contacts/common/list/ContactTileView.java
+++ b/src/com/android/contacts/common/list/ContactTileView.java
@@ -78,7 +78,7 @@
                 if (mListener == null) return;
                 mListener.onContactSelected(
                         getLookupUri(),
-                        MoreContactUtils.getTargetRectFromView(mContext, ContactTileView.this));
+                        MoreContactUtils.getTargetRectFromView(ContactTileView.this));
             }
         };
     }
diff --git a/src/com/android/contacts/common/list/PinnedHeaderListView.java b/src/com/android/contacts/common/list/PinnedHeaderListView.java
index db247b3..8d34981 100644
--- a/src/com/android/contacts/common/list/PinnedHeaderListView.java
+++ b/src/com/android/contacts/common/list/PinnedHeaderListView.java
@@ -30,6 +30,8 @@
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.ListAdapter;
 
+import com.android.contacts.common.util.ViewUtil;
+
 /**
  * A ListView that maintains a header pinned at the top of the list. The
  * pinned header can be pushed up and dissolved as needed.
@@ -543,7 +545,7 @@
         if (header.visible) {
             View view = header.view;
             int saveCount = canvas.save();
-            canvas.translate(isLayoutRtl() ?
+            canvas.translate(ViewUtil.isViewLayoutRtl(this) ?
                     getWidth() - mHeaderPaddingStart - mHeaderWidth : mHeaderPaddingStart,
                     header.y);
             if (header.state == FADING) {
diff --git a/src/com/android/contacts/common/list/ShortcutIntentBuilder.java b/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
index 3189e9c..21819bb 100644
--- a/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
@@ -352,7 +352,7 @@
 
         // Now draw the overlay
         Drawable overlay = mContext.getResources().getDrawableForDensity(
-                com.android.internal.R.drawable.quickcontact_badge_overlay_dark, mIconDensity);
+                R.drawable.quickcontact_badge_overlay_dark, mIconDensity);
 
         overlay.setBounds(dst);
         overlay.draw(canvas);
@@ -412,7 +412,7 @@
 
             final float sidePadding = mBorderWidth;
             overlay = TextUtils.ellipsize(overlay, textPaint, mIconSize - 2 * sidePadding,
-                    TruncateAt.END_SMALL);
+                    TruncateAt.END);
             final float textWidth = textPaint.measureText(overlay, 0, overlay.length());
             canvas.drawText(overlay, 0, overlay.length(), (mIconSize - textWidth) / 2, mIconSize
                     - fmi.descent - textPadding, textPaint);
diff --git a/src/com/android/contacts/common/model/account/AccountType.java b/src/com/android/contacts/common/model/account/AccountType.java
index cfafa79..53ab47d 100644
--- a/src/com/android/contacts/common/model/account/AccountType.java
+++ b/src/com/android/contacts/common/model/account/AccountType.java
@@ -197,16 +197,6 @@
         return null;
     }
 
-    /** Returns an optional Activity string that can be used to view the stream item. */
-    public String getViewStreamItemActivity() {
-        return null;
-    }
-
-    /** Returns an optional Activity string that can be used to view the stream item photo. */
-    public String getViewStreamItemPhotoActivity() {
-        return null;
-    }
-
     public CharSequence getDisplayLabel(Context context) {
         // Note this resource is defined in the sync adapter package, not resourcePackageName.
         return getResourceText(context, syncAdapterPackageName, titleRes, accountType);
diff --git a/src/com/android/contacts/common/model/account/ExternalAccountType.java b/src/com/android/contacts/common/model/account/ExternalAccountType.java
index f6ab375..0097592 100644
--- a/src/com/android/contacts/common/model/account/ExternalAccountType.java
+++ b/src/com/android/contacts/common/model/account/ExternalAccountType.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 import android.util.Xml;
 
+import com.android.contacts.common.R;
 import com.android.contacts.common.model.dataitem.DataKind;
 import com.google.common.annotations.VisibleForTesting;
 
@@ -61,9 +62,6 @@
     private static final String ATTR_VIEW_CONTACT_NOTIFY_SERVICE = "viewContactNotifyService";
     private static final String ATTR_VIEW_GROUP_ACTIVITY = "viewGroupActivity";
     private static final String ATTR_VIEW_GROUP_ACTION_LABEL = "viewGroupActionLabel";
-    private static final String ATTR_VIEW_STREAM_ITEM_ACTIVITY = "viewStreamItemActivity";
-    private static final String ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY =
-            "viewStreamItemPhotoActivity";
     private static final String ATTR_DATA_SET = "dataSet";
     private static final String ATTR_EXTENSION_PACKAGE_NAMES = "extensionPackageNames";
 
@@ -84,8 +82,6 @@
     private String mViewGroupActivity;
     private String mViewGroupLabelAttribute;
     private int mViewGroupLabelResId;
-    private String mViewStreamItemActivity;
-    private String mViewStreamItemPhotoActivity;
     private List<String> mExtensionPackageNames;
     private String mAccountTypeLabelAttribute;
     private String mAccountTypeIconAttribute;
@@ -265,16 +261,6 @@
     }
 
     @Override
-    public String getViewStreamItemActivity() {
-        return mViewStreamItemActivity;
-    }
-
-    @Override
-    public String getViewStreamItemPhotoActivity() {
-        return mViewStreamItemPhotoActivity;
-    }
-
-    @Override
     public List<String> getExtensionPackageNames() {
         return mExtensionPackageNames;
     }
@@ -327,10 +313,6 @@
                     mViewGroupActivity = value;
                 } else if (ATTR_VIEW_GROUP_ACTION_LABEL.equals(attr)) {
                     mViewGroupLabelAttribute = value;
-                } else if (ATTR_VIEW_STREAM_ITEM_ACTIVITY.equals(attr)) {
-                    mViewStreamItemActivity = value;
-                } else if (ATTR_VIEW_STREAM_ITEM_PHOTO_ACTIVITY.equals(attr)) {
-                    mViewStreamItemPhotoActivity = value;
                 } else if (ATTR_DATA_SET.equals(attr)) {
                     dataSet = value;
                 } else if (ATTR_EXTENSION_PACKAGE_NAMES.equals(attr)) {
@@ -362,21 +344,19 @@
                     parseEditSchema(context, parser, attrs);
                 } else if (TAG_CONTACTS_DATA_KIND.equals(tag)) {
                     final TypedArray a = context.obtainStyledAttributes(attrs,
-                            android.R.styleable.ContactsDataKind);
+                            R.styleable.ContactsDataKind);
                     final DataKind kind = new DataKind();
 
                     kind.mimeType = a
-                            .getString(android.R.styleable.ContactsDataKind_mimeType);
+                            .getString(R.styleable.ContactsDataKind_android_mimeType);
                     final String summaryColumn = a.getString(
-                            android.R.styleable.ContactsDataKind_summaryColumn);
+                            R.styleable.ContactsDataKind_android_summaryColumn);
                     if (summaryColumn != null) {
                         // Inflate a specific column as summary when requested
                         kind.actionHeader = new SimpleInflater(summaryColumn);
                     }
-
                     final String detailColumn = a.getString(
-                            android.R.styleable.ContactsDataKind_detailColumn);
-
+                            R.styleable.ContactsDataKind_android_detailColumn);
                     if (detailColumn != null) {
                         // Inflate specific column as summary
                         kind.actionBody = new SimpleInflater(detailColumn);
diff --git a/src/com/android/contacts/common/model/account/GoogleAccountType.java b/src/com/android/contacts/common/model/account/GoogleAccountType.java
index 33a8f63..7d43e64 100644
--- a/src/com/android/contacts/common/model/account/GoogleAccountType.java
+++ b/src/com/android/contacts/common/model/account/GoogleAccountType.java
@@ -18,6 +18,7 @@
 
 import android.content.ContentValues;
 import android.content.Context;
+import android.os.SystemProperties;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Event;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -37,7 +38,7 @@
     public static final String ACCOUNT_TYPE = "com.google";
 
     private static final List<String> mExtensionPackages =
-            Lists.newArrayList("com.google.android.apps.plus");
+            Lists.newArrayList(getPlusExtensionPackageName());
 
     public GoogleAccountType(Context context, String authenticatorPackageName) {
         this.accountType = ACCOUNT_TYPE;
@@ -194,4 +195,26 @@
     public String getViewContactNotifyServicePackageName() {
         return "com.google.android.syncadapters.contacts";
     }
+
+    /**
+     * The package name that we should load contacts.xml from and rely on to handle
+     * G+ account actions. In the future, this will be gmscore by default. In the
+     * mean time, we will rely on G+ app by default and use gmscore only for testing.
+     *
+     * STOPSHIP: remove this and use the gmscore package (b/13033233). This can be done after
+     * CP2 sync is handed over from G+ app to gmscore.
+     */
+    private static String getPlusExtensionPackageName() {
+        final String USE_GMS_EXTENSION_PACKAGE_SYSTEM_PROPERTY
+                = "persist.contacts.use_gms_ext";
+        final String GMS_CORE_PACKAGE = "com.google.android.gms";
+        final String G_PLUS_APP_PACKAGE = "com.google.android.apps.plus";
+        final int shouldUseGmsExtensionPackage = SystemProperties.getInt(
+                USE_GMS_EXTENSION_PACKAGE_SYSTEM_PROPERTY, 0);
+        if (shouldUseGmsExtensionPackage == 0) {
+            return G_PLUS_APP_PACKAGE;
+        } else {
+            return GMS_CORE_PACKAGE;
+        }
+    }
 }
diff --git a/src/com/android/contacts/common/util/ContactDisplayUtils.java b/src/com/android/contacts/common/util/ContactDisplayUtils.java
index 7817d90..7ec751a 100644
--- a/src/com/android/contacts/common/util/ContactDisplayUtils.java
+++ b/src/com/android/contacts/common/util/ContactDisplayUtils.java
@@ -22,7 +22,8 @@
 import android.util.Log;
 
 import com.android.contacts.common.R;
-import com.android.internal.util.Preconditions;
+
+import com.google.common.base.Preconditions;
 
 /**
  * Methods for handling various contact data labels.
diff --git a/src/com/android/contacts/common/util/LocalizedNameResolver.java b/src/com/android/contacts/common/util/LocalizedNameResolver.java
index f8d8151..3c21946 100644
--- a/src/com/android/contacts/common/util/LocalizedNameResolver.java
+++ b/src/com/android/contacts/common/util/LocalizedNameResolver.java
@@ -31,6 +31,8 @@
 import android.util.Log;
 import android.util.Xml;
 
+import com.android.contacts.common.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -118,11 +120,11 @@
                 String name = parser.getName();
                 if (type == XmlPullParser.START_TAG && CONTACTS_DATA_KIND.equals(name)) {
                     final TypedArray typedArray = context.obtainStyledAttributes(attrs,
-                            android.R.styleable.ContactsDataKind);
+                            R.styleable.ContactsDataKind);
                     try {
                         // See if a string has been hardcoded directly into the xml
                         final String nonResourceString = typedArray.getNonResourceString(
-                                android.R.styleable.ContactsDataKind_allContactsName);
+                                R.styleable.ContactsDataKind_android_allContactsName);
                         if (nonResourceString != null) {
                             return nonResourceString;
                         }
@@ -130,7 +132,7 @@
                         // See if a resource is referenced. We can't rely on getString
                         // to automatically resolve it as the resource lives in a different package
                         int id = typedArray.getResourceId(
-                                android.R.styleable.ContactsDataKind_allContactsName, 0);
+                                R.styleable.ContactsDataKind_android_allContactsName, 0);
                         if (id == 0) return null;
 
                         // Resolve the resource Id
diff --git a/src/com/android/contacts/common/util/MemoryUtils.java b/src/com/android/contacts/common/util/MemoryUtils.java
deleted file mode 100644
index 033f4f2..0000000
--- a/src/com/android/contacts/common/util/MemoryUtils.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.common.util;
-
-import com.android.internal.util.MemInfoReader;
-
-public final class MemoryUtils {
-    private MemoryUtils() {
-    }
-
-    private static long sTotalMemorySize = -1;
-
-    public static long getTotalMemorySize() {
-        if (sTotalMemorySize < 0) {
-            MemInfoReader reader = new MemInfoReader();
-            reader.readMemInfo();
-
-            // getTotalSize() returns the "MemTotal" value from /proc/meminfo.
-            // Because the linux kernel doesn't see all the RAM on the system (e.g. GPU takes some),
-            // this is usually smaller than the actual RAM size.
-            sTotalMemorySize = reader.getTotalSize();
-        }
-        return sTotalMemorySize;
-    }
-}
diff --git a/src/com/android/contacts/common/util/PhoneNumberHelper.java b/src/com/android/contacts/common/util/PhoneNumberHelper.java
new file mode 100644
index 0000000..2cbfce7
--- /dev/null
+++ b/src/com/android/contacts/common/util/PhoneNumberHelper.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.common.util;
+
+import android.content.Context;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+import com.google.i18n.phonenumbers.ShortNumberInfo;
+
+import java.util.Locale;
+
+/**
+ * This class wraps several PhoneNumberUtil calls and TelephonyManager calls. Some of them are
+ * the same as the ones in the framework's code base. We can remove those once they are part of
+ * the public API.
+ */
+public class PhoneNumberHelper {
+
+    private static final String LOG_TAG = PhoneNumberHelper.class.getSimpleName();
+
+    /**
+     * Returns whether a number is an emergency number given the location.
+     * @param number Phone number
+     * @param context Application context
+     * @return True if the number is an emergency number in the location. False otherwise
+     *
+     * Differences introduced due to unbundling:
+     *
+     * ecclist property is set by the Android Radio Interface Library to contain a list of valid
+     * Emergency call codes (See {@link PhoneNumberUtils.isEmergencyNumber(String)}).
+     * Before if the ecclist property is not empty but does not contain the
+     * number, the number will be immediately considered as not an emergency number. However, after
+     * unbundling and formatting like this, if the number is not listed in the *non-empty* ecclist
+     * property, we still check it with libphonenumber to see whether they think this is an
+     * emergency number.
+     *
+     * TODO: Remove if PhoneNumberUtils.isLocalEmergencyNumber(String number, Context context)
+     * is made public.
+     */
+    public static boolean isLocalEmergencyNumber(String number, Context context) {
+        if (number == null) {
+            return false;
+        }
+
+        final Locale locale = context.getResources().getConfiguration().locale;
+        String countryIso = TelephonyManagerUtils.getCurrentCountryIso(context, locale);
+
+        if (PhoneNumberUtils.isEmergencyNumber(number)) {
+            // If the number is listed in system properties, return true
+            return true;
+        }
+
+        // No ecclist system property, or the ecclist system property does not contain the
+        // number, so use our own list.
+        if (countryIso == null) {
+            return ("112".equals(number) || "911".equals(number));
+        } else {
+            ShortNumberInfo util = ShortNumberInfo.getInstance();
+            return util.isEmergencyNumber(number, countryIso);
+        }
+    }
+
+    /**
+     * Determines if the specified number is actually a URI (i.e. a SIP address) rather than a
+     * regular PSTN phone number, based on whether or not the number contains an "@" character.
+     *
+     * @param number Phone number
+     * @return true if number contains @
+     *
+     * TODO: Remove if PhoneNumberUtils.isUriNumber(String number) is made public.
+     */
+    public static boolean isUriNumber(String number) {
+        // Note we allow either "@" or "%40" to indicate a URI, in case
+        // the passed-in string is URI-escaped.  (Neither "@" nor "%40"
+        // will ever be found in a legal PSTN number.)
+        return number != null && (number.contains("@") || number.contains("%40"));
+    }
+
+    /**
+     * Formats the phone number only if the given number hasn't been formatted.
+     * <p>
+     * The number which has only dailable character is treated as not being
+     * formatted.
+     *
+     * @param phoneNumber the number to be formatted.
+     * @param phoneNumberE164 The E164 format number whose country code is used if the given
+     * phoneNumber doesn't have the country code.
+     * @param defaultCountryIso The ISO 3166-1 two letters country code whose convention will
+     * be used if the phoneNumberE164 is null or invalid, or if phoneNumber contains IDD.
+     * @return The formatted number if the given number has been formatted, otherwise, return the 
+     * given number.
+     *
+     * TODO: Remove if PhoneNumberUtils.formatNumber(String phoneNumber, String phoneNumberE164,
+     * String defaultCountryIso) is made public.
+     */
+    public static String formatNumber(
+            String phoneNumber, String phoneNumberE164, String defaultCountryIso) {
+        int len = phoneNumber.length();
+        for (int i = 0; i < len; i++) {
+            if (!PhoneNumberUtils.isDialable(phoneNumber.charAt(i))) {
+                return phoneNumber;
+            }
+        }
+        PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+        // Get the country code from phoneNumberE164
+        if (phoneNumberE164 != null && phoneNumberE164.length() >= 2
+                && phoneNumberE164.charAt(0) == '+') {
+            try {
+                // The number to be parsed is in E164 format, so the default region used doesn't
+                // matter.
+                PhoneNumber pn = util.parse(phoneNumberE164, "ZZ");
+                String regionCode = util.getRegionCodeForNumber(pn);
+                if (!TextUtils.isEmpty(regionCode) &&
+                        // This makes sure phoneNumber doesn't contain an IDD
+                        normalizeNumber(phoneNumber).indexOf(phoneNumberE164.substring(1)) <= 0) {
+                    defaultCountryIso = regionCode;
+                }
+            } catch (NumberParseException e) {
+                Log.w(LOG_TAG, "The number could not be parsed in E164 format!");
+            }
+        }
+
+        String result = formatNumber(phoneNumber, defaultCountryIso);
+        return result == null ? phoneNumber : result;
+    }
+
+    /**
+     * Format a phone number.
+     * <p>
+     * If the given number doesn't have the country code, the phone will be
+     * formatted to the default country's convention.
+     *
+     * @param phoneNumber The number to be formatted.
+     * @param defaultCountryIso The ISO 3166-1 two letters country code whose convention will
+     * be used if the given number doesn't have the country code.
+     * @return The formatted number, or null if the given number is not valid.
+     *
+     * TODO: Remove if PhoneNumberUtils.formatNumber(String phoneNumber, String defaultCountryIso)
+     * is made public.
+     */
+    public static String formatNumber(String phoneNumber, String defaultCountryIso) {
+        // Do not attempt to format numbers that start with a hash or star symbol.
+        if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) {
+            return phoneNumber;
+        }
+
+        final PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+        String result = null;
+        try {
+            PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
+            result = util.formatInOriginalFormat(pn, defaultCountryIso);
+        } catch (NumberParseException e) {
+            Log.w(LOG_TAG, "Number could not be parsed with the given country code!");
+        }
+        return result;
+    }
+
+    /**
+     * Normalize a phone number by removing the characters other than digits. If
+     * the given number has keypad letters, the letters will be converted to
+     * digits first.
+     *
+     * @param phoneNumber The number to be normalized.
+     * @return The normalized number.
+     *
+     * TODO: Remove if PhoneNumberUtils.normalizeNumber(String phoneNumber) is made public.
+     */
+    public static String normalizeNumber(String phoneNumber) {
+        StringBuilder sb = new StringBuilder();
+        int len = phoneNumber.length();
+        for (int i = 0; i < len; i++) {
+            char c = phoneNumber.charAt(i);
+            // Character.digit() supports ASCII and Unicode digits (fullwidth, Arabic-Indic, etc.)
+            int digit = Character.digit(c, 10);
+            if (digit != -1) {
+                sb.append(digit);
+            } else if (i == 0 && c == '+') {
+                sb.append(c);
+            } else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+                return normalizeNumber(PhoneNumberUtils.convertKeypadLettersToDigits(phoneNumber));
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * @return the "username" part of the specified SIP address, i.e. the part before the "@"
+     * character (or "%40").
+     *
+     * @param number SIP address of the form "username@domainname" (or the URI-escaped equivalent
+     * "username%40domainname")
+     *
+     * TODO: Remove if PhoneNumberUtils.getUsernameFromUriNumber(String number) is made public.
+     */
+    public static String getUsernameFromUriNumber(String number) {
+        // The delimiter between username and domain name can be
+        // either "@" or "%40" (the URI-escaped equivalent.)
+        int delimiterIndex = number.indexOf('@');
+        if (delimiterIndex < 0) {
+            delimiterIndex = number.indexOf("%40");
+        }
+        if (delimiterIndex < 0) {
+            Log.w(LOG_TAG,
+                    "getUsernameFromUriNumber: no delimiter found in SIP addr '" + number + "'");
+            return number;
+        }
+        return number.substring(0, delimiterIndex);
+    }
+}
diff --git a/src/com/android/contacts/common/util/TelephonyManagerUtils.java b/src/com/android/contacts/common/util/TelephonyManagerUtils.java
new file mode 100644
index 0000000..d01f599
--- /dev/null
+++ b/src/com/android/contacts/common/util/TelephonyManagerUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.common.util;
+
+import android.content.Context;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Locale;
+
+/**
+ * This class provides several TelephonyManager util functions.
+ */
+public class TelephonyManagerUtils {
+
+    private static final String LOG_TAG = TelephonyManagerUtils.class.getSimpleName();
+
+    /**
+     * Gets the voicemail tag from Telephony Manager.
+     * @param context Current application context
+     * @return Voicemail tag, the alphabetic identifier associated with the voice mail number.
+     */
+    public static String getVoiceMailAlphaTag(Context context) {
+        final TelephonyManager telephonyManager =
+                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        final String voiceMailLabel = telephonyManager.getVoiceMailAlphaTag();
+        return voiceMailLabel;
+    }
+
+   /**
+    * Checks a given number against the voicemail number provided by the RIL and SIM card. The
+    * caller must have the READ_PHONE_STATE credential.
+    *
+    * @param number the number to look up.
+    * @return true if the number is in the list of voicemail. False
+    * otherwise, including if the caller does not have the permission
+    * to read the VM number.
+    *
+    * TODO: Remove if PhoneNumberUtils.isVoiceMailNumber(String number) is made public.
+    */
+    public static boolean isVoiceMailNumber(String number, Context context) {
+       String vmNumber;
+       final TelephonyManager telephonyManager =
+           (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+       try {
+           vmNumber = telephonyManager.getVoiceMailNumber();
+       } catch (SecurityException ex) {
+           Log.w(LOG_TAG, "SecurtyException: could not get voicemail number.");
+           return false;
+       }
+
+       // Strip the separators from the number before comparing it to the list.
+       number = PhoneNumberUtils.extractNetworkPortion(number);
+
+       // The "compare" API tolerates null so we need to make sure that we don't return true
+       // when both are null.
+       return !TextUtils.isEmpty(number) && PhoneNumberUtils.compare(number, vmNumber);
+    }
+
+    /**
+     * @return The ISO 3166-1 two letters country code of the country the user
+     *         is in based on the network location. If the network location does not exist, fall
+     *         back to the locale setting.
+     */
+    public static String getCurrentCountryIso(Context context, Locale locale) {
+        // Without framework function calls, this seems to be the most accurate location service
+        // we can rely on.
+        final TelephonyManager telephonyManager =
+            (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        String countryIso = telephonyManager.getNetworkCountryIso();
+
+        if (countryIso == null) {
+            countryIso = locale.getCountry();
+            Log.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: "
+                    + countryIso);
+        }
+        return countryIso;
+    }
+}
diff --git a/src/com/android/contacts/common/util/ViewUtil.java b/src/com/android/contacts/common/util/ViewUtil.java
index 190075a..fadb3de 100644
--- a/src/com/android/contacts/common/util/ViewUtil.java
+++ b/src/com/android/contacts/common/util/ViewUtil.java
@@ -39,4 +39,14 @@
         }
         return p.width;
     }
+
+    /**
+     * Returns a boolean indicating whether or not the view's layout direction is RTL
+     *
+     * @param view - A valid view
+     * @return True if the view's layout direction is RTL
+     */
+    public static boolean isViewLayoutRtl(View view) {
+        return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+    }
 }
diff --git a/src/com/android/contacts/common/vcard/ExportProcessor.java b/src/com/android/contacts/common/vcard/ExportProcessor.java
index 0d5c2f3..791f2f9 100644
--- a/src/com/android/contacts/common/vcard/ExportProcessor.java
+++ b/src/com/android/contacts/common/vcard/ExportProcessor.java
@@ -138,9 +138,7 @@
             // composer = new VCardComposer(ExportVCardActivity.this, vcardType, true);
 
             writer = new BufferedWriter(new OutputStreamWriter(outputStream));
-            final Uri contentUriForRawContactsEntity = RawContactsEntity.CONTENT_URI.buildUpon()
-                    .appendQueryParameter(RawContactsEntity.FOR_EXPORT_ONLY, "1")
-                    .build();
+            final Uri contentUriForRawContactsEntity = RawContactsEntity.CONTENT_URI;
             // TODO: should provide better selection.
             if (!composer.init(Contacts.CONTENT_URI, new String[] {Contacts._ID},
                     null, null,