diff options
6 files changed, 139 insertions, 36 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 569a0db768aa..2c865642cca5 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10516,6 +10516,8 @@ public final class Settings { * entity_list_default use ":" as delimiter for values. Ex: * * <pre> + * smart_linkify_enabled (boolean) + * system_textclassifier_enabled (boolean) * model_dark_launch_enabled (boolean) * smart_selection_enabled (boolean) * smart_text_share_enabled (boolean) diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java index 32a7f376c4b1..21b56031556c 100644 --- a/core/java/android/view/textclassifier/TextClassificationConstants.java +++ b/core/java/android/view/textclassifier/TextClassificationConstants.java @@ -30,6 +30,8 @@ import java.util.StringJoiner; * This is encoded as a key=value list, separated by commas. Ex: * * <pre> + * smart_linkify_enabled (boolean) + * system_textclassifier_enabled (boolean) * model_dark_launch_enabled (boolean) * smart_selection_enabled (boolean) * smart_text_share_enabled (boolean) @@ -58,6 +60,10 @@ public final class TextClassificationConstants { private static final String LOG_TAG = "TextClassificationConstants"; + private static final String LOCAL_TEXT_CLASSIFIER_ENABLED = + "local_textclassifier_enabled"; + private static final String SYSTEM_TEXT_CLASSIFIER_ENABLED = + "system_textclassifier_enabled"; private static final String MODEL_DARK_LAUNCH_ENABLED = "model_dark_launch_enabled"; private static final String SMART_SELECTION_ENABLED = @@ -83,6 +89,8 @@ public final class TextClassificationConstants { private static final String ENTITY_LIST_EDITABLE = "entity_list_editable"; + private static final boolean LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT = true; + private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT = true; private static final boolean MODEL_DARK_LAUNCH_ENABLED_DEFAULT = false; private static final boolean SMART_SELECTION_ENABLED_DEFAULT = true; private static final boolean SMART_TEXT_SHARE_ENABLED_DEFAULT = true; @@ -102,6 +110,8 @@ public final class TextClassificationConstants { .add(TextClassifier.TYPE_DATE_TIME) .add(TextClassifier.TYPE_FLIGHT_NUMBER).toString(); + private final boolean mSystemTextClassifierEnabled; + private final boolean mLocalTextClassifierEnabled; private final boolean mModelDarkLaunchEnabled; private final boolean mSmartSelectionEnabled; private final boolean mSmartTextShareEnabled; @@ -123,6 +133,12 @@ public final class TextClassificationConstants { // Failed to parse the settings string, log this and move on with defaults. Slog.e(LOG_TAG, "Bad TextClassifier settings: " + settings); } + mSystemTextClassifierEnabled = parser.getBoolean( + SYSTEM_TEXT_CLASSIFIER_ENABLED, + SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT); + mLocalTextClassifierEnabled = parser.getBoolean( + LOCAL_TEXT_CLASSIFIER_ENABLED, + LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT); mModelDarkLaunchEnabled = parser.getBoolean( MODEL_DARK_LAUNCH_ENABLED, MODEL_DARK_LAUNCH_ENABLED_DEFAULT); @@ -130,8 +146,8 @@ public final class TextClassificationConstants { SMART_SELECTION_ENABLED, SMART_SELECTION_ENABLED_DEFAULT); mSmartTextShareEnabled = parser.getBoolean( - SMART_TEXT_SHARE_ENABLED, - SMART_TEXT_SHARE_ENABLED_DEFAULT); + SMART_TEXT_SHARE_ENABLED, + SMART_TEXT_SHARE_ENABLED_DEFAULT); mSmartLinkifyEnabled = parser.getBoolean( SMART_LINKIFY_ENABLED, SMART_LINKIFY_ENABLED_DEFAULT); @@ -166,6 +182,14 @@ public final class TextClassificationConstants { return new TextClassificationConstants(settings); } + public boolean isLocalTextClassifierEnabled() { + return mLocalTextClassifierEnabled; + } + + public boolean isSystemTextClassifierEnabled() { + return mSystemTextClassifierEnabled; + } + public boolean isModelDarkLaunchEnabled() { return mModelDarkLaunchEnabled; } diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java index fea932cf2a50..a7f1ca1aa239 100644 --- a/core/java/android/view/textclassifier/TextClassificationManager.java +++ b/core/java/android/view/textclassifier/TextClassificationManager.java @@ -22,7 +22,9 @@ import android.content.Context; import android.os.ServiceManager; import android.provider.Settings; import android.service.textclassifier.TextClassifierService; +import android.view.textclassifier.TextClassifier.TextClassifierType; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; /** @@ -31,16 +33,18 @@ import com.android.internal.util.Preconditions; @SystemService(Context.TEXT_CLASSIFICATION_SERVICE) public final class TextClassificationManager { - // TODO: Make this a configurable flag. - private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED = true; - private static final String LOG_TAG = "TextClassificationManager"; private final Object mLock = new Object(); private final Context mContext; private final TextClassificationConstants mSettings; + + @GuardedBy("mLock") private TextClassifier mTextClassifier; + @GuardedBy("mLock") + private TextClassifier mLocalTextClassifier; + @GuardedBy("mLock") private TextClassifier mSystemTextClassifier; /** @hide */ @@ -51,38 +55,19 @@ public final class TextClassificationManager { } /** - * Returns the system's default TextClassifier. - * @hide - */ - // TODO: Unhide when this is ready. - public TextClassifier getSystemDefaultTextClassifier() { - synchronized (mLock) { - if (mSystemTextClassifier == null && isSystemTextClassifierEnabled()) { - try { - Log.d(LOG_TAG, "Initialized SystemTextClassifier"); - mSystemTextClassifier = new SystemTextClassifier(mContext, mSettings); - } catch (ServiceManager.ServiceNotFoundException e) { - Log.e(LOG_TAG, "Could not initialize SystemTextClassifier", e); - } - } - if (mSystemTextClassifier == null) { - Log.d(LOG_TAG, "Using an in-process TextClassifier as the system default"); - mSystemTextClassifier = new TextClassifierImpl(mContext, mSettings); - } - } - return mSystemTextClassifier; - } - - /** - * Returns the text classifier. + * Returns the text classifier that was set via {@link #setTextClassifier(TextClassifier)}. + * If this is null, this method returns a default text classifier (i.e. either the system text + * classifier if one exists, or a local text classifier running in this app.) + * + * @see #setTextClassifier(TextClassifier) */ public TextClassifier getTextClassifier() { synchronized (mLock) { if (mTextClassifier == null) { if (isSystemTextClassifierEnabled()) { - mTextClassifier = getSystemDefaultTextClassifier(); + mTextClassifier = getSystemTextClassifier(); } else { - mTextClassifier = new TextClassifierImpl(mContext, mSettings); + mTextClassifier = getLocalTextClassifier(); } } return mTextClassifier; @@ -100,8 +85,62 @@ public final class TextClassificationManager { } } + /** + * Returns a specific type of text classifier. + * If the specified text classifier cannot be found, this returns {@link TextClassifier#NO_OP}. + * + * @see TextClassifier#LOCAL + * @see TextClassifier#SYSTEM + * @hide + */ + // TODO: Expose as system API. + public TextClassifier getTextClassifier(@TextClassifierType int type) { + switch (type) { + case TextClassifier.LOCAL: + return getLocalTextClassifier(); + default: + return getSystemTextClassifier(); + } + } + + /** @hide */ + public TextClassificationConstants getSettings() { + return mSettings; + } + + private TextClassifier getSystemTextClassifier() { + synchronized (mLock) { + if (mSystemTextClassifier == null && isSystemTextClassifierEnabled()) { + try { + mSystemTextClassifier = new SystemTextClassifier(mContext, mSettings); + Log.d(LOG_TAG, "Initialized SystemTextClassifier"); + } catch (ServiceManager.ServiceNotFoundException e) { + Log.e(LOG_TAG, "Could not initialize SystemTextClassifier", e); + } + } + } + if (mSystemTextClassifier != null) { + return mSystemTextClassifier; + } + return TextClassifier.NO_OP; + } + + private TextClassifier getLocalTextClassifier() { + synchronized (mLock) { + if (mLocalTextClassifier == null) { + if (mSettings.isLocalTextClassifierEnabled()) { + mLocalTextClassifier = new TextClassifierImpl(mContext, mSettings); + } else { + Log.d(LOG_TAG, "Local TextClassifier disabled"); + mLocalTextClassifier = TextClassifierImpl.NO_OP; + } + } + return mLocalTextClassifier; + } + } + private boolean isSystemTextClassifierEnabled() { - return SYSTEM_TEXT_CLASSIFIER_ENABLED + return mSettings.isSystemTextClassifierEnabled() && TextClassifierService.getServiceComponentName(mContext) != null; } diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java index 0321bb6d62fa..ec40fdd0ffb1 100644 --- a/core/java/android/view/textclassifier/TextClassifier.java +++ b/core/java/android/view/textclassifier/TextClassifier.java @@ -16,6 +16,7 @@ package android.view.textclassifier; +import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -49,6 +50,16 @@ public interface TextClassifier { /** @hide */ String DEFAULT_LOG_TAG = "androidtc"; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {LOCAL, SYSTEM}) + @interface TextClassifierType {} // TODO: Expose as system APIs. + /** Specifies a TextClassifier that runs locally in the app's process. @hide */ + int LOCAL = 0; + /** Specifies a TextClassifier that runs in the system process and serves all apps. @hide */ + int SYSTEM = 1; + /** The TextClassifier failed to run. */ String TYPE_UNKNOWN = ""; /** The classifier ran, but didn't recognize a known entity. */ diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java index 7f16359ad269..54007fb98e67 100644 --- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationConstantsTest.java @@ -32,7 +32,9 @@ public class TextClassificationConstantsTest { @Test public void testLoadFromString() { - final String s = "model_dark_launch_enabled=true," + final String s = "local_textclassifier_enabled=true," + + "system_textclassifier_enabled=true," + + "model_dark_launch_enabled=true," + "smart_selection_enabled=true," + "smart_text_share_enabled=true," + "smart_linkify_enabled=true," @@ -43,6 +45,10 @@ public class TextClassificationConstantsTest { + "generate_links_log_sample_rate=13"; final TextClassificationConstants constants = TextClassificationConstants.loadFromString(s); + assertTrue("local_textclassifier_enabled", + constants.isLocalTextClassifierEnabled()); + assertTrue("system_textclassifier_enabled", + constants.isSystemTextClassifierEnabled()); assertTrue("model_dark_launch_enabled", constants.isModelDarkLaunchEnabled()); assertTrue("smart_selection_enabled", constants.isSmartSelectionEnabled()); assertTrue("smart_text_share_enabled", constants.isSmartTextShareEnabled()); @@ -60,7 +66,9 @@ public class TextClassificationConstantsTest { @Test public void testLoadFromString_differentValues() { - final String s = "model_dark_launch_enabled=false," + final String s = "local_textclassifier_enabled=false," + + "system_textclassifier_enabled=false," + + "model_dark_launch_enabled=false," + "smart_selection_enabled=false," + "smart_text_share_enabled=false," + "smart_linkify_enabled=false," @@ -71,6 +79,10 @@ public class TextClassificationConstantsTest { + "generate_links_log_sample_rate=5"; final TextClassificationConstants constants = TextClassificationConstants.loadFromString(s); + assertFalse("local_textclassifier_enabled", + constants.isLocalTextClassifierEnabled()); + assertFalse("system_textclassifier_enabled", + constants.isSystemTextClassifierEnabled()); assertFalse("model_dark_launch_enabled", constants.isModelDarkLaunchEnabled()); assertFalse("smart_selection_enabled", constants.isSmartSelectionEnabled()); assertFalse("smart_text_share_enabled", constants.isSmartTextShareEnabled()); diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java index 5407ce69abcf..57db153ddcd5 100644 --- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java +++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java @@ -22,7 +22,9 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; +import android.content.Context; import android.os.LocaleList; +import android.service.textclassifier.TextClassifierService; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -44,6 +46,7 @@ public class TextClassificationManagerTest { private static final LocaleList LOCALES = LocaleList.forLanguageTags("en-US"); private static final String NO_TYPE = null; + private Context mContext; private TextClassificationManager mTcm; private TextClassifier mClassifier; private TextSelection.Options mSelectionOptions; @@ -52,8 +55,8 @@ public class TextClassificationManagerTest { @Before public void setup() { - mTcm = InstrumentationRegistry.getTargetContext() - .getSystemService(TextClassificationManager.class); + mContext = InstrumentationRegistry.getTargetContext(); + mTcm = mContext.getSystemService(TextClassificationManager.class); mTcm.setTextClassifier(null); mClassifier = mTcm.getTextClassifier(); mSelectionOptions = new TextSelection.Options().setDefaultLocales(LOCALES); @@ -282,6 +285,18 @@ public class TextClassificationManagerTest { assertEquals(classifier, mTcm.getTextClassifier()); } + @Test + public void testGetLocalTextClassifier() { + assertTrue(mTcm.getTextClassifier(TextClassifier.LOCAL) instanceof TextClassifierImpl); + } + + @Test + public void testGetSystemTextClassifier() { + assertTrue( + TextClassifierService.getServiceComponentName(mContext) == null + || mTcm.getTextClassifier(TextClassifier.SYSTEM) instanceof SystemTextClassifier); + } + private boolean isTextClassifierDisabled() { return mClassifier == TextClassifier.NO_OP; } |