import android.util.KeyValueListParser;
import android.util.Slog;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringJoiner;
+
/**
* TextClassifier specific settings.
* This is encoded as a key=value list, separated by commas. Ex:
* <pre>
* smart_selection_dark_launch (boolean)
* smart_selection_enabled_for_edit_text (boolean)
+ * suggest_selection_max_range_length (int)
+ * classify_text_max_range_length (int)
+ * generate_links_max_text_length (int)
+ * entity_list_default (String[])
+ * entity_list_not_editable (String[])
+ * entity_list_editable (String[])
* </pre>
*
* <p>
* see also android.provider.Settings.Global.TEXT_CLASSIFIER_CONSTANTS
*
* Example of setting the values for testing.
- * adb shell settings put global text_classifier_constants smart_selection_dark_launch=true,smart_selection_enabled_for_edit_text=true
+ * adb shell settings put global text_classifier_constants \
+ * smart_selection_dark_launch=true,smart_selection_enabled_for_edit_text=true,\
+ * entity_list_default=phone:address
* @hide
*/
public final class TextClassifierConstants {
"generate_links_max_text_length";
private static final String GENERATE_LINKS_LOG_SAMPLE_RATE =
"generate_links_log_sample_rate";
+ private static final String ENTITY_LIST_DEFAULT =
+ "entity_list_default";
+ private static final String ENTITY_LIST_NOT_EDITABLE =
+ "entity_list_not_editable";
+ private static final String ENTITY_LIST_EDITABLE =
+ "entity_list_editable";
private static final boolean SMART_SELECTION_DARK_LAUNCH_DEFAULT = false;
private static final boolean SMART_SELECTION_ENABLED_FOR_EDIT_TEXT_DEFAULT = true;
private static final int CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT = 10 * 1000;
private static final int GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT = 100 * 1000;
private static final int GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT = 100;
+ private static final String ENTITY_LIST_DELIMITER = ":";
+ private static final String ENTITY_LIST_DEFAULT_VALUE = new StringJoiner(ENTITY_LIST_DELIMITER)
+ .add(TextClassifier.TYPE_ADDRESS)
+ .add(TextClassifier.TYPE_EMAIL)
+ .add(TextClassifier.TYPE_PHONE)
+ .add(TextClassifier.TYPE_URL)
+ .add(TextClassifier.TYPE_DATE)
+ .add(TextClassifier.TYPE_DATE_TIME)
+ .add(TextClassifier.TYPE_FLIGHT_NUMBER).toString();
/** Default settings. */
static final TextClassifierConstants DEFAULT = new TextClassifierConstants();
private final int mClassifyTextMaxRangeLength;
private final int mGenerateLinksMaxTextLength;
private final int mGenerateLinksLogSampleRate;
+ private final List<String> mEntityListDefault;
+ private final List<String> mEntityListNotEditable;
+ private final List<String> mEntityListEditable;
private TextClassifierConstants() {
mDarkLaunch = SMART_SELECTION_DARK_LAUNCH_DEFAULT;
mClassifyTextMaxRangeLength = CLASSIFY_TEXT_MAX_RANGE_LENGTH_DEFAULT;
mGenerateLinksMaxTextLength = GENERATE_LINKS_MAX_TEXT_LENGTH_DEFAULT;
mGenerateLinksLogSampleRate = GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT;
+ mEntityListDefault = parseEntityList(ENTITY_LIST_DEFAULT_VALUE);
+ mEntityListNotEditable = mEntityListDefault;
+ mEntityListEditable = mEntityListDefault;
}
private TextClassifierConstants(@Nullable String settings) {
mGenerateLinksLogSampleRate = parser.getInt(
GENERATE_LINKS_LOG_SAMPLE_RATE,
GENERATE_LINKS_LOG_SAMPLE_RATE_DEFAULT);
+ mEntityListDefault = parseEntityList(parser.getString(
+ ENTITY_LIST_DEFAULT,
+ ENTITY_LIST_DEFAULT_VALUE));
+ mEntityListNotEditable = parseEntityList(parser.getString(
+ ENTITY_LIST_NOT_EDITABLE,
+ ENTITY_LIST_DEFAULT_VALUE));
+ mEntityListEditable = parseEntityList(parser.getString(
+ ENTITY_LIST_EDITABLE,
+ ENTITY_LIST_DEFAULT_VALUE));
}
- static TextClassifierConstants loadFromString(String settings) {
+ /** Load from a settings string. */
+ public static TextClassifierConstants loadFromString(String settings) {
return new TextClassifierConstants(settings);
}
public int getGenerateLinksLogSampleRate() {
return mGenerateLinksLogSampleRate;
}
+
+ public List<String> getEntityListDefault() {
+ return mEntityListDefault;
+ }
+
+ public List<String> getEntityListNotEditable() {
+ return mEntityListNotEditable;
+ }
+
+ public List<String> getEntityListEditable() {
+ return mEntityListEditable;
+ }
+
+ private static List<String> parseEntityList(String listStr) {
+ return Collections.unmodifiableList(Arrays.asList(listStr.split(ENTITY_LIST_DELIMITER)));
+ }
}
private static final String MODEL_FILE_REGEX = "textclassifier\\.(.*)\\.model";
private static final String UPDATED_MODEL_FILE_PATH =
"/data/misc/textclassifier/textclassifier.model";
- private static final List<String> ENTITY_TYPES_ALL =
- Collections.unmodifiableList(Arrays.asList(
- TextClassifier.TYPE_ADDRESS,
- TextClassifier.TYPE_EMAIL,
- TextClassifier.TYPE_PHONE,
- TextClassifier.TYPE_URL,
- TextClassifier.TYPE_DATE,
- TextClassifier.TYPE_DATE_TIME,
- TextClassifier.TYPE_FLIGHT_NUMBER));
private final Context mContext;
private final TextClassifier mFallback;
options != null && options.getEntityConfig() != null
? options.getEntityConfig().resolveEntityListModifications(
getEntitiesForHints(options.getEntityConfig().getHints()))
- : ENTITY_TYPES_ALL;
+ : getSettings().getEntityListDefault();
final TextClassifierImplNative nativeImpl =
getNative(defaultLocales);
final TextClassifierImplNative.AnnotatedSpan[] annotations =
}
private Collection<String> getEntitiesForHints(Collection<String> hints) {
- return ENTITY_TYPES_ALL;
+ final boolean editable = hints.contains(HINT_TEXT_IS_EDITABLE);
+ final boolean notEditable = hints.contains(HINT_TEXT_IS_NOT_EDITABLE);
+
+ // Use the default if there is no hint, or conflicting ones.
+ final boolean useDefault = editable == notEditable;
+ if (useDefault) {
+ return getSettings().getEntityListDefault();
+ } else if (editable) {
+ return getSettings().getEntityListEditable();
+ } else { // notEditable
+ return getSettings().getEntityListNotEditable();
+ }
}
@Override
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.textclassifier;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TextClassifierConstantsTest {
+
+ @Test
+ public void testEntityListParsing() {
+ final TextClassifierConstants constants = TextClassifierConstants.loadFromString(
+ "entity_list_default=phone,"
+ + "entity_list_not_editable=address:flight,"
+ + "entity_list_editable=date:datetime");
+ assertEquals(1, constants.getEntityListDefault().size());
+ assertEquals("phone", constants.getEntityListDefault().get(0));
+ assertEquals(2, constants.getEntityListNotEditable().size());
+ assertEquals("address", constants.getEntityListNotEditable().get(0));
+ assertEquals("flight", constants.getEntityListNotEditable().get(1));
+ assertEquals(2, constants.getEntityListEditable().size());
+ assertEquals("date", constants.getEntityListEditable().get(0));
+ assertEquals("datetime", constants.getEntityListEditable().get(1));
+ }
+}