Slice rendering test

Test: ./gradlew :slices-view:connectedCheck
Change-Id: I50ceec5efbaa18835e76abf3d79fc191dff2125f
diff --git a/slices/view/build.gradle b/slices/view/build.gradle
index 92e117e..93e9fc5 100644
--- a/slices/view/build.gradle
+++ b/slices/view/build.gradle
@@ -29,6 +29,7 @@
     api(ARCH_LIFECYCLE_EXTENSIONS, libs.exclude_annotations_transitive)
 
     androidTestImplementation(TEST_RUNNER)
+    androidTestImplementation(ESPRESSO_CORE)
     androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy)
     androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy)
 }
diff --git a/slices/view/src/androidTest/AndroidManifest.xml b/slices/view/src/androidTest/AndroidManifest.xml
index 5a7abb6..6800706 100644
--- a/slices/view/src/androidTest/AndroidManifest.xml
+++ b/slices/view/src/androidTest/AndroidManifest.xml
@@ -16,9 +16,22 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="androidx.app.slice.view.test">
 
+    <uses-sdk android:targetSdkVersion="21" />
+
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
     <application>
         <provider android:name="androidx.app.slice.SliceManagerTest$TestSliceProvider"
                   android:authorities="androidx.app.slice.view.test"
                   android:exported="true"/>
