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

Commit ed188281 authored by Brian Attwell's avatar Brian Attwell
Browse files

Don't access mRecentLoaderResults in background

Lists inside mRecentLoaderResults are cleared inside
Loader#onReset. Therefore, Retreiving items inside mRecentLoaderResults's
lists on a background thread can result in retreiving nulled out
ArrayList entries.

Fix:
* Only access mRecentLoaderResults on the main thread
* Don't crash when encountering null entries inside mRecentLoaderResults,
  in case I'm wrong about the reason these entries are null
  (although I can't see any other causes)
* make bindRecentData() sorting stable, since I'm already editing
  this code anyway

Bug: 19320314
Change-Id: Id871a8c0de3685baf07a6c4d65a4835380b1b99a
parent f0a2a8b2
Loading
Loading
Loading
Loading
+25 −5
Original line number Diff line number Diff line
@@ -1876,6 +1876,9 @@ public class QuickContactActivity extends ContactsActivity {
    private List<Entry> contactInteractionsToEntries(List<ContactInteraction> interactions) {
        final List<Entry> entries = new ArrayList<>();
        for (ContactInteraction interaction : interactions) {
            if (interaction == null) {
                continue;
            }
            entries.add(new Entry(/* id = */ -1,
                    interaction.getIcon(this),
                    interaction.getViewHeader(this),
@@ -2030,20 +2033,37 @@ public class QuickContactActivity extends ContactsActivity {
        final List<ContactInteraction> allInteractions = new ArrayList<>();
        final List<List<Entry>> interactionsWrapper = new ArrayList<>();

        // Serialize mRecentLoaderResults into a single list. This should be done on the main
        // thread to avoid races against mRecentLoaderResults edits.
        for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) {
            allInteractions.addAll(loaderInteractions);
        }

        mRecentDataTask = new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                Trace.beginSection("sort recent loader results");

                for (List<ContactInteraction> loaderInteractions : mRecentLoaderResults.values()) {
                    allInteractions.addAll(loaderInteractions);
                }

                // Sort the interactions by most recent
                Collections.sort(allInteractions, new Comparator<ContactInteraction>() {
                    @Override
                    public int compare(ContactInteraction a, ContactInteraction b) {
                        return a.getInteractionDate() >= b.getInteractionDate() ? -1 : 1;
                        if (a == null && b == null) {
                            return 0;
                        }
                        if (a == null) {
                            return 1;
                        }
                        if (b == null) {
                            return -1;
                        }
                        if (a.getInteractionDate() > b.getInteractionDate()) {
                            return -1;
                        }
                        if (a.getInteractionDate() == b.getInteractionDate()) {
                            return 0;
                        }
                        return 1;
                    }
                });