1 /* 2 * Copyright (C) 2017 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 package android.text; 17 18 import static android.text.Layout.Alignment.ALIGN_NORMAL; 19 20 import android.graphics.Canvas; 21 import android.perftests.utils.BenchmarkState; 22 import android.perftests.utils.PerfStatusReporter; 23 import android.support.test.filters.LargeTest; 24 import android.text.NonEditableTextGenerator.TextType; 25 import android.view.DisplayListCanvas; 26 import android.view.RenderNode; 27 28 import org.junit.Rule; 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 import org.junit.runners.Parameterized; 32 33 import java.util.ArrayList; 34 import java.util.Collection; 35 import java.util.List; 36 import java.util.Random; 37 38 /** 39 * Performance test for multi line, single style {@link StaticLayout} creation/draw. 40 */ 41 @LargeTest 42 @RunWith(Parameterized.class) 43 public class StaticLayoutCreateDrawPerfTest { 44 45 private static final boolean[] BOOLEANS = new boolean[]{false, true}; 46 47 private static final float SPACING_ADD = 10f; 48 private static final float SPACING_MULT = 1.5f; 49 50 @Rule 51 public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); 52 53 @Parameterized.Parameters(name = "cached={3},{1}chars,{0}") 54 public static Collection cases() { 55 final List<Object[]> params = new ArrayList<>(); 56 for (int length : new int[]{128}) { 57 for (boolean cached : BOOLEANS) { 58 for (TextType textType : new TextType[]{TextType.STRING, 59 TextType.SPANNABLE_BUILDER}) { 60 params.add(new Object[]{textType.name(), length, textType, cached}); 61 } 62 } 63 } 64 return params; 65 } 66 67 private final int mLineWidth; 68 private final int mLength; 69 private final TextType mTextType; 70 private final boolean mCached; 71 private final TextPaint mTextPaint; 72 73 public StaticLayoutCreateDrawPerfTest(String label, int length, TextType textType, 74 boolean cached) { 75 mLength = length; 76 mTextType = textType; 77 mCached = cached; 78 mTextPaint = new TextPaint(); 79 mTextPaint.setTextSize(10); 80 mLineWidth = Integer.MAX_VALUE; 81 } 82 83 /** 84 * Measures the creation time for a multi line {@link StaticLayout}. 85 */ 86 @Test 87 public void timeCreate() throws Exception { 88 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 89 90 state.pauseTiming(); 91 Canvas.freeTextLayoutCaches(); 92 final CharSequence text = createRandomText(mLength); 93 createLayout(text); 94 state.resumeTiming(); 95 96 while (state.keepRunning()) { 97 state.pauseTiming(); 98 if (!mCached) Canvas.freeTextLayoutCaches(); 99 state.resumeTiming(); 100 101 createLayout(text); 102 } 103 } 104 105 /** 106 * Measures the draw time for a multi line {@link StaticLayout}. 107 */ 108 @Test 109 public void timeDraw() throws Exception { 110 final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); 111 112 state.pauseTiming(); 113 Canvas.freeTextLayoutCaches(); 114 final RenderNode node = RenderNode.create("benchmark", null); 115 final CharSequence text = createRandomText(mLength); 116 final Layout layout = createLayout(text); 117 state.resumeTiming(); 118 119 while (state.keepRunning()) { 120 121 state.pauseTiming(); 122 final DisplayListCanvas canvas = node.start(1200, 200); 123 int save = canvas.save(); 124 if (!mCached) Canvas.freeTextLayoutCaches(); 125 state.resumeTiming(); 126 127 layout.draw(canvas); 128 129 state.pauseTiming(); 130 canvas.restoreToCount(save); 131 node.end(canvas); 132 state.resumeTiming(); 133 } 134 } 135 136 private Layout createLayout(CharSequence text) { 137 return StaticLayout.Builder.obtain(text, 0 /*start*/, text.length() /*end*/, mTextPaint, 138 mLineWidth) 139 .setAlignment(ALIGN_NORMAL) 140 .setIncludePad(true) 141 .setLineSpacing(SPACING_ADD, SPACING_MULT) 142 .build(); 143 } 144 145 private CharSequence createRandomText(int length) { 146 return new NonEditableTextGenerator(new Random(0)) 147 .setSequenceLength(length) 148 .setTextType(mTextType) 149 .build(); 150 } 151 } 152