Add SlowNestedRecyclerViewActivity
Bug: 31063101
Test: adb shell am instrument -e iterations 10 -w -e class com.android.uibench.janktests.UiBenchJankTests#testSlowNestedRecyclerViewFling com.android.uibench.janktests/android.test.InstrumentationTestRunner
Change-Id: I43e988e889f356323c9aea099f0efc6a04556f11
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index b7b4894..29154aa 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -102,10 +102,18 @@
<activity
android:name=".SlowBindRecyclerViewActivity"
android:label="General/Slow Bind RecyclerView" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="com.android.test.uibench.TEST" />
- </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.uibench.TEST" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".SlowNestedRecyclerViewActivity"
+ android:label="General/Slow Nested RecyclerView" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.uibench.TEST" />
+ </intent-filter>
</activity>
<activity
android:name=".ActivityTransition"
diff --git a/tests/UiBench/src/com/android/test/uibench/SlowNestedRecyclerViewActivity.java b/tests/UiBench/src/com/android/test/uibench/SlowNestedRecyclerViewActivity.java
new file mode 100644
index 0000000..305c051
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/SlowNestedRecyclerViewActivity.java
@@ -0,0 +1,181 @@
+/*
+ * 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.android.test.uibench;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.InsetDrawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.test.uibench.recyclerview.RvCompatListActivity;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+public class SlowNestedRecyclerViewActivity extends RvCompatListActivity {
+ private static final int OUTER_ITEM_COUNT = 100;
+ private static final int INNER_ITEM_COUNT = 20;
+
+ private static final long INNER_ITEM_CREATE_NS = TimeUnit.MILLISECONDS.toNanos(6);
+ private static final long INNER_ITEM_BIND_NS = TimeUnit.MILLISECONDS.toNanos(1);
+ private static final long INNER_ITEM_ATTACH_NS = TimeUnit.MILLISECONDS.toNanos(1);
+
+ private static final long OUTER_ITEM_CREATE_NS = TimeUnit.MILLISECONDS.toNanos(3);
+ private static final long OUTER_ITEM_BIND_NS = TimeUnit.MILLISECONDS.toNanos(1);
+ private static final long OUTER_ITEM_ATTACH_NS = TimeUnit.MILLISECONDS.toNanos(1);
+
+ private SizeData mSizeData;
+
+ private static class SizeData {
+ final int innerItemWidth;
+ final int innerItemHeight;
+ final int headerHeight;
+
+ SizeData(Resources resources) {
+ innerItemWidth = (int) (resources.getDisplayMetrics().widthPixels / 3.3f);
+ innerItemHeight = (int) (innerItemWidth * 1.6f);
+ headerHeight = (int) (resources.getDisplayMetrics().heightPixels * 0.5f);
+ }
+ }
+
+ private SizeData getSizeData(Resources resources) {
+ if (mSizeData == null) {
+ mSizeData = new SizeData(resources);
+ }
+ return mSizeData;
+ }
+
+ @Override
+ protected RecyclerView.LayoutManager createLayoutManager(Context context) {
+ return new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
+ }
+
+ @Override
+ protected RecyclerView.Adapter createAdapter() {
+ return new OuterAdapter();
+ }
+
+ private class InnerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ final long start = System.nanoTime();
+
+ final float density = parent.getResources().getDisplayMetrics().density;
+ View view = new View(parent.getContext()) {
+ @Override
+ protected void onAttachedToWindow() {
+ final long start = System.nanoTime();
+ super.onAttachedToWindow();
+ while (System.nanoTime() - start < INNER_ITEM_ATTACH_NS);
+ }
+ };
+
+ SizeData sizeData = getSizeData(parent.getResources());
+ view.setMinimumWidth(sizeData.innerItemWidth);
+ view.setMinimumHeight(sizeData.innerItemHeight);
+
+ GradientDrawable bg = new GradientDrawable();
+ bg.setCornerRadius(10 * density);
+ bg.setColor(Color.BLACK);
+ final int pad = (int)(10 * density);
+ view.setPadding(pad, pad, pad, pad);
+ view.setBackgroundDrawable(new InsetDrawable(bg, pad));
+ RecyclerView.ViewHolder holder = new RecyclerView.ViewHolder(view) {};
+
+ while (System.nanoTime() - start < INNER_ITEM_CREATE_NS);
+ return holder;
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ final long start = System.nanoTime();
+ while (System.nanoTime() - start < INNER_ITEM_BIND_NS);
+ }
+
+ @Override
+ public int getItemCount() { return INNER_ITEM_COUNT; }
+ }
+
+ private class OuterAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+ static final int TYPE_HEADER = 0;
+ static final int TYPE_RECYCLER = 1;
+
+ ArrayList<InnerAdapter> mAdapters = new ArrayList<>();
+ RecyclerView.RecycledViewPool mSharedPool = new RecyclerView.RecycledViewPool();
+
+ OuterAdapter() {
+ for (int i = 0; i < OUTER_ITEM_COUNT; i++) {
+ mAdapters.add(new InnerAdapter());
+ }
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ SizeData sizeData = getSizeData(parent.getResources());
+ if (viewType == TYPE_HEADER) {
+ View view = new View(parent.getContext());
+ view.setMinimumHeight(sizeData.headerHeight);
+ return new RecyclerView.ViewHolder(view) {};
+ } else {
+ final long start = System.nanoTime();
+
+ RecyclerView rv = new RecyclerView(parent.getContext()) {
+ @Override
+ protected void onAttachedToWindow() {
+ final long start = System.nanoTime();
+ super.onAttachedToWindow();
+ while (System.nanoTime() - start < OUTER_ITEM_ATTACH_NS);
+
+ }
+ };
+
+ rv.setLayoutParams(new RecyclerView.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, sizeData.innerItemHeight));
+ rv.setLayoutManager(new LinearLayoutManager(parent.getContext(),
+ LinearLayoutManager.HORIZONTAL, false));
+ rv.setRecycledViewPool(mSharedPool);
+ RecyclerView.ViewHolder holder = new RecyclerView.ViewHolder(rv) {};
+
+ while (System.nanoTime() - start < OUTER_ITEM_CREATE_NS);
+ return holder;
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
+ if (getItemViewType(position) == TYPE_RECYCLER) {
+ final long start = System.nanoTime();
+ ((RecyclerView)holder.itemView).setAdapter(mAdapters.get(position));
+ while (System.nanoTime() - start < OUTER_ITEM_BIND_NS);
+ }
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return position == 0 ? TYPE_HEADER : TYPE_RECYCLER;
+ }
+
+ @Override
+ public int getItemCount() {
+ return mAdapters.size();
+ }
+ }
+}