Merge "Improvements to measuring view / handling padding"
diff --git a/car/build.gradle b/car/build.gradle
index a1212e2..8660f6f 100644
--- a/car/build.gradle
+++ b/car/build.gradle
@@ -9,7 +9,7 @@
 dependencies {
     api project(':appcompat-v7')
     api project(':cardview-v7')
-    api("com.android.support:design:28.0.0-alpha1") {
+    api("com.android.support:design-widget:28.0.0-alpha1") {
         exclude group: 'com.android.support', module: 'support-annotations'
         exclude group: 'com.android.support', module: 'support-compat'
         exclude group: 'com.android.support', module: 'support-core-ui'
diff --git a/fragment/src/main/java/android/support/v4/app/FragmentManager.java b/fragment/src/main/java/android/support/v4/app/FragmentManager.java
index 48807fc..0ab1497 100644
--- a/fragment/src/main/java/android/support/v4/app/FragmentManager.java
+++ b/fragment/src/main/java/android/support/v4/app/FragmentManager.java
@@ -4044,7 +4044,7 @@
             boolean more = super.getTransformation(currentTime, t);
             if (!more) {
                 mEnded = true;
-                mParent.post(this);
+                OneShotPreDrawListener.add(mParent, this);
             }
             return true;
         }
@@ -4058,7 +4058,7 @@
             boolean more = super.getTransformation(currentTime, outTransformation, scale);
             if (!more) {
                 mEnded = true;
-                mParent.post(this);
+                OneShotPreDrawListener.add(mParent, this);
             }
             return true;
         }
diff --git a/gradle.properties b/gradle.properties
index abb4a67..85bd83e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,3 +3,4 @@
 org.gradle.configureondemand=true
 org.gradle.parallel=true
 android.builder.sdkDownload=false
+android.enableD8=true
diff --git a/loader/src/androidTest/java/android/support/v4/app/LoaderInfoTest.java b/loader/src/androidTest/java/android/support/v4/app/LoaderInfoTest.java
index 5df61dc..e3ef804 100644
--- a/loader/src/androidTest/java/android/support/v4/app/LoaderInfoTest.java
+++ b/loader/src/androidTest/java/android/support/v4/app/LoaderInfoTest.java
@@ -19,7 +19,11 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import android.arch.lifecycle.Lifecycle;
+import android.arch.lifecycle.LifecycleOwner;
+import android.arch.lifecycle.LifecycleRegistry;
 import android.content.Context;
 import android.os.SystemClock;
 import android.support.annotation.Nullable;
@@ -32,6 +36,7 @@
 import android.support.v4.content.AsyncTaskLoader;
 import android.support.v4.content.Loader;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -43,6 +48,18 @@
 @SmallTest
 public class LoaderInfoTest {
 
+    private LifecycleOwner mOwner;
+    private LifecycleRegistry mRegistry;
+
+    @Before
+    public void setup() {
+        mOwner = mock(LifecycleOwner.class);
+        mRegistry = new LifecycleRegistry(mOwner);
+        when(mOwner.getLifecycle()).thenReturn(mRegistry);
+        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+    }
+
     @Rule
     public ActivityTestRule<EmptyActivity> mActivityRule =
             new ActivityTestRule<>(EmptyActivity.class);
@@ -136,6 +153,61 @@
 
     @UiThreadTest
     @Test
+    public void testMarkForRedelivery() throws Throwable {
+        DummyLoaderCallbacks loaderCallback =
+                new DummyLoaderCallbacks(mock(Context.class));
+        Loader<Boolean> loader = loaderCallback.onCreateLoader(0, null);
+        LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
+                0, null, loader);
+        loaderInfo.setCallback(mOwner, loaderCallback);
+        assertTrue("onLoadFinished should be called after setCallback",
+                loaderCallback.mOnLoadFinished);
+
+        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
+        loaderCallback.mOnLoadFinished = false;
+        loaderInfo.markForRedelivery();
+        assertFalse("onLoadFinished should not be called when stopped after markForRedelivery",
+                loaderCallback.mOnLoadFinished);
+
+        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+        assertTrue("onLoadFinished should be called after markForRedelivery",
+                loaderCallback.mOnLoadFinished);
+    }
+
+    @UiThreadTest
+    @Test
+    public void testMarkForRedelivery_replace() throws Throwable {
+        DummyLoaderCallbacks initialCallback =
+                new DummyLoaderCallbacks(mock(Context.class));
+        Loader<Boolean> loader = initialCallback.onCreateLoader(0, null);
+        LoaderManagerImpl.LoaderInfo<Boolean> loaderInfo = new LoaderManagerImpl.LoaderInfo<>(
+                0, null, loader);
+        loaderInfo.setCallback(mOwner, initialCallback);
+        assertTrue("onLoadFinished for initial should be called after setCallback initial",
+                initialCallback.mOnLoadFinished);
+
+        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
+        initialCallback.mOnLoadFinished = false;
+        loaderInfo.markForRedelivery();
+        assertFalse("onLoadFinished should not be called when stopped after markForRedelivery",
+                initialCallback.mOnLoadFinished);
+
+        // Replace the callback
+        final DummyLoaderCallbacks replacementCallback =
+                new DummyLoaderCallbacks(mock(Context.class));
+        loaderInfo.setCallback(mOwner, replacementCallback);
+
+        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
+        assertFalse("onLoadFinished for initial should not be called "
+                        + "after setCallback replacement",
+                initialCallback.mOnLoadFinished);
+        assertTrue("onLoadFinished for replacement should be called "
+                        + " after setCallback replacement",
+                replacementCallback.mOnLoadFinished);
+    }
+
+    @UiThreadTest
+    @Test
     public void testDestroy() throws Throwable {
         final DummyLoaderCallbacks loaderCallback = new DummyLoaderCallbacks(mock(Context.class));
         final Loader<Boolean> loader = loaderCallback.onCreateLoader(0, null);
diff --git a/loader/src/main/java/android/support/v4/app/LoaderManagerImpl.java b/loader/src/main/java/android/support/v4/app/LoaderManagerImpl.java
index fbda089..edb6aaf 100644
--- a/loader/src/main/java/android/support/v4/app/LoaderManagerImpl.java
+++ b/loader/src/main/java/android/support/v4/app/LoaderManagerImpl.java
@@ -110,7 +110,8 @@
                 // Removing and re-adding the observer ensures that the
                 // observer is called again, even if they had already
                 // received the current data
-                removeObserver(observer);
+                // Use super.removeObserver to avoid nulling out mLifecycleOwner & mObserver
+                super.removeObserver(observer);
                 observe(lifecycleOwner, observer);
             }
         }
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 6230dd0..125d0db 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
@@ -18,6 +18,10 @@
 
 import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
