Merge "Add support for the line divider." into androidx-master-dev
diff --git a/slices/builders/api/current.txt b/slices/builders/api/current.txt
index 38e864c..2274a73 100644
--- a/slices/builders/api/current.txt
+++ b/slices/builders/api/current.txt
@@ -110,6 +110,7 @@
     method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction);
     method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction, boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setContentDescription(CharSequence);
+    method public androidx.slice.builders.ListBuilder.RowBuilder setEndOfSection(boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setLayoutDirection(int);
     method public androidx.slice.builders.ListBuilder.RowBuilder setPrimaryAction(androidx.slice.builders.SliceAction);
     method public androidx.slice.builders.ListBuilder.RowBuilder setSubtitle(CharSequence);
diff --git a/slices/builders/api/public_plus_experimental_current.txt b/slices/builders/api/public_plus_experimental_current.txt
index 38e864c..2274a73 100644
--- a/slices/builders/api/public_plus_experimental_current.txt
+++ b/slices/builders/api/public_plus_experimental_current.txt
@@ -110,6 +110,7 @@
     method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction);
     method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction, boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setContentDescription(CharSequence);
+    method public androidx.slice.builders.ListBuilder.RowBuilder setEndOfSection(boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setLayoutDirection(int);
     method public androidx.slice.builders.ListBuilder.RowBuilder setPrimaryAction(androidx.slice.builders.SliceAction);
     method public androidx.slice.builders.ListBuilder.RowBuilder setSubtitle(CharSequence);
diff --git a/slices/builders/api/restricted_current.txt b/slices/builders/api/restricted_current.txt
index 23e4d4a..0d562805 100644
--- a/slices/builders/api/restricted_current.txt
+++ b/slices/builders/api/restricted_current.txt
@@ -111,6 +111,7 @@
     method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction);
     method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(androidx.slice.builders.SliceAction, boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setContentDescription(CharSequence);
+    method public androidx.slice.builders.ListBuilder.RowBuilder setEndOfSection(boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setLayoutDirection(int);
     method public androidx.slice.builders.ListBuilder.RowBuilder setPrimaryAction(androidx.slice.builders.SliceAction);
     method public androidx.slice.builders.ListBuilder.RowBuilder setSubtitle(CharSequence);
diff --git a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
index f84891b..03b74fc 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
@@ -1191,6 +1191,7 @@
     public static class RowBuilder {
 
         private final Uri mUri;
+        private boolean mIsEndOfSection;
         private boolean mHasEndActionOrToggle;
         private boolean mHasEndImage;
         private boolean mHasDefaultToggle;
@@ -1244,6 +1245,15 @@
         }
 
         /**
+         * Indicate that this row is an end for a section.
+         */
+        @NonNull
+        public RowBuilder setEndOfSection(boolean isEndOfSection) {
+            mIsEndOfSection = isEndOfSection;
+            return this;
+        }
+
+        /**
          * Sets the title item to be the provided timestamp. Only one timestamp can be added, if
          * one is already added this will throw {@link IllegalArgumentException}.
          * <p>
@@ -1529,6 +1539,14 @@
          * @hide
          */
         @RestrictTo(LIBRARY)
+        public boolean isEndOfSection() {
+            return mIsEndOfSection;
+        }
+
+        /**
+         * @hide
+         */
+        @RestrictTo(LIBRARY)
         public boolean hasEndActionOrToggle() {
             return mHasEndActionOrToggle;
         }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java
index 6d411ce..83f1662 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderImpl.java
@@ -41,6 +41,7 @@
 import static androidx.slice.Slice.SUBTYPE_RANGE_MODE;
 import static androidx.slice.builders.ListBuilder.INFINITY;
 import static androidx.slice.builders.ListBuilder.RANGE_MODE_DETERMINATE;
+import static androidx.slice.core.SliceHints.HINT_END_OF_SECTION;
 import static androidx.slice.core.SliceHints.SUBTYPE_MILLIS;
 import static androidx.slice.core.SliceHints.SUBTYPE_MIN;
 import static androidx.slice.core.SliceHints.SUBTYPE_SELECTION;
@@ -169,6 +170,9 @@
     public void addRow(@NonNull RowBuilderImpl builder) {
         checkRow(true, builder.hasText());
         builder.getBuilder().addHints(HINT_LIST_ITEM);
+        if (builder.isEndOfSection()) {
+            builder.getBuilder().addHints(HINT_END_OF_SECTION);
+        }
         getBuilder().addSubSlice(builder.build());
     }
 
@@ -466,6 +470,7 @@
      */
     public static class RowBuilderImpl extends TemplateBuilderImpl {
 
+        private boolean mIsEndOfSection;
         private SliceAction mPrimaryAction;
         private SliceItem mTitleItem;
         private SliceItem mSubtitleItem;
@@ -497,6 +502,7 @@
                 setBuilder(new Slice.Builder(builder.getUri()));
             }
             setPrimaryAction(builder.getPrimaryAction());
+            mIsEndOfSection = builder.isEndOfSection();
             if (builder.getLayoutDirection() != -1) {
                 setLayoutDirection(builder.getLayoutDirection());
             }
@@ -637,6 +643,12 @@
             getBuilder().addInt(layoutDirection, SUBTYPE_LAYOUT_DIRECTION);
         }
 
+        /**
+         */
+        public boolean isEndOfSection() {
+            return mIsEndOfSection;
+        }
+
         boolean hasText() {
             return mTitleItem != null || mSubtitleItem != null;
         }
diff --git a/slices/core/api/restricted_current.txt b/slices/core/api/restricted_current.txt
index a8fe615..82062d6 100644
--- a/slices/core/api/restricted_current.txt
+++ b/slices/core/api/restricted_current.txt
@@ -229,6 +229,7 @@
     field public static final int DETERMINATE_RANGE = 0; // 0x0
     field public static final String HINT_ACTIVITY = "activity";
     field public static final String HINT_CACHED = "cached";
+    field public static final String HINT_END_OF_SECTION = "end_of_section";
     field public static final String HINT_OVERLAY = "overlay";
     field public static final String HINT_RAW = "raw";
     field public static final String HINT_SELECTION_OPTION = "selection_option";
diff --git a/slices/core/src/main/java/androidx/slice/Slice.java b/slices/core/src/main/java/androidx/slice/Slice.java
index 6a9f7ac..1d07c5d 100644
--- a/slices/core/src/main/java/androidx/slice/Slice.java
+++ b/slices/core/src/main/java/androidx/slice/Slice.java
@@ -45,6 +45,7 @@
 import static androidx.slice.SliceConvert.unwrap;
 import static androidx.slice.core.SliceHints.HINT_ACTIVITY;
 import static androidx.slice.core.SliceHints.HINT_CACHED;
+import static androidx.slice.core.SliceHints.HINT_END_OF_SECTION;
 import static androidx.slice.core.SliceHints.HINT_OVERLAY;
 import static androidx.slice.core.SliceHints.HINT_RAW;
 import static androidx.slice.core.SliceHints.HINT_SELECTION_OPTION;
@@ -139,6 +140,7 @@
             HINT_ERROR,
             HINT_ACTIVITY,
             HINT_CACHED,
+            HINT_END_OF_SECTION,
             HINT_SELECTION_OPTION,
             HINT_RAW,
             HINT_OVERLAY,
diff --git a/slices/core/src/main/java/androidx/slice/core/SliceHints.java b/slices/core/src/main/java/androidx/slice/core/SliceHints.java
index b01b25c..c85391a 100644
--- a/slices/core/src/main/java/androidx/slice/core/SliceHints.java
+++ b/slices/core/src/main/java/androidx/slice/core/SliceHints.java
@@ -70,6 +70,12 @@
     public static final String HINT_ACTIVITY = "activity";
 
     /**
+     * Hint indicating that this slice is the end of section and may need some form of visual
+     * separation.
+     */
+    public static final String HINT_END_OF_SECTION = "end_of_section";
+
+    /**
      * Hint indicating that this slice was parsed from a serialized format.
      */
     public static final String HINT_CACHED = "cached";
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowContent.java b/slices/view/src/main/java/androidx/slice/widget/RowContent.java
index 236ac24..1f3044e 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowContent.java
@@ -35,6 +35,7 @@
 import static android.app.slice.SliceItem.FORMAT_SLICE;
 import static android.app.slice.SliceItem.FORMAT_TEXT;
 
+import static androidx.slice.core.SliceHints.HINT_END_OF_SECTION;
 import static androidx.slice.core.SliceHints.SUBTYPE_SELECTION;
 import static androidx.slice.core.SliceHints.SUBTYPE_SELECTION_OPTION_KEY;
 import static androidx.slice.core.SliceHints.SUBTYPE_SELECTION_OPTION_VALUE;
@@ -87,6 +88,10 @@
      * @return whether this row has content that is valid to display.
      */
     private boolean populate(SliceItem rowSlice, boolean isHeader) {
+        if (rowSlice.hasHint(HINT_END_OF_SECTION)) {
+            showBottomDivider(true);
+        }
+
         mIsHeader = isHeader;
         if (!isValidRow(rowSlice)) {
             Log.w(TAG, "Provided SliceItem is invalid for RowContent");