Merge "Make filter appear floating in ManagerApplication."
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 88478e3..49e2a76 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -107,12 +107,12 @@
                 }
             }
         }
-        return getFinalDisplayableCards(result);
+        return getDisplayableCards(result);
     }
 
     // Get final displayed cards and log what cards will be displayed/hidden
     @VisibleForTesting
-    List<ContextualCard> getFinalDisplayableCards(List<ContextualCard> candidates) {
+    List<ContextualCard> getDisplayableCards(List<ContextualCard> candidates) {
         final List<ContextualCard> eligibleCards = filterEligibleCards(candidates);
         final List<ContextualCard> visibleCards = new ArrayList<>();
         final List<ContextualCard> hiddenCards = new ArrayList<>();
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 067de7c..12088f8 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -17,6 +17,7 @@
 package com.android.settings.homepage.contextualcards;
 
 import static com.android.settings.homepage.contextualcards.ContextualCardLoader.CARD_CONTENT_LOADER_ID;
+import static com.android.settings.intelligence.ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE;
 
 import static java.util.stream.Collectors.groupingBy;
 
@@ -172,7 +173,8 @@
 
         //replace with the new data
         mContextualCards.clear();
-        mContextualCards.addAll(sortCards(allCards));
+        final List<ContextualCard> sortedCards = sortCards(allCards);
+        mContextualCards.addAll(assignCardWidth(sortedCards));
 
         loadCardControllers();
 
@@ -224,6 +226,24 @@
         mListener = listener;
     }
 
+    @VisibleForTesting
+    List<ContextualCard> assignCardWidth(List<ContextualCard> cards) {
+        final List<ContextualCard> result = new ArrayList<>(cards);
+        // Shows as half cards if 2 suggestion type of cards are next to each other.
+        // Shows as full card if 1 suggestion type of card lives alone.
+        for (int index = 1; index < result.size(); index++) {
+            final ContextualCard previous = result.get(index - 1);
+            final ContextualCard current = result.get(index);
+            if (current.getCategory() == SUGGESTION_VALUE
+                    && previous.getCategory() == SUGGESTION_VALUE) {
+                result.set(index - 1, previous.mutate().setIsHalfWidth(true).build());
+                result.set(index, current.mutate().setIsHalfWidth(true).build());
+                index++;
+            }
+        }
+        return result;
+    }
+
     private List<ContextualCard> getCardsToKeep(List<ContextualCard> cards) {
         if (mSavedCards != null) {
             //screen rotate
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java
index 2986dbc..24d654d 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java
@@ -16,13 +16,24 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
+import android.app.PendingIntent;
 import android.content.Context;
+import android.util.Log;
 import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.slice.Slice;
+import androidx.slice.SliceMetadata;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.EventInfo;
 
+import com.android.settings.R;
 import com.android.settings.homepage.contextualcards.ContextualCard;
+import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 
 /**
  * Card renderer helper for {@link ContextualCard} built as slice half card.
@@ -37,10 +48,38 @@
     }
 
     RecyclerView.ViewHolder createViewHolder(View view) {
-        return null;
+        return new HalfCardViewHolder(view);
     }
 
     void bindView(RecyclerView.ViewHolder holder, ContextualCard card, Slice slice) {
+        final HalfCardViewHolder view = (HalfCardViewHolder) holder;
+        final SliceMetadata sliceMetadata = SliceMetadata.from(mContext, slice);
+        final SliceAction primaryAction = sliceMetadata.getPrimaryAction();
+        view.icon.setImageDrawable(primaryAction.getIcon().loadDrawable(mContext));
+        view.title.setText(primaryAction.getTitle());
+        view.content.setOnClickListener(v -> {
+            try {
+                primaryAction.getAction().send();
+            } catch (PendingIntent.CanceledException e) {
+                Log.w(TAG, "Failed to start intent " + primaryAction.getTitle());
+            }
+            final ContextualCardFeatureProvider contextualCardFeatureProvider =
+                    FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
+            contextualCardFeatureProvider.logContextualCardClick(card, 0 /* row */,
+                    EventInfo.ACTION_TYPE_CONTENT);
+        });
+    }
 
