Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 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 android.view.textclassifier; |
| 18 | |
| 19 | import android.annotation.IntRange; |
| 20 | import android.annotation.NonNull; |
Abodunrinwa Toki | 4cfda0b | 2017-02-28 18:56:47 +0000 | [diff] [blame] | 21 | import android.annotation.Nullable; |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 22 | import android.annotation.StringDef; |
Abodunrinwa Toki | e0b5789 | 2017-04-28 19:59:57 +0100 | [diff] [blame] | 23 | import android.annotation.WorkerThread; |
Abodunrinwa Toki | 4cfda0b | 2017-02-28 18:56:47 +0000 | [diff] [blame] | 24 | import android.os.LocaleList; |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 25 | |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 26 | import com.android.internal.util.Preconditions; |
| 27 | |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 28 | import java.lang.annotation.Retention; |
| 29 | import java.lang.annotation.RetentionPolicy; |
| 30 | |
| 31 | /** |
| 32 | * Interface for providing text classification related features. |
| 33 | * |
Abodunrinwa Toki | 33ff200 | 2017-10-24 00:49:27 +0100 | [diff] [blame] | 34 | * <p>Unless otherwise stated, methods of this interface are blocking operations. |
| 35 | * Avoid calling them on the UI thread. |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 36 | */ |
| 37 | public interface TextClassifier { |
| 38 | |
Abodunrinwa Toki | 692b196 | 2017-08-15 15:05:11 +0100 | [diff] [blame] | 39 | /** @hide */ |
Abodunrinwa Toki | 008f387 | 2017-11-27 19:32:35 +0000 | [diff] [blame] | 40 | String DEFAULT_LOG_TAG = "androidtc"; |
Abodunrinwa Toki | 692b196 | 2017-08-15 15:05:11 +0100 | [diff] [blame] | 41 | |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 42 | String TYPE_UNKNOWN = ""; |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 43 | String TYPE_OTHER = "other"; |
| 44 | String TYPE_EMAIL = "email"; |
| 45 | String TYPE_PHONE = "phone"; |
| 46 | String TYPE_ADDRESS = "address"; |
Abodunrinwa Toki | 9b4c82a | 2017-02-06 20:29:36 +0000 | [diff] [blame] | 47 | String TYPE_URL = "url"; |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 48 | |
Abodunrinwa Toki | 45cb3e6 | 2017-03-29 21:51:45 +0100 | [diff] [blame] | 49 | /** @hide */ |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 50 | @Retention(RetentionPolicy.SOURCE) |
Jeff Sharkey | 5db9a91 | 2017-12-08 17:32:32 -0700 | [diff] [blame] | 51 | @StringDef(prefix = { "TYPE_" }, value = { |
| 52 | TYPE_UNKNOWN, |
| 53 | TYPE_OTHER, |
| 54 | TYPE_EMAIL, |
| 55 | TYPE_PHONE, |
| 56 | TYPE_ADDRESS, |
| 57 | TYPE_URL, |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 58 | }) |
| 59 | @interface EntityType {} |
| 60 | |
| 61 | /** |
| 62 | * No-op TextClassifier. |
| 63 | * This may be used to turn off TextClassifier features. |
| 64 | */ |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 65 | TextClassifier NO_OP = new TextClassifier() {}; |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 66 | |
| 67 | /** |
Abodunrinwa Toki | 33ff200 | 2017-10-24 00:49:27 +0100 | [diff] [blame] | 68 | * Returns suggested text selection start and end indices, recognized entity types, and their |
| 69 | * associated confidence scores. The entity types are ordered from highest to lowest scoring. |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 70 | * |
| 71 | * @param text text providing context for the selected text (which is specified |
| 72 | * by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex) |
| 73 | * @param selectionStartIndex start index of the selected part of text |
| 74 | * @param selectionEndIndex end index of the selected part of text |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 75 | * @param options optional input parameters |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 76 | * |
| 77 | * @throws IllegalArgumentException if text is null; selectionStartIndex is negative; |
Abodunrinwa Toki | 4cfda0b | 2017-02-28 18:56:47 +0000 | [diff] [blame] | 78 | * selectionEndIndex is greater than text.length() or not greater than selectionStartIndex |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 79 | * |
| 80 | * @see #suggestSelection(CharSequence, int, int) |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 81 | */ |
Abodunrinwa Toki | e0b5789 | 2017-04-28 19:59:57 +0100 | [diff] [blame] | 82 | @WorkerThread |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 83 | @NonNull |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 84 | default TextSelection suggestSelection( |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 85 | @NonNull CharSequence text, |
| 86 | @IntRange(from = 0) int selectionStartIndex, |
Abodunrinwa Toki | 4cfda0b | 2017-02-28 18:56:47 +0000 | [diff] [blame] | 87 | @IntRange(from = 0) int selectionEndIndex, |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 88 | @Nullable TextSelection.Options options) { |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 89 | Utils.validateInput(text, selectionStartIndex, selectionEndIndex); |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 90 | return new TextSelection.Builder(selectionStartIndex, selectionEndIndex).build(); |
| 91 | } |
| 92 | |
| 93 | /** |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 94 | * Returns suggested text selection start and end indices, recognized entity types, and their |
| 95 | * associated confidence scores. The entity types are ordered from highest to lowest scoring. |
| 96 | * |
| 97 | * <p><b>NOTE:</b> Do not implement. The default implementation of this method calls |
| 98 | * {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. If that method |
| 99 | * calls this method, a stack overflow error will happen. |
| 100 | * |
| 101 | * @param text text providing context for the selected text (which is specified |
| 102 | * by the sub sequence starting at selectionStartIndex and ending at selectionEndIndex) |
| 103 | * @param selectionStartIndex start index of the selected part of text |
| 104 | * @param selectionEndIndex end index of the selected part of text |
| 105 | * |
| 106 | * @throws IllegalArgumentException if text is null; selectionStartIndex is negative; |
| 107 | * selectionEndIndex is greater than text.length() or not greater than selectionStartIndex |
| 108 | * |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 109 | * @see #suggestSelection(CharSequence, int, int, TextSelection.Options) |
| 110 | */ |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 111 | @WorkerThread |
| 112 | @NonNull |
| 113 | default TextSelection suggestSelection( |
| 114 | @NonNull CharSequence text, |
| 115 | @IntRange(from = 0) int selectionStartIndex, |
| 116 | @IntRange(from = 0) int selectionEndIndex) { |
| 117 | return suggestSelection(text, selectionStartIndex, selectionEndIndex, |
| 118 | (TextSelection.Options) null); |
| 119 | } |
| 120 | |
| 121 | /** |
| 122 | * See {@link #suggestSelection(CharSequence, int, int)} or |
| 123 | * {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. |
| 124 | * |
| 125 | * <p><b>NOTE:</b> Do not implement. The default implementation of this method calls |
| 126 | * {@link #suggestSelection(CharSequence, int, int, TextSelection.Options)}. If that method |
| 127 | * calls this method, a stack overflow error will happen. |
| 128 | */ |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 129 | @WorkerThread |
| 130 | @NonNull |
| 131 | default TextSelection suggestSelection( |
| 132 | @NonNull CharSequence text, |
| 133 | @IntRange(from = 0) int selectionStartIndex, |
| 134 | @IntRange(from = 0) int selectionEndIndex, |
| 135 | @Nullable LocaleList defaultLocales) { |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 136 | final TextSelection.Options options = (defaultLocales != null) |
| 137 | ? new TextSelection.Options().setDefaultLocales(defaultLocales) |
| 138 | : null; |
| 139 | return suggestSelection(text, selectionStartIndex, selectionEndIndex, options); |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 140 | } |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 141 | |
| 142 | /** |
Abodunrinwa Toki | e0b5789 | 2017-04-28 19:59:57 +0100 | [diff] [blame] | 143 | * Classifies the specified text and returns a {@link TextClassification} object that can be |
| 144 | * used to generate a widget for handling the classified text. |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 145 | * |
| 146 | * @param text text providing context for the text to classify (which is specified |
| 147 | * by the sub sequence starting at startIndex and ending at endIndex) |
| 148 | * @param startIndex start index of the text to classify |
| 149 | * @param endIndex end index of the text to classify |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 150 | * @param options optional input parameters |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 151 | * |
| 152 | * @throws IllegalArgumentException if text is null; startIndex is negative; |
Abodunrinwa Toki | 4cfda0b | 2017-02-28 18:56:47 +0000 | [diff] [blame] | 153 | * endIndex is greater than text.length() or not greater than startIndex |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 154 | * |
| 155 | * @see #classifyText(CharSequence, int, int) |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 156 | */ |
Abodunrinwa Toki | e0b5789 | 2017-04-28 19:59:57 +0100 | [diff] [blame] | 157 | @WorkerThread |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 158 | @NonNull |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 159 | default TextClassification classifyText( |
Abodunrinwa Toki | 4cfda0b | 2017-02-28 18:56:47 +0000 | [diff] [blame] | 160 | @NonNull CharSequence text, |
| 161 | @IntRange(from = 0) int startIndex, |
| 162 | @IntRange(from = 0) int endIndex, |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 163 | @Nullable TextClassification.Options options) { |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 164 | Utils.validateInput(text, startIndex, endIndex); |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 165 | return TextClassification.EMPTY; |
| 166 | } |
| 167 | |
| 168 | /** |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 169 | * Classifies the specified text and returns a {@link TextClassification} object that can be |
| 170 | * used to generate a widget for handling the classified text. |
| 171 | * |
| 172 | * <p><b>NOTE:</b> Do not implement. The default implementation of this method calls |
| 173 | * {@link #classifyText(CharSequence, int, int, TextClassification.Options)}. If that method |
| 174 | * calls this method, a stack overflow error will happen. |
| 175 | * |
| 176 | * @param text text providing context for the text to classify (which is specified |
| 177 | * by the sub sequence starting at startIndex and ending at endIndex) |
| 178 | * @param startIndex start index of the text to classify |
| 179 | * @param endIndex end index of the text to classify |
| 180 | * |
| 181 | * @throws IllegalArgumentException if text is null; startIndex is negative; |
| 182 | * endIndex is greater than text.length() or not greater than startIndex |
| 183 | * |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 184 | * @see #classifyText(CharSequence, int, int, TextClassification.Options) |
| 185 | */ |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 186 | @WorkerThread |
| 187 | @NonNull |
| 188 | default TextClassification classifyText( |
| 189 | @NonNull CharSequence text, |
| 190 | @IntRange(from = 0) int startIndex, |
| 191 | @IntRange(from = 0) int endIndex) { |
| 192 | return classifyText(text, startIndex, endIndex, (TextClassification.Options) null); |
| 193 | } |
| 194 | |
| 195 | /** |
| 196 | * See {@link #classifyText(CharSequence, int, int, TextClassification.Options)} or |
| 197 | * {@link #classifyText(CharSequence, int, int)}. |
| 198 | * |
| 199 | * <p><b>NOTE:</b> Do not implement. The default implementation of this method calls |
| 200 | * {@link #classifyText(CharSequence, int, int, TextClassification.Options)}. If that method |
| 201 | * calls this method, a stack overflow error will happen. |
| 202 | */ |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 203 | @WorkerThread |
| 204 | @NonNull |
| 205 | default TextClassification classifyText( |
| 206 | @NonNull CharSequence text, |
| 207 | @IntRange(from = 0) int startIndex, |
| 208 | @IntRange(from = 0) int endIndex, |
| 209 | @Nullable LocaleList defaultLocales) { |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 210 | final TextClassification.Options options = (defaultLocales != null) |
| 211 | ? new TextClassification.Options().setDefaultLocales(defaultLocales) |
| 212 | : null; |
| 213 | return classifyText(text, startIndex, endIndex, options); |
Abodunrinwa Toki | 2b6020f | 2017-10-28 02:28:45 +0100 | [diff] [blame] | 214 | } |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 215 | |
| 216 | /** |
Richard Ledley | 68d9452 | 2017-10-05 10:52:19 +0100 | [diff] [blame] | 217 | * Returns a {@link TextLinks} that may be applied to the text to annotate it with links |
| 218 | * information. |
| 219 | * |
| 220 | * @param text the text to generate annotations for |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 221 | * @param options configuration for link generation |
Richard Ledley | 68d9452 | 2017-10-05 10:52:19 +0100 | [diff] [blame] | 222 | * |
| 223 | * @throws IllegalArgumentException if text is null |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 224 | * |
| 225 | * @see #generateLinks(CharSequence) |
Richard Ledley | 68d9452 | 2017-10-05 10:52:19 +0100 | [diff] [blame] | 226 | */ |
| 227 | @WorkerThread |
| 228 | default TextLinks generateLinks( |
| 229 | @NonNull CharSequence text, @Nullable TextLinks.Options options) { |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 230 | Utils.validateInput(text); |
Richard Ledley | 68d9452 | 2017-10-05 10:52:19 +0100 | [diff] [blame] | 231 | return new TextLinks.Builder(text.toString()).build(); |
| 232 | } |
| 233 | |
| 234 | /** |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 235 | * Returns a {@link TextLinks} that may be applied to the text to annotate it with links |
| 236 | * information. |
| 237 | * |
| 238 | * <p><b>NOTE:</b> Do not implement. The default implementation of this method calls |
| 239 | * {@link #generateLinks(CharSequence, TextLinks.Options)}. If that method calls this method, |
| 240 | * a stack overflow error will happen. |
| 241 | * |
| 242 | * @param text the text to generate annotations for |
| 243 | * |
| 244 | * @throws IllegalArgumentException if text is null |
| 245 | * |
| 246 | * @see #generateLinks(CharSequence, TextLinks.Options) |
| 247 | */ |
| 248 | @WorkerThread |
| 249 | default TextLinks generateLinks(@NonNull CharSequence text) { |
| 250 | return generateLinks(text, null); |
| 251 | } |
| 252 | |
| 253 | /** |
Abodunrinwa Toki | 1d77557 | 2017-05-08 16:03:01 +0100 | [diff] [blame] | 254 | * Logs a TextClassifier event. |
| 255 | * |
| 256 | * @param source the text classifier used to generate this event |
| 257 | * @param event the text classifier related event |
| 258 | * @hide |
| 259 | */ |
| 260 | @WorkerThread |
| 261 | default void logEvent(String source, String event) {} |
Abodunrinwa Toki | 0e6b43e | 2017-09-19 23:18:40 +0100 | [diff] [blame] | 262 | |
| 263 | /** |
| 264 | * Returns this TextClassifier's settings. |
| 265 | * @hide |
| 266 | */ |
| 267 | default TextClassifierConstants getSettings() { |
| 268 | return TextClassifierConstants.DEFAULT; |
| 269 | } |
Abodunrinwa Toki | 4d232d6 | 2017-11-23 12:22:45 +0000 | [diff] [blame] | 270 | |
| 271 | |
| 272 | /** |
| 273 | * Utility functions for TextClassifier methods. |
| 274 | * |
| 275 | * <ul> |
| 276 | * <li>Provides validation of input parameters to TextClassifier methods |
| 277 | * </ul> |
| 278 | * |
| 279 | * Intended to be used only in this package. |
| 280 | * @hide |
| 281 | */ |
| 282 | final class Utils { |
| 283 | |
| 284 | /** |
| 285 | * @throws IllegalArgumentException if text is null; startIndex is negative; |
| 286 | * endIndex is greater than text.length() or is not greater than startIndex; |
| 287 | * options is null |
| 288 | */ |
| 289 | static void validateInput( |
| 290 | @NonNull CharSequence text, int startIndex, int endIndex) { |
| 291 | Preconditions.checkArgument(text != null); |
| 292 | Preconditions.checkArgument(startIndex >= 0); |
| 293 | Preconditions.checkArgument(endIndex <= text.length()); |
| 294 | Preconditions.checkArgument(endIndex > startIndex); |
| 295 | } |
| 296 | |
| 297 | /** |
| 298 | * @throws IllegalArgumentException if text is null or options is null |
| 299 | */ |
| 300 | static void validateInput(@NonNull CharSequence text) { |
| 301 | Preconditions.checkArgument(text != null); |
| 302 | } |
| 303 | } |
Abodunrinwa Toki | f001fef | 2017-01-04 23:51:42 +0000 | [diff] [blame] | 304 | } |