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

Commit 058d2d10 authored by Doris Ling's avatar Doris Ling
Browse files

Fix crash when dismissing suggestions.

When the suggestions are in default mode and the number of suggestions
are more than the default count, we set the sublist of the suggestions
list as the suggestion adapter data. In this case, operation on the
suggestions list should be done in the sublist instead of the original
list to maintain the list consistency check.

Hence, when dismissing the suggestion, change to remove the suggestion
from the sugestion adapter instead of from the dashboard adapter, so
that any following interaction with the suggestions will not trigger the
concurrent modification exception.

Change-Id: I4caba74cfcc7bd0d53ad8c7dffcb127b3ebd845d
Merged-In: I970b6af8a1c72bc0c3ee89fef890ae6a669c71d2
Fix: 64279080
Test: make RunSettingsRoboTests
parent 713e4f65
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -232,8 +232,7 @@ public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.Dash
                    .build();
            notifyDashboardDataChanged(prevData);
        } else {
            suggestions.remove(suggestion);
            mSuggestionAdapter.notifyDataSetChanged();
            mSuggestionAdapter.removeSuggestion(suggestion);
        }
    }

+4 −0
Original line number Diff line number Diff line
@@ -134,4 +134,8 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
        return null;
    }

    public void removeSuggestion(Tile suggestion) {
        mSuggestions.remove(suggestion);
        notifyDataSetChanged();
    }
}
+24 −2
Original line number Diff line number Diff line
@@ -34,14 +34,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -355,6 +353,30 @@ public class DashboardAdapterTest {
        verify(adapter, never()).notifyDashboardDataChanged(any());
    }

    @Test
    public void testSuggestionDismissed_moreThanTwoSuggestions_defaultMode_shouldNotCrash() {
        final RecyclerView data = new RecyclerView(RuntimeEnvironment.application);
        final View itemView = mock(View.class);
        when(itemView.findViewById(R.id.data)).thenReturn(data);
        final DashboardAdapter.SuggestionAndConditionContainerHolder holder =
                new DashboardAdapter.SuggestionAndConditionContainerHolder(itemView);
        final List<Tile> suggestions =
                makeSuggestions("pkg1", "pkg2", "pkg3", "pkg4");
        final DashboardAdapter adapter = spy(new DashboardAdapter(mContext, null /*savedInstance */,
                null /* conditions */, null /* suggestionParser */, null /* callback */));
        adapter.setCategoriesAndSuggestions(new ArrayList<>(), suggestions);
        adapter.onBindConditionAndSuggestion(
                holder, DashboardAdapter.SUGGESTION_CONDITION_HEADER_POSITION);
        // default mode, only displaying 2 suggestions

        adapter.onSuggestionDismissed(suggestions.get(1));

        // verify operations that access the lists will not cause ConcurrentModificationException
        assertThat(holder.data.getAdapter().getItemCount()).isEqualTo(1);
        adapter.setCategoriesAndSuggestions(new ArrayList<>(), suggestions);
        // should not crash
    }

    @Test
    public void testSuggestioDismissed_onlySuggestion_updateDashboardData() {
        DashboardAdapter adapter =