1 /* 2 * Copyright (C) 2019 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 17 package com.android.uibench.microbenchmark; 18 19 import android.app.Instrumentation; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.Bundle; 24 import android.os.SystemClock; 25 import android.platform.helpers.AbstractStandardAppHelper; 26 import android.support.test.uiautomator.By; 27 import android.support.test.uiautomator.Direction; 28 import android.support.test.uiautomator.UiObject2; 29 import android.support.test.uiautomator.Until; 30 import android.util.DisplayMetrics; 31 import android.view.KeyEvent; 32 import android.widget.EditText; 33 import android.widget.ListView; 34 35 import junit.framework.Assert; 36 37 public class UiBenchJankHelper extends AbstractStandardAppHelper implements IUiBenchJankHelper { 38 public static final int LONG_TIMEOUT = 5000; 39 public static final int FULL_TEST_DURATION = 25000; 40 public static final int FIND_OBJECT_TIMEOUT = 250; 41 public static final int SHORT_TIMEOUT = 2000; 42 public static final int EXPECTED_FRAMES = 100; 43 public static final int KEY_DELAY = 1000; 44 public static final String EXTRA_BITMAP_UPLOAD = "extra_bitmap_upload"; 45 public static final String EXTRA_SHOW_FAST_LANE = "extra_show_fast_lane"; 46 47 /** 48 * Only to be used for initial-fling tests, or similar cases where perf during brief experience 49 * is important. 50 */ 51 public static final int SHORT_EXPECTED_FRAMES = 30; 52 53 public static final String PACKAGE_NAME = "com.android.test.uibench"; 54 55 public static final String APP_LAUNCHER_NAME = "UiBench"; 56 57 private static final int SLOW_FLING_SPEED = 3000; // compare to UiObject2#DEFAULT_FLING_SPEED 58 59 // Main UiObject2 exercised by the test. 60 private UiObject2 mContents, mNavigation; 61 UiBenchJankHelper(Instrumentation instr)62 public UiBenchJankHelper(Instrumentation instr) { 63 super(instr); 64 } 65 66 /** {@inheritDoc} */ 67 @Override getPackage()68 public String getPackage() { 69 return PACKAGE_NAME; 70 } 71 72 /** {@inheritDoc} */ 73 @Override getLauncherName()74 public String getLauncherName() { 75 return APP_LAUNCHER_NAME; 76 } 77 78 /** {@inheritDoc} */ 79 @Override dismissInitialDialogs()80 public void dismissInitialDialogs() {} 81 82 /** Launch activity using intent */ launchActivity(String activityName, Bundle extras, String verifyText)83 void launchActivity(String activityName, Bundle extras, String verifyText) { 84 ComponentName cn = 85 new ComponentName(PACKAGE_NAME, String.format("%s.%s", PACKAGE_NAME, activityName)); 86 Intent intent = new Intent(Intent.ACTION_MAIN); 87 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 88 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 89 if (extras != null) { 90 intent.putExtras(extras); 91 } 92 intent.setComponent(cn); 93 // Launch the activity 94 mInstrumentation.getContext().startActivity(intent); 95 UiObject2 expectedTextCmp = 96 mDevice.wait(Until.findObject(By.text(verifyText)), LONG_TIMEOUT); 97 Assert.assertNotNull(String.format("Issue in opening %s", activityName), expectedTextCmp); 98 } 99 launchActivity(String activityName, String verifyText)100 void launchActivity(String activityName, String verifyText) { 101 launchActivity(activityName, null, verifyText); 102 } 103 launchActivityAndAssert(String activityName, String verifyText)104 void launchActivityAndAssert(String activityName, String verifyText) { 105 launchActivity(activityName, verifyText); 106 mContents = 107 mDevice.wait(Until.findObject(By.res("android", "content")), FIND_OBJECT_TIMEOUT); 108 Assert.assertNotNull(activityName + " isn't found", mContents); 109 } 110 getEdgeSensitivity()111 int getEdgeSensitivity() { 112 int resId = 113 mInstrumentation 114 .getContext() 115 .getResources() 116 .getIdentifier("config_backGestureInset", "dimen", "android"); 117 return mInstrumentation.getContext().getResources().getDimensionPixelSize(resId) + 1; 118 } 119 120 /** To perform the fling down and up on given content for flingCount number of times */ 121 @Override flingUpDown(int flingCount)122 public void flingUpDown(int flingCount) { 123 flingUpDown(flingCount, false); 124 } 125 126 @Override flingDownUp(int flingCount)127 public void flingDownUp(int flingCount) { 128 flingUpDown(flingCount, true); 129 } 130 flingUpDown(int flingCount, boolean reverse)131 void flingUpDown(int flingCount, boolean reverse) { 132 mContents.setGestureMargin(getEdgeSensitivity()); 133 for (int count = 0; count < flingCount; count++) { 134 SystemClock.sleep(SHORT_TIMEOUT); 135 mContents.fling(reverse ? Direction.UP : Direction.DOWN); 136 SystemClock.sleep(SHORT_TIMEOUT); 137 mContents.fling(reverse ? Direction.DOWN : Direction.UP); 138 } 139 } 140 141 /** To perform the swipe right and left on given content for swipeCount number of times */ 142 @Override swipeRightLeft(int swipeCount)143 public void swipeRightLeft(int swipeCount) { 144 mNavigation = 145 mDevice.wait( 146 Until.findObject(By.desc("Open navigation drawer")), FIND_OBJECT_TIMEOUT); 147 mContents.setGestureMargin(getEdgeSensitivity()); 148 for (int count = 0; count < swipeCount; count++) { 149 SystemClock.sleep(SHORT_TIMEOUT); 150 mNavigation.click(); 151 SystemClock.sleep(SHORT_TIMEOUT); 152 mContents.swipe(Direction.LEFT, 1); 153 } 154 } 155 156 @Override slowSingleFlingDown()157 public void slowSingleFlingDown() { 158 SystemClock.sleep(SHORT_TIMEOUT); 159 Context context = mInstrumentation.getContext(); 160 DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); 161 mContents.setGestureMargin(getEdgeSensitivity()); 162 mContents.fling(Direction.DOWN, (int) (SLOW_FLING_SPEED * displayMetrics.density)); 163 mDevice.waitForIdle(); 164 } 165 166 @Override openDialogList()167 public void openDialogList() { 168 launchActivity("DialogListActivity", "Dialog"); 169 mContents = mDevice.wait(Until.findObject(By.clazz(ListView.class)), FIND_OBJECT_TIMEOUT); 170 Assert.assertNotNull("Dialog List View isn't found", mContents); 171 } 172 173 @Override openFullscreenOverdraw()174 public void openFullscreenOverdraw() { 175 launchActivity("FullscreenOverdrawActivity", "General/Fullscreen Overdraw"); 176 } 177 178 @Override openGLTextureView()179 public void openGLTextureView() { 180 launchActivity("GlTextureViewActivity", "General/GL TextureView"); 181 } 182 183 @Override openInvalidate()184 public void openInvalidate() { 185 launchActivity("InvalidateActivity", "General/Invalidate"); 186 } 187 188 @Override openInvalidateTree()189 public void openInvalidateTree() { 190 launchActivity("InvalidateTreeActivity", "General/Invalidate Tree"); 191 } 192 193 @Override openTrivialAnimation()194 public void openTrivialAnimation() { 195 launchActivity("TrivialAnimationActivity", "General/Trivial Animation"); 196 } 197 198 @Override openTrivialListView()199 public void openTrivialListView() { 200 launchActivityAndAssert("TrivialListActivity", "General/Trivial ListView"); 201 } 202 203 @Override openFadingEdgeListView()204 public void openFadingEdgeListView() { 205 launchActivityAndAssert("FadingEdgeListActivity", "General/Fading Edge ListView"); 206 } 207 208 @Override openSaveLayerInterleaveActivity()209 public void openSaveLayerInterleaveActivity() { 210 launchActivityAndAssert("SaveLayerInterleaveActivity", "General/SaveLayer Animation"); 211 } 212 213 @Override openTrivialRecyclerView()214 public void openTrivialRecyclerView() { 215 launchActivityAndAssert("TrivialRecyclerViewActivity", "General/Trivial RecyclerView"); 216 } 217 218 @Override openSlowBindRecyclerView()219 public void openSlowBindRecyclerView() { 220 launchActivityAndAssert("SlowBindRecyclerViewActivity", "General/Slow Bind RecyclerView"); 221 } 222 223 @Override openSlowNestedRecyclerView()224 public void openSlowNestedRecyclerView() { 225 launchActivityAndAssert( 226 "SlowNestedRecyclerViewActivity", "General/Slow Nested RecyclerView"); 227 } 228 229 @Override openInflatingListView()230 public void openInflatingListView() { 231 launchActivityAndAssert("InflatingListActivity", "Inflation/Inflating ListView"); 232 } 233 234 @Override openInflatingEmojiListView()235 public void openInflatingEmojiListView() { 236 launchActivityAndAssert( 237 "InflatingEmojiListActivity", "Inflation/Inflating ListView with Emoji"); 238 } 239 240 @Override openInflatingHanListView()241 public void openInflatingHanListView() { 242 launchActivityAndAssert( 243 "InflatingHanListActivity", "Inflation/Inflating ListView with Han Characters"); 244 } 245 246 @Override openInflatingLongStringListView()247 public void openInflatingLongStringListView() { 248 launchActivityAndAssert( 249 "InflatingLongStringListActivity", "Inflation/Inflating ListView with long string"); 250 } 251 252 @Override openNavigationDrawerActivity()253 public void openNavigationDrawerActivity() { 254 launchActivityAndAssert("NavigationDrawerActivity", "Navigation Drawer Activity"); 255 mContents.setGestureMargins(0, 0, 10, 0); 256 } 257 258 @Override openNotificationShade()259 public void openNotificationShade() { 260 launchActivityAndAssert("NotificationShadeActivity", "Notification Shade"); 261 } 262 263 @Override openResizeHWLayer()264 public void openResizeHWLayer() { 265 launchActivity("ResizeHWLayerActivity", "General/Resize HW Layer"); 266 } 267 268 @Override openClippedListView()269 public void openClippedListView() { 270 launchActivityAndAssert("ClippedListActivity", "General/Clipped ListView"); 271 } 272 273 @Override openLeanbackActivity( boolean extraBitmapUpload, boolean extraShowFastLane, String activityName, String expectedText)274 public void openLeanbackActivity( 275 boolean extraBitmapUpload, 276 boolean extraShowFastLane, 277 String activityName, 278 String expectedText) { 279 Bundle extrasBundle = new Bundle(); 280 extrasBundle.putBoolean(EXTRA_BITMAP_UPLOAD, extraBitmapUpload); 281 extrasBundle.putBoolean(EXTRA_SHOW_FAST_LANE, extraShowFastLane); 282 launchActivity(activityName, extrasBundle, expectedText); 283 } 284 pressKeyCode(int keyCode)285 void pressKeyCode(int keyCode) { 286 SystemClock.sleep(KEY_DELAY); 287 mDevice.pressKeyCode(keyCode); 288 } 289 290 @Override scrollDownAndUp(int count)291 public void scrollDownAndUp(int count) { 292 for (int i = 0; i < count; i++) { 293 pressKeyCode(KeyEvent.KEYCODE_DPAD_DOWN); 294 } 295 for (int i = 0; i < count; i++) { 296 pressKeyCode(KeyEvent.KEYCODE_DPAD_UP); 297 } 298 } 299 300 // Open Bitmap Upload 301 @Override openBitmapUpload()302 public void openBitmapUpload() { 303 launchActivity("BitmapUploadActivity", "Rendering/Bitmap Upload"); 304 } 305 306 // Open Shadow Grid 307 @Override openRenderingList()308 public void openRenderingList() { 309 launchActivity("ShadowGridActivity", "Rendering/Shadow Grid"); 310 mContents = mDevice.wait(Until.findObject(By.clazz(ListView.class)), FIND_OBJECT_TIMEOUT); 311 Assert.assertNotNull("Shadow Grid list isn't found", mContents); 312 } 313 314 // Open EditText Typing 315 @Override openEditTextTyping()316 public void openEditTextTyping() { 317 launchActivity("EditTextTypeActivity", "Text/EditText Typing"); 318 mContents = mDevice.wait(Until.findObject(By.clazz(EditText.class)), FIND_OBJECT_TIMEOUT); 319 } 320 321 // Open Layout Cache High Hitrate 322 @Override openLayoutCacheHighHitrate()323 public void openLayoutCacheHighHitrate() { 324 launchActivity("TextCacheHighHitrateActivity", "Text/Layout Cache High Hitrate"); 325 mContents = mDevice.wait(Until.findObject(By.clazz(ListView.class)), FIND_OBJECT_TIMEOUT); 326 Assert.assertNotNull("LayoutCacheHighHitrateContents isn't found", mContents); 327 } 328 329 // Open Layout Cache Low Hitrate 330 @Override openLayoutCacheLowHitrate()331 public void openLayoutCacheLowHitrate() { 332 launchActivity("TextCacheLowHitrateActivity", "Text/Layout Cache Low Hitrate"); 333 mContents = mDevice.wait(Until.findObject(By.clazz(ListView.class)), FIND_OBJECT_TIMEOUT); 334 Assert.assertNotNull("LayoutCacheLowHitrateContents isn't found", mContents); 335 } 336 337 // Open Transitions 338 @Override openActivityTransition()339 public void openActivityTransition() { 340 launchActivity("ActivityTransition", "Transitions/Activity Transition"); 341 } 342 343 @Override openWindowInsetsController()344 public void openWindowInsetsController() { 345 launchActivityAndAssert("WindowInsetsControllerActivity", "WindowInsetsControllerActivity"); 346 } 347 348 // Get the image to click 349 @Override clickImage(String imageName)350 public void clickImage(String imageName) { 351 UiObject2 image = 352 mDevice.wait( 353 Until.findObject(By.res(PACKAGE_NAME, imageName)), FIND_OBJECT_TIMEOUT); 354 Assert.assertNotNull(imageName + "Image not found", image); 355 image.clickAndWait(Until.newWindow(), FIND_OBJECT_TIMEOUT); 356 mDevice.pressBack(); 357 } 358 359 // Open Scrollable WebView from WebView test 360 @Override openScrollableWebView()361 public void openScrollableWebView() { 362 launchActivity("ScrollableWebViewActivity", "WebView/Scrollable WebView"); 363 mContents = 364 mDevice.wait(Until.findObject(By.res("android", "content")), FIND_OBJECT_TIMEOUT); 365 } 366 } 367