1 /* 2 * Copyright (C) 2015 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 package com.android.test.uibench; 17 18 import android.icu.text.UnicodeSet; 19 import android.icu.text.UnicodeSetIterator; 20 21 import java.util.ArrayList; 22 import java.util.Random; 23 24 public class TextUtils { 25 private static final int STRING_COUNT = 200; 26 private static final int SIMPLE_STRING_LENGTH = 10; // in code points 27 UnicodeSetToArray(UnicodeSet set)28 private static String[] UnicodeSetToArray(UnicodeSet set) { 29 final UnicodeSetIterator iterator = new UnicodeSetIterator(set); 30 final ArrayList<String> out = new ArrayList<>(set.size()); 31 while (iterator.next()) { 32 out.add(iterator.getString()); 33 } 34 return out.toArray(new String[out.size()]); 35 } 36 37 /** 38 * Create word of random assortment of lower/upper case letters 39 */ randomWord(Random random, int length)40 private static String randomWord(Random random, int length) { 41 String result = ""; 42 for (int j = 0; j < length; j++) { 43 // add random letter 44 int base = random.nextInt(2) == 0 ? 'A' : 'a'; 45 result += (char)(random.nextInt(26) + base); 46 } 47 return result; 48 } 49 50 /** 51 * Create word from a random assortment of a given set of codepoints, given as strings. 52 */ randomWordFromStringSet(Random random, int length, String[] stringSet)53 private static String randomWordFromStringSet(Random random, int length, String[] stringSet) { 54 final StringBuilder sb = new StringBuilder(length); 55 final int setLength = stringSet.length; 56 for (int j = 0; j < length; j++) { 57 sb.append(stringSet[random.nextInt(setLength)]); 58 } 59 return sb.toString(); 60 } 61 buildSimpleStringList()62 public static String[] buildSimpleStringList() { 63 return buildSimpleStringList(SIMPLE_STRING_LENGTH); 64 } 65 buildEmojiStringList()66 public static String[] buildEmojiStringList() { 67 return buildEmojiStringList(SIMPLE_STRING_LENGTH); 68 } 69 buildHanStringList()70 public static String[] buildHanStringList() { 71 return buildHanStringList(SIMPLE_STRING_LENGTH); 72 } 73 buildLongStringList()74 public static String[] buildLongStringList() { 75 return buildLongStringList(SIMPLE_STRING_LENGTH); 76 } 77 buildSimpleStringList(int stringLength)78 public static String[] buildSimpleStringList(int stringLength) { 79 String[] strings = new String[STRING_COUNT]; 80 Random random = new Random(0); 81 for (int i = 0; i < strings.length; i++) { 82 strings[i] = randomWord(random, stringLength); 83 } 84 return strings; 85 } 86 buildStringListFromUnicodeSet(int stringLength, UnicodeSet set)87 private static String[] buildStringListFromUnicodeSet(int stringLength, UnicodeSet set) { 88 final String[] strings = new String[STRING_COUNT]; 89 final Random random = new Random(0); 90 final String[] stringSet = UnicodeSetToArray(set); 91 for (int i = 0; i < strings.length; i++) { 92 strings[i] = randomWordFromStringSet(random, stringLength, stringSet); 93 } 94 return strings; 95 } 96 buildEmojiStringList(int stringLength)97 public static String[] buildEmojiStringList(int stringLength) { 98 return buildStringListFromUnicodeSet(stringLength, new UnicodeSet("[:emoji:]")); 99 } 100 buildHanStringList(int stringLength)101 public static String[] buildHanStringList(int stringLength) { 102 return buildStringListFromUnicodeSet(stringLength, new UnicodeSet("[\\u4E00-\\u9FA0]")); 103 } 104 buildLongStringList(int stringLength)105 public static String[] buildLongStringList(int stringLength) { 106 final int WORD_COUNT = 100; 107 final String[] strings = new String[STRING_COUNT]; 108 final Random random = new Random(0); 109 for (int i = 0; i < strings.length; i++) { 110 final StringBuilder sb = new StringBuilder((stringLength + 1) * WORD_COUNT); 111 for (int j = 0; j < WORD_COUNT; ++j) { 112 if (j != 0) { 113 sb.append(' '); 114 } 115 sb.append(randomWord(random, stringLength)); 116 } 117 strings[i] = sb.toString(); 118 } 119 return strings; 120 } 121 122 // a small number of strings reused frequently, expected to hit 123 // in the word-granularity text layout cache 124 static final String[] CACHE_HIT_STRINGS = new String[] { 125 "a", 126 "small", 127 "number", 128 "of", 129 "strings", 130 "reused", 131 "frequently" 132 }; 133 134 private static final int WORDS_IN_PARAGRAPH = 150; 135 136 // misses are fairly long 'words' to ensure they miss 137 private static final int PARAGRAPH_MISS_MIN_LENGTH = 4; 138 private static final int PARAGRAPH_MISS_MAX_LENGTH = 9; 139 buildParagraphListWithHitPercentage(int hitPercentage)140 static String[] buildParagraphListWithHitPercentage(int hitPercentage) { 141 if (hitPercentage < 0 || hitPercentage > 100) throw new IllegalArgumentException(); 142 143 String[] strings = new String[STRING_COUNT]; 144 Random random = new Random(0); 145 for (int i = 0; i < strings.length; i++) { 146 String result = ""; 147 for (int word = 0; word < WORDS_IN_PARAGRAPH; word++) { 148 if (word != 0) { 149 result += " "; 150 } 151 if (random.nextInt(100) < hitPercentage) { 152 // add a common word, which is very likely to hit in the cache 153 result += CACHE_HIT_STRINGS[random.nextInt(CACHE_HIT_STRINGS.length)]; 154 } else { 155 // construct a random word, which will *most likely* miss 156 int length = PARAGRAPH_MISS_MIN_LENGTH; 157 length += random.nextInt(PARAGRAPH_MISS_MAX_LENGTH - PARAGRAPH_MISS_MIN_LENGTH); 158 159 result += randomWord(random, length); 160 } 161 } 162 strings[i] = result; 163 } 164 165 return strings; 166 } 167 } 168