+    static class HalfCardViewHolder extends RecyclerView.ViewHolder {
+        public final LinearLayout content;
+        public final ImageView icon;
+        public final TextView title;
+
+        public HalfCardViewHolder(View itemView) {
+            super(itemView);
+            content = itemView.findViewById(R.id.content);
+            icon = itemView.findViewById(android.R.id.icon);
+            title = itemView.findViewById(android.R.id.title);
+        }
     }
 }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index c62a6bb..c47fa38 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -29,16 +29,16 @@
 
 import com.android.settings.slices.CustomSliceRegistry;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
 @RunWith(RobolectricTestRunner.class)
 public class ContextualCardLoaderTest {
 
@@ -82,29 +82,29 @@
     }
 
     @Test
-    public void getFinalDisplayableCards_twoEligibleCards_shouldShowAll() {
+    public void getDisplayableCards_twoEligibleCards_shouldShowAll() {
         final List<ContextualCard> cards = getContextualCardList().stream().limit(2)
                 .collect(Collectors.toList());
         doReturn(cards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
 
-        final List<ContextualCard> result = mContextualCardLoader.getFinalDisplayableCards(cards);
+        final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(cards);
 
         assertThat(result).hasSize(cards.size());
     }
 
     @Test
-    public void getFinalDisplayableCards_fiveEligibleCardsNoLarge_shouldShowDefaultCardCount() {
+    public void getDisplayableCards_fiveEligibleCardsNoLarge_shouldShowDefaultCardCount() {
         final List<ContextualCard> fiveCards = getContextualCardListWithNoLargeCard();
         doReturn(fiveCards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
 
-        final List<ContextualCard> result = mContextualCardLoader.getFinalDisplayableCards(
+        final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(
                 fiveCards);
 
         assertThat(result).hasSize(DEFAULT_CARD_COUNT);
     }
 
     @Test
-    public void getFinalDisplayableCards_threeEligibleCardsOneLarge_shouldShowThreeCards() {
+    public void getDisplayableCards_threeEligibleCardsOneLarge_shouldShowThreeCards() {
         final List<ContextualCard> cards = getContextualCardList().stream().limit(2)
                 .collect(Collectors.toList());
         cards.add(new ContextualCard.Builder()
@@ -115,18 +115,18 @@
                 .build());
         doReturn(cards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
 
-        final List<ContextualCard> result = mContextualCardLoader.getFinalDisplayableCards(cards);
+        final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(cards);
 
         assertThat(result).hasSize(3);
     }
 
     @Test
-    public void getFinalDisplayableCards_threeEligibleCardsTwoLarge_shouldShowTwoCards() {
+    public void getDisplayableCards_threeEligibleCardsTwoLarge_shouldShowTwoCards() {
         final List<ContextualCard> threeCards = getContextualCardList().stream().limit(3)
                 .collect(Collectors.toList());
         doReturn(threeCards).when(mContextualCardLoader).filterEligibleCards(any(List.class));
 
-        final List<ContextualCard> result = mContextualCardLoader.getFinalDisplayableCards(
+        final List<ContextualCard> result = mContextualCardLoader.getDisplayableCards(
                 threeCards);
 
         assertThat(result).hasSize(2);
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
index c405ffc..3fc8e06 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardManagerTest.java
@@ -32,6 +32,8 @@
 import com.android.settings.homepage.contextualcards.conditional.ConditionFooterContextualCard;
 import com.android.settings.homepage.contextualcards.conditional.ConditionHeaderContextualCard;
 import com.android.settings.homepage.contextualcards.conditional.ConditionalContextualCard;
+import com.android.settings.intelligence.ContextualCardProto;
+import com.android.settings.slices.CustomSliceRegistry;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -203,6 +205,134 @@
         assertThat(actualCards).containsExactlyElementsIn(expectedCards);
     }
 
+
+    @Test
+    public void assignCardWidth_noSuggestionCards_shouldNotHaveHalfCards() {
+        final List<Integer> categories = Arrays.asList(
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE
+        );
+        final List<ContextualCard> noSuggestionCards = buildCategoriedCards(getContextualCardList(),
+                categories);
+
+        final List<ContextualCard> result = mManager.assignCardWidth(noSuggestionCards);
+
+        assertThat(result).hasSize(5);
+        for (ContextualCard card : result) {
+            assertThat(card.isHalfWidth()).isFalse();
+        }
+    }
+
+    @Test
+    public void assignCardWidth_oneSuggestionCards_shouldNotHaveHalfCards() {
+        final List<Integer> categories = Arrays.asList(
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE
+        );
+        final List<ContextualCard> oneSuggestionCards = buildCategoriedCards(
+                getContextualCardList(), categories);
+
+        final List<ContextualCard> result = mManager.assignCardWidth(oneSuggestionCards);
+
+        assertThat(result).hasSize(5);
+        for (ContextualCard card : result) {
+            assertThat(card.isHalfWidth()).isFalse();
+        }
+    }
+
+    @Test
+    public void assignCardWidth_twoConsecutiveSuggestionCards_shouldHaveTwoHalfCards() {
+        final List<Integer> categories = Arrays.asList(
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE
+        );
+        final List<ContextualCard> twoConsecutiveSuggestionCards = buildCategoriedCards(
+                getContextualCardList(), categories);
+        final List<Boolean> expectedValues = Arrays.asList(false, false, true, true, false);
+
+        final List<ContextualCard> result = mManager.assignCardWidth(
+                twoConsecutiveSuggestionCards);
+
+        assertThat(result).hasSize(5);
+        for (int i = 0; i < result.size(); i++) {
+            assertThat(result.get(i).isHalfWidth()).isEqualTo(expectedValues.get(i));
+        }
+    }
+
+    @Test
+    public void assignCardWidth_twoNonConsecutiveSuggestionCards_shouldNotHaveHalfCards() {
+        final List<Integer> categories = Arrays.asList(
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE
+        );
+        final List<ContextualCard> twoNonConsecutiveSuggestionCards = buildCategoriedCards(
+                getContextualCardList(), categories);
+
+        final List<ContextualCard> result = mManager.assignCardWidth(
+                twoNonConsecutiveSuggestionCards);
+
+        assertThat(result).hasSize(5);
+        for (ContextualCard card : result) {
+            assertThat(card.isHalfWidth()).isFalse();
+        }
+    }
+
+    @Test
+    public void assignCardWidth_threeConsecutiveSuggestionCards_shouldHaveTwoHalfCards() {
+        final List<Integer> categories = Arrays.asList(
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE
+        );
+        final List<ContextualCard> threeConsecutiveSuggestionCards = buildCategoriedCards(
+                getContextualCardList(), categories);
+        final List<Boolean> expectedValues = Arrays.asList(false, true, true, false, false);
+
+        final List<ContextualCard> result = mManager.assignCardWidth(
+                threeConsecutiveSuggestionCards);
+
+        assertThat(result).hasSize(5);
+        for (int i = 0; i < result.size(); i++) {
+            assertThat(result.get(i).isHalfWidth()).isEqualTo(expectedValues.get(i));
+        }
+    }
+
+    @Test
+    public void assignCardWidth_fourConsecutiveSuggestionCards_shouldHaveFourHalfCards() {
+        final List<Integer> categories = Arrays.asList(
+                ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE,
+                ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE
+        );
+        final List<ContextualCard> fourConsecutiveSuggestionCards = buildCategoriedCards(
+                getContextualCardList(), categories);
+        final List<Boolean> expectedValues = Arrays.asList(false, true, true, true, true);
+
+        final List<ContextualCard> result = mManager.assignCardWidth(
+                fourConsecutiveSuggestionCards);
+
+        assertThat(result).hasSize(5);
+        for (int i = 0; i < result.size(); i++) {
+            assertThat(result.get(i).isHalfWidth()).isEqualTo(expectedValues.get(i));
+        }
+    }
+
     private ContextualCard buildContextualCard(String sliceUri) {
         return new ContextualCard.Builder()
                 .setName(TEST_SLICE_NAME)
@@ -210,4 +340,45 @@
                 .setSliceUri(Uri.parse(sliceUri))
                 .build();
     }
+
+    private List<ContextualCard> buildCategoriedCards(List<ContextualCard> cards,
+            List<Integer> categories) {
+        final List<ContextualCard> result = new ArrayList<>();
+        for (int i = 0; i < cards.size(); i++) {
+            result.add(cards.get(i).mutate().setCategory(categories.get(i)).build());
+        }
+        return result;
+    }
+
+    private List<ContextualCard> getContextualCardList() {
+        final List<ContextualCard> cards = new ArrayList<>();
+        cards.add(new ContextualCard.Builder()
+                .setName("test_wifi")
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI)
+                .build());
+        cards.add(new ContextualCard.Builder()
+                .setName("test_flashlight")
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(
+                        Uri.parse("content://com.android.settings.test.slices/action/flashlight"))
+                .build());
+        cards.add(new ContextualCard.Builder()
+                .setName("test_connected")
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI)
+                .build());
+        cards.add(new ContextualCard.Builder()
+                .setName("test_gesture")
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(Uri.parse(
+                        "content://com.android.settings.test.slices/action/gesture_pick_up"))
+                .build());
+        cards.add(new ContextualCard.Builder()
+                .setName("test_battery")
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(CustomSliceRegistry.BATTERY_INFO_SLICE_URI)
+                .build());
+        return cards;
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelperTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelperTest.java
new file mode 100644
index 0000000..c38697e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelperTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards.slices;
+
+import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.net.Uri;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
+import androidx.slice.SliceProvider;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.ContextualCard;
+import com.android.settings.homepage.contextualcards.slices.SliceHalfCardRendererHelper.HalfCardViewHolder;
+import com.android.settings.intelligence.ContextualCardProto;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class SliceHalfCardRendererHelperTest {
+
+    private static final Uri TEST_SLICE_URI = Uri.parse("content://test/test");
+
+    private Activity mActivity;
+    private SliceHalfCardRendererHelper mHelper;
+
+    @Before
+    public void setUp() {
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+        mActivity = Robolectric.buildActivity(Activity.class).create().get();
+        mActivity.setTheme(R.style.Theme_Settings_Home);
+        mHelper = new SliceHalfCardRendererHelper(mActivity);
+    }
+
+    @Test
+    public void createViewHolder_shouldAlwaysReturnCustomViewHolder() {
+        final RecyclerView.ViewHolder viewHolder = getHalfCardViewHolder();
+
+        assertThat(viewHolder).isInstanceOf(HalfCardViewHolder.class);
+    }
+
+    @Test
+    public void bindView_shouldSetTitle() {
+        final RecyclerView.ViewHolder viewHolder = getHalfCardViewHolder();
+
+        mHelper.bindView(viewHolder, buildContextualCard(), buildSlice());
+
+        assertThat(((HalfCardViewHolder) viewHolder).title.getText()).isEqualTo("test_title");
+    }
+
+    private RecyclerView.ViewHolder getHalfCardViewHolder() {
+        final RecyclerView recyclerView = new RecyclerView(mActivity);
+        recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
+        final View view = LayoutInflater.from(mActivity).inflate(VIEW_TYPE_HALF_WIDTH, recyclerView,
+                false);
+
+        return mHelper.createViewHolder(view);
+    }
+
+    private ContextualCard buildContextualCard() {
+        return new ContextualCard.Builder()
+                .setName("test_name")
+                .setCategory(ContextualCardProto.ContextualCard.Category.SUGGESTION_VALUE)
+                .setCardType(ContextualCard.CardType.SLICE)
+                .setSliceUri(TEST_SLICE_URI)
+                .setIsHalfWidth(false /* isHalfWidth */)
+                .build();
+    }
+
+    private Slice buildSlice() {
+        final String title = "test_title";
+        final IconCompat icon = IconCompat.createWithResource(mActivity, R.drawable.empty_icon);
+        final PendingIntent pendingIntent = PendingIntent.getActivity(
+                mActivity,
+                title.hashCode() /* requestCode */,
+                new Intent("test action"),
+                0  /* flags */);
+        final SliceAction action
+                = SliceAction.createDeeplink(pendingIntent, icon, ListBuilder.SMALL_IMAGE, title);
+        return new ListBuilder(mActivity, TEST_SLICE_URI, ListBuilder.INFINITY)
+                .addRow(new ListBuilder.RowBuilder()
+                        .addEndItem(icon, ListBuilder.ICON_IMAGE)
+                        .setTitle(title)
+                        .setPrimaryAction(action))
+                .build();
+    }
+}