blob: 5be99d9d779e0535de8a33a13e4ffdcb469cb8bc [file] [log] [blame]
Rahul Ravikumar05336002019-10-14 15:04:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package android.text;
18
19import static android.text.Layout.Alignment.ALIGN_NORMAL;
20
21import android.graphics.Canvas;
22import android.graphics.Paint;
23import android.graphics.Paint.FontMetricsInt;
24import android.perftests.utils.BenchmarkState;
25import android.perftests.utils.PerfStatusReporter;
26import android.perftests.utils.StubActivity;
27import android.text.style.ReplacementSpan;
28import android.util.ArraySet;
29
30import androidx.test.filters.LargeTest;
31import androidx.test.rule.ActivityTestRule;
32
33import org.junit.Rule;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36import org.junit.runners.Parameterized;
37import org.junit.runners.Parameterized.Parameters;
38
39import java.util.Arrays;
40import java.util.Collection;
41import java.util.Random;
42
43@LargeTest
44@RunWith(Parameterized.class)
45public class DynamicLayoutPerfTest {
46
47 @Parameters(name = "{0}")
48 public static Collection cases() {
49 return Arrays.asList(new Object[][] {
50 { "0%", 0.0f},
51 { "1%", 0.01f},
52 { "5%", 0.05f},
53 { "30%", 0.3f},
54 { "100%", 1.0f},
55 });
56 }
57
58 private final String mMetricKey;
59 private final float mProbability;
60 public DynamicLayoutPerfTest(String metricKey, float probability) {
61 mMetricKey = metricKey;
62 mProbability = probability;
63 }
64
65 private static class MockReplacementSpan extends ReplacementSpan {
66 @Override
67 public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm) {
68 return 10;
69 }
70
71 @Override
72 public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top,
73 int y, int bottom, Paint paint) {
74 }
75 }
76
77 @Rule
78 public ActivityTestRule<StubActivity> mActivityRule = new ActivityTestRule(StubActivity.class);
79
80 @Rule
81 public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
82
83
84 private final static String ALPHABETS = "abcdefghijklmnopqrstuvwxyz";
85
86 private SpannableStringBuilder getText() {
87 final long seed = 1234567890;
88 final Random r = new Random(seed);
89 final SpannableStringBuilder builder = new SpannableStringBuilder();
90
91 final int paragraphCount = 100;
92 for (int i = 0; i < paragraphCount; i++) {
93 final int wordCount = 5 + r.nextInt(20);
94 final boolean containsReplacementSpan = r.nextFloat() < mProbability;
95 final int replacedWordIndex = containsReplacementSpan ? r.nextInt(wordCount) : -1;
96 for (int j = 0; j < wordCount; j++) {
97 final int startIndex = builder.length();
98 final int wordLength = 1 + r.nextInt(10);
99 for (int k = 0; k < wordLength; k++) {
100 char c = ALPHABETS.charAt(r.nextInt(ALPHABETS.length()));
101 builder.append(c);
102 }
103 if (replacedWordIndex == j) {
104 builder.setSpan(new MockReplacementSpan(), startIndex,
105 builder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
106 }
107 builder.append(' ');
108 }
109 builder.append('\n');
110 }
111 return builder;
112 }
113
114 @Test
115 public void testGetBlocksAlwaysNeedToBeRedrawn() {
116 final SpannableStringBuilder text = getText();
117 final DynamicLayout layout = new DynamicLayout(text, new TextPaint(), 1000,
118 ALIGN_NORMAL, 0, 0, false);
119
120 BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
121 final int steps = 10;
122 while (state.keepRunning()) {
123 for (int i = 0; i < steps; i++) {
124 int offset = (text.length() * i) / steps;
125 text.insert(offset, "\n");
126 text.delete(offset, offset + 1);
127 final ArraySet<Integer> set = layout.getBlocksAlwaysNeedToBeRedrawn();
128 if (set != null) {
129 for (int j = 0; j < set.size(); j++) {
130 layout.getBlockIndex(set.valueAt(j));
131 }
132 }
133 }
134 }
135 }
136}