Merge "Catch IllegalArgumentException during caching vCard and send feedback" into ub-contactsdialer-h-dev
diff --git a/AndroidManifest_common.xml b/AndroidManifest_common.xml
index 09e9c81..a41bedd 100644
--- a/AndroidManifest_common.xml
+++ b/AndroidManifest_common.xml
@@ -222,7 +222,7 @@
<activity android:name=".common.activity.LicenseActivity"
android:label="@string/activity_title_licenses"
android:theme="@style/ContactsPreferencesTheme"
- android:exported="false" />
+ android:exported="true" />
<!-- Used to filter contacts list by account -->
<activity
diff --git a/res/layout/fragment_sim_import.xml b/res/layout/fragment_sim_import.xml
index d6d3acf..f848cef 100644
--- a/res/layout/fragment_sim_import.xml
+++ b/res/layout/fragment_sim_import.xml
@@ -56,7 +56,7 @@
android:background="?android:colorBackground"
android:minHeight="48dp"
android:orientation="horizontal"
- android:paddingEnd="32dp"
+ android:paddingEnd="16dp"
android:paddingStart="16dp">
<ImageView
@@ -83,8 +83,8 @@
android:id="@+id/account_expander_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="9dp"
android:layout_gravity="center_vertical"
+ android:layout_marginEnd="10dp"
android:scaleType="center"
android:src="@drawable/ic_arrow_drop_down_black_24dp"
android:tint="?android:textColorSecondary"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d603973..de9764d 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -458,4 +458,9 @@
<dimen name="call_subject_dialog_secondary_text_size">14sp</dimen>
<!-- Row padding for call subject history items. -->
<dimen name="call_subject_history_item_padding">15dp</dimen>
+
+ <!-- Padding between SIM checkbox and end of row -->
+ <dimen name="sim_import_checkbox_end_padding">16dp</dimen>
+
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9a1dd19..250870f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -193,7 +193,7 @@
<string name="contacts_deleted_two_named_toast"><xliff:g id="name">%1$s</xliff:g> and <xliff:g id="name">%2$s</xliff:g> deleted</string>
<!-- Toast shown with names after user selected contacts are deleted by user action. [CHAR LIMIT=50] -->
- <string name="contacts_deleted_many_named_toast"><xliff:g id="name">%1$s</xliff:g>, <xliff:g id="name">%2$s</xliff:g>, <xliff:g id="name">%3$s</xliff:g>... deleted</string>
+ <string name="contacts_deleted_many_named_toast"><xliff:g id="name">%1$s</xliff:g>, <xliff:g id="name">%2$s</xliff:g>, <xliff:g id="name">%3$s</xliff:g>\u2026 deleted</string>
<!-- Toast shown after contacts that the user has selected are deleted by a user action. [CHAR LIMIT=30] -->
<plurals name="contacts_deleted_toast">
diff --git a/src/com/android/contacts/DynamicShortcuts.java b/src/com/android/contacts/DynamicShortcuts.java
index 52307e4..49cc722 100644
--- a/src/com/android/contacts/DynamicShortcuts.java
+++ b/src/com/android/contacts/DynamicShortcuts.java
@@ -215,9 +215,14 @@
final List<ShortcutInfo> result = new ArrayList<>();
try {
- // For some reason the limit query parameter is ignored for the strequent content uri
- for (int i = 0; i < MAX_SHORTCUTS && cursor.moveToNext(); i++) {
- result.add(createShortcutFromRow(cursor));
+ int i = 0;
+ while (i < MAX_SHORTCUTS && cursor.moveToNext()) {
+ final ShortcutInfo shortcut = createShortcutFromRow(cursor);
+ if (shortcut == null) {
+ continue;
+ }
+ result.add(shortcut);
+ i++;
}
} finally {
cursor.close();
@@ -229,6 +234,9 @@
@VisibleForTesting
ShortcutInfo createShortcutFromRow(Cursor cursor) {
final ShortcutInfo.Builder builder = builderForContactShortcut(cursor);
+ if (builder == null) {
+ return null;
+ }
addIconForContact(cursor, builder);
return builder.build();
}
@@ -243,6 +251,9 @@
@VisibleForTesting
ShortcutInfo.Builder builderForContactShortcut(long id, String lookupKey, String displayName) {
+ if (lookupKey == null || displayName == null) {
+ return null;
+ }
final PersistableBundle extras = new PersistableBundle();
extras.putLong(Contacts._ID, id);
@@ -392,8 +403,6 @@
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS))
.setTriggerContentUpdateDelay(mContentChangeMinUpdateDelay)
.setTriggerContentMaxDelay(mContentChangeMaxUpdateDelay)
- // Minimize impact on UX by waiting for idle before updating.
- .setRequiresDeviceIdle(true)
.build();
mJobScheduler.schedule(job);
}
diff --git a/src/com/android/contacts/SimImportFragment.java b/src/com/android/contacts/SimImportFragment.java
index 66be41b..09bc4de 100644
--- a/src/com/android/contacts/SimImportFragment.java
+++ b/src/com/android/contacts/SimImportFragment.java
@@ -325,9 +325,12 @@
private AccountWithDataSet mSelectedAccount;
private Map<AccountWithDataSet, Set<SimContact>> mExistingMap;
private Map<AccountWithDataSet, TreeSet<Long>> mPerAccountCheckedIds = new ArrayMap<>();
+ private final int mCheckboxPaddingEnd;
public SimContactAdapter(Context context) {
super(context);
+ mCheckboxPaddingEnd = context.getResources()
+ .getDimensionPixelOffset(R.dimen.sim_import_checkbox_end_padding);
}
@Override
@@ -344,6 +347,10 @@
// clickable
contactView.getCheckBox().setFocusable(false);
contactView.getCheckBox().setClickable(false);
+ // The default list pads the checkbox by a larger amount than we want.
+ contactView.setPaddingRelative(contactView.getPaddingStart(),
+ contactView.getPaddingTop(), mCheckboxPaddingEnd,
+ contactView.getPaddingBottom());
setViewEnabled(contactView, !existsInCurrentAccount(position));
}
diff --git a/src/com/android/contacts/common/model/account/ExternalAccountType.java b/src/com/android/contacts/common/model/account/ExternalAccountType.java
index 2f476e6..6803a6b 100644
--- a/src/com/android/contacts/common/model/account/ExternalAccountType.java
+++ b/src/com/android/contacts/common/model/account/ExternalAccountType.java
@@ -153,7 +153,12 @@
}
error.append(" for external package ");
error.append(packageName);
- FeedbackHelper.sendFeedback(context, TAG, "Failed to build external account type", e);
+ // Only send feedback if not from tests. There are tests that expect failures so no need
+ // to report those.
+ if (injectedMetadata == null) {
+ FeedbackHelper.sendFeedback(context, TAG, "Failed to build external account type",
+ e);
+ }
return;
} finally {
if (parser != null) {
diff --git a/src/com/android/contacts/common/preference/AboutPreferenceFragment.java b/src/com/android/contacts/common/preference/AboutPreferenceFragment.java
index 3b5a28d..d8426ba 100644
--- a/src/com/android/contacts/common/preference/AboutPreferenceFragment.java
+++ b/src/com/android/contacts/common/preference/AboutPreferenceFragment.java
@@ -35,8 +35,8 @@
*/
public class AboutPreferenceFragment extends PreferenceFragment {
- private static final String PRIVACY_POLICY_URL = "http://www.google.com/policies/privacy";
- private static final String TERMS_OF_SERVICE_URL = "http://www.google.com/policies/terms";
+ public static final String PRIVACY_POLICY_URL = "http://www.google.com/policies/privacy";
+ public static final String TERMS_OF_SERVICE_URL = "http://www.google.com/policies/terms";
public static AboutPreferenceFragment newInstance() {
return new AboutPreferenceFragment();
diff --git a/src/com/android/contacts/common/preference/DisplayOptionsPreferenceFragment.java b/src/com/android/contacts/common/preference/DisplayOptionsPreferenceFragment.java
index 901a15e..e2782f8 100644
--- a/src/com/android/contacts/common/preference/DisplayOptionsPreferenceFragment.java
+++ b/src/com/android/contacts/common/preference/DisplayOptionsPreferenceFragment.java
@@ -57,6 +57,7 @@
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.util.AccountFilterUtil;
import com.android.contacts.common.util.ImplicitIntentsUtil;
+import com.android.contactsbind.HelpUtils;
import java.util.List;
@@ -226,7 +227,9 @@
}
final Preference aboutPreference = findPreference(KEY_ABOUT);
- aboutPreference.setOnPreferenceClickListener(this);
+ if (aboutPreference != null) {
+ aboutPreference.setOnPreferenceClickListener(this);
+ }
final Preference customFilterPreference = findPreference(KEY_CUSTOM_CONTACTS_FILTER);
if (customFilterPreference != null) {
@@ -263,6 +266,10 @@
getPreferenceScreen().removePreference(findPreference(KEY_SORT_ORDER));
}
+ if (HelpUtils.isHelpAndFeedbackAvailable()) {
+ getPreferenceScreen().removePreference(findPreference(KEY_ABOUT));
+ }
+
// Disable display order for CJK locales as well
if (!resources.getBoolean(R.bool.config_display_order_user_changeable)) {
getPreferenceScreen().removePreference(findPreference(KEY_DISPLAY_ORDER));
diff --git a/tests/src/com/android/contacts/DynamicShortcutsTests.java b/tests/src/com/android/contacts/DynamicShortcutsTests.java
index 106b72a..34cd8c4 100644
--- a/tests/src/com/android/contacts/DynamicShortcutsTests.java
+++ b/tests/src/com/android/contacts/DynamicShortcutsTests.java
@@ -100,6 +100,14 @@
assertEquals(1l, shortcut.getExtras().getLong(Contacts._ID));
}
+ public void test_builderForContactShortcut_returnsNullWhenNameIsNull() {
+ final DynamicShortcuts sut = createDynamicShortcuts();
+
+ final ShortcutInfo.Builder shortcut = sut.builderForContactShortcut(1l, "lookup_key", null);
+
+ assertNull(shortcut);
+ }
+
public void test_builderForContactShortcut_ellipsizesLongNamesForLabels() {
final DynamicShortcuts sut = createDynamicShortcuts();
sut.setShortLabelMaxLength(5);
@@ -183,6 +191,43 @@
assertThat(arg.get(2), isShortcutForContact(3l, "starred_2", "Starred Two"));
}
+ public void test_refresh_skipsContactsWithNullName() {
+ final ShortcutManager mockShortcutManager = mock(ShortcutManager.class);
+ when(mockShortcutManager.getPinnedShortcuts()).thenReturn(
+ Collections.<ShortcutInfo>emptyList());
+ final DynamicShortcuts sut = createDynamicShortcuts(resolverWithExpectedQueries(
+ queryFor(Contacts.CONTENT_STREQUENT_URI,
+ 1l, "key1", "first",
+ 2l, "key2", "second",
+ 3l, "key3", null,
+ 4l, null, null,
+ 5l, "key5", "fifth",
+ 6l, "key6", "sixth")), mockShortcutManager);
+
+ sut.refresh();
+
+ final ArgumentCaptor<List<ShortcutInfo>> updateArgs =
+ ArgumentCaptor.forClass((Class) List.class);
+
+ verify(mockShortcutManager).setDynamicShortcuts(updateArgs.capture());
+
+ final List<ShortcutInfo> arg = updateArgs.getValue();
+ assertThat(arg.size(), equalTo(3));
+ assertThat(arg.get(0), isShortcutForContact(1l, "key1", "first"));
+ assertThat(arg.get(1), isShortcutForContact(2l, "key2", "second"));
+ assertThat(arg.get(2), isShortcutForContact(5l, "key5", "fifth"));
+
+
+ // Also verify that it doesn't crash if there are fewer than 3 valid strequent contacts
+ createDynamicShortcuts(resolverWithExpectedQueries(
+ queryFor(Contacts.CONTENT_STREQUENT_URI,
+ 1l, "key1", "first",
+ 2l, "key2", "second",
+ 3l, "key3", null,
+ 4l, null, null)), mock(ShortcutManager.class)).refresh();
+ }
+
+
public void test_handleFlagDisabled_stopsJob() {
final ShortcutManager mockShortcutManager = mock(ShortcutManager.class);
final JobScheduler mockJobScheduler = mock(JobScheduler.class);