1 /*
2  * Copyright (C) 2022 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 
17 package com.example.android.sampleinputmethodaccessibilityservice;
18 
19 import android.view.inputmethod.EditorInfo;
20 
21 import androidx.annotation.NonNull;
22 import androidx.annotation.Nullable;
23 
24 final class EditorInfoUtil {
25     /**
26      * Not intended to be instantiated.
27      */
EditorInfoUtil()28     private EditorInfoUtil() {
29     }
30 
dump(@ullable EditorInfo editorInfo)31     static String dump(@Nullable EditorInfo editorInfo) {
32         if (editorInfo == null) {
33             return "null";
34         }
35         final StringBuilder sb = new StringBuilder();
36         dump(sb, editorInfo);
37         return sb.toString();
38     }
39 
dump(@onNull StringBuilder sb, @NonNull EditorInfo editorInfo)40     static void dump(@NonNull StringBuilder sb, @NonNull EditorInfo editorInfo) {
41         sb.append("packageName=").append(editorInfo.packageName).append("\n")
42                 .append("inputType=");
43         dumpInputType(sb, editorInfo.inputType);
44         sb.append("\n");
45         sb.append("imeOptions=");
46         dumpImeOptions(sb, editorInfo.imeOptions);
47         sb.append("\n");
48         sb.append("initialSelection=(").append(editorInfo.initialSelStart)
49                 .append(",").append(editorInfo.initialSelEnd).append(")");
50         sb.append("\n");
51         sb.append("initialCapsMode=");
52         dumpCapsMode(sb, editorInfo.initialCapsMode);
53         sb.append("\n");
54     }
55 
dumpInputType(@onNull StringBuilder sb, int inputType)56     static void dumpInputType(@NonNull StringBuilder sb, int inputType) {
57         final int inputClass = inputType & EditorInfo.TYPE_MASK_CLASS;
58         final int inputVariation = inputType & EditorInfo.TYPE_MASK_VARIATION;
59         final int inputFlags = inputType & EditorInfo.TYPE_MASK_FLAGS;
60         switch (inputClass) {
61             case EditorInfo.TYPE_NULL:
62                 sb.append("Null");
63                 break;
64             case EditorInfo.TYPE_CLASS_TEXT: {
65                 sb.append("Text");
66                 switch (inputVariation) {
67                     case EditorInfo.TYPE_TEXT_VARIATION_NORMAL:
68                         break;
69                     case EditorInfo.TYPE_TEXT_VARIATION_URI:
70                         sb.append(":URI");
71                         break;
72                     case EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
73                         sb.append(":EMAIL_ADDRESS");
74                         break;
75                     case EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT:
76                         sb.append(":EMAIL_SUBJECT");
77                         break;
78                     case EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE:
79                         sb.append(":SHORT_MESSAGE");
80                         break;
81                     case EditorInfo.TYPE_TEXT_VARIATION_LONG_MESSAGE:
82                         sb.append(":LONG_MESSAGE");
83                         break;
84                     case EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME:
85                         sb.append(":PERSON_NAME");
86                         break;
87                     case EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS:
88                         sb.append(":POSTAL_ADDRESS");
89                         break;
90                     case EditorInfo.TYPE_TEXT_VARIATION_PASSWORD:
91                         sb.append(":PASSWORD");
92                         break;
93                     case EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
94                         sb.append(":VISIBLE_PASSWORD");
95                         break;
96                     case EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT:
97                         sb.append(":WEB_EDIT_TEXT");
98                         break;
99                     case EditorInfo.TYPE_TEXT_VARIATION_FILTER:
100                         sb.append(":FILTER");
101                         break;
102                     case EditorInfo.TYPE_TEXT_VARIATION_PHONETIC:
103                         sb.append(":PHONETIC");
104                         break;
105                     case EditorInfo.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
106                         sb.append(":WEB_EMAIL_ADDRESS");
107                         break;
108                     case EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD:
109                         sb.append(":WEB_PASSWORD");
110                         break;
111                     default:
112                         sb.append(":UNKNOWN=").append(inputVariation);
113                         break;
114                 }
115                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
116                     sb.append("|CAP_CHARACTERS");
117                 }
118                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS) != 0) {
119                     sb.append("|CAP_WORDS");
120                 }
121                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0) {
122                     sb.append("|CAP_SENTENCES");
123                 }
124                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) != 0) {
125                     sb.append("|AUTO_CORRECT");
126                 }
127                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) {
128                     sb.append("|AUTO_COMPLETE");
129                 }
130                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) != 0) {
131                     sb.append("|MULTI_LINE");
132                 }
133                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) {
134                     sb.append("|NO_SUGGESTIONS");
135                 }
136                 if ((inputFlags & EditorInfo.TYPE_TEXT_FLAG_ENABLE_TEXT_CONVERSION_SUGGESTIONS)
137                         != 0) {
138                     sb.append("|ENABLE_TEXT_CONVERSION_SUGGESTIONS");
139                 }
140                 break;
141             }
142             case EditorInfo.TYPE_CLASS_NUMBER: {
143                 sb.append("Number");
144                 switch (inputVariation) {
145                     case EditorInfo.TYPE_NUMBER_VARIATION_NORMAL:
146                         sb.append(":NORMAL");
147                         break;
148                     case EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD:
149                         sb.append(":PASSWORD");
150                         break;
151                     default:
152                         sb.append(":UNKNOWN=").append(inputVariation);
153                         break;
154                 }
155                 if ((inputFlags & EditorInfo.TYPE_NUMBER_FLAG_SIGNED) != 0) {
156                     sb.append("|SIGNED");
157                 }
158                 if ((inputFlags & EditorInfo.TYPE_NUMBER_FLAG_DECIMAL) != 0) {
159                     sb.append("|DECIMAL");
160                 }
161                 break;
162             }
163             case EditorInfo.TYPE_CLASS_PHONE:
164                 sb.append("Phone");
165                 break;
166             case EditorInfo.TYPE_CLASS_DATETIME: {
167                 sb.append("DateTime");
168                 switch (inputVariation) {
169                     case EditorInfo.TYPE_DATETIME_VARIATION_NORMAL:
170                         sb.append(":NORMAL");
171                         break;
172                     case EditorInfo.TYPE_DATETIME_VARIATION_DATE:
173                         sb.append(":DATE");
174                         break;
175                     case EditorInfo.TYPE_DATETIME_VARIATION_TIME:
176                         sb.append(":TIME");
177                         break;
178                     default:
179                         sb.append(":UNKNOWN=").append(inputVariation);
180                         break;
181                 }
182                 break;
183             }
184             default:
185                 sb.append("UnknownClass=").append(inputClass);
186                 if (inputVariation != 0) {
187                     sb.append(":variation=").append(inputVariation);
188                 }
189                 if (inputFlags != 0) {
190                     sb.append("|flags=0x").append(Integer.toHexString(inputFlags));
191                 }
192                 break;
193         }
194     }
195 
dumpImeOptions(@onNull StringBuilder sb, int imeOptions)196     static void dumpImeOptions(@NonNull StringBuilder sb, int imeOptions) {
197         final int action = imeOptions & EditorInfo.IME_MASK_ACTION;
198         final int flags = imeOptions & ~EditorInfo.IME_MASK_ACTION;
199         sb.append("Action:");
200         switch (action) {
201             case EditorInfo.IME_ACTION_UNSPECIFIED:
202                 sb.append("UNSPECIFIED");
203                 break;
204             case EditorInfo.IME_ACTION_NONE:
205                 sb.append("NONE");
206                 break;
207             case EditorInfo.IME_ACTION_GO:
208                 sb.append("GO");
209                 break;
210             case EditorInfo.IME_ACTION_SEARCH:
211                 sb.append("SEARCH");
212                 break;
213             case EditorInfo.IME_ACTION_SEND:
214                 sb.append("SEND");
215                 break;
216             case EditorInfo.IME_ACTION_NEXT:
217                 sb.append("NEXT");
218                 break;
219             case EditorInfo.IME_ACTION_DONE:
220                 sb.append("DONE");
221                 break;
222             case EditorInfo.IME_ACTION_PREVIOUS:
223                 sb.append("PREVIOUS");
224                 break;
225             default:
226                 sb.append("UNKNOWN=").append(action);
227                 break;
228         }
229         if ((flags & EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING) != 0) {
230             sb.append("|NO_PERSONALIZED_LEARNING");
231         }
232         if ((flags & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0) {
233             sb.append("|NO_FULLSCREEN");
234         }
235         if ((flags & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0) {
236             sb.append("|NAVIGATE_PREVIOUS");
237         }
238         if ((flags & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0) {
239             sb.append("|NAVIGATE_NEXT");
240         }
241         if ((flags & EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) {
242             sb.append("|NO_EXTRACT_UI");
243         }
244         if ((flags & EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION) != 0) {
245             sb.append("|NO_ACCESSORY_ACTION");
246         }
247         if ((flags & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
248             sb.append("|NO_ENTER_ACTION");
249         }
250         if ((flags & EditorInfo.IME_FLAG_FORCE_ASCII) != 0) {
251             sb.append("|FORCE_ASCII");
252         }
253     }
254 
dumpCapsMode(@onNull StringBuilder sb, int capsMode)255     static void dumpCapsMode(@NonNull StringBuilder sb, int capsMode) {
256         if (capsMode == 0) {
257             sb.append("none");
258             return;
259         }
260         boolean addSeparator = false;
261         if ((capsMode & EditorInfo.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
262             sb.append("CHARACTERS");
263             addSeparator = true;
264         }
265         if ((capsMode & EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS) != 0) {
266             if (addSeparator) {
267                 sb.append('|');
268             }
269             sb.append("WORDS");
270             addSeparator = true;
271         }
272         if ((capsMode & EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0) {
273             if (addSeparator) {
274                 sb.append('|');
275             }
276             sb.append("SENTENCES");
277         }
278     }
279 }
280