Allow GridBuilder to specify a top-level content intent

Bug: 68378574
Test: manual, check weather / contact / gallery slices
      Check that weather is tappable
Change-Id: If10c48a05c0991b371887ee167799db6a5c7641d
diff --git a/slices/view/src/androidTest/java/androidx/app/slice/render/SliceCreator.java b/slices/view/src/androidTest/java/androidx/app/slice/render/SliceCreator.java
index d4551ef..ca24c98 100644
--- a/slices/view/src/androidTest/java/androidx/app/slice/render/SliceCreator.java
+++ b/slices/view/src/androidTest/java/androidx/app/slice/render/SliceCreator.java
@@ -98,7 +98,11 @@
     }
 
     private Slice createWeather(Uri sliceUri) {
+        SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST,
+                "open weather app"), Icon.createWithResource(getContext(), R.drawable.weather_1),
+                "Weather is happening!");
         GridBuilder b = new GridBuilder(getContext(), sliceUri);
+        b.setPrimaryAction(primaryAction);
         return b.addCell(new GridBuilder.CellBuilder(b)
                         .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_1))
                         .addText("MON")
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/GridContent.java b/slices/view/src/main/java/androidx/app/slice/widget/GridContent.java
index 9569dc0..794187d 100644
--- a/slices/view/src/main/java/androidx/app/slice/widget/GridContent.java
+++ b/slices/view/src/main/java/androidx/app/slice/widget/GridContent.java
@@ -16,6 +16,9 @@
 
 package androidx.app.slice.widget;
 
+import static android.app.slice.Slice.HINT_ACTIONS;
+import static android.app.slice.Slice.HINT_SHORTCUT;
+import static android.app.slice.Slice.HINT_TITLE;
 import static android.app.slice.Slice.SUBTYPE_COLOR;
 import static android.app.slice.SliceItem.FORMAT_ACTION;
 import static android.app.slice.SliceItem.FORMAT_IMAGE;
@@ -24,6 +27,7 @@
 import static android.app.slice.SliceItem.FORMAT_TEXT;
 import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
 
+import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 
 import java.util.ArrayList;
@@ -40,8 +44,9 @@
 public class GridContent {
 
     private boolean mAllImages;
-    public SliceItem mColorItem;
-    public ArrayList<CellContent> mGridContent = new ArrayList<>();
+    private SliceItem mColorItem;
+    private SliceItem mPrimaryAction;
+    private ArrayList<CellContent> mGridContent = new ArrayList<>();
 
     public GridContent(SliceItem gridItem) {
         populate(gridItem);
@@ -58,9 +63,13 @@
     public boolean populate(SliceItem gridItem) {
         reset();
         mColorItem = SliceQuery.findSubtype(gridItem, FORMAT_INT, SUBTYPE_COLOR);
+        String[] hints = new String[] {HINT_SHORTCUT, HINT_TITLE};
+        mPrimaryAction = SliceQuery.find(gridItem, FORMAT_SLICE, hints,
+                new String[] {HINT_ACTIONS} /* nonHints */);
         mAllImages = true;
         if (FORMAT_SLICE.equals(gridItem.getFormat())) {
             List<SliceItem> items = gridItem.getSlice().getItems();
+            items = filterInvalidItems(items);
             // Check if it it's only one item that is a slice
             if (items.size() == 1 && items.get(0).getFormat().equals(FORMAT_SLICE)) {
                 items = items.get(0).getSlice().getItems();
@@ -99,6 +108,14 @@
     }
 
     /**
+     * @return the content intent item for this grid.
+     */
+    @Nullable
+    public SliceItem getContentIntent() {
+        return mPrimaryAction;
+    }
+
+    /**
      * @return whether this grid has content that is valid to display.
      */
     public boolean isValid() {
@@ -112,6 +129,17 @@
         return mAllImages;
     }
 
+    private List<SliceItem> filterInvalidItems(List<SliceItem> items) {
+        List<SliceItem> filteredItems = new ArrayList<>();
+        for (int i = 0; i < items.size(); i++) {
+            SliceItem item = items.get(i);
+            if (!item.hasHint(HINT_SHORTCUT)) {
+                filteredItems.add(item);
+            }
+        }
+        return filteredItems;
+    }
+
     /**
      * Extracts information required to present content in a cell.
      * @hide
@@ -130,7 +158,8 @@
          */
         public boolean populate(SliceItem cellItem) {
             final String format = cellItem.getFormat();
-            if (FORMAT_SLICE.equals(format) || FORMAT_ACTION.equals(format)) {
+            if (!cellItem.hasHint(HINT_SHORTCUT)
+                    && (FORMAT_SLICE.equals(format) || FORMAT_ACTION.equals(format))) {
                 List<SliceItem> items = cellItem.getSlice().getItems();
                 // If we've only got one item that's a slice / action use those items instead
                 if (items.size() == 1 && (FORMAT_ACTION.equals(items.get(0).getFormat())
diff --git a/slices/view/src/main/java/androidx/app/slice/widget/GridRowView.java b/slices/view/src/main/java/androidx/app/slice/widget/GridRowView.java
index 6b0ae5a..f837713 100644
--- a/slices/view/src/main/java/androidx/app/slice/widget/GridRowView.java
+++ b/slices/view/src/main/java/androidx/app/slice/widget/GridRowView.java
@@ -162,6 +162,13 @@
     }
 
     private void populateViews(GridContent gc) {
+        if (gc.getContentIntent() != null) {
+            EventInfo info = new EventInfo(getMode(), EventInfo.ACTION_TYPE_CONTENT,
+                    EventInfo.ROW_TYPE_GRID, mRowIndex);
+            Pair<SliceItem, EventInfo> tagItem = new Pair(gc.getContentIntent(), info);
+            mViewContainer.setTag(tagItem);
+            makeClickable(mViewContainer);
+        }
         mIsAllImages = gc.isAllImages();
         ArrayList<GridContent.CellContent> cells = gc.getGridContent();
         final int max = mIsAllImages ? MAX_IMAGES : MAX_ALL;