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>