Update shortcut view / slice actions to work together

* Adds constructor to SliceAction that takes image mode
* ShortcutView now prefers the primary action specified
  in the header of the Slice

Bug: 74074403 (will make some of the work here easier)
Test: ./gradlew slices-view:connectedCheck
Change-Id: Id13f4aa9c6e65699802ddb788e2777d67802726f
diff --git a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
index 36a29ee..dfb82f5 100644
--- a/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
+++ b/samples/SupportSliceDemos/src/main/java/com/example/androidx/slice/demos/SampleSliceProvider.java
@@ -293,7 +293,8 @@
                 DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE);
         SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST,
                 "See contact info"), Icon.createWithResource(getContext(),
-                R.drawable.mady), "Mady");
+                R.drawable.mady), SMALL_IMAGE, "Mady");
+
         return new ListBuilder(getContext(), sliceUri)
                 .setColor(0xff3949ab)
                 .setHeader(b -> b
diff --git a/slices/builders/api/current.txt b/slices/builders/api/current.txt
index 03b7c6b..96b8d75 100644
--- a/slices/builders/api/current.txt
+++ b/slices/builders/api/current.txt
@@ -111,6 +111,7 @@
 
   public class SliceAction {
     ctor public SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, java.lang.CharSequence);
+    ctor public SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, int, java.lang.CharSequence);
     ctor public SliceAction(android.app.PendingIntent, android.graphics.drawable.Icon, java.lang.CharSequence, boolean);
     ctor public SliceAction(android.app.PendingIntent, java.lang.CharSequence, boolean);
     method public android.app.PendingIntent getAction();
diff --git a/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java b/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java
index 0b70ceb..00adbd4 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/SliceAction.java
@@ -16,21 +16,24 @@
 
 package androidx.slice.builders;
 
+import static android.app.slice.Slice.HINT_NO_TINT;
 import static android.app.slice.Slice.HINT_SELECTED;
 import static android.app.slice.Slice.HINT_SHORTCUT;
 import static android.app.slice.Slice.HINT_TITLE;
 import static android.app.slice.Slice.SUBTYPE_CONTENT_DESCRIPTION;
 import static android.app.slice.Slice.SUBTYPE_PRIORITY;
 import static android.app.slice.Slice.SUBTYPE_TOGGLE;
+
 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
 
 import android.app.PendingIntent;
 import android.graphics.drawable.Icon;
+
 import androidx.annotation.IntRange;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
-
 import androidx.slice.Slice;
 
 /**
@@ -40,6 +43,7 @@
 
     private PendingIntent mAction;
     private Icon mIcon;
+    private int mImageMode;
     private CharSequence mTitle;
     private CharSequence mContentDescription;
     private boolean mIsToggle;
@@ -56,9 +60,32 @@
      */
     public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
             @NonNull CharSequence actionTitle) {
+        this(action, actionIcon, ICON_IMAGE, actionTitle);
+    }
+
+    /**
+     * Construct a SliceAction representing a tappable icon. Use this method to specify the
+     * format of the image, {@link ListBuilder#ICON_IMAGE} will be presented as a tintable icon.
+     * Note that there is no difference between {@link ListBuilder#SMALL_IMAGE} and
+     * {@link ListBuilder#LARGE_IMAGE} for actions; these will just be represented as an
+     * non-tintable image.
+     *
+     * @param action the pending intent to invoke for this action.
+     * @param actionIcon the icon to display for this action.
+     * @param imageMode the mode this icon should be displayed in.
+     * @param actionTitle the title for this action, also used for content description if one hasn't
+     *                    been set via {@link #setContentDescription(CharSequence)}.
+     *
+     * @see ListBuilder#ICON_IMAGE
+     * @see ListBuilder#SMALL_IMAGE
+     * @see ListBuilder#LARGE_IMAGE
+     */
+    public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
+            @ListBuilder.ImageMode int imageMode, @NonNull CharSequence actionTitle) {
         mAction = action;
         mIcon = actionIcon;
         mTitle = actionTitle;
+        mImageMode = imageMode;
     }
 
     /**
@@ -73,7 +100,7 @@
      */
     public SliceAction(@NonNull PendingIntent action, @NonNull Icon actionIcon,
             @NonNull CharSequence actionTitle, boolean isChecked) {
-        this(action, actionIcon, actionTitle);
+        this(action, actionIcon, ICON_IMAGE, actionTitle);
         mIsChecked = isChecked;
         mIsToggle = true;
     }
