xref: /aosp_15_r20/frameworks/base/apct-tests/perftests/core/src/android/text/NonEditableTextGenerator.java (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 package android.text;
2 
3 import static android.text.Spanned.SPAN_INCLUSIVE_INCLUSIVE;
4 
5 import android.text.style.BulletSpan;
6 
7 import java.util.Random;
8 
9 /**
10  *
11  */
12 public class NonEditableTextGenerator {
13 
14     enum TextType {
15         STRING,
16         SPANNED,
17         SPANNABLE_BUILDER
18     }
19 
20     private boolean mCreateBoring;
21     private TextType mTextType;
22     private int mSequenceLength;
23     private final Random mRandom;
24 
NonEditableTextGenerator(Random random)25     public NonEditableTextGenerator(Random random) {
26         mRandom = random;
27     }
28 
setCreateBoring(boolean createBoring)29     public NonEditableTextGenerator setCreateBoring(boolean createBoring) {
30         mCreateBoring = createBoring;
31         return this;
32     }
33 
setTextType(TextType textType)34     public NonEditableTextGenerator setTextType(TextType textType) {
35         mTextType = textType;
36         return this;
37     }
38 
setSequenceLength(int sequenceLength)39     public NonEditableTextGenerator setSequenceLength(int sequenceLength) {
40         mSequenceLength = sequenceLength;
41         return this;
42     }
43 
44     /**
45      * Sample charSequence generated:
46      * NRjPzjvUadHmH ExoEoTqfx pCLw qtndsqfpk AqajVCbgjGZ igIeC dfnXRgA
47      */
build()48     public CharSequence build() {
49         final RandomCharSequenceGenerator sequenceGenerator = new RandomCharSequenceGenerator(
50                 mRandom);
51         if (mSequenceLength > 0) {
52             sequenceGenerator.setSequenceLength(mSequenceLength);
53         }
54 
55         final CharSequence charSequence = sequenceGenerator.buildLatinSequence();
56 
57         switch (mTextType) {
58             case SPANNED:
59             case SPANNABLE_BUILDER:
60                 return createSpannable(charSequence);
61             case STRING:
62             default:
63                 return createString(charSequence);
64         }
65     }
66 
createSpannable(CharSequence charSequence)67     private Spannable createSpannable(CharSequence charSequence) {
68         final Spannable spannable = (mTextType == TextType.SPANNABLE_BUILDER) ?
69                 new SpannableStringBuilder(charSequence) : new SpannableString(charSequence);
70 
71         if (!mCreateBoring) {
72             // add a paragraph style to make it non boring
73             spannable.setSpan(new BulletSpan(), 0, spannable.length(), SPAN_INCLUSIVE_INCLUSIVE);
74         }
75 
76         spannable.setSpan(new Object(), 0, spannable.length(), SPAN_INCLUSIVE_INCLUSIVE);
77         spannable.setSpan(new Object(), 0, 1, SPAN_INCLUSIVE_INCLUSIVE);
78 
79         return spannable;
80     }
81 
createString(CharSequence charSequence)82     private String createString(CharSequence charSequence) {
83         if (mCreateBoring) {
84             return charSequence.toString();
85         } else {
86             // BoringLayout checks to see if there is a surrogate pair and if so tells that
87             // the charSequence is not suitable for boring. Add an emoji to make it non boring.
88             // Emoji is added instead of RTL, since emoji stays in the same run and is a more
89             // common case.
90             return charSequence.toString() + "\uD83D\uDC68\uD83C\uDFFF";
91         }
92     }
93 
94     public static class RandomCharSequenceGenerator {
95 
96         private static final int DEFAULT_MIN_WORD_LENGTH = 3;
97         private static final int DEFAULT_MAX_WORD_LENGTH = 15;
98         private static final int DEFAULT_SEQUENCE_LENGTH = 256;
99 
100         private int mMinWordLength = DEFAULT_MIN_WORD_LENGTH;
101         private int mMaxWordLength = DEFAULT_MAX_WORD_LENGTH;
102         private int mSequenceLength = DEFAULT_SEQUENCE_LENGTH;
103         private final Random mRandom;
104 
RandomCharSequenceGenerator(Random random)105         public RandomCharSequenceGenerator(Random random) {
106             mRandom = random;
107         }
108 
setSequenceLength(int sequenceLength)109         public RandomCharSequenceGenerator setSequenceLength(int sequenceLength) {
110             mSequenceLength = sequenceLength;
111             return this;
112         }
113 
buildLatinSequence()114         public CharSequence buildLatinSequence() {
115             final StringBuilder result = new StringBuilder();
116             while (result.length() < mSequenceLength) {
117                 // add random word
118                 result.append(buildLatinWord());
119                 result.append(' ');
120             }
121             return result.substring(0, mSequenceLength);
122         }
123 
buildLatinWord()124         public CharSequence buildLatinWord() {
125             final StringBuilder result = new StringBuilder();
126             // create a random length that is (mMinWordLength + random amount of chars) where
127             // total size is less than mMaxWordLength
128             final int length = mRandom.nextInt(mMaxWordLength - mMinWordLength) + mMinWordLength;
129             while (result.length() < length) {
130                 // add random letter
131                 int base = mRandom.nextInt(2) == 0 ? 'A' : 'a';
132                 result.append(Character.toChars(mRandom.nextInt(26) + base));
133             }
134             return result.toString();
135         }
136     }
137 
138 }
139