+import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
+
 import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -135,27 +139,27 @@
                 .setPrimaryAction(primaryAction)
                 .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("MON")
                         .addTitleText("69\u00B0"))
                 .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_2),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("TUE")
                         .addTitleText("71\u00B0"))
                 .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_3),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("WED")
                         .addTitleText("76\u00B0"))
                 .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_4),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("THU")
                         .addTitleText("72\u00B0"))
                 .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("FRI")
                         .addTitleText("68\u00B0")))
                 .build();
@@ -178,25 +182,25 @@
                 .addGrid(b -> b
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.slices_1),
-                            GridBuilder.LARGE_IMAGE))
+                            LARGE_IMAGE))
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.slices_2),
-                                GridBuilder.LARGE_IMAGE))
+                                LARGE_IMAGE))
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.slices_3),
-                                GridBuilder.LARGE_IMAGE))
+                                LARGE_IMAGE))
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.slices_4),
-                                GridBuilder.LARGE_IMAGE))
+                                LARGE_IMAGE))
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.slices_2),
-                                GridBuilder.LARGE_IMAGE))
+                                LARGE_IMAGE))
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.slices_3),
-                                GridBuilder.LARGE_IMAGE))
+                                LARGE_IMAGE))
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.slices_4),
-                                GridBuilder.LARGE_IMAGE)))
+                                LARGE_IMAGE)))
                 .build();
     }
 
@@ -213,22 +217,22 @@
                 .addGrid(gb
                         .addCell(new GridBuilder.CellBuilder(gb)
                                 .addImage(Icon.createWithResource(getContext(), R.drawable.ic_call),
-                                        GridBuilder.ICON_IMAGE)
+                                        ICON_IMAGE)
                                 .addText("Call")
                                 .setContentIntent(getBroadcastIntent(ACTION_TOAST, "call")))
                         .addCell(new GridBuilder.CellBuilder(gb)
                                 .addImage(Icon.createWithResource(getContext(), R.drawable.ic_text),
-                                        GridBuilder.ICON_IMAGE)
+                                        ICON_IMAGE)
                                 .addText("Text")
                                 .setContentIntent(getBroadcastIntent(ACTION_TOAST, "text")))
                         .addCell(new GridBuilder.CellBuilder(gb)
                                 .addImage(Icon.createWithResource(getContext(),
-                                        R.drawable.ic_video), GridBuilder.ICON_IMAGE)
+                                        R.drawable.ic_video), ICON_IMAGE)
                                 .setContentIntent(getBroadcastIntent(ACTION_TOAST, "video"))
                                 .addText("Video"))
                         .addCell(new GridBuilder.CellBuilder(gb)
                                 .addImage(Icon.createWithResource(getContext(),
-                                        R.drawable.ic_email), GridBuilder.ICON_IMAGE)
+                                        R.drawable.ic_email), ICON_IMAGE)
                                 .addText("Email")
                                 .setContentIntent(getBroadcastIntent(ACTION_TOAST, "email"))))
                 .build();
@@ -321,7 +325,7 @@
                 .addGrid(b -> b
                     .addCell(cb -> cb
                         .addImage(Icon.createWithResource(getContext(), R.drawable.reservation),
-                            GridBuilder.LARGE_IMAGE)))
+                            LARGE_IMAGE)))
                 .addGrid(b -> b
                     .addCell(cb -> cb
                         .addTitleText("Check In")
@@ -438,8 +442,7 @@
             Icon icon = Icon.createWithResource(getContext(), iconId);
             final String networkName = "Network" + i;
             ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(lb);
-            rb.setTitleItem(icon)
-                .setTitle("Network" + networkName);
+            rb.setTitleItem(icon, ICON_IMAGE).setTitle("Network" + networkName);
             boolean locked = i % 3 == 0;
             if (locked) {
                 rb.addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_lock));
@@ -568,7 +571,7 @@
     private GridBuilder.CellBuilder createCell(GridBuilder.CellBuilder cb, String text1,
             String text2, Icon icon, boolean isLoading) {
         return cb.addText(text1, isLoading).addText(text2, isLoading).addImage(icon,
-                GridBuilder.SMALL_IMAGE, isLoading);
+                SMALL_IMAGE, isLoading);
     }
 
     private PendingIntent getIntent(String action) {
diff --git a/slices/builders/api/current.txt b/slices/builders/api/current.txt
index 6200f15..5aa4f42 100644
--- a/slices/builders/api/current.txt
+++ b/slices/builders/api/current.txt
@@ -8,9 +8,9 @@
     method public androidx.slice.builders.GridBuilder addSeeMoreCell(androidx.slice.builders.GridBuilder.CellBuilder);
     method public androidx.slice.builders.GridBuilder addSeeMoreCell(java.util.function.Consumer<androidx.slice.builders.GridBuilder.CellBuilder>);
     method public androidx.slice.builders.GridBuilder setPrimaryAction(androidx.slice.builders.SliceAction);
-    field public static final int ICON_IMAGE = 0; // 0x0
-    field public static final int LARGE_IMAGE = 2; // 0x2
-    field public static final int SMALL_IMAGE = 1; // 0x1
+    field public static final deprecated int ICON_IMAGE = 0; // 0x0
+    field public static final deprecated int LARGE_IMAGE = 2; // 0x2
+    field public static final deprecated int SMALL_IMAGE = 1; // 0x1
   }
 
   public static final class GridBuilder.CellBuilder extends androidx.slice.builders.TemplateSliceBuilder {
@@ -45,6 +45,9 @@
     method public androidx.slice.builders.ListBuilder addSeeMoreRow(java.util.function.Consumer<androidx.slice.builders.ListBuilder.RowBuilder>);
     method public androidx.slice.builders.ListBuilder setHeader(androidx.slice.builders.ListBuilder.HeaderBuilder);
     method public androidx.slice.builders.ListBuilder setHeader(java.util.function.Consumer<androidx.slice.builders.ListBuilder.HeaderBuilder>);
+    field public static final int ICON_IMAGE = 0; // 0x0
+    field public static final int LARGE_IMAGE = 2; // 0x2
+    field public static final int SMALL_IMAGE = 1; // 0x1
   }
 
   public static class ListBuilder.HeaderBuilder extends androidx.slice.builders.TemplateSliceBuilder {
@@ -76,8 +79,10 @@
     ctor public ListBuilder.RowBuilder(androidx.slice.builders.ListBuilder, android.net.Uri);
     ctor public ListBuilder.RowBuilder(android.content.Context, android.net.Uri);
     method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(long);
-    method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon);
-    method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, boolean);
+    method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon);
+    method public deprecated androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, boolean);
+    method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, int);
+    method public androidx.slice.builders.ListBuilder.RowBuilder addEndItem(android.graphics.drawable.Icon, int, boolean);
     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 setPrimaryAction(androidx.slice.builders.SliceAction);
