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,