Merge "Improve analytics" into lmp-mr1-dev
diff --git a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
index 437d855..c6483cc 100644
--- a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
@@ -304,12 +304,12 @@
private static class AdapterEntry {
public final String mLabel;
public final int mChoiceResourceId;
- public final long mSubscriptionId;
+ public final int mSubscriptionId;
- public AdapterEntry(String label, int resId, long subscriptionId) {
+ public AdapterEntry(String label, int resId, int subId) {
mLabel = label;
mChoiceResourceId = resId;
- mSubscriptionId = subscriptionId;
+ mSubscriptionId = subId;
}
public AdapterEntry(String label, int resId) {
diff --git a/src/com/android/contacts/common/list/ContactListItemView.java b/src/com/android/contacts/common/list/ContactListItemView.java
index e5de1f4..d90af13 100644
--- a/src/com/android/contacts/common/list/ContactListItemView.java
+++ b/src/com/android/contacts/common/list/ContactListItemView.java
@@ -49,6 +49,7 @@
import com.android.contacts.common.ContactStatusUtil;
import com.android.contacts.common.R;
import com.android.contacts.common.format.TextHighlighter;
+import com.android.contacts.common.util.ContactDisplayUtils;
import com.android.contacts.common.util.SearchUtil;
import com.android.contacts.common.util.ViewUtil;
@@ -1038,6 +1039,13 @@
} else {
mTextHighlighter.setPrefixText(getSnippetView(), text, mHighlightedPrefix);
mSnippetView.setVisibility(VISIBLE);
+ if (ContactDisplayUtils.isPossiblePhoneNumber(text)) {
+ // Give the text-to-speech engine a hint that it's a phone number
+ mSnippetView.setContentDescription(
+ ContactDisplayUtils.getTelephoneTtsSpannable(text));
+ } else {
+ mSnippetView.setContentDescription(null);
+ }
}
}
@@ -1149,6 +1157,14 @@
name = mUnknownNameText;
}
setMarqueeText(getNameTextView(), name);
+
+ if (ContactDisplayUtils.isPossiblePhoneNumber(name)) {
+ // Give the text-to-speech engine a hint that it's a phone number
+ mNameTextView.setContentDescription(
+ ContactDisplayUtils.getTelephoneTtsSpannable(name.toString()));
+ } else {
+ mNameTextView.setContentDescription(null);
+ }
}
public void hideDisplayName() {
diff --git a/src/com/android/contacts/common/list/ViewPagerTabs.java b/src/com/android/contacts/common/list/ViewPagerTabs.java
index ec95de6..006d632 100644
--- a/src/com/android/contacts/common/list/ViewPagerTabs.java
+++ b/src/com/android/contacts/common/list/ViewPagerTabs.java
@@ -198,7 +198,12 @@
@Override
public void onPageSelected(int position) {
position = getRtlPosition(position);
- if (mPrevSelected >= 0) {
+ int tabStripChildCount = mTabStrip.getChildCount();
+ if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) {
+ return;
+ }
+
+ if (mPrevSelected >= 0 && mPrevSelected < tabStripChildCount) {
mTabStrip.getChildAt(mPrevSelected).setSelected(false);
}
final View selectedChild = mTabStrip.getChildAt(position);
diff --git a/src/com/android/contacts/common/model/account/BaseAccountType.java b/src/com/android/contacts/common/model/account/BaseAccountType.java
index 984cb78..648a6dc 100644
--- a/src/com/android/contacts/common/model/account/BaseAccountType.java
+++ b/src/com/android/contacts/common/model/account/BaseAccountType.java
@@ -99,20 +99,20 @@
static final String TYPE = "type";
}
- private interface Weight {
+ protected interface Weight {
static final int NONE = -1;
- static final int ORGANIZATION = 5;
static final int PHONE = 10;
static final int EMAIL = 15;
- static final int IM = 20;
static final int STRUCTURED_POSTAL = 25;
- static final int NOTE = 110;
- static final int NICKNAME = 115;
- static final int WEBSITE = 120;
- static final int SIP_ADDRESS = 130;
- static final int EVENT = 150;
- static final int RELATIONSHIP = 160;
- static final int GROUP_MEMBERSHIP = 999;
+ static final int NICKNAME = 111;
+ static final int EVENT = 120;
+ static final int ORGANIZATION = 125;
+ static final int NOTE = 130;
+ static final int IM = 140;
+ static final int SIP_ADDRESS = 145;
+ static final int GROUP_MEMBERSHIP = 150;
+ static final int WEBSITE = 160;
+ static final int RELATIONSHIP = 999;
}
public BaseAccountType() {
@@ -148,7 +148,7 @@
protected DataKind addDataKindStructuredName(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
- R.string.nameLabelsGroup, -1, true));
+ R.string.nameLabelsGroup, Weight.NONE, true));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
kind.typeOverallMax = 1;
@@ -178,7 +178,7 @@
protected DataKind addDataKindDisplayName(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
- R.string.nameLabelsGroup, -1, true));
+ R.string.nameLabelsGroup, Weight.NONE, true));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
kind.typeOverallMax = 1;
@@ -219,7 +219,7 @@
protected DataKind addDataKindPhoneticName(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
- R.string.name_phonetic, -1, true));
+ R.string.name_phonetic, Weight.NONE, true));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
kind.typeOverallMax = 1;
@@ -239,7 +239,7 @@
protected DataKind addDataKindNickname(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,
- R.string.nicknameLabelsGroup, 115, true));
+ R.string.nicknameLabelsGroup, Weight.NICKNAME, true));
kind.typeOverallMax = 1;
kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -255,7 +255,7 @@
protected DataKind addDataKindPhone(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
- 10, true));
+ Weight.PHONE, true));
kind.iconAltRes = R.drawable.ic_text_holo_light;
kind.iconAltDescriptionRes = R.string.sms;
kind.actionHeader = new PhoneActionInflater();
@@ -294,7 +294,7 @@
protected DataKind addDataKindEmail(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE, R.string.emailLabelsGroup,
- 15, true));
+ Weight.EMAIL, true));
kind.actionHeader = new EmailActionInflater();
kind.actionBody = new SimpleInflater(Email.DATA);
kind.typeColumn = Email.TYPE;
@@ -314,7 +314,7 @@
protected DataKind addDataKindStructuredPostal(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE,
- R.string.postalLabelsGroup, 25, true));
+ R.string.postalLabelsGroup, Weight.STRUCTURED_POSTAL, true));
kind.actionHeader = new PostalActionInflater();
kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS);
kind.typeColumn = StructuredPostal.TYPE;
@@ -336,8 +336,8 @@
}
protected DataKind addDataKindIm(Context context) throws DefinitionException {
- DataKind kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup, 20,
- true));
+ DataKind kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup,
+ Weight.IM, true));
kind.actionHeader = new ImActionInflater();
kind.actionBody = new SimpleInflater(Im.DATA);
@@ -368,7 +368,7 @@
protected DataKind addDataKindOrganization(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE,
- R.string.organizationLabelsGroup, 5, true));
+ R.string.organizationLabelsGroup, Weight.ORGANIZATION, true));
kind.actionHeader = new SimpleInflater(R.string.organizationLabelsGroup);
kind.actionBody = ORGANIZATION_BODY_INFLATER;
kind.typeOverallMax = 1;
@@ -383,7 +383,7 @@
}
protected DataKind addDataKindPhoto(Context context) throws DefinitionException {
- DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, true));
+ DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, Weight.NONE, true));
kind.typeOverallMax = 1;
kind.fieldList = Lists.newArrayList();
kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1));
@@ -391,8 +391,8 @@
}
protected DataKind addDataKindNote(Context context) throws DefinitionException {
- DataKind kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE, R.string.label_notes, 110,
- true));
+ DataKind kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE, R.string.label_notes,
+ Weight.NOTE, true));
kind.typeOverallMax = 1;
kind.actionHeader = new SimpleInflater(R.string.label_notes);
kind.actionBody = new SimpleInflater(Note.NOTE);
@@ -406,7 +406,7 @@
protected DataKind addDataKindWebsite(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE,
- R.string.websiteLabelsGroup, 120, true));
+ R.string.websiteLabelsGroup, Weight.WEBSITE, true));
kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup);
kind.actionBody = new SimpleInflater(Website.URL);
kind.defaultValues = new ContentValues();
@@ -420,7 +420,7 @@
protected DataKind addDataKindSipAddress(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
- R.string.label_sip_address, 130, true));
+ R.string.label_sip_address, Weight.SIP_ADDRESS, true));
kind.typeOverallMax = 1;
kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
@@ -434,7 +434,7 @@
protected DataKind addDataKindGroupMembership(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(GroupMembership.CONTENT_ITEM_TYPE,
- R.string.groupsLabel, 999, true));
+ R.string.groupsLabel, Weight.GROUP_MEMBERSHIP, true));
kind.typeOverallMax = 1;
kind.fieldList = Lists.newArrayList();
diff --git a/src/com/android/contacts/common/model/account/ExchangeAccountType.java b/src/com/android/contacts/common/model/account/ExchangeAccountType.java
index 04b5263..7020836 100644
--- a/src/com/android/contacts/common/model/account/ExchangeAccountType.java
+++ b/src/com/android/contacts/common/model/account/ExchangeAccountType.java
@@ -80,7 +80,7 @@
@Override
protected DataKind addDataKindStructuredName(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
- R.string.nameLabelsGroup, -1, true));
+ R.string.nameLabelsGroup, Weight.NONE, true));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -109,7 +109,7 @@
@Override
protected DataKind addDataKindDisplayName(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
- R.string.nameLabelsGroup, -1, true));
+ R.string.nameLabelsGroup, Weight.NONE, true));
boolean displayOrderPrimary =
context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
@@ -142,7 +142,7 @@
@Override
protected DataKind addDataKindPhoneticName(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
- R.string.name_phonetic, -1, true));
+ R.string.name_phonetic, Weight.NONE, true));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -307,7 +307,7 @@
protected DataKind addDataKindEvent(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE, R.string.eventLabelsGroup,
- 150, true));
+ Weight.EVENT, true));
kind.actionHeader = new EventActionInflater();
kind.actionBody = new SimpleInflater(Event.START_DATE);
diff --git a/src/com/android/contacts/common/model/account/GoogleAccountType.java b/src/com/android/contacts/common/model/account/GoogleAccountType.java
index 8705ae3..6877187 100644
--- a/src/com/android/contacts/common/model/account/GoogleAccountType.java
+++ b/src/com/android/contacts/common/model/account/GoogleAccountType.java
@@ -122,7 +122,7 @@
private DataKind addDataKindRelation(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Relation.CONTENT_ITEM_TYPE,
- R.string.relationLabelsGroup, 160, true));
+ R.string.relationLabelsGroup, Weight.RELATIONSHIP, true));
kind.actionHeader = new RelationActionInflater();
kind.actionBody = new SimpleInflater(Relation.NAME);
@@ -157,7 +157,7 @@
private DataKind addDataKindEvent(Context context) throws DefinitionException {
DataKind kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE,
- R.string.eventLabelsGroup, 150, true));
+ R.string.eventLabelsGroup, Weight.EVENT, true));
kind.actionHeader = new EventActionInflater();
kind.actionBody = new SimpleInflater(Event.START_DATE);
diff --git a/src/com/android/contacts/common/util/AccountSelectionUtil.java b/src/com/android/contacts/common/util/AccountSelectionUtil.java
index 68217b9..da30e89 100644
--- a/src/com/android/contacts/common/util/AccountSelectionUtil.java
+++ b/src/com/android/contacts/common/util/AccountSelectionUtil.java
@@ -55,12 +55,12 @@
final private Context mContext;
final private int mResId;
- final private long mSubscriptionId;
+ final private int mSubscriptionId;
final protected List<AccountWithDataSet> mAccountList;
public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList,
- int resId, long subscriptionId) {
+ int resId, int subscriptionId) {
if (accountList == null || accountList.size() == 0) {
Log.e(LOG_TAG, "The size of Account list is 0.");
}
diff --git a/src/com/android/contacts/common/util/ContactDisplayUtils.java b/src/com/android/contacts/common/util/ContactDisplayUtils.java
index 7ec751a..24bb6ef 100644
--- a/src/com/android/contacts/common/util/ContactDisplayUtils.java
+++ b/src/com/android/contacts/common/util/ContactDisplayUtils.java
@@ -19,10 +19,18 @@
import static android.provider.ContactsContract.CommonDataKinds.Phone;
import android.content.Context;
+import android.telephony.PhoneNumberUtils;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.TtsSpan;
import android.util.Log;
+import android.util.Patterns;
import com.android.contacts.common.R;
+import com.android.i18n.phonenumbers.NumberParseException;
+import com.android.i18n.phonenumbers.PhoneNumberUtil;
+import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.google.common.base.Preconditions;
/**
@@ -187,4 +195,74 @@
}
}
+ /**
+ * Whether the given text could be a phone number.
+ *
+ * Note this will miss many things that are legitimate phone numbers, for example,
+ * phone numbers with letters.
+ */
+ public static boolean isPossiblePhoneNumber(CharSequence text) {
+ return text == null ? false : Patterns.PHONE.matcher(text.toString()).matches();
+ }
+
+ /**
+ * Returns a Spannable for the given phone number with a telephone {@link TtsSpan} set over
+ * the entire length of the given phone number.
+ */
+ public static Spannable getTelephoneTtsSpannable(String phoneNumber) {
+ final Spannable spannable = new SpannableString(phoneNumber);
+ final TtsSpan ttsSpan = getTelephoneTtsSpan(phoneNumber);
+ spannable.setSpan(ttsSpan, 0, phoneNumber.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ return spannable;
+ }
+
+ /**
+ * Returns a Spannable for the given message with a telephone {@link TtsSpan} set for
+ * the given phone number text wherever it is found within the message.
+ */
+ public static Spannable getTelephoneTtsSpannable(String message, String phoneNumber) {
+ final Spannable spannable = new SpannableString(message);
+ int start = message.indexOf(phoneNumber);
+ while (start >= 0) {
+ final int end = start + phoneNumber.length();
+ final TtsSpan ttsSpan = getTelephoneTtsSpan(phoneNumber);
+ spannable.setSpan(ttsSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ start = message.indexOf(phoneNumber, end);
+ }
+ return spannable;
+ }
+
+ /**
+ * Returns a telephone {@link TtsSpan} for the given phone number.
+ */
+ public static TtsSpan getTelephoneTtsSpan(String phoneNumberString) {
+ if (phoneNumberString == null) {
+ throw new NullPointerException();
+ }
+
+ // Parse the phone number
+ final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+ PhoneNumber phoneNumber = null;
+ try {
+ // Don't supply a defaultRegion so this fails for non-international numbers because
+ // we don't want to TalkBalk to read a country code (e.g. +1) if it is not already
+ // present
+ phoneNumber = phoneNumberUtil.parse(phoneNumberString, /* defaultRegion */ null);
+ } catch (NumberParseException ignored) {
+ }
+
+ // Build a telephone tts span
+ final TtsSpan.TelephoneBuilder builder = new TtsSpan.TelephoneBuilder();
+ if (phoneNumber == null) {
+ // Strip separators otherwise TalkBack will be silent
+ // (this behavior was observed with TalkBalk 4.0.2 from their alpha channel)
+ builder.setNumberParts(PhoneNumberUtils.stripSeparators(phoneNumberString));
+ } else {
+ if (phoneNumber.hasCountryCode()) {
+ builder.setCountryCode(Integer.toString(phoneNumber.getCountryCode()));
+ }
+ builder.setNumberParts(Long.toString(phoneNumber.getNationalNumber()));
+ }
+ return builder.build();
+ }
}
diff --git a/src/com/android/contacts/common/util/MaterialColorMapUtils.java b/src/com/android/contacts/common/util/MaterialColorMapUtils.java
index 9c8862c..1e44643 100644
--- a/src/com/android/contacts/common/util/MaterialColorMapUtils.java
+++ b/src/com/android/contacts/common/util/MaterialColorMapUtils.java
@@ -23,7 +23,6 @@
import android.os.Trace;
public class MaterialColorMapUtils {
-
private final TypedArray sPrimaryColors;
private final TypedArray sSecondaryColors;
@@ -41,6 +40,36 @@
}
public final int mPrimaryColor;
public final int mSecondaryColor;
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MaterialPalette other = (MaterialPalette) obj;
+ if (mPrimaryColor != other.mPrimaryColor) {
+ return false;
+ }
+ if (mSecondaryColor != other.mSecondaryColor) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + mPrimaryColor;
+ result = prime * result + mSecondaryColor;
+ return result;
+ }
}
/**
diff --git a/src/com/android/contacts/common/widget/SelectPhoneAccountDialogFragment.java b/src/com/android/contacts/common/widget/SelectPhoneAccountDialogFragment.java
index 0dbe70a..ca62ce5 100644
--- a/src/com/android/contacts/common/widget/SelectPhoneAccountDialogFragment.java
+++ b/src/com/android/contacts/common/widget/SelectPhoneAccountDialogFragment.java
@@ -132,20 +132,18 @@
}
private class SelectAccountListAdapter extends ArrayAdapter<PhoneAccountHandle> {
- private Context mContext;
private int mResId;
public SelectAccountListAdapter(
Context context, int resource, List<PhoneAccountHandle> accountHandles) {
super(context, resource, accountHandles);
- mContext = context;
mResId = resource;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)
- mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView;
final ViewHolder holder;
@@ -166,7 +164,7 @@
PhoneAccountHandle accountHandle = getItem(position);
PhoneAccount account = mTelecomManager.getPhoneAccount(accountHandle);
holder.textView.setText(account.getLabel());
- holder.imageView.setImageDrawable(account.getIcon(mContext));
+ holder.imageView.setImageDrawable(account.getIcon(getContext()));
return rowView;
}
@@ -183,4 +181,4 @@
}
super.onPause();
}
-}
\ No newline at end of file
+}