@@ -86,8 +91,10 @@
     method public androidx.slice.builders.ListBuilder.RowBuilder setTitle(java.lang.CharSequence);
     method public androidx.slice.builders.ListBuilder.RowBuilder setTitle(java.lang.CharSequence, boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(long);
-    method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon);
-    method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, boolean);
+    method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon);
+    method public deprecated androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, boolean);
+    method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, int);
+    method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(android.graphics.drawable.Icon, int, boolean);
     method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.slice.builders.SliceAction);
     method public androidx.slice.builders.ListBuilder.RowBuilder setTitleItem(androidx.slice.builders.SliceAction, boolean);
   }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java
index bfa6a65..e0c3190 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/GridBuilder.java
@@ -22,7 +22,6 @@
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Build;
-import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
@@ -46,25 +45,25 @@
     private boolean mHasSeeMore;
 
     /**
-     * @hide
+     * Indicates that an image should be presented as an icon and it can be tinted.
+     *
+     * @deprecated use {@link ListBuilder#ICON_IMAGE}
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    @IntDef({
-            LARGE_IMAGE, SMALL_IMAGE, ICON_IMAGE
-    })
-    public @interface ImageMode{}
-
-    /**
-     * Indicates that an image presented in the grid is a icon and it can be tinted.
-     */
+    @Deprecated
     public static final int ICON_IMAGE = 0;
     /**
-     * Indicates that an image presented in the grid should be displayed in a small format.
+     * Indicates that an image should be presented in a smaller size and it shouldn't be tinted.
+     *
+     * @deprecated use {@link ListBuilder#SMALL_IMAGE}
      */
+    @Deprecated
     public static final int SMALL_IMAGE = 1;
     /**
-     * Indicates that an image presented in the grid should be displayed in a large format.
+     * Indicates that an image presented in a larger size and it shouldn't be tinted.
+     *
+     * @deprecated use {@link ListBuilder#LARGE_IMAGE}
      */
+    @Deprecated
     public static final int LARGE_IMAGE = 2;
 
     /**
@@ -288,7 +287,7 @@
         @NonNull
         @Deprecated
         public CellBuilder addLargeImage(@NonNull Icon image) {
-            return addImage(image, LARGE_IMAGE, false /* isLoading */);
+            return addImage(image, ListBuilder.LARGE_IMAGE, false /* isLoading */);
         }
 
         /**
@@ -304,7 +303,7 @@
         @NonNull
         @Deprecated
         public CellBuilder addLargeImage(@Nullable Icon image, boolean isLoading) {
-            return addImage(image, LARGE_IMAGE, isLoading);
+            return addImage(image, ListBuilder.LARGE_IMAGE, isLoading);
         }
 
         /**
@@ -316,7 +315,7 @@
         @NonNull
         @Deprecated
         public CellBuilder addImage(@NonNull Icon image) {
-            return addImage(image, SMALL_IMAGE, false /* isLoading */);
+            return addImage(image, ListBuilder.SMALL_IMAGE, false /* isLoading */);
         }
 
         /**
@@ -332,7 +331,7 @@
         @NonNull
         @Deprecated
         public CellBuilder addImage(@Nullable Icon image, boolean isLoading) {
-            return addImage(image, SMALL_IMAGE, isLoading);
+            return addImage(image, ListBuilder.SMALL_IMAGE, isLoading);
         }
 
         /**
@@ -342,12 +341,12 @@
          * @param image the image to display in the cell.
          * @param imageMode the mode that image should be displayed in.
          *
-         * @see #ICON_IMAGE
-         * @see #SMALL_IMAGE
-         * @see #LARGE_IMAGE
+         * @see ListBuilder#ICON_IMAGE
+         * @see ListBuilder#SMALL_IMAGE
+         * @see ListBuilder#LARGE_IMAGE
          */
         @NonNull
