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 */
16package com.android.test.uibench.leanback;
17
18import android.app.Activity;
19import android.content.Context;
20import android.graphics.Bitmap;
21import android.graphics.Canvas;
22import android.support.v17.leanback.app.BackgroundManager;
23import android.support.v17.leanback.widget.ArrayObjectAdapter;
24import android.support.v17.leanback.widget.HeaderItem;
25import android.support.v17.leanback.widget.ListRow;
26import android.support.v17.leanback.widget.ListRowPresenter;
27import android.support.v17.leanback.widget.ObjectAdapter;
28import android.support.v17.leanback.widget.Presenter;
29import android.util.DisplayMetrics;
30import android.util.TypedValue;
31
32public 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
67        ListRowPresenterBuilder(Context context) {
68        }
69
70        public ListRowPresenterBuilder configShadow(boolean shadow) {
71            mShadow = shadow;
72            return this;
73        }
74
75        public ListRowPresenterBuilder configRoundedCorner(boolean roundedCorner) {
76            mRoundedCorner = roundedCorner;
77            return this;
78        }
79
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
93        CardPresenterBuilder(Context context) {
94            mContext = context;
95        }
96
97        public CardPresenterBuilder configWidthDP(int widthDP) {
98            mWidthDP = widthDP;
99            return this;
100        }
101
102        public CardPresenterBuilder configHeightDP(int hightDP) {
103            mHeightDP = hightDP;
104            return this;
105        }
106
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         */
133        public RowsAdapterBuilder(Context context) {
134            mContext = context;
135            mCardPresenterBuilder = new CardPresenterBuilder(context);
136            mListRowPresenterBuilder = new ListRowPresenterBuilder(context);
137        }
138
139        public ListRowPresenterBuilder getListRowPresenterBuilder() {
140            return mListRowPresenterBuilder;
141        }
142
143        public CardPresenterBuilder getCardPresenterBuilder() {
144            return mCardPresenterBuilder;
145        }
146
147        public RowsAdapterBuilder configRows(int rows) {
148            mRows = rows;
149            return this;
150        }
151
152        public RowsAdapterBuilder configCardsPerRow(int cardsPerRow) {
153            mCardsPerRow = cardsPerRow;
154            return this;
155        }
156
157        public RowsAdapterBuilder configBitmapUpLoad(boolean bitmapUpload) {
158            mBitmapUpload = bitmapUpload;
159            return this;
160        }
161
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
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
194    public static boolean runEntranceTransition(Activity activity) {
195        return activity.getIntent().getBooleanExtra(EXTRA_ENTRANCE_TRANSITION,
196                DEFAULT_ENTRANCE_TRANSITION);
197    }
198
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
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
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