+
+        <activity android:name="androidx.app.slice.render.SliceRenderActivity"
+            android:theme="@style/AppTheme.NoActionBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/slices/view/src/androidTest/java/androidx/app/slice/render/RenderTest.java b/slices/view/src/androidTest/java/androidx/app/slice/render/RenderTest.java
new file mode 100644
index 0000000..6cf6182
--- /dev/null
+++ b/slices/view/src/androidTest/java/androidx/app/slice/render/RenderTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 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 androidx.app.slice.render;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RenderTest {
+
+    private final Context mContext = InstrumentationRegistry.getContext();
+
+    @Test
+    public void testRender() throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        BroadcastReceiver receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                latch.countDown();
+            }
+        };
+        mContext.registerReceiver(receiver,
+                new IntentFilter(SliceRenderActivity.ACTION_RENDER_DONE));
+        mContext.startActivity(new Intent(mContext, SliceRenderActivity.class)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+
+        latch.await(30000, TimeUnit.MILLISECONDS);
+    }
+}
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
new file mode 100644
index 0000000..114d0e1
--- /dev/null
+++ b/slices/view/src/androidTest/java/androidx/app/slice/render/SliceCreator.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2018 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 androidx.app.slice.render;
+
+import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
+
+import android.app.PendingIntent;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.net.wifi.WifiManager;
+import android.provider.Settings;
+import android.text.SpannableString;
+import android.text.format.DateUtils;
+import android.text.style.ForegroundColorSpan;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.builders.GridBuilder;
+import androidx.app.slice.builders.ListBuilder;
+import androidx.app.slice.builders.MessagingSliceBuilder;
+import androidx.app.slice.view.test.R;
+
+/**
+ * Examples of using slice template builders.
+ */
+public class SliceCreator {
+
+    public static final String ACTION_WIFI_CHANGED =
+            "com.example.androidx.slice.action.WIFI_CHANGED";
+    public static final String ACTION_TOAST =
+            "com.example.androidx.slice.action.TOAST";
+    public static final String EXTRA_TOAST_MESSAGE = "com.example.androidx.extra.TOAST_MESSAGE";
+
+    public static final String[] URI_PATHS = {"message", "wifi", "note", "ride", "toggle",
+            "toggle2", "contact", "gallery", "weather"};
+
+    private final Context mContext;
+
+    public SliceCreator(Context context) {
+        mContext = context;
+    }
+
+    private Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * @return Uri with the provided path
+     */
+    public static Uri getUri(String path, Context context) {
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority("androidx.app.slice.view.test")
+                .appendPath(path)
+                .build();
+    }
+
+    public Slice onBindSlice(Uri sliceUri) {
+        String path = sliceUri.getPath();
+        switch (path) {
+            case "/message":
+                return createMessagingSlice(sliceUri);
+            case "/wifi":
+                return createWifiSlice(sliceUri);
+            case "/note":
+                return createNoteSlice(sliceUri);
+            case "/ride":
+                return createRideSlice(sliceUri);
+            case "/toggle":
+                return createCustomToggleSlice(sliceUri);
+            case "/toggle2":
+                return createTwoCustomToggleSlices(sliceUri);
+            case "/contact":
+                return createContact(sliceUri);
+            case "/gallery":
+                return createGallery(sliceUri);
+            case "/weather":
+                return createWeather(sliceUri);
+        }
+        throw new IllegalArgumentException("Unknown uri " + sliceUri);
+    }
+
+    private Slice createWeather(Uri sliceUri) {
+        GridBuilder b = new GridBuilder(getContext(), sliceUri);
+        return b.addCell(new GridBuilder.CellBuilder(b)
+                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_1))
+                        .addText("MON")
+                        .addTitleText("69\u00B0"))
+                .addCell(new GridBuilder.CellBuilder(b)
+                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_2))
+                        .addText("TUE")
+                        .addTitleText("71\u00B0"))
+                .addCell(new GridBuilder.CellBuilder(b)
+                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_3))
+                        .addText("WED")
+                        .addTitleText("76\u00B0"))
+                .addCell(new GridBuilder.CellBuilder(b)
+                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_4))
+                        .addText("THU")
+                        .addTitleText("72\u00B0"))
+                .addCell(new GridBuilder.CellBuilder(b)
+                        .addLargeImage(Icon.createWithResource(getContext(), R.drawable.weather_1))
+                        .addText("FRI")
+                        .addTitleText("68\u00B0"))
+                .build();
+    }
+
+    private Slice createGallery(Uri sliceUri) {
+        GridBuilder b = new GridBuilder(getContext(), sliceUri);
+        return b.addCell(new GridBuilder.CellBuilder(b)
+                    .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_1)))
+                .addCell(new GridBuilder.CellBuilder(b)
+                    .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_2)))
+                .addCell(new GridBuilder.CellBuilder(b)
+                    .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_3)))
+                .addCell(new GridBuilder.CellBuilder(b)
+                    .addLargeImage(Icon.createWithResource(getContext(), R.drawable.slices_4)))
+                .build();
+    }
+
+    private Slice createContact(Uri sliceUri) {
+        ListBuilder b = new ListBuilder(getContext(), sliceUri);
+        ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(b);
+        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)))
+                .addGrid(gb
+                        .addCell(new GridBuilder.CellBuilder(gb)
+                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_call))
+                            .addText("Call")
+                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "call")))
+                        .addCell(new GridBuilder.CellBuilder(gb)
+                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_text))
+                            .addText("Text")
+                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "text")))
+                        .addCell(new GridBuilder.CellBuilder(gb)
+                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_video))
+                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "video"))
+                            .addText("Video"))
+                        .addCell(new GridBuilder.CellBuilder(gb)
+                            .addImage(Icon.createWithResource(getContext(), R.drawable.ic_email))
+                            .addText("Email")
+                            .setContentIntent(getBroadcastIntent(ACTION_TOAST, "email"))))
+                .build();
+    }
+
+    private Slice createMessagingSlice(Uri sliceUri) {
+        // TODO: Remote input.
+        MessagingSliceBuilder mb = new MessagingSliceBuilder(getContext(), sliceUri);
+        return mb
+                .add(new MessagingSliceBuilder.MessageBuilder(mb)
+                        .addText("yo home \uD83C\uDF55, I emailed you the info")
+                        .addTimestamp(System.currentTimeMillis() - 20 * DateUtils.MINUTE_IN_MILLIS)
+                        .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+                .add(new MessagingSliceBuilder.MessageBuilder(mb)
+                        .addText("just bought my tickets")
+                        .addTimestamp(System.currentTimeMillis() - 10 * DateUtils.MINUTE_IN_MILLIS))
+                .add(new MessagingSliceBuilder.MessageBuilder(mb)
+                        .addText("yay! can't wait for getContext() weekend!\n"
+                                + "\uD83D\uDE00")
+                        .addTimestamp(System.currentTimeMillis() - 5 * DateUtils.MINUTE_IN_MILLIS)
+                        .addSource(Icon.createWithResource(getContext(), R.drawable.mady)))
+                .build();
+
+    }
+
+    private Slice createNoteSlice(Uri sliceUri) {
+        // TODO: Remote input.
+        ListBuilder lb = new ListBuilder(getContext(), sliceUri);
+        return lb.setColor(0xfff4b400)
+                .addRow(new ListBuilder.RowBuilder(lb)
+                    .setTitle("Create new note")
+                    .setSubtitle("with this note taking app")
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_create),
+                            getBroadcastIntent(ACTION_TOAST, "create note"))
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_voice),
+                            getBroadcastIntent(ACTION_TOAST, "voice note"))
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_camera),
+                            getIntent("android.media.action.IMAGE_CAPTURE")))
+                .build();
+    }
+
+    private Slice createRideSlice(Uri sliceUri) {
+        final ForegroundColorSpan colorSpan = new ForegroundColorSpan(0xff0F9D58);
+        SpannableString headerSubtitle = new SpannableString("Ride in 4 min");
+        headerSubtitle.setSpan(colorSpan, 8, headerSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
+        SpannableString homeSubtitle = new SpannableString("12 miles | 12 min | $9.00");
+        homeSubtitle.setSpan(colorSpan, 20, homeSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
+        SpannableString workSubtitle = new SpannableString("44 miles | 1 hour 45 min | $31.41");
+        workSubtitle.setSpan(colorSpan, 27, workSubtitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        ListBuilder b = new ListBuilder(getContext(), sliceUri);
+        return b.setColor(0xff0F9D58)
+            .addRow(new ListBuilder.RowBuilder(b)
+                    .setContentIntent(getBroadcastIntent(ACTION_TOAST, "work"))
+                    .setTitle("Work")
+                    .setSubtitle(workSubtitle)
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_work),
+                        getBroadcastIntent(ACTION_TOAST, "work")))
+            .addRow(new ListBuilder.RowBuilder(b)
+                    .setContentIntent(getBroadcastIntent(ACTION_TOAST, "home"))
+                    .setTitle("Home")
+                    .setSubtitle(homeSubtitle)
+                    .addEndItem(Icon.createWithResource(getContext(), R.drawable.ic_home),
+                        getBroadcastIntent(ACTION_TOAST, "home")))
+            .build();
+    }
+
+    private Slice createCustomToggleSlice(Uri sliceUri) {
+        ListBuilder b = new ListBuilder(getContext(), sliceUri);
+        return b.setColor(0xffff4081)
+                .addRow(new ListBuilder.RowBuilder(b)
+                    .setTitle("Custom toggle")
+                    .setSubtitle("It can support two states")
+                    .addToggle(getBroadcastIntent(ACTION_TOAST, "star toggled"),
+                            true /* isChecked */,
+                            Icon.createWithResource(getContext(), R.drawable.toggle_star)))
+                .build();
+    }
+
+    private Slice createTwoCustomToggleSlices(Uri sliceUri) {
+        ListBuilder lb = new ListBuilder(getContext(), sliceUri);
+        return lb.setColor(0xffff4081)
+                .addRow(new ListBuilder.RowBuilder(lb)
+                        .setTitle("2 toggles")
+                        .setSubtitle("each supports two states")
+                        .addToggle(getBroadcastIntent(ACTION_TOAST, "first star toggled"),
+                                true /* isChecked */,
+                                Icon.createWithResource(getContext(), R.drawable.toggle_star))
+                        .addToggle(getBroadcastIntent(ACTION_TOAST, "second star toggled"),
+                                false /* isChecked */,
+                                Icon.createWithResource(getContext(), R.drawable.toggle_star)))
+                .build();
+    }
+
+    private Slice createWifiSlice(Uri sliceUri) {
+        // Get wifi state
+        WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+        int wifiState = wifiManager.getWifiState();
+        boolean wifiEnabled = false;
+        String state;
+        switch (wifiState) {
+            case WifiManager.WIFI_STATE_DISABLED:
+            case WifiManager.WIFI_STATE_DISABLING:
+                state = "disconnected";
+                break;
+            case WifiManager.WIFI_STATE_ENABLED:
+            case WifiManager.WIFI_STATE_ENABLING:
+                state = wifiManager.getConnectionInfo().getSSID();
+                wifiEnabled = true;
+                break;
+            case WifiManager.WIFI_STATE_UNKNOWN:
+            default:
+                state = ""; // just don't show anything?
+                break;
+        }
+        boolean finalWifiEnabled = wifiEnabled;
+        ListBuilder b = new ListBuilder(getContext(), sliceUri);
+        return b.setColor(0xff4285f4)
+                .addRow(new ListBuilder.RowBuilder(b)
+                    .setTitle("Wi-fi")
+                    .setTitleItem(Icon.createWithResource(getContext(), R.drawable.ic_wifi))
+                    .setSubtitle(state)
+                    .addToggle(getBroadcastIntent(ACTION_WIFI_CHANGED, null), finalWifiEnabled)
+                    .setContentIntent(getIntent(Settings.ACTION_WIFI_SETTINGS)))
+            .build();
+    }
+
+    private PendingIntent getIntent(String action) {
+        Intent intent = new Intent(action);
+        intent.setClassName(getContext().getPackageName(), SliceRenderActivity.class.getName());
+        PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0);
+        return pi;
+    }
+
+    private PendingIntent getBroadcastIntent(String action, String message) {
+        Intent intent = new Intent(action);
+        intent.setClassName(getContext().getPackageName(), SliceRenderActivity.class.getName());
+        // Ensure a new PendingIntent is created for each message.
+        int requestCode = 0;
+        if (message != null) {
+            intent.putExtra(EXTRA_TOAST_MESSAGE, message);
+            requestCode = message.hashCode();
+        }
+        return PendingIntent.getBroadcast(getContext(), requestCode, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+}
diff --git a/slices/view/src/androidTest/java/androidx/app/slice/render/SliceRenderActivity.java b/slices/view/src/androidTest/java/androidx/app/slice/render/SliceRenderActivity.java
new file mode 100644
index 0000000..debb280
--- /dev/null
+++ b/slices/view/src/androidTest/java/androidx/app/slice/render/SliceRenderActivity.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018 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 androidx.app.slice.render;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+
+public class SliceRenderActivity extends Activity {
+    public static final String ACTION_RENDER_DONE = "androidx.app.slice.render.RENDER_DONE";
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        new SliceRenderer(this).renderAll(new Runnable() {
+
+            @Override
+            public void run() {
+                sendBroadcast(new Intent(ACTION_RENDER_DONE));
+                finish();
+            }
+        });
+    }
+}
diff --git a/slices/view/src/androidTest/java/androidx/app/slice/render/SliceRenderer.java b/slices/view/src/androidTest/java/androidx/app/slice/render/SliceRenderer.java
new file mode 100644
index 0000000..d2b8619
--- /dev/null
+++ b/slices/view/src/androidTest/java/androidx/app/slice/render/SliceRenderer.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2018 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 androidx.app.slice.render;
+
+import static android.view.View.MeasureSpec.makeMeasureSpec;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.os.AsyncTask;
+import android.os.Environment;
+import android.os.Handler;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.util.concurrent.CountDownLatch;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceProvider;
+import androidx.app.slice.view.test.R;
+import androidx.app.slice.widget.SliceLiveData;
+import androidx.app.slice.widget.SliceView;
+
+public class SliceRenderer {
+
+    private static final String TAG = "SliceRenderer";
+    private static final String SCREENSHOT_DIR = "slice-screenshots";
+    private static File sScreenshotDirectory;
+
+    private final Activity mContext;
+    private final View mLayout;
+    private final SliceView mSV1;
+    private final SliceView mSV2;
+    private final SliceView mSV3;
+    private final ViewGroup mParent;
+    private final Handler mHandler;
+    private final SliceCreator mSliceCreator;
+    private CountDownLatch mDoneLatch;
+
+    public SliceRenderer(Activity context) {
+        mContext = context;
+        mParent = new ViewGroup(mContext) {
+            @Override
+            protected void onLayout(boolean changed, int l, int t, int r, int b) {
+                int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 900,
+                        mContext.getResources().getDisplayMetrics());
+                int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200,
+                        mContext.getResources().getDisplayMetrics());
+                mLayout.measure(makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+                        makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
+                mLayout.layout(0, 0, width, height);
+            }
+
+            @Override
+            protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+                return false;
+            }
+        };
+        mLayout = LayoutInflater.from(context).inflate(R.layout.render_layout, null);
+        mSV1 = mLayout.findViewById(R.id.sv1);
+        mSV1.setMode(SliceView.MODE_SHORTCUT);
+        mSV2 = mLayout.findViewById(R.id.sv2);
+        mSV2.setMode(SliceView.MODE_SMALL);
+        mSV3 = mLayout.findViewById(R.id.sv3);
+        mSV3.setMode(SliceView.MODE_LARGE);
+        disableAnims(mLayout);
+        mHandler = new Handler();
+        ((ViewGroup) mContext.getWindow().getDecorView()).addView(mParent);
+        mParent.addView(mLayout);
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+        mSliceCreator = new SliceCreator(mContext);
+    }
+
+    private void disableAnims(View view) {
+        if (view instanceof RecyclerView) {
+            ((RecyclerView) view).setItemAnimator(null);
+        }
+        if (view instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) view;
+            for (int i = 0; i < viewGroup.getChildCount(); i++) {
+                disableAnims(viewGroup.getChildAt(i));
+            }
+        }
+    }
+
+
+    private static File getScreenshotDirectory() {
+        if (sScreenshotDirectory == null) {
+            File storage = Environment.getExternalStorageDirectory();
+            sScreenshotDirectory = new File(storage, SCREENSHOT_DIR);
+            if (!sScreenshotDirectory.exists()) {
+                if (!sScreenshotDirectory.mkdirs()) {
+                    throw new RuntimeException(
+                            "Failed to create a screenshot directory.");
+                }
+            }
+        }
+        return sScreenshotDirectory;
+    }
+
+
+    private void doRender() {
+        File output = getScreenshotDirectory();
+        if (!output.exists()) {
+            output.mkdir();
+        }
+        mDoneLatch = new CountDownLatch(SliceCreator.URI_PATHS.length);
+        for (String slice : SliceCreator.URI_PATHS) {
+            doRender(slice, new File(output, String.format("%s.png", slice)));
+        }
+        Log.d(TAG, "Wrote render to " + output.getAbsolutePath());
+        mContext.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                ((ViewGroup) mParent.getParent()).removeView(mParent);
+            }
+        });
+        try {
+            mDoneLatch.await();
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private void doRender(final String slice, final File file) {
+        Log.d(TAG, "Rendering " + slice + " to " + file.getAbsolutePath());
+
+        final Slice s = mSliceCreator.onBindSlice(SliceCreator.getUri(slice, mContext));
+
+        final CountDownLatch l = new CountDownLatch(1);
+        mContext.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mSV1.setSlice(s);
+                mSV2.setSlice(s);
+                mSV3.setSlice(s);
+                mSV1.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+                    @Override
+                    public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                            int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                        mSV1.removeOnLayoutChangeListener(this);
+                        mSV1.postDelayed(new Runnable() {
+                            @Override
+                            public void run() {
+                                Log.d(TAG, "Drawing " + slice);
+                                Bitmap b = Bitmap.createBitmap(mLayout.getMeasuredWidth(),
+                                        mLayout.getMeasuredHeight(),
+                                        Bitmap.Config.ARGB_8888);
+
+                                mLayout.draw(new Canvas(b));
+                                try {
+                                    doCompress(slice, b, new FileOutputStream(file));
+                                } catch (FileNotFoundException e) {
+                                    throw new RuntimeException(e);
+                                }
+                                l.countDown();
+                            }
+                        }, 10);
+                    }
+                });
+            }
+        });
+        try {
+            l.await();
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private void doCompress(final String slice, final Bitmap b, final FileOutputStream s) {
+        AsyncTask.execute(new Runnable() {
+            @Override
+            public void run() {
+                Log.d(TAG, "Compressing " + slice);
+                if (!b.compress(Bitmap.CompressFormat.PNG, 100, s)) {
+                    throw new RuntimeException("Unable to compress");
+                }
+
+                b.recycle();
+                Log.d(TAG, "Done " + slice);
+                mDoneLatch.countDown();
+            }
+        });
+    }
+
+    public void renderAll(final Runnable runnable) {
+        final ProgressDialog dialog = ProgressDialog.show(mContext, null, "Rendering...");
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                doRender();
+                mContext.runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        dialog.dismiss();
+                        runnable.run();
+                    }
+                });
+            }
+        }).start();
+    }
+}
diff --git a/slices/view/src/androidTest/res/drawable/ic_call.xml b/slices/view/src/androidTest/res/drawable/ic_call.xml
new file mode 100644
index 0000000..ebf9de6
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_call.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_camera.xml b/slices/view/src/androidTest/res/drawable/ic_camera.xml
new file mode 100644
index 0000000..74b6bf9
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_camera.xml
@@ -0,0 +1,32 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 12 8.8 C 13.7673111995 8.8 15.2 10.2326888005 15.2 12 C 15.2 13.7673111995 13.7673111995 15.2 12 15.2 C 10.2326888005 15.2 8.8 13.7673111995 8.8 12 C 8.8 10.2326888005 10.2326888005 8.8 12 8.8 Z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1 .9 2 2 2h16c1.1 0 2-.9
+2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5
+5-2.24 5-5 5z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/slices/view/src/androidTest/res/drawable/ic_car.xml b/slices/view/src/androidTest/res/drawable/ic_car.xml
new file mode 100644
index 0000000..6bab660
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_car.xml
@@ -0,0 +1,31 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21 .42 -1.42 1.01L3 12v8c0
+.55 .45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55 .45 1 1 1h1c.55 0 1-.45
+1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5 .67 1.5
+1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5 .67 1.5
+1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/slices/view/src/androidTest/res/drawable/ic_create.xml b/slices/view/src/androidTest/res/drawable/ic_create.xml
new file mode 100644
index 0000000..d1666a8
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_create.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_email.xml b/slices/view/src/androidTest/res/drawable/ic_email.xml
new file mode 100644
index 0000000..ce97ab8
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_email.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_home.xml b/slices/view/src/androidTest/res/drawable/ic_home.xml
new file mode 100644
index 0000000..b278230
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_home.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="#000000"
+        android:pathData="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
+    <path
+        android:pathData="M0 0h24v24H0z" />
+</vector>
\ No newline at end of file
diff --git a/slices/view/src/androidTest/res/drawable/ic_large.xml b/slices/view/src/androidTest/res/drawable/ic_large.xml
new file mode 100644
index 0000000..79ac590
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_large.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48.0dp"
+        android:height="48.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M34.0,2.02L14.0,2.0c-2.21,0.0 -4.0,1.79 -4.0,4.0l0.0,36.0c0.0,2.21 1.79,4.0 4.0,4.0l20.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L38.0,6.0c0.0,-2.21 -1.79,-3.98 -4.0,-3.98zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0l0.0,28.0z"/>
+    <path
+        android:strokeColor="#FF000000"
+        android:strokeWidth="2"
+        android:pathData="M16,18 l16,0 l0,10 l-16,0z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_shortcut.xml b/slices/view/src/androidTest/res/drawable/ic_shortcut.xml
new file mode 100644
index 0000000..bf9572a
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_shortcut.xml
@@ -0,0 +1,34 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="48.0dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="48.0dp">
+    <path
+        android:fillColor="#e2e2e2"
+        android:pathData="M24.0,24.0m-19.0,0.0a19.0,19.0 0.0,1.0 1.0,38.0 0.0a19.0,19.0 0.0,1.0 1.0,-38.0 0.0"/>
+    <group
+        android:scaleX=".7"
+        android:scaleY=".7"
+        android:translateX="7.2"
+        android:translateY="7.2">
+
+        <path
+            android:fillColor="#ff000000"
+            android:pathData="M12.0,36.0c0.0,1.0 0.9,2.0 2.0,2.0l2.0,0.0l0.0,7.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0l0.0,-7.0l4.0,0.0l0.0,7.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0l0.0,-7.0l2.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L36.0,16.0L12.0,16.0l0.0,20.0zM7.0,16.0c-1.66,0.0 -3.0,1.34 -3.0,3.0l0.0,14.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0L10.0,19.0c0.0,-1.66 -1.34,-3.0 -3.0,-3.0zm34.0,0.0c-1.66,0.0 -3.0,1.34 -3.0,3.0l0.0,14.0c0.0,1.66 1.34,3.0 3.0,3.0s3.0,-1.34 3.0,-3.0L44.0,19.0c0.0,-1.66 -1.34,-3.0 -3.0,-3.0zM31.06,4.32l2.61,-2.61c0.39,-0.3 0.39,-1.02 0.0,-1.41 -0.39,-0.39 -1.02,-0.39 -1.41,0.0L29.3,3.25C27.7,2.46 25.91,2.0 24.0,2.0c-1.92,0.0 -3.7,0.46 -5.33,1.26L15.0,0.29c-0.39,-0.39 -1.02,-0.39 -1.41,0.0 -0.3,0.39 -0.39,1.02 0.0,1.41l2.62,2.62C13.94,6.51 12.0,10.03 12.0,14.0l24.0,0.0c0.0,-3.98 -1.95,-7.5 -4.94,-9.68zM20.0,10.0l-2.0,0.0L18.0,8.0l2.0,0.0l0.0,2.0zm10.0,0.0l-2.0,0.0L28.0,8.0l2.0,0.0l0.0,2.0z"/>
+    </group>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_small.xml b/slices/view/src/androidTest/res/drawable/ic_small.xml
new file mode 100644
index 0000000..8fd43df
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_small.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48.0dp"
+        android:height="48.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M34.0,2.02L14.0,2.0c-2.21,0.0 -4.0,1.79 -4.0,4.0l0.0,36.0c0.0,2.21 1.79,4.0 4.0,4.0l20.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L38.0,6.0c0.0,-2.21 -1.79,-3.98 -4.0,-3.98zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0l0.0,28.0z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M16,18 l16,0 l0,4 l-16,0z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_star_off.xml b/slices/view/src/androidTest/res/drawable/ic_star_off.xml
new file mode 100644
index 0000000..7f023b3
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_star_off.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_star_on.xml b/slices/view/src/androidTest/res/drawable/ic_star_on.xml
new file mode 100644
index 0000000..f3ca086
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_star_on.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_text.xml b/slices/view/src/androidTest/res/drawable/ic_text.xml
new file mode 100644
index 0000000..d2876bf
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_text.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_video.xml b/slices/view/src/androidTest/res/drawable/ic_video.xml
new file mode 100644
index 0000000..e23eac8
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_video.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_voice.xml b/slices/view/src/androidTest/res/drawable/ic_voice.xml
new file mode 100644
index 0000000..8f465bb
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_voice.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,15c1.66,0 2.99,-1.34 2.99,-3L15,6c0,-1.66 -1.34,-3 -3,-3S9,4.34 9,6v6c0,1.66 1.34,3 3,3zM17.3,12c0,3 -2.54,5.1 -5.3,5.1S6.7,15 6.7,12L5,12c0,3.42 2.72,6.23 6,6.72L11,22h2v-3.28c3.28,-0.48 6,-3.3 6,-6.72h-1.7z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_wifi.xml b/slices/view/src/androidTest/res/drawable/ic_wifi.xml
new file mode 100644
index 0000000..4fbfd60
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_wifi.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12.01,21.49L23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4C5.28,3 0.81,6.66 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01z"
+        android:fillAlpha=".3"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3.53,10.95l8.46,10.54 0.01,0.01 0.01,-0.01 8.46,-10.54C20.04,10.62 16.81,8 12,8c-4.81,0 -8.04,2.62 -8.47,2.95z"/>
+</vector>
diff --git a/slices/view/src/androidTest/res/drawable/ic_work.xml b/slices/view/src/androidTest/res/drawable/ic_work.xml
new file mode 100644
index 0000000..6806402
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/ic_work.xml
@@ -0,0 +1,28 @@
+<!--
+  ~ Copyright 2017 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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M0 0h24v24H0z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11 0-1.99 .89 -1.99 2L2
+19c0 1.11 .89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-6 0h-4V4h4v2z" />
+</vector>
\ No newline at end of file
diff --git a/slices/view/src/androidTest/res/drawable/mady.jpg b/slices/view/src/androidTest/res/drawable/mady.jpg
new file mode 100644
index 0000000..8b61f1b
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/mady.jpg
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/slices_1.jpg b/slices/view/src/androidTest/res/drawable/slices_1.jpg
new file mode 100644
index 0000000..31cc065
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/slices_1.jpg
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/slices_2.jpg b/slices/view/src/androidTest/res/drawable/slices_2.jpg
new file mode 100644
index 0000000..adbe1d3
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/slices_2.jpg
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/slices_3.jpg b/slices/view/src/androidTest/res/drawable/slices_3.jpg
new file mode 100644
index 0000000..6617019
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/slices_3.jpg
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/slices_4.jpg b/slices/view/src/androidTest/res/drawable/slices_4.jpg
new file mode 100644
index 0000000..d00a8b3
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/slices_4.jpg
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/toggle_star.xml b/slices/view/src/androidTest/res/drawable/toggle_star.xml
new file mode 100644
index 0000000..e964925
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/toggle_star.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/on"
+        android:state_checked="true"
+        android:drawable="@drawable/ic_star_on" />
+    <item
+        android:id="@+id/off"
+        android:drawable="@drawable/ic_star_off" />
+</selector>
\ No newline at end of file
diff --git a/slices/view/src/androidTest/res/drawable/weather_1.png b/slices/view/src/androidTest/res/drawable/weather_1.png
new file mode 100644
index 0000000..7c4034e
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/weather_1.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/weather_2.png b/slices/view/src/androidTest/res/drawable/weather_2.png
new file mode 100644
index 0000000..f1b6672
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/weather_2.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/weather_3.png b/slices/view/src/androidTest/res/drawable/weather_3.png
new file mode 100644
index 0000000..a5db683
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/weather_3.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/drawable/weather_4.png b/slices/view/src/androidTest/res/drawable/weather_4.png
new file mode 100644
index 0000000..0b7f3b0
--- /dev/null
+++ b/slices/view/src/androidTest/res/drawable/weather_4.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/layout/activity_demo.xml b/slices/view/src/androidTest/res/layout/activity_demo.xml
new file mode 100644
index 0000000..f557f40
--- /dev/null
+++ b/slices/view/src/androidTest/res/layout/activity_demo.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.example.android.support.content.demos.ContentPagerDemoActivity">
+
+    <android.support.v7.widget.Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:background="?attr/colorPrimary"
+        android:theme="@style/AppTheme.AppBarOverlay"
+        app:popupTheme="@style/AppTheme.PopupOverlay"/>
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@+id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</LinearLayout>
diff --git a/slices/view/src/androidTest/res/layout/render_layout.xml b/slices/view/src/androidTest/res/layout/render_layout.xml
new file mode 100644
index 0000000..a8ed779
--- /dev/null
+++ b/slices/view/src/androidTest/res/layout/render_layout.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="1200dp"
+              android:layout_height="400dp"
+              android:background="@android:color/black"
+              android:orientation="horizontal"
+              android:padding="20dp">
+
+
+    <FrameLayout android:layout_width="wrap_content"
+                 android:layout_height="wrap_content">
+        <androidx.app.slice.widget.SliceView
+            android:id="@+id/sv1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+    </FrameLayout>
+
+    <FrameLayout android:layout_width="400dp"
+                 android:layout_height="wrap_content"
+                 android:layout_marginStart="20dp">
+        <androidx.app.slice.widget.SliceView
+            android:id="@+id/sv2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@android:color/white"
+            android:paddingEnd="16dp"
+            android:paddingStart="16dp"/>
+    </FrameLayout>
+
+    <FrameLayout android:layout_width="400dp"
+                 android:layout_height="wrap_content"
+                 android:layout_marginStart="20dp">
+        <androidx.app.slice.widget.SliceView
+            android:id="@+id/sv3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@android:color/white"
+            android:paddingEnd="16dp"
+            android:paddingStart="16dp"/>
+    </FrameLayout>
+
+
+</LinearLayout>
\ No newline at end of file
diff --git a/slices/view/src/androidTest/res/mipmap-hdpi/ic_launcher.png b/slices/view/src/androidTest/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-hdpi/ic_launcher_round.png b/slices/view/src/androidTest/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9a078e3
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-mdpi/ic_launcher.png b/slices/view/src/androidTest/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-mdpi/ic_launcher_round.png b/slices/view/src/androidTest/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..efc028a
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-xhdpi/ic_launcher.png b/slices/view/src/androidTest/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-xhdpi/ic_launcher_round.png b/slices/view/src/androidTest/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..3af2608
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-xxhdpi/ic_launcher.png b/slices/view/src/androidTest/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-xxhdpi/ic_launcher_round.png b/slices/view/src/androidTest/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..9bec2e6
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-xxxhdpi/ic_launcher.png b/slices/view/src/androidTest/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..aee44e1
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/mipmap-xxxhdpi/ic_launcher_round.png b/slices/view/src/androidTest/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..34947cd
--- /dev/null
+++ b/slices/view/src/androidTest/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/slices/view/src/androidTest/res/values/colors.xml b/slices/view/src/androidTest/res/values/colors.xml
new file mode 100644
index 0000000..86b4304
--- /dev/null
+++ b/slices/view/src/androidTest/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+
+<resources>
+    <color name="colorPrimary">#3F51B5</color>
+    <color name="colorPrimaryDark">#303F9F</color>
+    <color name="colorAccent">#FF4081</color>
+</resources>
diff --git a/slices/view/src/androidTest/res/values/strings.xml b/slices/view/src/androidTest/res/values/strings.xml
new file mode 100644
index 0000000..89583bd
--- /dev/null
+++ b/slices/view/src/androidTest/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Slice Browser</string>
+</resources>
diff --git a/slices/view/src/androidTest/res/values/styles.xml b/slices/view/src/androidTest/res/values/styles.xml
new file mode 100644
index 0000000..afb6bad
--- /dev/null
+++ b/slices/view/src/androidTest/res/values/styles.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+    <style name="AppTheme.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+    </style>
+    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
+    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
+
+</resources>