Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2e38089 authored by Marcus Hagerott's avatar Marcus Hagerott
Browse files

Fix NPE when creating dynamic shortcuts

An NPE was being thrown if a strequent contact had a null display_name

test
* ran GoogleContactsTests
* manually verified that dynamic shortcuts still update correctly

Bug 32945535

Change-Id: I5fbf28c26930abe0f50035e6c7830f94a05e2612
parent e6493181
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -215,9 +215,14 @@ public class DynamicShortcuts {
        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 @@ public class DynamicShortcuts {
    @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 @@ public class DynamicShortcuts {

    @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 @@ public class DynamicShortcuts {
                        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);
    }
+45 −0
Original line number Diff line number Diff line
@@ -100,6 +100,14 @@ public class DynamicShortcutsTests extends AndroidTestCase {
        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 @@ public class DynamicShortcutsTests extends AndroidTestCase {
        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);