1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.test.uibench.leanback;
17 
18 import android.app.Activity;
19 import android.content.Context;
20 import android.graphics.Bitmap;
21 import android.graphics.Canvas;
22 import androidx.leanback.app.BackgroundManager;
23 import androidx.leanback.widget.ArrayObjectAdapter;
24 import androidx.leanback.widget.HeaderItem;
25 import androidx.leanback.widget.ListRow;
26 import androidx.leanback.widget.ListRowPresenter;
27 import androidx.leanback.widget.ObjectAdapter;
28 import androidx.leanback.widget.Presenter;
29 import android.util.DisplayMetrics;
30 import android.util.TypedValue;
31 
32 public class TestHelper {
33 
34     public static final String EXTRA_BACKGROUND = "extra_bg";
35     public static final String EXTRA_ROWS = "extra_rows";
36     public static final String EXTRA_CARDS_PER_ROW = "extra_cards_per_row";
37     public static final String EXTRA_CARD_HEIGHT_DP = "extra_card_height";
38     public static final String EXTRA_CARD_WIDTH_DP = "extra_card_width";
39     public static final String EXTRA_CARD_SHADOW = "extra_card_shadow";
40     public static final String EXTRA_CARD_ROUND_RECT = "extra_card_round_rect";
41     public static final String EXTRA_ENTRANCE_TRANSITION = "extra_entrance_transition";
42     public static final String EXTRA_BITMAP_UPLOAD = "extra_bitmap_upload";
43     public static final String EXTRA_SHOW_FAST_LANE = "extra_show_fast_lane";
44 
45     /**
46      * Dont change the default values, they gave baseline for measuring the performance
47      */
48     static final int DEFAULT_CARD_HEIGHT_DP = 180;
49     static final int DEFAULT_CARD_WIDTH_DP = 125;
50     static final int DEFAULT_CARDS_PER_ROW = 20;
51     static final int DEFAULT_ROWS = 10;
52     static final boolean DEFAULT_ENTRANCE_TRANSITION = false;
53     static final boolean DEFAULT_BACKGROUND = true;
54     static final boolean DEFAULT_CARD_SHADOW = true;
55     static final boolean DEFAULT_CARD_ROUND_RECT = true;
56     static final boolean DEFAULT_BITMAP_UPLOAD = true;
57     static final boolean DEFAULT_SHOW_FAST_LANE = true;
58 
59     static long sCardIdSeed = 0;
60     static long sRowIdSeed = 0;
61 
62     public static class ListRowPresenterBuilder {
63 
64         boolean mShadow = DEFAULT_CARD_SHADOW;
65         boolean mRoundedCorner = DEFAULT_CARD_ROUND_RECT;
66 
ListRowPresenterBuilder(Context context)67         ListRowPresenterBuilder(Context context) {
68         }
69 
configShadow(boolean shadow)70         public ListRowPresenterBuilder configShadow(boolean shadow) {
71             mShadow = shadow;
72             return this;
73         }
74 
configRoundedCorner(boolean roundedCorner)75         public ListRowPresenterBuilder configRoundedCorner(boolean roundedCorner) {
76             mRoundedCorner = roundedCorner;
77             return this;
78         }
79 
build()80         public ListRowPresenter build() {
81             ListRowPresenter listRowPresenter = new ListRowPresenter();
82             listRowPresenter.setShadowEnabled(mShadow);
83             listRowPresenter.enableChildRoundedCorners(mRoundedCorner);
84             return listRowPresenter;
85         }
86     }
87 
88     public static class CardPresenterBuilder {
89         Context mContext;
90         int mWidthDP = DEFAULT_CARD_WIDTH_DP;
91         int mHeightDP = DEFAULT_CARD_HEIGHT_DP;
92 
CardPresenterBuilder(Context context)93         CardPresenterBuilder(Context context) {
94             mContext = context;
95         }
96 
configWidthDP(int widthDP)97         public CardPresenterBuilder configWidthDP(int widthDP) {
98             mWidthDP = widthDP;
99             return this;
100         }
101 
configHeightDP(int hightDP)102         public CardPresenterBuilder configHeightDP(int hightDP) {
103             mHeightDP = hightDP;
104             return this;
105         }
106 
build()107         public Presenter build() {
108             DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
109             return new CardPresenter(
110                     (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mWidthDP, dm),
111                     (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mHeightDP, dm));
112         }
113     }
114 
115     public static class RowsAdapterBuilder {
116 
117         Context mContext;
118         int mCardsPerRow = DEFAULT_CARDS_PER_ROW;
119         int mRows = DEFAULT_ROWS;
120         CardPresenterBuilder mCardPresenterBuilder;
121         ListRowPresenterBuilder mListRowPresenterBuilder;
122         Presenter mCardPresenter;
123         boolean mBitmapUpload = DEFAULT_BITMAP_UPLOAD;
124 
125         static final String[] sSampleStrings = new String[] {
126                 "Hello world", "This is a test", "Android TV", "UI Jank Test",
127                 "Scroll Up", "Scroll Down", "Load Bitmaps"
128         };
129 
130         /**
131          * Create a RowsAdapterBuilder with default settings
132          */
RowsAdapterBuilder(Context context)133         public RowsAdapterBuilder(Context context) {
134             mContext = context;
135             mCardPresenterBuilder = new CardPresenterBuilder(context);
136             mListRowPresenterBuilder = new ListRowPresenterBuilder(context);
137         }
138 
getListRowPresenterBuilder()139         public ListRowPresenterBuilder getListRowPresenterBuilder() {
140             return mListRowPresenterBuilder;
141         }
142 
getCardPresenterBuilder()143         public CardPresenterBuilder getCardPresenterBuilder() {
144             return mCardPresenterBuilder;
145         }
146 
configRows(int rows)147         public RowsAdapterBuilder configRows(int rows) {
148             mRows = rows;
149             return this;
150         }
151 
configCardsPerRow(int cardsPerRow)152         public RowsAdapterBuilder configCardsPerRow(int cardsPerRow) {
153             mCardsPerRow = cardsPerRow;
154             return this;
155         }
156 
configBitmapUpLoad(boolean bitmapUpload)157         public RowsAdapterBuilder configBitmapUpLoad(boolean bitmapUpload) {
158             mBitmapUpload = bitmapUpload;
159             return this;
160         }
161 
buildListRow()162         public ListRow buildListRow() {
163             ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(mCardPresenter);
164             ListRow listRow = new ListRow(new HeaderItem(sRowIdSeed++, "Row"), listRowAdapter);
165             int indexSample = 0;
166             for (int i = 0; i < mCardsPerRow; i++) {
167                 // when doing bitmap upload, use different id so each card has different bitmap
168                 // otherwise all cards share the same bitmap
169                 listRowAdapter.add(new PhotoItem(sSampleStrings[indexSample],
170                         (mBitmapUpload ? sCardIdSeed++ : 0)));
171                 indexSample++;
172                 if (indexSample >= sSampleStrings.length) {
173                     indexSample = 0;
174                 }
175             }
176             return listRow;
177         }
178 
build()179         public ObjectAdapter build() {
180             try {
181                 mCardPresenter = mCardPresenterBuilder.build();
182                 ArrayObjectAdapter adapter = new ArrayObjectAdapter(
183                         mListRowPresenterBuilder.build());
184                 for (int i = 0; i < mRows; i++) {
185                     adapter.add(buildListRow());
186                 }
187                 return adapter;
188             } finally {
189                 mCardPresenter = null;
190             }
191         }
192     }
193 
runEntranceTransition(Activity activity)194     public static boolean runEntranceTransition(Activity activity) {
195         return activity.getIntent().getBooleanExtra(EXTRA_ENTRANCE_TRANSITION,
196                 DEFAULT_ENTRANCE_TRANSITION);
197     }
198 
initRowsAdapterBuilder(Activity activity)199     public static RowsAdapterBuilder initRowsAdapterBuilder(Activity activity) {
200         RowsAdapterBuilder builder = new RowsAdapterBuilder(activity);
201         boolean shadow = activity.getIntent().getBooleanExtra(EXTRA_CARD_SHADOW,
202                 DEFAULT_CARD_SHADOW);
203         boolean roundRect = activity.getIntent().getBooleanExtra(EXTRA_CARD_ROUND_RECT,
204                 DEFAULT_CARD_ROUND_RECT);
205         int widthDp = activity.getIntent().getIntExtra(EXTRA_CARD_WIDTH_DP,
206                 DEFAULT_CARD_WIDTH_DP);
207         int heightDp = activity.getIntent().getIntExtra(EXTRA_CARD_HEIGHT_DP,
208                 DEFAULT_CARD_HEIGHT_DP);
209         int rows = activity.getIntent().getIntExtra(EXTRA_ROWS, DEFAULT_ROWS);
210         int cardsPerRow = activity.getIntent().getIntExtra(EXTRA_CARDS_PER_ROW,
211                 DEFAULT_CARDS_PER_ROW);
212         boolean bitmapUpload = activity.getIntent().getBooleanExtra(EXTRA_BITMAP_UPLOAD,
213                 DEFAULT_BITMAP_UPLOAD);
214         builder.configRows(rows)
215                 .configCardsPerRow(cardsPerRow)
216                 .configBitmapUpLoad(bitmapUpload);
217         builder.getListRowPresenterBuilder()
218                 .configRoundedCorner(roundRect)
219                 .configShadow(shadow);
220         builder.getCardPresenterBuilder()
221                 .configWidthDP(widthDp)
222                 .configHeightDP(heightDp);
223         return builder;
224     }
225 
initBackground(Activity activity)226     public static void initBackground(Activity activity) {
227         if (activity.getIntent().getBooleanExtra(EXTRA_BACKGROUND, DEFAULT_BACKGROUND)) {
228             BackgroundManager manager = BackgroundManager.getInstance(activity);
229             manager.attach(activity.getWindow());
230             DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
231             int width = metrics.widthPixels;
232             int height = metrics.heightPixels;
233             Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
234             Canvas canvas = new Canvas(bitmap);
235             canvas.drawARGB(255, 128, 128, 128);
236             canvas.setBitmap(null);
237             manager.setBitmap(bitmap);
238         }
239     }
240 
initHeaderState(BrowseFragment fragment)241     public static void initHeaderState(BrowseFragment fragment) {
242         if (!fragment.getActivity().getIntent()
243                 .getBooleanExtra(EXTRA_SHOW_FAST_LANE, DEFAULT_SHOW_FAST_LANE)) {
244             fragment.setHeadersState(BrowseFragment.HEADERS_HIDDEN);
245         }
246     }
247 }
248