@@ -194,7 +221,10 @@
     public Slice buildSlice(@NonNull Slice.Builder builder) {
         Slice.Builder sb = new Slice.Builder(builder);
         if (mIcon != null) {
-            sb.addIcon(mIcon, null);
+            @Slice.SliceHint String[] hints = mImageMode == ICON_IMAGE
+                    ? new String[] {}
+                    : new String[] {HINT_NO_TINT};
+            sb.addIcon(mIcon, null, hints);
         }
         if (mTitle != null) {
             sb.addText(mTitle, null, HINT_TITLE);
diff --git a/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java b/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
index 26c7704..aa60b38 100644
--- a/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
+++ b/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
@@ -34,8 +34,6 @@
 import android.text.format.DateUtils;
 import android.text.style.ForegroundColorSpan;
 
-import java.util.Arrays;
-
 import androidx.slice.Slice;
 import androidx.slice.builders.GridBuilder;
 import androidx.slice.builders.ListBuilder;
@@ -43,6 +41,8 @@
 import androidx.slice.builders.SliceAction;
 import androidx.slice.view.test.R;
 
+import java.util.Arrays;
+
 /**
  * Examples of using slice template builders.
  */
@@ -220,13 +220,15 @@
     private Slice createContact(Uri sliceUri) {
         ListBuilder b = new ListBuilder(getContext(), sliceUri);
         ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(b);
+        SliceAction primaryAction = new SliceAction(getBroadcastIntent(ACTION_TOAST,
+                "See contact info"), Icon.createWithResource(getContext(),
+                R.drawable.mady), SMALL_IMAGE, "Mady");
         GridBuilder gb = new GridBuilder(b);
         return b.setColor(0xff3949ab)
                 .addRow(rb
                         .setTitle("Mady Pitza")
                         .setSubtitle("Frequently contacted contact")
-                        .addEndItem(Icon.createWithResource(getContext(), R.drawable.mady),
-                        SMALL_IMAGE))
+                        .addEndItem(primaryAction))
                 .addGrid(gb
                         .addCell(new GridBuilder.CellBuilder(gb)
                             .addImage(Icon.createWithResource(getContext(), R.drawable.ic_call),
diff --git a/slices/view/src/main/java/androidx/slice/widget/ListContent.java b/slices/view/src/main/java/androidx/slice/widget/ListContent.java
index 5259ce7..1a0f069 100644
--- a/slices/view/src/main/java/androidx/slice/widget/ListContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/ListContent.java
@@ -31,9 +31,6 @@
 
 import android.content.Context;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RestrictTo;
@@ -42,6 +39,9 @@
 import androidx.slice.SliceUtils;
 import androidx.slice.core.SliceQuery;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Extracts information required to present content in a list format from a slice.
  * @hide
@@ -208,6 +208,15 @@
         return mHeaderItem != null && isValidHeader(mHeaderItem);
     }
 
+    /**
+     * @return the primary action for this list; i.e. action on the header or first row.
+     */
+    @Nullable
+    public SliceItem getPrimaryAction() {
+        RowContent rc = new RowContent(mContext, mHeaderItem, false);
+        return rc.getPrimaryAction();
+    }
+
     @Nullable
     private static SliceItem findHeaderItem(@NonNull Slice slice) {
         // See if header is specified
diff --git a/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java b/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
index 2235e92..b068c26 100644
--- a/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
@@ -39,9 +39,9 @@
 import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.shapes.OvalShape;
 import android.net.Uri;
-import androidx.annotation.RestrictTo;
 import android.widget.ImageView;
 
+import androidx.annotation.RestrictTo;
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.core.SliceQuery;
@@ -141,15 +141,15 @@
      * Looks at the slice and determines which items are best to use to compose the shortcut.
      */
     private void determineShortcutItems(Context context, Slice slice) {
-        SliceItem titleItem = SliceQuery.find(slice, FORMAT_ACTION,
-                HINT_TITLE, null);
+        ListContent lc = new ListContent(context, slice);
+        SliceItem primaryAction = lc.getPrimaryAction();
 
-        if (titleItem != null) {
-            // Preferred case: hinted action containing hinted image and text
-            mActionItem = titleItem;
-            mIcon = SliceQuery.find(titleItem.getSlice(), FORMAT_IMAGE, HINT_TITLE,
+        if (primaryAction != null) {
+            // Preferred case: slice has a primary action
+            mActionItem = primaryAction.getSlice().getItems().get(0);
+            mIcon = SliceQuery.find(primaryAction.getSlice(), FORMAT_IMAGE, (String) null,
                     null);
-            mLabel = SliceQuery.find(titleItem.getSlice(), FORMAT_TEXT, HINT_TITLE,
+            mLabel = SliceQuery.find(primaryAction.getSlice(), FORMAT_TEXT, (String) null,
                     null);
         } else {
             // No hinted action; just use the first one