1b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi/* 2b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * Copyright (C) 2016 The Android Open Source Project 3b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * 4b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * Licensed under the Apache License, Version 2.0 (the "License"); 5b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * you may not use this file except in compliance with the License. 6b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * You may obtain a copy of the License at 7b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * 8b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * http://www.apache.org/licenses/LICENSE-2.0 9b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * 10b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * Unless required by applicable law or agreed to in writing, software 11b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * distributed under the License is distributed on an "AS IS" BASIS, 12b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * See the License for the specific language governing permissions and 14b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi * limitations under the License. 15b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi */ 16b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 17b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagipackage android.widget; 18b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 19b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport java.util.Arrays; 20b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport java.util.Collection; 21b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport java.util.Locale; 22b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport java.util.Random; 23b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 24b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport org.junit.Rule; 25b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport org.junit.Test; 26b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport org.junit.runner.RunWith; 27b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport org.junit.runners.Parameterized; 28b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport org.junit.runners.Parameterized.Parameters; 29b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 30b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.app.Activity; 31b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.graphics.Bitmap; 32b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.graphics.Canvas; 33b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.util.Log; 34b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.view.KeyEvent; 35b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.view.RenderNodeAnimator; 36b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.view.ViewGroup; 37b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.view.View.MeasureSpec; 38b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 39b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.perftests.utils.BenchmarkState; 40b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.perftests.utils.PerfStatusReporter; 41b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.perftests.utils.StubActivity; 42b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.support.test.filters.LargeTest; 43b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.support.test.runner.AndroidJUnit4; 44b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.support.test.rule.ActivityTestRule; 45b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagiimport android.support.test.InstrumentationRegistry; 46b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 47b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi@LargeTest 48b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi@RunWith(Parameterized.class) 49b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagipublic class EditTextLongTextPerfTest { 50b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi @Parameters(name = "{0}") 51b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi public static Collection cases() { 52b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi return Arrays.asList(new Object[][] { 53b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi { "10x30K", 10, 30000 }, 54b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi { "300x1K", 300, 1000 }, 55b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi }); 56b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi } 57b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 58b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi private final String mMetricKey; 59b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi private final int mChars; 60b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi private final int mLines; 61b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 62b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi public EditTextLongTextPerfTest(String metricKey, int chars, int lines) { 63b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi mMetricKey = metricKey; 64b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi mChars = chars; 65b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi mLines = lines; 66b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi } 67b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 68b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi @Rule 69b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class); 70b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 71b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi @Rule 72b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); 73b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 74b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi private EditText setupEditText() { 75b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi final EditText editText = new EditText(mActivityRule.getActivity()); 76b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 77b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi String alphabet = "abcdefghijklmnopqrstuvwxyz"; 78b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi final long seed = 1234567890; 79b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi Random r = new Random(seed); 80b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi StringBuilder sb = new StringBuilder(); 81b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi for (int i = 0; i < mLines; i++) { 82b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi for (int j = 0; j < mChars; j++) { 83b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi char c = alphabet.charAt(r.nextInt(alphabet.length())); 84b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi sb.append(c); 85b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi } 86b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi sb.append('\n'); 87b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi } 88b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 89b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi final int height = 1000; 90b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi final int width = 1000; 91b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi editText.setHeight(height); 92b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi editText.setWidth(width); 93b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi editText.setLayoutParams(new ViewGroup.LayoutParams(width, height)); 94b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 95b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi Activity activity = mActivityRule.getActivity(); 96b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi activity.setContentView(editText); 97b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 98b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi editText.setText(sb.toString(), TextView.BufferType.EDITABLE); 99b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi editText.invalidate(); 100b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi editText.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 101b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); 102b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi editText.layout(0, 0, height, width); 103b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 104b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi return editText; 105b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi } 106b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi 107b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi @Test 10836e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka public void testEditText() throws Throwable { 10936e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka mActivityRule.runOnUiThread(() -> { 11036e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 11136e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka final EditText editText = setupEditText(); 11236e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka final KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER); 11336e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka final int steps = 100; 11436e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka while (state.keepRunning()) { 11536e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka for (int i = 0; i < steps; i++) { 11636e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka int offset = (editText.getText().length() * i) / steps; 11736e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka editText.setSelection(offset); 11836e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka editText.bringPointIntoView(offset); 11936e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka editText.onKeyDown(keyEvent.getKeyCode(), keyEvent); 12036e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka editText.updateDisplayListIfDirty(); 12136e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka } 122b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi } 12336e0f128929ca2cdcd51dcb1d0c1fc6557414875Seigo Nonaka }); 124b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi } 125b7ff1333fe4e5d37ccf5d5b8860bf21235d38a1bKeisuke Kuroyanagi} 126