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

Commit 7bd7f0d1 authored by Steve McKay's avatar Steve McKay
Browse files

Guard against NPEs in pre-init selection helper.

Some input events may arrive in such an order that DocsSelectionHelper
gets called before it's `reset` method. In those cases we're
seeing an NPE.

BUG: 69306667
Test: Added new basic.
Change-Id: I0e6c73861a7cd7b3d65512e2822b7854622e11ab
parent 5eecb743
Loading
Loading
Loading
Loading
+99 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.support.v7.widget.RecyclerView;

import com.android.documentsui.selection.DefaultSelectionHelper;
import com.android.documentsui.selection.DefaultSelectionHelper.SelectionMode;
import com.android.documentsui.selection.MutableSelection;
import com.android.documentsui.selection.Selection;
import com.android.documentsui.selection.SelectionHelper;

@@ -37,7 +38,10 @@ public final class DocsSelectionHelper extends SelectionHelper {
    private final DelegateFactory mFactory;
    private final @SelectionMode int mSelectionMode;

    private @Nullable SelectionHelper mDelegate;
    // initialize to a dummy object incase we get some input
    // event drive calls before we're properly initialized.
    // See: b/69306667.
    private SelectionHelper mDelegate = new DummySelectionHelper();

    @VisibleForTesting
    DocsSelectionHelper(DelegateFactory factory, @SelectionMode int mode) {
@@ -188,4 +192,98 @@ public final class DocsSelectionHelper extends SelectionHelper {
            return new DefaultSelectionHelper(mode, adapter, stableIds, canSetState);
        }
    }

    /**
     * A dummy SelectHelper used by DocsSelectionHelper before a real
     * SelectionHelper has been initialized by DirectoryFragment.
     */
    private static final class DummySelectionHelper extends SelectionHelper {

        @Override
        public void addObserver(SelectionObserver listener) {
        }

        @Override
        public boolean hasSelection() {
            return false;
        }

        @Override
        public Selection getSelection() {
            return new MutableSelection();
        }

        @Override
        public void copySelection(Selection dest) {
        }

        @Override
        public boolean isSelected(String id) {
            return false;
        }

        @VisibleForTesting
        public void replaceSelection(Iterable<String> ids) {
        }

        @Override
        public void restoreSelection(Selection other) {
        }

        @Override
        public boolean setItemsSelected(Iterable<String> ids, boolean selected) {
            return false;
        }

        @Override
        public void clearSelection() {
        }

        @Override
        public boolean select(String modelId) {
            return false;
        }

        @Override
        public boolean deselect(String modelId) {
            return false;
        }

        @Override
        public void startRange(int pos) {
        }

        @Override
        public void extendRange(int pos) {
        }

        @Override
        public void extendProvisionalRange(int pos) {
        }

        @Override
        public void clearProvisionalSelection() {
        }

        @Override
        public void setProvisionalSelection(Set<String> newSelection) {
        }

        @Override
        public void mergeProvisionalSelection() {
        }

        @Override
        public void endRange() {
        }

        @Override
        public boolean isRangeActive() {
            return false;
        }

        @Override
        public void anchorRange(int position) {
        }
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.documentsui;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.support.test.filters.SmallTest;
@@ -71,6 +73,13 @@ public class DocsSelectionHelperTest {
        mSelectionMgr = new DocsSelectionHelper(mFactory, DefaultSelectionHelper.MODE_MULTIPLE);
    }

    @Test
    public void testCallableBeforeReset() {
        mSelectionMgr.hasSelection();
        assertNotNull(mSelectionMgr.getSelection());
        assertFalse(mSelectionMgr.isSelected("poodle"));
    }

    @Test
    public void testReset_CreatesNewInstances() {
        mSelectionMgr.reset(null, null, null);  // nulls are passed to factory. We ignore.