Added sample app for testing jank using the leanback library.

Change-Id: If3a062a9a0d8461d3cb0b9fbab9611c271d8d8f6
diff --git a/samples/SupportLeanbackJank/Android.mk b/samples/SupportLeanbackJank/Android.mk
new file mode 100644
index 0000000..21e3f31
--- /dev/null
+++ b/samples/SupportLeanbackJank/Android.mk
@@ -0,0 +1,40 @@
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+# Build the samples.
+# We need to add some special AAPT flags to generate R classes
+# for resources that are included from the libraries.
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_PACKAGE_NAME := SupportLeanbackJank
+LOCAL_MODULE_TAGS := samples tests
+LOCAL_SDK_VERSION := current
+LOCAL_MIN_SDK_VERSION := 17
+LOCAL_DEX_PREOPT := false
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := glide
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+        android-support-compat \
+        android-support-core-ui \
+        android-support-media-compat \
+        android-support-fragment \
+        android-support-v7-recyclerview \
+        android-support-v17-leanback \
+        android-support-v17-preference-leanback \
+        android-support-v7-preference \
+        android-support-v14-preference
+
+include $(BUILD_PACKAGE)
diff --git a/samples/SupportLeanbackJank/AndroidManifest.xml b/samples/SupportLeanbackJank/AndroidManifest.xml
new file mode 100644
index 0000000..87be772
--- /dev/null
+++ b/samples/SupportLeanbackJank/AndroidManifest.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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
+  -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.google.android.leanbackjank">
+
+    <uses-sdk
+        android:minSdkVersion="21"
+        android:targetSdkVersion="24"/>
+
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false"/>
+
+    <uses-feature
+        android:name="android.software.leanback"
+        android:required="true"/>
+
+    <application
+        android:banner="@drawable/app_banner"
+        android:label="@string/app_name"
+        android:logo="@drawable/app_banner"
+        android:theme="@style/JankApp">
+        <activity
+            android:name=".ui.MainActivity"
+            android:banner="@drawable/app_banner"
+            android:icon="@drawable/app_banner"
+            android:label="@string/app_name"
+            android:logo="@drawable/app_banner"
+            android:screenOrientation="landscape"
+            android:theme="@style/Theme.Leanback.Browse">
+            <intent-filter>
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".ui.VideoActivity"
+            android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
+            android:launchMode="singleTask"
+            android:resizeableActivity="true"
+            android:supportsPictureInPicture="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/samples/SupportLeanbackJank/README.txt b/samples/SupportLeanbackJank/README.txt
new file mode 100644
index 0000000..09de019
--- /dev/null
+++ b/samples/SupportLeanbackJank/README.txt
@@ -0,0 +1,6 @@
+Sample leanback browser app intended to represent current best practices, while providing a set of
+features and capabilities that are relevant to performance.
+
+This app's initial purpose is to aid in the testing of hardware performance for Android TV. It is
+used in tests that are used in a test suite designed to verify hardware performance. It is placed
+here because it might also prove useful for other testing scenarios.
\ No newline at end of file
diff --git a/samples/SupportLeanbackJank/build.gradle b/samples/SupportLeanbackJank/build.gradle
new file mode 100644
index 0000000..48960bf
--- /dev/null
+++ b/samples/SupportLeanbackJank/build.gradle
@@ -0,0 +1,36 @@
+apply plugin: 'com.android.application'
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    compile 'com.github.bumptech.glide:glide:3.7.0'
+    compile project(':support-leanback-v17')
+    compile project(':support-preference-leanback-v17')
+}
+
+android {
+    compileSdkVersion project.ext.currentSdk
+
+    defaultConfig {
+        minSdkVersion 17
+    }
+
+    sourceSets {
+        main.manifest.srcFile 'AndroidManifest.xml'
+        main.java.srcDirs = ['src']
+        main.aidl.srcDirs = ['src']
+        main.res.srcDirs = ['res']
+    }
+
+    lintOptions {
+        abortOnError false
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
+}
+
diff --git a/samples/SupportLeanbackJank/res/drawable/android_header.png b/samples/SupportLeanbackJank/res/drawable/android_header.png
new file mode 100644
index 0000000..56206ec
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/drawable/android_header.png
Binary files differ
diff --git a/samples/SupportLeanbackJank/res/drawable/app_banner.png b/samples/SupportLeanbackJank/res/drawable/app_banner.png
new file mode 100644
index 0000000..4eeaa6f
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/drawable/app_banner.png
Binary files differ
diff --git a/samples/SupportLeanbackJank/res/drawable/default_background.xml b/samples/SupportLeanbackJank/res/drawable/default_background.xml
new file mode 100644
index 0000000..e367de8
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/drawable/default_background.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    <gradient
+            android:startColor="@color/jank_yellow"
+            android:endColor="@color/jank_green"
+            android:angle="0" />
+</shape>
\ No newline at end of file
diff --git a/samples/SupportLeanbackJank/res/drawable/movie.png b/samples/SupportLeanbackJank/res/drawable/movie.png
new file mode 100644
index 0000000..cb5cb6d
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/drawable/movie.png
Binary files differ
diff --git a/samples/SupportLeanbackJank/res/layout/header_item.xml b/samples/SupportLeanbackJank/res/layout/header_item.xml
new file mode 100644
index 0000000..2e11b08
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/layout/header_item.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/header_icon"
+        android:layout_width="32dp"
+        android:layout_height="32dp" />
+    <TextView
+        android:id="@+id/header_label"
+        android:textColor="#000000"
+        android:layout_marginTop="6dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/samples/SupportLeanbackJank/res/layout/main.xml b/samples/SupportLeanbackJank/res/layout/main.xml
new file mode 100644
index 0000000..d1fdee2
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/layout/main.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/main_frame"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <fragment
+        android:id="@+id/main_browse_fragment"
+        android:name="com.google.android.leanbackjank.ui.MainFragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+</FrameLayout>
diff --git a/samples/SupportLeanbackJank/res/raw/testvideo_1080p_60fps.mp4 b/samples/SupportLeanbackJank/res/raw/testvideo_1080p_60fps.mp4
new file mode 100644
index 0000000..9878a2a
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/raw/testvideo_1080p_60fps.mp4
Binary files differ
diff --git a/samples/SupportLeanbackJank/res/values/colors.xml b/samples/SupportLeanbackJank/res/values/colors.xml
new file mode 100644
index 0000000..e89b729
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/values/colors.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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="jank_yellow">#FABB05</color>
+    <color name="jank_green">#34A853</color>
+    <color name="jank_red">#EA4335</color>
+    <color name="jank_blue">#4285F4</color>
+    <color name="search_opaque">#ffaa3f</color>
+</resources>
\ No newline at end of file
diff --git a/samples/SupportLeanbackJank/res/values/dimens.xml b/samples/SupportLeanbackJank/res/values/dimens.xml
new file mode 100644
index 0000000..e2b1f9f
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/values/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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>
+    <dimen name="grid_item_width">100dp</dimen>
+    <dimen name="grid_item_height">100dp</dimen>
+    <dimen name="card_width">156dp</dimen>
+    <dimen name="card_height">88dp</dimen>
+</resources>
diff --git a/samples/SupportLeanbackJank/res/values/strings.xml b/samples/SupportLeanbackJank/res/values/strings.xml
new file mode 100644
index 0000000..37ceb80
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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>
+    <string name="app_name"><![CDATA[Leanback library jank test application]]></string>
+    <string name="browse_title"><![CDATA[Leanback library jank test application]]></string>
+</resources>
diff --git a/samples/SupportLeanbackJank/res/values/styles.xml b/samples/SupportLeanbackJank/res/values/styles.xml
new file mode 100644
index 0000000..ef7efe9
--- /dev/null
+++ b/samples/SupportLeanbackJank/res/values/styles.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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>
+    <style name="JankApp" parent="Theme.Leanback">
+        <item name="android:colorPrimary">@color/jank_yellow</item>
+        <item name="android:windowAllowReturnTransitionOverlap">true</item>
+        <item name="android:windowAllowEnterTransitionOverlap">true</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentDefaults.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentDefaults.java
new file mode 100644
index 0000000..7eba903
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentDefaults.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank;
+
+public final class IntentDefaults {
+
+    public static final int CATEGORY_COUNT = 20;
+    public static final int ENTRIES_PER_CATEGORY = 20;
+    public static final int CARD_WIDTH = 313;
+    public static final int CARD_HEIGHT = 176;
+    public static final boolean DISABLE_SHADOWS = false;
+    public static final boolean PLAY_VIDEO = false;
+    public static final boolean USE_SINGLE_BITMAP = false;
+
+    private IntentDefaults() {
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentKeys.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentKeys.java
new file mode 100644
index 0000000..c25ed0a
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/IntentKeys.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank;
+
+public final class IntentKeys {
+
+    public static final String CATEGORY_COUNT = "CATEGORY_COUNT";
+    public static final String ENTRIES_PER_CATEGORY = "ENTRIES_PER_CATEGORY";
+    public static final String CARD_WIDTH = "CARD_WIDTH";
+    public static final String CARD_HEIGHT = "CARD_HEIGHT";
+    public static final String DISABLE_SHADOWS = "ENABLE_SHADOWS";
+    public static final String PLAY_VIDEO = "PLAY_VIDEO";
+    public static final String USE_SINGLE_BITMAP = "USE_SINGLE_BITMAP";
+
+    private IntentKeys() {
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/data/VideoProvider.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/data/VideoProvider.java
new file mode 100644
index 0000000..a9e0dd5
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/data/VideoProvider.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.data;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Shader;
+import android.graphics.Shader.TileMode;
+import android.net.Uri;
+import android.util.Log;
+
+import com.google.android.leanbackjank.model.VideoInfo;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Generates fake data for populating the video cards.
+ */
+public final class VideoProvider {
+
+    private static final String TAG = "JankVideoProvider";
+    private static final int STUDIO_COUNT = 13;
+
+    private static final List<Integer> COLORS = Arrays.asList(
+            Color.parseColor("#4285F4"),
+            Color.parseColor("#EA4335"),
+            Color.parseColor("#FABB05"),
+            Color.parseColor("#34A853")
+    );
+
+    private VideoProvider() {
+    }
+
+    public static HashMap<String, List<VideoInfo>> buildMedia(int categoryCount, int entriesPerCat,
+            int width, int height, Context context, boolean useSingleBitmap) {
+        HashMap<String, List<VideoInfo>> ret = new HashMap<>();
+
+        int count = 0;
+        String rootPath = String.format(Locale.US, "%s/%d_%d/", context.getFilesDir(), width,
+                height);
+        File rootDirectory = new File(rootPath);
+        rootDirectory.mkdirs();
+
+        for (int i = 0; i < categoryCount; i++) {
+            List<VideoInfo> list = new ArrayList<>();
+            String category = "Category " + Integer.toString(i);
+            ret.put(category, list);
+            for (int j = 0; j < entriesPerCat; j++) {
+                String description = String.format(Locale.US,
+                        "The gripping yet whimsical description of videoInfo %d in category %d", j,
+                        i);
+                String title = String.format(Locale.US, "Video %d-%d", i, j);
+                String studio = String.format(Locale.US, "Studio %d", count % STUDIO_COUNT);
+
+                VideoInfo videoInfo = new VideoInfo();
+                videoInfo.setId(Integer.toString(count));
+                videoInfo.setTitle(title);
+                videoInfo.setDescription(description);
+                videoInfo.setStudio(studio);
+                videoInfo.setCategory(category);
+
+                int videoNumber = useSingleBitmap ? 0 : count;
+                File file = new File(rootPath + videoNumber + ".jpg");
+                if (!file.exists()) {
+                    makeIcon(width, height, "Jank", file);
+                }
+                videoInfo.setImageUri(Uri.fromFile(file));
+
+                count++;
+
+                list.add(videoInfo);
+            }
+        }
+
+        return ret;
+    }
+
+    public static void makeIcon(int width, int height, String string, File file) {
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+
+        Collections.shuffle(COLORS);
+
+        Paint paint = new Paint();
+        paint.setAntiAlias(true);
+        paint.setTextAlign(Paint.Align.CENTER);
+
+        // Draw background gradient.
+        Shader shader = new LinearGradient(0, 0, width - 1, height - 1, COLORS.get(0),
+                COLORS.get(1), TileMode.CLAMP);
+        paint.setShader(shader);
+        canvas.drawRect(0, 0, width - 1, height - 1, paint);
+
+        paint.setTextSize(height * 0.5f);
+        Rect rect = new Rect();
+        paint.getTextBounds(string, 0, string.length(), rect);
+
+        int hOffset = (height - rect.height()) / 2;
+        int wOffset = (width - rect.width()) / 2;
+        shader = new LinearGradient(wOffset, height - hOffset, width - wOffset, hOffset,
+                COLORS.get(2), COLORS.get(3), TileMode.CLAMP);
+        paint.setShader(shader);
+
+        canvas.drawText(string, width / 2, (height + rect.height()) / 2, paint);
+
+        try (FileOutputStream outputStream = new FileOutputStream(file)) {
+            bitmap.compress(CompressFormat.JPEG, 90, outputStream);
+        } catch (IOException e) {
+            Log.e(TAG, "Cannot write image to file: " + file, e);
+        }
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/model/VideoInfo.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/model/VideoInfo.java
new file mode 100644
index 0000000..7e8cc8a
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/model/VideoInfo.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.model;
+
+import android.net.Uri;
+
+/**
+ * VideoInfo class represents video entity with title, description, image thumbs and video url.
+ */
+public class VideoInfo {
+    private String mId;
+    private String mTitle;
+    private String mDescription;
+    private String mStudio;
+    private String mCategory;
+    private Uri mImageUri;
+
+    public VideoInfo() {
+    }
+
+    public String getId() {
+        return mId;
+    }
+
+    public void setId(String id) {
+        mId = id;
+    }
+
+    public String getTitle() {
+        return mTitle;
+    }
+
+    public void setTitle(String title) {
+        mTitle = title;
+    }
+
+    public String getDescription() {
+        return mDescription;
+    }
+
+    public void setDescription(String description) {
+        mDescription = description;
+    }
+
+    public String getStudio() {
+        return mStudio;
+    }
+
+    public void setStudio(String studio) {
+        mStudio = studio;
+    }
+
+    public String getCategory() {
+        return mCategory;
+    }
+
+    public void setCategory(String category) {
+        mCategory = category;
+    }
+
+    public Uri getImageUri() {
+        return mImageUri;
+    }
+
+    public void setImageUri(Uri imageUri) {
+        mImageUri = imageUri;
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
new file mode 100644
index 0000000..564ff92
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/CardPresenter.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.presenter;
+
+import android.support.v17.leanback.widget.ImageCardView;
+import android.support.v17.leanback.widget.Presenter;
+import android.view.ViewGroup;
+
+import com.bumptech.glide.Glide;
+import com.google.android.leanbackjank.R;
+import com.google.android.leanbackjank.model.VideoInfo;
+
+public class CardPresenter extends Presenter {
+    private int mSelectedBackgroundColor = -1;
+    private int mDefaultBackgroundColor = -1;
+    private int mCardWidth;
+    private int mCardHeight;
+
+    public CardPresenter(int width, int height) {
+        mCardWidth = width;
+        mCardHeight = height;
+    }
+
+    @Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent) {
+        mDefaultBackgroundColor = parent.getResources().getColor(R.color.jank_blue, null);
+        mSelectedBackgroundColor = parent.getResources().getColor(R.color.jank_red, null);
+
+        ImageCardView cardView = new ImageCardView(parent.getContext()) {
+            @Override
+            public void setSelected(boolean selected) {
+                updateCardBackgroundColor(this, selected);
+                super.setSelected(selected);
+            }
+        };
+
+        cardView.setFocusable(true);
+        cardView.setFocusableInTouchMode(true);
+        updateCardBackgroundColor(cardView, false);
+        return new ViewHolder(cardView);
+    }
+
+    private void updateCardBackgroundColor(ImageCardView view, boolean selected) {
+        int color = selected ? mSelectedBackgroundColor : mDefaultBackgroundColor;
+
+        // Both background colors should be set because the view's
+        // background is temporarily visible during animations.
+        view.setBackgroundColor(color);
+        view.findViewById(R.id.info_field).setBackgroundColor(color);
+    }
+
+    @Override
+    public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
+        VideoInfo videoInfo = (VideoInfo) item;
+
+        ImageCardView cardView = (ImageCardView) viewHolder.view;
+        cardView.setTitleText(videoInfo.getTitle());
+        cardView.setContentText(videoInfo.getStudio());
+        cardView.setMainImageDimensions(mCardWidth, mCardHeight);
+
+        Glide.with(cardView.getContext())
+                .load(videoInfo.getImageUri())
+                .into(cardView.getMainImageView());
+    }
+
+    @Override
+    public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
+        ImageCardView cardView = (ImageCardView) viewHolder.view;
+
+        // Remove references to images so that the garbage collector can free up memory.
+        cardView.setBadgeImage(null);
+        cardView.setMainImage(null);
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/GridItemPresenter.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/GridItemPresenter.java
new file mode 100644
index 0000000..ff99a9b
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/GridItemPresenter.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.presenter;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.support.v17.leanback.widget.Presenter;
+import android.view.Gravity;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.google.android.leanbackjank.R;
+
+public class GridItemPresenter extends Presenter {
+
+    @Override
+    public ViewHolder onCreateViewHolder(ViewGroup parent) {
+        TextView view = new TextView(parent.getContext());
+
+        Resources res = parent.getResources();
+        int width = res.getDimensionPixelSize(R.dimen.grid_item_width);
+        int height = res.getDimensionPixelSize(R.dimen.grid_item_height);
+
+        view.setLayoutParams(new ViewGroup.LayoutParams(width, height));
+        view.setFocusable(true);
+        view.setFocusableInTouchMode(true);
+        view.setBackgroundColor(parent.getResources().getColor(R.color.jank_yellow, null));
+        view.setTextColor(Color.WHITE);
+        view.setGravity(Gravity.CENTER);
+        return new ViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+        ((TextView) viewHolder.view).setText((String) item);
+    }
+
+    @Override
+    public void onUnbindViewHolder(ViewHolder viewHolder) {
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/HeaderItemPresenter.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/HeaderItemPresenter.java
new file mode 100644
index 0000000..9740088
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/presenter/HeaderItemPresenter.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.presenter;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.RowHeaderPresenter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.google.android.leanbackjank.R;
+
+public class HeaderItemPresenter extends RowHeaderPresenter {
+    private float mUnselectedAlpha;
+
+    @Override
+    public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {
+        mUnselectedAlpha = viewGroup.getResources()
+                .getFraction(R.fraction.lb_browse_header_unselect_alpha, 1, 1);
+        LayoutInflater inflater = (LayoutInflater) viewGroup.getContext()
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        View view = inflater.inflate(R.layout.header_item, null);
+        view.setAlpha(mUnselectedAlpha); // Initialize icons to be at half-opacity.
+
+        return new ViewHolder(view);
+    }
+
+    @Override
+    public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item) {
+        HeaderItem headerItem = ((ListRow) item).getHeaderItem();
+        View rootView = viewHolder.view;
+        rootView.setFocusable(true);
+
+        ImageView iconView = (ImageView) rootView.findViewById(R.id.header_icon);
+        Drawable icon = rootView.getResources().getDrawable(R.drawable.android_header, null);
+        iconView.setImageDrawable(icon);
+
+        TextView label = (TextView) rootView.findViewById(R.id.header_label);
+        label.setText(headerItem.getName());
+    }
+
+    @Override
+    public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
+        // no op
+    }
+
+    // TODO: This is a temporary fix. Remove me when leanback onCreateViewHolder no longer sets the
+    // mUnselectAlpha, and also assumes the xml inflation will return a RowHeaderView.
+    @Override
+    protected void onSelectLevelChanged(RowHeaderPresenter.ViewHolder holder) {
+        holder.view.setAlpha(
+                mUnselectedAlpha + holder.getSelectLevel() * (1.0f - mUnselectedAlpha));
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainActivity.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainActivity.java
new file mode 100644
index 0000000..0097b31
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainActivity.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.ui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.google.android.leanbackjank.R;
+
+
+/**
+ * MainActivity class that loads MainFragment
+ */
+public class MainActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+
+    @Override
+    protected void onStop() {
+        Intent intent = new Intent(this, VideoActivity.class);
+        startActivity(intent);
+
+        super.onStop();
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
new file mode 100644
index 0000000..507c562
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.ui;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v17.leanback.app.BackgroundManager;
+import android.support.v17.leanback.app.BrowseFragment;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.PresenterSelector;
+
+import com.google.android.leanbackjank.IntentDefaults;
+import com.google.android.leanbackjank.IntentKeys;
+import com.google.android.leanbackjank.R;
+import com.google.android.leanbackjank.data.VideoProvider;
+import com.google.android.leanbackjank.model.VideoInfo;
+import com.google.android.leanbackjank.presenter.CardPresenter;
+import com.google.android.leanbackjank.presenter.GridItemPresenter;
+import com.google.android.leanbackjank.presenter.HeaderItemPresenter;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Main class to show BrowseFragment with header and rows of videos
+ */
+public class MainFragment extends BrowseFragment {
+
+    private BackgroundManager mBackgroundManager;
+    private ArrayObjectAdapter mRowsAdapter;
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        // Define defaults.
+        int categoryCount = IntentDefaults.CATEGORY_COUNT;
+        int entriesPerCat = IntentDefaults.ENTRIES_PER_CATEGORY;
+        boolean disableShadows = IntentDefaults.DISABLE_SHADOWS;
+        int cardWidth = IntentDefaults.CARD_WIDTH;
+        int cardHeight = IntentDefaults.CARD_HEIGHT;
+        boolean playVideo = IntentDefaults.PLAY_VIDEO;
+        boolean useSingleBitmap = IntentDefaults.USE_SINGLE_BITMAP;
+
+        Intent intent = getActivity().getIntent();
+        if (intent.getExtras() != null) {
+            categoryCount = intent.getIntExtra(IntentKeys.CATEGORY_COUNT, categoryCount);
+            entriesPerCat = intent.getIntExtra(IntentKeys.ENTRIES_PER_CATEGORY, entriesPerCat);
+            disableShadows = intent.getBooleanExtra(IntentKeys.DISABLE_SHADOWS, disableShadows);
+            cardWidth = intent.getIntExtra(IntentKeys.CARD_WIDTH, cardWidth);
+            cardHeight = intent.getIntExtra(IntentKeys.CARD_HEIGHT, cardHeight);
+            playVideo = intent.getBooleanExtra(IntentKeys.PLAY_VIDEO, playVideo);
+            useSingleBitmap = intent.getBooleanExtra(IntentKeys.USE_SINGLE_BITMAP, useSingleBitmap);
+        }
+
+        loadVideoData(categoryCount, entriesPerCat, disableShadows, useSingleBitmap, cardWidth,
+                cardHeight);
+        setBackground();
+        setupUIElements();
+
+        if (playVideo) {
+            Uri uri = Uri.parse("android.resource://" + getContext().getPackageName() + "/"
+                    + R.raw.testvideo_1080p_60fps);
+            Intent videoIntent = new Intent(Intent.ACTION_VIEW, uri, getContext(),
+                    VideoActivity.class);
+            startActivity(videoIntent);
+        }
+    }
+
+    private void setBackground() {
+        mBackgroundManager = BackgroundManager.getInstance(getActivity());
+        mBackgroundManager.attach(getActivity().getWindow());
+        mBackgroundManager.setDrawable(
+                getResources().getDrawable(R.drawable.default_background, null));
+    }
+
+    private void setupUIElements() {
+        setBadgeDrawable(getActivity().getResources().getDrawable(R.drawable.app_banner, null));
+        // Badge, when set, takes precedent over title
+        setTitle(getString(R.string.browse_title));
+        setHeadersState(HEADERS_ENABLED);
+        setHeadersTransitionOnBackEnabled(true);
+        // set headers background color
+        setBrandColor(getResources().getColor(R.color.jank_yellow));
+        // set search icon color
+        setSearchAffordanceColor(getResources().getColor(R.color.search_opaque));
+
+        setHeaderPresenterSelector(new PresenterSelector() {
+            @Override
+            public Presenter getPresenter(Object o) {
+                return new HeaderItemPresenter();
+            }
+        });
+    }
+
+    private void loadVideoData(int categoryCount, int entriesPerCat, boolean disableShadows,
+            boolean useSingleBitmap, int cardWidth, int cardHeight) {
+        ListRowPresenter listRowPresenter = new ListRowPresenter();
+        listRowPresenter.setShadowEnabled(!disableShadows);
+        mRowsAdapter = new ArrayObjectAdapter(listRowPresenter);
+        HashMap<String, List<VideoInfo>> data = VideoProvider.buildMedia(categoryCount,
+                entriesPerCat, cardWidth, cardHeight, getContext(), useSingleBitmap);
+        CardPresenter cardPresenter = new CardPresenter(cardWidth, cardHeight);
+
+        int i = 0;
+        for (Map.Entry<String, List<VideoInfo>> entry : data.entrySet()) {
+            ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
+            for (VideoInfo videoInfo : entry.getValue()) {
+                listRowAdapter.add(videoInfo);
+            }
+            HeaderItem header = new HeaderItem(i++, entry.getKey());
+            mRowsAdapter.add(new ListRow(header, listRowAdapter));
+        }
+
+        ArrayObjectAdapter settingsListAdapter = new ArrayObjectAdapter(new GridItemPresenter());
+        for (int j = 0; j < entriesPerCat; j++) {
+            settingsListAdapter.add("Settings " + j);
+        }
+        HeaderItem settingsHeader = new HeaderItem(i++, "Settings");
+        mRowsAdapter.add(new ListRow(settingsHeader, settingsListAdapter));
+
+        setAdapter(mRowsAdapter);
+    }
+}
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/VideoActivity.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/VideoActivity.java
new file mode 100644
index 0000000..f026cc2
--- /dev/null
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/VideoActivity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 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 com.google.android.leanbackjank.ui;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.VideoView;
+
+public class VideoActivity extends Activity {
+
+    private VideoView mVideoView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+                WindowManager.LayoutParams.FLAG_FULLSCREEN);
+
+        mVideoView = new VideoView(this);
+        mVideoView.setOnPreparedListener(new OnPreparedListener() {
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                mp.setLooping(true);
+            }
+        });
+        setContentView(mVideoView);
+
+        if (checkIntent(getIntent())) {
+            enterPictureInPictureMode();
+        }
+    }
+
+    private void playVideo(Uri uri) {
+        mVideoView.setVideoURI(uri);
+        mVideoView.start();
+    }
+
+    private boolean checkIntent(Intent intent) {
+        if (Intent.ACTION_VIEW.equals(intent.getAction())) {
+            Uri uri = intent.getData();
+            playVideo(uri);
+            return true;
+        } else {
+            finish();
+            return false;
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        checkIntent(intent);
+    }
+
+    @Override
+    protected void onStop() {
+        if (mVideoView != null) {
+            mVideoView.stopPlayback();
+        }
+        super.onStop();
+        finish();
+    }
+}
diff --git a/settings.gradle b/settings.gradle
index dd64402..b217355 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -102,6 +102,9 @@
 include ':support-leanback-demos'
 project(':support-leanback-demos').projectDir = new File(samplesRoot, 'SupportLeanbackDemos')
 
+include ':support-leanback-jank'
+project(':support-leanback-jank').projectDir = new File(samplesRoot, 'SupportLeanbackJank')
+
 include ':support-percent-demos'
 project(':support-percent-demos').projectDir = new File(samplesRoot, 'SupportPercentDemos')