-        public CellBuilder addImage(@NonNull Icon image, @ImageMode int imageMode) {
+        public CellBuilder addImage(@NonNull Icon image, @ListBuilder.ImageMode int imageMode) {
             return addImage(image, imageMode, false /* isLoading */);
         }
 
@@ -363,12 +362,12 @@
          * @param isLoading indicates whether the app is doing work to load the added content in the
          *                  background or not.
          *
-         * @see #ICON_IMAGE
-         * @see #SMALL_IMAGE
-         * @see #LARGE_IMAGE
+         * @see ListBuilder#ICON_IMAGE
+         * @see ListBuilder#SMALL_IMAGE
+         * @see ListBuilder#LARGE_IMAGE
          */
         @NonNull
-        public CellBuilder addImage(@Nullable Icon image, @ImageMode int imageMode,
+        public CellBuilder addImage(@Nullable Icon image, @ListBuilder.ImageMode int imageMode,
                 boolean isLoading) {
             mImpl.addImage(image, imageMode, isLoading);
             return this;
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 786a69e..6a4b385 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/ListBuilder.java
@@ -25,6 +25,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.support.annotation.ColorInt;
+import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
@@ -62,6 +63,28 @@
     private androidx.slice.builders.impl.ListBuilder mImpl;
 
     /**
+     * @hide
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef({
+            LARGE_IMAGE, SMALL_IMAGE, ICON_IMAGE
+    })
+    public @interface ImageMode{}
+
+    /**
+     * Indicates that an image should be presented as an icon and it can be tinted.
+     */
+    public static final int ICON_IMAGE = 0;
+    /**
+     * Indicates that an image should be presented in a smaller size and it shouldn't be tinted.
+     */
+    public static final int SMALL_IMAGE = 1;
+    /**
+     * Indicates that an image presented in a larger size and it shouldn't be tinted.
+     */
+    public static final int LARGE_IMAGE = 2;
+
+    /**
      * Create a builder which will construct a slice that will display rows of content.
      * @param uri Uri to tag for this slice.
      */
@@ -473,11 +496,13 @@
         /**
          * Sets the title item to be the provided icon. There can only be one title item, this
          * will replace any other title items that may have been set.
+         *
+         * @deprecated use ListBuilder{@link #setTitleItem(Icon, int)} instead.
          */
+        @Deprecated
         @NonNull
         public RowBuilder setTitleItem(@NonNull Icon icon) {
-            mImpl.setTitleItem(icon);
-            return this;
+            return setTitleItem(icon, ICON_IMAGE);
         }
 
         /**
@@ -489,10 +514,51 @@
          * </p>
          * @param isLoading indicates whether the app is doing work to load the added content in the
          *                  background or not.
+         *
+         * @deprecated use ListBuilder{@link #setTitleItem(Icon, int, boolean)} instead.
          */
+        @Deprecated
         @NonNull
         public RowBuilder setTitleItem(@Nullable Icon icon, boolean isLoading) {
-            mImpl.setTitleItem(icon, isLoading);
+            return setTitleItem(icon, ICON_IMAGE, isLoading);
+        }
+
+        /**
+         * Sets the title item to be the provided icon. There can only be one title item, this
+         * will replace any other title items that may have been set.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
+         *
+         * @see #ICON_IMAGE
+         * @see #SMALL_IMAGE
+         * @see #LARGE_IMAGE
+         */
+        public RowBuilder setTitleItem(@NonNull Icon icon, @ImageMode int imageMode) {
+            mImpl.setTitleItem(icon, imageMode, false /* isLoading */);
+            return this;
+        }
+
+        /**
+         * Sets the title item to be the provided icon. There can only be one title item, this
+         * will replace any other title items that may have been set.
+         * <p>
+         * When set to true, the parameter {@code isLoading} indicates that the app is doing work
+         * to load this content in the background, in this case the template displays a placeholder
+         * until updated.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
+         * @param isLoading whether this content is being loaded in the background.
+         *
+         * @see #ICON_IMAGE
+         * @see #SMALL_IMAGE
+         * @see #LARGE_IMAGE
+         */
+        @NonNull
+        public RowBuilder setTitleItem(@Nullable Icon icon, @ImageMode int imageMode,
+                boolean isLoading) {
+            mImpl.setTitleItem(icon, imageMode, isLoading /* isLoading */);
             return this;
         }
 
@@ -596,10 +662,13 @@
          * Adds an icon to be displayed at the end of the row. A mixture of icons and actions
          * is not permitted. If an action has already been added this will throw
          * {@link IllegalArgumentException}.
+         *
+         * @deprecated use ListBuilder{@link #addEndItem(Icon, int)} instead.
          */
+        @Deprecated
         @NonNull
         public RowBuilder addEndItem(@NonNull Icon icon) {
-            return addEndItem(icon, false /* isLoading */);
+            return addEndItem(icon, ICON_IMAGE, false /* isLoading */);
         }
 
         /**
@@ -612,15 +681,54 @@
          * </p>
          * @param isLoading indicates whether the app is doing work to load the added content in the
          *                  background or not.
+         *
+         * @deprecated use ListBuilder{@link #addEndItem(Icon, int, boolean)} instead.
          */
+        @Deprecated
         @NonNull
         public RowBuilder addEndItem(@NonNull Icon icon, boolean isLoading) {
+            return addEndItem(icon, ICON_IMAGE, isLoading);
+        }
+
+        /**
+         * Adds an icon to be displayed at the end of the row.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
+         *
+         * @see #ICON_IMAGE
+         * @see #SMALL_IMAGE
+         * @see #LARGE_IMAGE
+         */
+        @NonNull
+        public RowBuilder addEndItem(@NonNull Icon icon, @ImageMode int imageMode) {
+            return addEndItem(icon, imageMode, false /* isLoading */);
+        }
+
+        /**
+         * Adds an icon to be displayed at the end of the row.
+         * <p>
+         * When set to true, the parameter {@code isLoading} indicates that the app is doing work
+         * to load this content in the background, in this case the template displays a placeholder
+         * until updated.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
+         * @param isLoading whether this content is being loaded in the background.
+         *
+         * @see #ICON_IMAGE
+         * @see #SMALL_IMAGE
+         * @see #LARGE_IMAGE
+         */
+        @NonNull
+        public RowBuilder addEndItem(@Nullable Icon icon, @ImageMode int imageMode,
+                boolean isLoading) {
             if (mHasEndActionOrToggle) {
                 throw new IllegalArgumentException("Trying to add an icon to end items when an"
                         + "action has already been added. End items cannot have a mixture of "
                         + "actions and icons.");
             }
-            mImpl.addEndItem(icon, isLoading);
+            mImpl.addEndItem(icon, imageMode, isLoading);
             mHasEndImage = true;
             return this;
         }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/GridBuilderListV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/GridBuilderListV1Impl.java
index e4c3dce..da33bfa 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/GridBuilderListV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/GridBuilderListV1Impl.java
@@ -26,8 +26,8 @@
 import static android.app.slice.Slice.HINT_TITLE;
 import static android.support.annotation.RestrictTo.Scope.LIBRARY;
 
-import static androidx.slice.builders.GridBuilder.ICON_IMAGE;
-import static androidx.slice.builders.GridBuilder.LARGE_IMAGE;
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
 
 import android.app.PendingIntent;
 import android.graphics.drawable.Icon;
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
index 032e0ce..bc9641c 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilder.java
@@ -172,8 +172,11 @@
         /**
          * Sets the title item to be the provided icon. There can only be one title item, this
          * will replace any other title items that may have been set.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
          */
-        void setTitleItem(Icon icon);
+        void setTitleItem(Icon icon, int imageMode);
 
         /**
          * Sets the title item to be the provided icon. There can only be one title item, this
@@ -182,8 +185,12 @@
          * When set to true, the parameter {@code isLoading} indicates that the app is doing work
          * to load this content in the background, in this case the template displays a placeholder
          * until updated.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
+         * @param isLoading whether this content is being loaded in the background.
          */
-        void setTitleItem(Icon icon, boolean isLoading);
+        void setTitleItem(Icon icon, int imageMode, boolean isLoading);
 
         /**
          * Sets the title item to be a tappable icon. There can only be one title item, this will
@@ -241,8 +248,11 @@
 
         /**
          * Adds an icon to be displayed at the end of the row.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
          */
-        void addEndItem(Icon icon);
+        void addEndItem(Icon icon, int imageMode);
 
         /**
          * Adds an icon to be displayed at the end of the row.
@@ -250,8 +260,12 @@
          * When set to true, the parameter {@code isLoading} indicates that the app is doing work
          * to load this content in the background, in this case the template displays a placeholder
          * until updated.
+         *
+         * @param icon the image to display.
+         * @param imageMode the mode that image should be displayed in.
+         * @param isLoading whether this content is being loaded in the background.
          */
-        void addEndItem(Icon icon, boolean isLoading);
+        void addEndItem(Icon icon, int imageMode, boolean isLoading);
 
         /**
          * Adds a tappable icon to be displayed at the end of the row.
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
index 8ef53e7..7601a11 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderBasicImpl.java
@@ -165,20 +165,6 @@
         /**
          */
         @Override
-        public void addEndItem(Icon icon) {
-
-        }
-
-        /**
-         */
-        @Override
-        public void addEndItem(Icon icon, boolean isLoading) {
-
-        }
-
-        /**
-         */
-        @Override
         public void addEndItem(SliceAction action) {
 
         }
@@ -200,13 +186,14 @@
         /**
          */
         @Override
-        public void setTitleItem(Icon icon) {
+        public void setTitleItem(Icon icon, int imageMode) {
+
         }
 
         /**
          */
         @Override
-        public void setTitleItem(Icon icon, boolean isLoading) {
+        public void setTitleItem(Icon icon, int imageMode, boolean isLoading) {
 
         }
 
@@ -266,6 +253,20 @@
         /**
          */
         @Override
+        public void addEndItem(Icon icon, int imageMode) {
+
+        }
+
+        /**
+         */
+        @Override
+        public void addEndItem(Icon icon, int imageMode, boolean isLoading) {
+
+        }
+
+        /**
+         */
+        @Override
         public void apply(Slice.Builder builder) {
 
         }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
index 84c7325..0ee9dda 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/ListBuilderV1Impl.java
@@ -29,6 +29,8 @@
 import static android.app.slice.SliceItem.FORMAT_TEXT;
 import static android.support.annotation.RestrictTo.Scope.LIBRARY;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
 import static androidx.slice.core.SliceHints.SUBTYPE_MAX;
 import static androidx.slice.core.SliceHints.SUBTYPE_RANGE;
 import static androidx.slice.core.SliceHints.SUBTYPE_VALUE;
@@ -38,7 +40,6 @@
 import android.net.Uri;
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 import android.support.annotation.RestrictTo;
 
 import java.util.ArrayList;
@@ -314,15 +315,27 @@
          */
         @NonNull
         @Override
-        public void setTitleItem(@NonNull Icon icon) {
-            setTitleItem(icon, false /* isLoading */);
+        public void setTitleItem(Icon icon, int imageMode) {
+            setTitleItem(icon, imageMode, false /* isLoading */);
         }
 
         /**
          */
+        @NonNull
         @Override
-        public void setTitleItem(@Nullable Icon icon, boolean isLoading) {
-            Slice.Builder sb = new Slice.Builder(getBuilder()).addIcon(icon, null /* subtype */);
+        public void setTitleItem(Icon icon, int imageMode, boolean isLoading) {
+            ArrayList<String> hints = new ArrayList<>();
+            if (imageMode != ICON_IMAGE) {
+                hints.add(HINT_NO_TINT);
+            }
+            if (imageMode == LARGE_IMAGE) {
+                hints.add(HINT_LARGE);
+            }
+            if (isLoading) {
+                hints.add(HINT_PARTIAL);
+            }
+            Slice.Builder sb = new Slice.Builder(getBuilder())
+                    .addIcon(icon, null /* subType */, hints);
             if (isLoading) {
                 sb.addHints(HINT_PARTIAL);
             }
@@ -405,16 +418,27 @@
          */
         @NonNull
         @Override
-        public void addEndItem(@NonNull Icon icon) {
-            addEndItem(icon, false /* isLoading */);
+        public void addEndItem(Icon icon, int imageMode) {
+            addEndItem(icon, imageMode, false /* isLoading */);
         }
 
         /**
          */
+        @NonNull
         @Override
-        public void addEndItem(Icon icon, boolean isLoading) {
-            Slice.Builder sb = new Slice.Builder(getBuilder()).addIcon(icon, null /* subType */,
-                    HINT_NO_TINT, HINT_LARGE);
+        public void addEndItem(Icon icon, int imageMode, boolean isLoading) {
+            ArrayList<String> hints = new ArrayList<>();
+            if (imageMode != ICON_IMAGE) {
+                hints.add(HINT_NO_TINT);
+            }
+            if (imageMode == LARGE_IMAGE) {
+                hints.add(HINT_LARGE);
+            }
+            if (isLoading) {
+                hints.add(HINT_PARTIAL);
+            }
+            Slice.Builder sb = new Slice.Builder(getBuilder())
+                    .addIcon(icon, null /* subType */, hints);
             if (isLoading) {
                 sb.addHints(HINT_PARTIAL);
             }
diff --git a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java
index 46481bf..6b08db0 100644
--- a/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java
+++ b/slices/builders/src/main/java/androidx/slice/builders/impl/MessagingListV1Impl.java
@@ -18,6 +18,8 @@
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY;
 
+import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
+
 import android.graphics.drawable.Icon;
 import android.support.annotation.RestrictTo;
 
@@ -82,7 +84,7 @@
          */
         @Override
         public void addSource(Icon source) {
-            mListBuilder.setTitleItem(source);
+            mListBuilder.setTitleItem(source, SMALL_IMAGE);
         }
 
         /**
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 3c5aa5b..31475d9 100644
--- a/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
+++ b/slices/view/src/androidTest/java/androidx/slice/render/SliceCreator.java
@@ -18,6 +18,10 @@
 
 import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
+import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
+
 import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -108,27 +112,27 @@
         gb.setPrimaryAction(primaryAction);
         gb.addCell(new GridBuilder.CellBuilder(gb)
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("MON")
                         .addTitleText("69\u00B0"))
                 .addCell(new GridBuilder.CellBuilder(gb)
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_2),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("TUE")
                         .addTitleText("71\u00B0"))
                 .addCell(new GridBuilder.CellBuilder(gb)
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_3),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("WED")
                         .addTitleText("76\u00B0"))
                 .addCell(new GridBuilder.CellBuilder(gb)
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_4),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("THU")
                         .addTitleText("72\u00B0"))
                 .addCell(new GridBuilder.CellBuilder(gb)
                         .addImage(Icon.createWithResource(getContext(), R.drawable.weather_1),
-                                GridBuilder.SMALL_IMAGE)
+                                SMALL_IMAGE)
                         .addText("FRI")
                         .addTitleText("68\u00B0"));
         return b.addGrid(gb).build();
@@ -139,16 +143,16 @@
         GridBuilder gb = new GridBuilder(b);
         return gb.addCell(new GridBuilder.CellBuilder(gb)
                     .addImage(Icon.createWithResource(getContext(), R.drawable.slices_1),
-                            GridBuilder.LARGE_IMAGE))
+                            LARGE_IMAGE))
                 .addCell(new GridBuilder.CellBuilder(gb)
                     .addImage(Icon.createWithResource(getContext(), R.drawable.slices_2),
-                            GridBuilder.LARGE_IMAGE))
+                            LARGE_IMAGE))
                 .addCell(new GridBuilder.CellBuilder(gb)
                     .addImage(Icon.createWithResource(getContext(), R.drawable.slices_3),
-                            GridBuilder.LARGE_IMAGE))
+                            LARGE_IMAGE))
                 .addCell(new GridBuilder.CellBuilder(gb)
                     .addImage(Icon.createWithResource(getContext(), R.drawable.slices_4),
-                            GridBuilder.LARGE_IMAGE))
+                            LARGE_IMAGE))
                 .build();
     }
 
@@ -164,22 +168,22 @@
                 .addGrid(gb
                         .addCell(new GridBuilder.CellBuilder(gb)
                             .addImage(Icon.createWithResource(getContext(), R.drawable.ic_call),
-                                    GridBuilder.ICON_IMAGE)
+                                    ICON_IMAGE)
                             .addText("Call")
                             .setContentIntent(getBroadcastIntent(ACTION_TOAST, "call")))
                         .addCell(new GridBuilder.CellBuilder(gb)
                             .addImage(Icon.createWithResource(getContext(), R.drawable.ic_text),
-                                    GridBuilder.ICON_IMAGE)
+                                    ICON_IMAGE)
                             .addText("Text")
                             .setContentIntent(getBroadcastIntent(ACTION_TOAST, "text")))
                         .addCell(new GridBuilder.CellBuilder(gb)
                             .addImage(Icon.createWithResource(getContext(), R.drawable.ic_video),
-                                    GridBuilder.ICON_IMAGE)
+                                    ICON_IMAGE)
                             .setContentIntent(getBroadcastIntent(ACTION_TOAST, "video"))
                             .addText("Video"))
                         .addCell(new GridBuilder.CellBuilder(gb)
                             .addImage(Icon.createWithResource(getContext(), R.drawable.ic_email),
-                                    GridBuilder.ICON_IMAGE)
+                                    ICON_IMAGE)
                             .addText("Email")
                             .setContentIntent(getBroadcastIntent(ACTION_TOAST, "email"))))
                 .build();
@@ -313,7 +317,7 @@
         lb.setColor(0xff4285f4);
         lb.addRow(new ListBuilder.RowBuilder(lb)
                 .setTitle("Wi-fi")
-                .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_wifi))
+                .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_wifi), ICON_IMAGE)
                 .setSubtitle(state)
                 .addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED, null),
                         "Toggle wifi", finalWifiEnabled))
@@ -326,8 +330,8 @@
             final int iconId = wifiIcons[i % wifiIcons.length];
             Icon icon = Icon.createWithResource(getContext(), iconId);
             final String networkName = "Network" + i;
-            ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(lb);
-            rb.setTitleItem(icon)
+            ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(lb)
+                    .setTitleItem(icon, ICON_IMAGE)
                     .setTitle("Network" + networkName);
             boolean locked = i % 3 == 0;
             if (locked) {
diff --git a/slices/view/src/main/java/androidx/slice/widget/GridContent.java b/slices/view/src/main/java/androidx/slice/widget/GridContent.java
index f883643..70bfb20 100644
--- a/slices/view/src/main/java/androidx/slice/widget/GridContent.java
+++ b/slices/view/src/main/java/androidx/slice/widget/GridContent.java
@@ -27,6 +27,10 @@
 import static android.app.slice.SliceItem.FORMAT_TEXT;
 import static android.app.slice.SliceItem.FORMAT_TIMESTAMP;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+import static androidx.slice.builders.ListBuilder.LARGE_IMAGE;
+import static androidx.slice.builders.ListBuilder.SMALL_IMAGE;
+
 import android.app.slice.Slice;
 import android.content.Context;
 import android.content.res.Resources;
@@ -38,7 +42,7 @@
 import java.util.List;
 
 import androidx.slice.SliceItem;
-import androidx.slice.builders.GridBuilder;
+import androidx.slice.builders.ListBuilder;
 import androidx.slice.core.SliceQuery;
 import androidx.slice.view.R;
 
@@ -55,7 +59,7 @@
     private ArrayList<CellContent> mGridContent = new ArrayList<>();
     private int mMaxCellLineCount;
     private boolean mHasImage;
-    private @GridBuilder.ImageMode int mLargestImageMode;
+    private @ListBuilder.ImageMode int mLargestImageMode;
 
     private int mBigPicMinHeight;
     private int mBigPicMaxHeight;
@@ -209,13 +213,13 @@
         if (mAllImages) {
             return mGridContent.size() == 1
                     ? isSmall ? mBigPicMinHeight : mBigPicMaxHeight
-                    : mLargestImageMode == GridBuilder.ICON_IMAGE ? mMinHeight : mAllImagesHeight;
+                    : mLargestImageMode == ICON_IMAGE ? mMinHeight : mAllImagesHeight;
         } else {
             boolean twoLines = getMaxCellLineCount() > 1;
             boolean hasImage = hasImage();
             return (twoLines && !isSmall)
                     ? hasImage ? mMaxHeight : mMinHeight
-                    : mLargestImageMode == GridBuilder.ICON_IMAGE ? mMinHeight : mImageTextHeight;
+                    : mLargestImageMode == ICON_IMAGE ? mMinHeight : mImageTextHeight;
         }
     }
 
@@ -264,10 +268,10 @@
                     } else if (imageCount < 1 && FORMAT_IMAGE.equals(item.getFormat())) {
                         if (item.hasHint(Slice.HINT_NO_TINT)) {
                             mImageMode = item.hasHint(Slice.HINT_LARGE)
-                                    ? GridBuilder.LARGE_IMAGE
-                                    : GridBuilder.SMALL_IMAGE;
+                                    ? LARGE_IMAGE
+                                    : SMALL_IMAGE;
                         } else {
-                            mImageMode = GridBuilder.ICON_IMAGE;
+                            mImageMode = ICON_IMAGE;
                         }
                         imageCount++;
                         mHasImage = true;
diff --git a/slices/view/src/main/java/androidx/slice/widget/RowView.java b/slices/view/src/main/java/androidx/slice/widget/RowView.java
index 8bc93bd..49001f4 100644
--- a/slices/view/src/main/java/androidx/slice/widget/RowView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/RowView.java
@@ -94,12 +94,15 @@
     private boolean mIsHeader;
     private List<SliceItem> mHeaderActions;
 
+    private int mImageSize;
     private int mIconSize;
     private int mPadding;
 
     public RowView(Context context) {
         super(context);
         mIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.abc_slice_icon_size);
+        mImageSize = getContext().getResources().getDimensionPixelSize(
+                R.dimen.abc_slice_small_image_size);
         mPadding = getContext().getResources().getDimensionPixelSize(R.dimen.abc_slice_padding);
         inflate(context, R.layout.abc_slice_small_template, this);
 
@@ -426,13 +429,17 @@
         if (image != null) {
             ImageView iv = new ImageView(getContext());
             iv.setImageIcon(image.getIcon());
-            if (color != -1 && !sliceItem.hasHint(HINT_NO_TINT)) {
-                iv.setColorFilter(color);
+            int size = mImageSize;
+            if (!image.hasHint(HINT_NO_TINT)) {
+                if (color != -1) {
+                    iv.setColorFilter(color);
+                }
+                size = mIconSize;
             }
             container.addView(iv);
             LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) iv.getLayoutParams();
-            lp.width = mIconSize;
-            lp.height = mIconSize;
+            lp.width = size;
+            lp.height = size;
             lp.setMarginStart(padding);
             addedView = iv;
         } else if (timeStamp != null) {
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 9bf058c..af9e4ed 100644
--- a/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
+++ b/slices/view/src/main/java/androidx/slice/widget/ShortcutView.java
@@ -17,9 +17,9 @@
 package androidx.slice.widget;
 
 import static android.app.slice.Slice.HINT_LARGE;
+import static android.app.slice.Slice.HINT_NO_TINT;
 import static android.app.slice.Slice.HINT_TITLE;
 import static android.app.slice.Slice.SUBTYPE_COLOR;
-import static android.app.slice.Slice.SUBTYPE_SOURCE;
 import static android.app.slice.SliceItem.FORMAT_ACTION;
 import static android.app.slice.SliceItem.FORMAT_IMAGE;
 import static android.app.slice.SliceItem.FORMAT_INT;
@@ -87,14 +87,16 @@
         ShapeDrawable circle = new ShapeDrawable(new OvalShape());
         circle.setTint(color);
         ImageView iv = new ImageView(getContext());
-        iv.setBackground(circle);
+        if (mIcon != null && !mIcon.hasHint(HINT_NO_TINT)) {
+            // Only set the background if we're tintable
+            iv.setBackground(circle);
+        }
         addView(iv);
         if (mIcon != null) {
-            final boolean isLarge = mIcon.hasHint(HINT_LARGE)
-                    || SUBTYPE_SOURCE.equals(mIcon.getSubType());
-            final int iconSize = isLarge ? mLargeIconSize : mSmallIconSize;
+            boolean isImage = mIcon.hasHint(HINT_NO_TINT);
+            final int iconSize = isImage ? mLargeIconSize : mSmallIconSize;
             SliceViewUtil.createCircledIcon(getContext(), iconSize, mIcon.getIcon(),
-                    isLarge, this /* parent */);
+                    isImage, this /* parent */);
             mUri = slice.getUri();
             setClickable(true);
         } else {
diff --git a/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java b/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java
index d1aabbe..8c6c870 100644
--- a/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java
+++ b/slices/view/src/main/java/androidx/slice/widget/SliceViewUtil.java
@@ -159,6 +159,8 @@
             Icon icon, boolean isLarge, ViewGroup parent) {
         ImageView v = new ImageView(context);
         v.setImageIcon(icon);
+        v.setScaleType(isLarge ? ImageView.ScaleType.CENTER_CROP
+                : ImageView.ScaleType.CENTER_INSIDE);
         parent.addView(v);
         FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
         if (isLarge) {
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/TestActivity.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/TestActivity.java
index f94d9d6..7a1a31f 100644
--- a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/TestActivity.java
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/TestActivity.java
@@ -20,11 +20,14 @@
 import android.support.v4.app.FragmentActivity;
 
 import androidx.viewpager2.test.R;
+import androidx.viewpager2.widget.ViewPager2;
 
 public class TestActivity extends FragmentActivity {
     @Override
     public void onCreate(Bundle bundle) {
         super.onCreate(bundle);
         setContentView(R.layout.activity_test_layout);
+
+        ViewPager2Tests.sAdapterStrategy.setAdapter((ViewPager2) findViewById(R.id.view_pager));
     }
 }
diff --git a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/ViewPager2Tests.java b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/ViewPager2Tests.java
index 119256d..f84ee56 100644
--- a/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/ViewPager2Tests.java
+++ b/viewpager2/src/androidTest/java/androidx/viewpager2/widget/tests/ViewPager2Tests.java
@@ -43,6 +43,8 @@
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.util.Preconditions;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.Adapter;
 import android.support.v7.widget.RecyclerView.ViewHolder;
@@ -84,25 +86,30 @@
             Color.parseColor("#BBB30CE8"),
             Color.parseColor("#BBFF00D0")};
 
+    /** mean of injecting different adapters into {@link TestActivity#onCreate(Bundle)} */
+    static AdapterStrategy sAdapterStrategy;
+    interface AdapterStrategy {
+        void setAdapter(ViewPager2 viewPager);
+    }
+
     @Rule
     public final ActivityTestRule<TestActivity> mActivityTestRule;
     @Rule
     public ExpectedException mExpectedException = ExpectedException.none();
 
-    private ViewPager2 mViewPager;
-
     // allows to wait until swipe operation is finished (Smooth Scroller done)
     private CountDownLatch mStableAfterSwipe;
 
     public ViewPager2Tests() {
-        mActivityTestRule = new ActivityTestRule<>(TestActivity.class);
+        mActivityTestRule = new ActivityTestRule<>(TestActivity.class, true, false);
     }
 
-    @Before
-    public void setUp() {
-        mViewPager = mActivityTestRule.getActivity().findViewById(R.id.view_pager);
+    private void setUpActivity(AdapterStrategy adapterStrategy) {
+        sAdapterStrategy = Preconditions.checkNotNull(adapterStrategy);
+        mActivityTestRule.launchActivity(null);
 
-        mViewPager.addOnScrollListener(new RecyclerView.OnScrollListener() {
+        ViewPager2 viewPager = mActivityTestRule.getActivity().findViewById(R.id.view_pager);
+        viewPager.addOnScrollListener(new RecyclerView.OnScrollListener() {
             @Override
             public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                 // coming to idle from another state (dragging or setting) means we're stable now
@@ -112,6 +119,18 @@
             }
         });
 
+        if (Build.VERSION.SDK_INT < 16) { // TODO(b/71500143): remove temporary workaround
+            RecyclerView mRecyclerView = (RecyclerView) viewPager.getChildAt(0);
+            mRecyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
+        }
+
+        onView(withId(viewPager.getId())).check(matches(isDisplayed()));
+    }
+
+    @Before
+    public void setUp() {
+        sAdapterStrategy = null;
+
         final long seed = RANDOM.nextLong();
         RANDOM.setSeed(seed);
         Log.i(getClass().getName(), "Random seed: " + seed);
@@ -199,15 +218,15 @@
 
     @Test
     public void fragmentAdapter_random() throws Throwable {
-        final int totalPages = 10;
-        final int sequenceLength = 50;
+        final int totalPages = 8; // increase when stress testing locally
+        final int sequenceLength = 20; // increase when stress testing locally
         testFragmentLifecycle_random(totalPages, sequenceLength, PageMutator.NO_OP);
     }
 
     @Test
     public void fragmentAdapter_random_withMutations() throws Throwable {
-        final int totalPages = 10;
-        final int sequenceLength = 50;
+        final int totalPages = 8; // increase when stress testing locally
+        final int sequenceLength = 20; // increase when stress testing locally
         testFragmentLifecycle_random(totalPages, sequenceLength, PageMutator.RANDOM);
     }
 
@@ -334,10 +353,11 @@
             expectedValues[i] = i;
         }
 
-        mActivityTestRule.runOnUiThread(new Runnable() {
+        setUpActivity(new AdapterStrategy() {
             @Override
-            public void run() {
-                mViewPager.setAdapter(mActivityTestRule.getActivity().getSupportFragmentManager(),
+            public void setAdapter(ViewPager2 viewPager) {
+                viewPager.setAdapter(
+                        ((FragmentActivity) viewPager.getContext()).getSupportFragmentManager(),
                         new ViewPager2.FragmentProvider() {
                             @Override
                             public Fragment getItem(final int position) {
@@ -439,23 +459,17 @@
     public void viewAdapter_rendersAndHandlesSwiping() throws Throwable {
         final int totalPages = 8;
 
-        if (Build.VERSION.SDK_INT < 16) { // TODO(b/71500143): remove temporary workaround
-            RecyclerView mRecyclerView = (RecyclerView) mViewPager.getChildAt(0);
-            mRecyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
-        }
-
-        onView(withId(mViewPager.getId())).check(matches(isDisplayed()));
-        mActivityTestRule.runOnUiThread(new Runnable() {
+        setUpActivity(new AdapterStrategy() {
             @Override
-            public void run() {
-                mViewPager.setAdapter(
+            public void setAdapter(final ViewPager2 viewPager) {
+                viewPager.setAdapter(
                         new Adapter<ViewHolder>() {
                             @NonNull
                             @Override
                             public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,
                                     int viewType) {
                                 return new ViewHolder(
-                                        mActivityTestRule.getActivity().getLayoutInflater().inflate(
+                                        LayoutInflater.from(viewPager.getContext()).inflate(
                                                 R.layout.item_test_layout, parent, false)) {
                                 };
                             }
@@ -474,6 +488,7 @@
             }
         });
 
+
         List<Integer> pageSequence = Arrays.asList(0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 6, 5, 4, 3, 2,
                 1, 0, 0, 0);
         verifyView(0);